From 5727f8b8a97d9fdf2837499f4b4a6b41bf78949a Mon Sep 17 00:00:00 2001 From: Prachig-Microsoft Date: Fri, 20 Mar 2026 17:39:58 +0530 Subject: [PATCH 1/7] Standardize environment variable naming conventions - Renamed AZURE_ENV_OPENAI_LOCATION to AZURE_ENV_AI_SERVICE_LOCATION - Renamed AZURE_ENV_MODEL_NAME to AZURE_ENV_GPT_MODEL_NAME - Renamed AZURE_ENV_MODEL_VERSION to AZURE_ENV_GPT_MODEL_VERSION - Renamed AZURE_ENV_MODEL_CAPACITY to AZURE_ENV_GPT_MODEL_CAPACITY - Renamed AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID to AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID - Renamed AZURE_EXISTING_AI_PROJECT_RESOURCE_ID to AZURE_ENV_FOUNDRY_PROJECT_RID Updated 14 files across workflows, parameter files, scripts, and documentation to maintain consistency throughout the project. --- .github/workflows/azure-dev.yml | 4 +- .github/workflows/deploy-orchestrator.yml | 10 +-- .github/workflows/deploy-v2.yml | 46 +++++------ .github/workflows/job-cleanup-deployment.yml | 4 +- .github/workflows/job-deploy-linux.yml | 80 +++++++++---------- .github/workflows/job-deploy-windows.yml | 82 ++++++++++---------- .github/workflows/job-deploy.yml | 58 +++++++------- docs/CustomizingAzdParameters.md | 14 ++-- docs/re-use-foundry-project.md | 2 +- docs/re-use-log-analytics.md | 2 +- infra/main.parameters.json | 12 +-- infra/main.waf.parameters.json | 12 +-- infra/scripts/validate_model_quota.ps1 | 4 +- infra/scripts/validate_model_quota.sh | 4 +- 14 files changed, 167 insertions(+), 167 deletions(-) diff --git a/.github/workflows/azure-dev.yml b/.github/workflows/azure-dev.yml index 23bed8a20..e09a24a1d 100644 --- a/.github/workflows/azure-dev.yml +++ b/.github/workflows/azure-dev.yml @@ -29,8 +29,8 @@ jobs: AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} AZURE_ENV_NAME: ${{ secrets.AZURE_ENV_NAME }} AZURE_LOCATION: ${{ secrets.AZURE_LOCATION }} - AZURE_ENV_OPENAI_LOCATION : ${{ secrets.AZURE_AI_DEPLOYMENT_LOCATION }} - AZURE_ENV_MODEL_CAPACITY: 1 + AZURE_ENV_AI_SERVICE_LOCATION : ${{ secrets.AZURE_AI_DEPLOYMENT_LOCATION }} + AZURE_ENV_GPT_MODEL_CAPACITY: 1 AZURE_ENV_MODEL_4_1_CAPACITY: 1 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} AZURE_DEV_COLLECT_TELEMETRY: ${{ vars.AZURE_DEV_COLLECT_TELEMETRY }} diff --git a/.github/workflows/deploy-orchestrator.yml b/.github/workflows/deploy-orchestrator.yml index 8a9f90838..cedee1934 100644 --- a/.github/workflows/deploy-orchestrator.yml +++ b/.github/workflows/deploy-orchestrator.yml @@ -42,12 +42,12 @@ on: required: false default: 'GoldenPath-Testing' type: string - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: + AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: description: 'Log Analytics Workspace ID (Optional)' required: false default: '' type: string - AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: + AZURE_ENV_FOUNDRY_PROJECT_RID: description: 'AI Project Resource ID (Optional)' required: false default: '' @@ -86,8 +86,8 @@ jobs: EXP: ${{ inputs.EXP }} build_docker_image: ${{ inputs.build_docker_image }} existing_webapp_url: ${{ inputs.existing_webapp_url }} - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }} - AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }} + AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} + AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} docker_image_tag: ${{ needs.docker-build.outputs.IMAGE_TAG }} run_e2e_tests: ${{ inputs.run_e2e_tests }} cleanup_resources: ${{ inputs.cleanup_resources }} @@ -134,7 +134,7 @@ jobs: existing_webapp_url: ${{ inputs.existing_webapp_url }} RESOURCE_GROUP_NAME: ${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }} AZURE_LOCATION: ${{ needs.deploy.outputs.AZURE_LOCATION }} - AZURE_ENV_OPENAI_LOCATION: ${{ needs.deploy.outputs.AZURE_ENV_OPENAI_LOCATION }} + AZURE_ENV_AI_SERVICE_LOCATION: ${{ needs.deploy.outputs.AZURE_ENV_AI_SERVICE_LOCATION }} ENV_NAME: ${{ needs.deploy.outputs.ENV_NAME }} IMAGE_TAG: ${{ needs.deploy.outputs.IMAGE_TAG }} secrets: inherit diff --git a/.github/workflows/deploy-v2.yml b/.github/workflows/deploy-v2.yml index 2d7234d68..cfc617588 100644 --- a/.github/workflows/deploy-v2.yml +++ b/.github/workflows/deploy-v2.yml @@ -75,12 +75,12 @@ on: - 'Smoke-Testing' - 'None' - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: + AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: description: 'Log Analytics Workspace ID (Optional)' required: false default: '' type: string - AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: + AZURE_ENV_FOUNDRY_PROJECT_RID: description: 'AI Project Resource ID (Optional)' required: false default: '' @@ -108,7 +108,7 @@ jobs: cleanup_resources: ${{ steps.validate.outputs.cleanup_resources }} run_e2e_tests: ${{ steps.validate.outputs.run_e2e_tests }} azure_env_log_analytics_workspace_id: ${{ steps.validate.outputs.azure_env_log_analytics_workspace_id }} - azure_existing_ai_project_resource_id: ${{ steps.validate.outputs.azure_existing_ai_project_resource_id }} + azure_env_foundry_project_rid: ${{ steps.validate.outputs.azure_env_foundry_project_rid }} existing_webapp_url: ${{ steps.validate.outputs.existing_webapp_url }} steps: - name: Validate Workflow Input Parameters @@ -123,8 +123,8 @@ jobs: INPUT_BUILD_DOCKER_IMAGE: ${{ github.event.inputs.build_docker_image }} INPUT_CLEANUP_RESOURCES: ${{ github.event.inputs.cleanup_resources }} INPUT_RUN_E2E_TESTS: ${{ github.event.inputs.run_e2e_tests }} - INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ github.event.inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }} - INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ github.event.inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }} + INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ github.event.inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} + INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ github.event.inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} INPUT_EXISTING_WEBAPP_URL: ${{ github.event.inputs.existing_webapp_url }} run: | echo "šŸ” Validating workflow input parameters..." @@ -214,32 +214,32 @@ jobs: echo "āœ… run_e2e_tests: '$TEST_OPTION' is valid" fi - # Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID (optional, Azure Resource ID format) - if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" ]]; then - if [[ ! "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then - echo "āŒ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID is invalid. Must be a valid Azure Resource ID format:" + # Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID (optional, Azure Resource ID format) + if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" ]]; then + if [[ ! "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then + echo "āŒ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID is invalid. Must be a valid Azure Resource ID format:" echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}" - echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID'" + echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: Valid Resource ID format" + echo "āœ… AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: Valid Resource ID format" fi else - echo "āœ… AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: Not provided (optional)" + echo "āœ… AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: Not provided (optional)" fi - # Validate AZURE_EXISTING_AI_PROJECT_RESOURCE_ID (optional, Azure Resource ID format) - if [[ -n "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" ]]; then - if [[ ! "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then - echo "āŒ ERROR: AZURE_EXISTING_AI_PROJECT_RESOURCE_ID is invalid. Must be a valid Azure Resource ID format:" + # Validate AZURE_ENV_FOUNDRY_PROJECT_RID (optional, Azure Resource ID format) + if [[ -n "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" ]]; then + if [[ ! "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then + echo "āŒ ERROR: AZURE_ENV_FOUNDRY_PROJECT_RID is invalid. Must be a valid Azure Resource ID format:" echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/projects/{projectName}" - echo " Got: '$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID'" + echo " Got: '$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: Valid Resource ID format" + echo "āœ… AZURE_ENV_FOUNDRY_PROJECT_RID: Valid Resource ID format" fi else - echo "āœ… AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: Not provided (optional)" + echo "āœ… AZURE_ENV_FOUNDRY_PROJECT_RID: Not provided (optional)" fi # Validate existing_webapp_url (optional, must start with https) @@ -274,8 +274,8 @@ jobs: echo "build_docker_image=$BUILD_DOCKER" >> $GITHUB_OUTPUT echo "cleanup_resources=$CLEANUP_RESOURCES" >> $GITHUB_OUTPUT echo "run_e2e_tests=$TEST_OPTION" >> $GITHUB_OUTPUT - echo "azure_env_log_analytics_workspace_id=$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" >> $GITHUB_OUTPUT - echo "azure_existing_ai_project_resource_id=$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" >> $GITHUB_OUTPUT + echo "azure_env_log_analytics_workspace_id=$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" >> $GITHUB_OUTPUT + echo "azure_env_foundry_project_rid=$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" >> $GITHUB_OUTPUT echo "existing_webapp_url=$INPUT_EXISTING_WEBAPP_URL" >> $GITHUB_OUTPUT Run: @@ -291,8 +291,8 @@ jobs: build_docker_image: ${{ needs.validate-inputs.outputs.build_docker_image == 'true' }} cleanup_resources: ${{ needs.validate-inputs.outputs.cleanup_resources == 'true' }} run_e2e_tests: ${{ needs.validate-inputs.outputs.run_e2e_tests || 'GoldenPath-Testing' }} - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ needs.validate-inputs.outputs.azure_env_log_analytics_workspace_id || '' }} - AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ needs.validate-inputs.outputs.azure_existing_ai_project_resource_id || '' }} + AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ needs.validate-inputs.outputs.azure_env_log_analytics_workspace_id || '' }} + AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ needs.validate-inputs.outputs.azure_env_foundry_project_rid || '' }} existing_webapp_url: ${{ needs.validate-inputs.outputs.existing_webapp_url || '' }} trigger_type: ${{ github.event_name }} secrets: inherit diff --git a/.github/workflows/job-cleanup-deployment.yml b/.github/workflows/job-cleanup-deployment.yml index 48c2586b0..f5ae08e58 100644 --- a/.github/workflows/job-cleanup-deployment.yml +++ b/.github/workflows/job-cleanup-deployment.yml @@ -29,7 +29,7 @@ on: description: 'Azure Location' required: true type: string - AZURE_ENV_OPENAI_LOCATION: + AZURE_ENV_AI_SERVICE_LOCATION: description: 'Azure OpenAI Location' required: true type: string @@ -50,7 +50,7 @@ jobs: env: RESOURCE_GROUP_NAME: ${{ inputs.RESOURCE_GROUP_NAME }} AZURE_LOCATION: ${{ inputs.AZURE_LOCATION }} - AZURE_ENV_OPENAI_LOCATION: ${{ inputs.AZURE_ENV_OPENAI_LOCATION }} + AZURE_ENV_AI_SERVICE_LOCATION: ${{ inputs.AZURE_ENV_AI_SERVICE_LOCATION }} ENV_NAME: ${{ inputs.ENV_NAME }} IMAGE_TAG: ${{ inputs.IMAGE_TAG }} steps: diff --git a/.github/workflows/job-deploy-linux.yml b/.github/workflows/job-deploy-linux.yml index 60c5458ef..21ddbb627 100644 --- a/.github/workflows/job-deploy-linux.yml +++ b/.github/workflows/job-deploy-linux.yml @@ -6,7 +6,7 @@ on: ENV_NAME: required: true type: string - AZURE_ENV_OPENAI_LOCATION: + AZURE_ENV_AI_SERVICE_LOCATION: required: true type: string AZURE_LOCATION: @@ -28,10 +28,10 @@ on: required: false type: string default: 'false' - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: + AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: required: false type: string - AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: + AZURE_ENV_FOUNDRY_PROJECT_RID: required: false type: string outputs: @@ -59,15 +59,15 @@ jobs: shell: bash env: INPUT_ENV_NAME: ${{ inputs.ENV_NAME }} - INPUT_AZURE_ENV_OPENAI_LOCATION: ${{ inputs.AZURE_ENV_OPENAI_LOCATION }} + INPUT_AZURE_ENV_AI_SERVICE_LOCATION: ${{ inputs.AZURE_ENV_AI_SERVICE_LOCATION }} INPUT_AZURE_LOCATION: ${{ inputs.AZURE_LOCATION }} INPUT_RESOURCE_GROUP_NAME: ${{ inputs.RESOURCE_GROUP_NAME }} INPUT_IMAGE_TAG: ${{ inputs.IMAGE_TAG }} INPUT_BUILD_DOCKER_IMAGE: ${{ inputs.BUILD_DOCKER_IMAGE }} INPUT_EXP: ${{ inputs.EXP }} INPUT_WAF_ENABLED: ${{ inputs.WAF_ENABLED }} - INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }} - INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }} + INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} + INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} run: | echo "šŸ” Validating workflow input parameters..." VALIDATION_FAILED=false @@ -83,15 +83,15 @@ jobs: echo "āœ… ENV_NAME: '$INPUT_ENV_NAME' is valid" fi - # Validate AZURE_ENV_OPENAI_LOCATION (required, Azure region format) - if [[ -z "$INPUT_AZURE_ENV_OPENAI_LOCATION" ]]; then - echo "āŒ ERROR: AZURE_ENV_OPENAI_LOCATION is required but not provided" + # Validate AZURE_ENV_AI_SERVICE_LOCATION (required, Azure region format) + if [[ -z "$INPUT_AZURE_ENV_AI_SERVICE_LOCATION" ]]; then + echo "āŒ ERROR: AZURE_ENV_AI_SERVICE_LOCATION is required but not provided" VALIDATION_FAILED=true - elif [[ ! "$INPUT_AZURE_ENV_OPENAI_LOCATION" =~ ^[a-z0-9]+$ ]]; then - echo "āŒ ERROR: AZURE_ENV_OPENAI_LOCATION '$INPUT_AZURE_ENV_OPENAI_LOCATION' is invalid. Must contain only lowercase letters and numbers" + elif [[ ! "$INPUT_AZURE_ENV_AI_SERVICE_LOCATION" =~ ^[a-z0-9]+$ ]]; then + echo "āŒ ERROR: AZURE_ENV_AI_SERVICE_LOCATION '$INPUT_AZURE_ENV_AI_SERVICE_LOCATION' is invalid. Must contain only lowercase letters and numbers" VALIDATION_FAILED=true else - echo "āœ… AZURE_ENV_OPENAI_LOCATION: '$INPUT_AZURE_ENV_OPENAI_LOCATION' is valid" + echo "āœ… AZURE_ENV_AI_SERVICE_LOCATION: '$INPUT_AZURE_ENV_AI_SERVICE_LOCATION' is valid" fi # Validate AZURE_LOCATION (required, Azure region format) @@ -154,27 +154,27 @@ jobs: echo "āœ… WAF_ENABLED: '$INPUT_WAF_ENABLED' is valid" fi - # Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID (optional, if provided must be valid Resource ID) - if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" ]]; then - if [[ ! "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then - echo "āŒ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID is invalid. Must be a valid Azure Resource ID format:" - echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}" - echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID'" + # Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID (optional, if provided must be valid Resource ID) + if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" ]]; then + if [[ ! "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then + echo "āŒ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID is invalid. Must be a valid Azure Resource ID format:" + echo " Expected: /subscriptions/{guid}/resourceGroups/{rg}/providers/Microsoft.OperationalInsights/workspaces/{name}" + echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: Valid Resource ID format" + echo "āœ… AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: Valid Resource ID format" fi fi - # Validate AZURE_EXISTING_AI_PROJECT_RESOURCE_ID (optional, if provided must be valid Resource ID) - if [[ -n "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" ]]; then - if [[ ! "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then - echo "āŒ ERROR: AZURE_EXISTING_AI_PROJECT_RESOURCE_ID is invalid. Must be a valid Azure Resource ID format:" - echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/projects/{projectName}" - echo " Got: '$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID'" + # Validate AZURE_ENV_FOUNDRY_PROJECT_RID (optional, if provided must be valid Resource ID) + if [[ -n "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" ]]; then + if [[ ! "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then + echo "āŒ ERROR: AZURE_ENV_FOUNDRY_PROJECT_RID is invalid. Must be a valid Azure Resource ID format:" + echo " Expected: /subscriptions/{guid}/resourceGroups/{rg}/providers/Microsoft.CognitiveServices/accounts/{account}/projects/{project}" + echo " Got: '$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: Valid Resource ID format" + echo "āœ… AZURE_ENV_FOUNDRY_PROJECT_RID: Valid Resource ID format" fi fi @@ -222,14 +222,14 @@ jobs: shell: bash env: INPUT_ENV_NAME: ${{ inputs.ENV_NAME }} - INPUT_AZURE_ENV_OPENAI_LOCATION: ${{ inputs.AZURE_ENV_OPENAI_LOCATION }} + INPUT_AZURE_ENV_AI_SERVICE_LOCATION: ${{ inputs.AZURE_ENV_AI_SERVICE_LOCATION }} INPUT_AZURE_LOCATION: ${{ inputs.AZURE_LOCATION }} INPUT_RESOURCE_GROUP_NAME: ${{ inputs.RESOURCE_GROUP_NAME }} INPUT_IMAGE_TAG: ${{ inputs.IMAGE_TAG }} INPUT_BUILD_DOCKER_IMAGE: ${{ inputs.BUILD_DOCKER_IMAGE }} INPUT_EXP: ${{ inputs.EXP }} - INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }} - INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }} + INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} + INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} run: | set -e @@ -242,7 +242,7 @@ jobs: # Set additional parameters azd env set AZURE_SUBSCRIPTION_ID="${{ secrets.AZURE_SUBSCRIPTION_ID }}" - azd env set AZURE_ENV_OPENAI_LOCATION="$INPUT_AZURE_ENV_OPENAI_LOCATION" + azd env set AZURE_ENV_AI_SERVICE_LOCATION="$INPUT_AZURE_ENV_AI_SERVICE_LOCATION" azd env set AZURE_LOCATION="$INPUT_AZURE_LOCATION" azd env set AZURE_RESOURCE_GROUP="$INPUT_RESOURCE_GROUP_NAME" azd env set AZURE_ENV_IMAGE_TAG="$INPUT_IMAGE_TAG" @@ -258,22 +258,22 @@ jobs: if [[ "$INPUT_EXP" == "true" ]]; then echo "āœ… EXP ENABLED - Setting EXP parameters..." - if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" ]]; then - EXP_LOG_ANALYTICS_ID="$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" + if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" ]]; then + EXP_LOG_ANALYTICS_ID="$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" else - EXP_LOG_ANALYTICS_ID="${{ secrets.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}" + EXP_LOG_ANALYTICS_ID="${{ secrets.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }}" fi - if [[ -n "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" ]]; then - EXP_AI_PROJECT_ID="$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" + if [[ -n "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" ]]; then + EXP_AI_PROJECT_ID="$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" else EXP_AI_PROJECT_ID="${{ secrets.AZURE_ENV_FOUNDRY_PROJECT_ID }}" fi - echo "AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: $EXP_LOG_ANALYTICS_ID" + echo "AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: $EXP_LOG_ANALYTICS_ID" echo "AZURE_ENV_FOUNDRY_PROJECT_ID: $EXP_AI_PROJECT_ID" - azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID="$EXP_LOG_ANALYTICS_ID" - azd env set AZURE_EXISTING_AI_PROJECT_RESOURCE_ID="$EXP_AI_PROJECT_ID" + azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID="$EXP_LOG_ANALYTICS_ID" + azd env set AZURE_ENV_FOUNDRY_PROJECT_RID="$EXP_AI_PROJECT_ID" else echo "EXP DISABLED - Skipping EXP parameters" fi @@ -336,7 +336,7 @@ jobs: INPUT_WAF_ENABLED: ${{ inputs.WAF_ENABLED }} INPUT_EXP: ${{ inputs.EXP }} INPUT_AZURE_LOCATION: ${{ inputs.AZURE_LOCATION }} - INPUT_AZURE_ENV_OPENAI_LOCATION: ${{ inputs.AZURE_ENV_OPENAI_LOCATION }} + INPUT_AZURE_ENV_AI_SERVICE_LOCATION: ${{ inputs.AZURE_ENV_AI_SERVICE_LOCATION }} INPUT_IMAGE_TAG: ${{ inputs.IMAGE_TAG }} run: | echo "## šŸš€ Deploy Job Summary (Linux)" >> $GITHUB_STEP_SUMMARY @@ -357,7 +357,7 @@ jobs: fi echo "| **Configuration Type** | \`$CONFIG_TYPE\` |" >> $GITHUB_STEP_SUMMARY echo "| **Azure Region (Infrastructure)** | \`$INPUT_AZURE_LOCATION\` |" >> $GITHUB_STEP_SUMMARY - echo "| **Azure OpenAI Region** | \`$INPUT_AZURE_ENV_OPENAI_LOCATION\` |" >> $GITHUB_STEP_SUMMARY + echo "| **Azure OpenAI Region** | \`$INPUT_AZURE_ENV_AI_SERVICE_LOCATION\` |" >> $GITHUB_STEP_SUMMARY echo "| **Docker Image Tag** | \`$INPUT_IMAGE_TAG\` |" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY if [[ "${{ job.status }}" == "success" ]]; then diff --git a/.github/workflows/job-deploy-windows.yml b/.github/workflows/job-deploy-windows.yml index 030c9619f..5c2321f72 100644 --- a/.github/workflows/job-deploy-windows.yml +++ b/.github/workflows/job-deploy-windows.yml @@ -6,7 +6,7 @@ on: ENV_NAME: required: true type: string - AZURE_ENV_OPENAI_LOCATION: + AZURE_ENV_AI_SERVICE_LOCATION: required: true type: string AZURE_LOCATION: @@ -28,10 +28,10 @@ on: required: false type: string default: 'false' - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: + AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: required: false type: string - AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: + AZURE_ENV_FOUNDRY_PROJECT_RID: required: false type: string outputs: @@ -58,15 +58,15 @@ jobs: shell: bash env: INPUT_ENV_NAME: ${{ inputs.ENV_NAME }} - INPUT_AZURE_ENV_OPENAI_LOCATION: ${{ inputs.AZURE_ENV_OPENAI_LOCATION }} + INPUT_AZURE_ENV_AI_SERVICE_LOCATION: ${{ inputs.AZURE_ENV_AI_SERVICE_LOCATION }} INPUT_AZURE_LOCATION: ${{ inputs.AZURE_LOCATION }} INPUT_RESOURCE_GROUP_NAME: ${{ inputs.RESOURCE_GROUP_NAME }} INPUT_IMAGE_TAG: ${{ inputs.IMAGE_TAG }} INPUT_BUILD_DOCKER_IMAGE: ${{ inputs.BUILD_DOCKER_IMAGE }} INPUT_EXP: ${{ inputs.EXP }} INPUT_WAF_ENABLED: ${{ inputs.WAF_ENABLED }} - INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }} - INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }} + INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} + INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} run: | echo "šŸ” Validating workflow input parameters..." VALIDATION_FAILED=false @@ -82,15 +82,15 @@ jobs: echo "āœ… ENV_NAME: '$INPUT_ENV_NAME' is valid" fi - # Validate AZURE_ENV_OPENAI_LOCATION (required, Azure region format) - if [[ -z "$INPUT_AZURE_ENV_OPENAI_LOCATION" ]]; then - echo "āŒ ERROR: AZURE_ENV_OPENAI_LOCATION is required but not provided" + # Validate AZURE_ENV_AI_SERVICE_LOCATION (required, Azure region format) + if [[ -z "$INPUT_AZURE_ENV_AI_SERVICE_LOCATION" ]]; then + echo "āŒ ERROR: AZURE_ENV_AI_SERVICE_LOCATION is required but not provided" VALIDATION_FAILED=true - elif [[ ! "$INPUT_AZURE_ENV_OPENAI_LOCATION" =~ ^[a-z0-9]+$ ]]; then - echo "āŒ ERROR: AZURE_ENV_OPENAI_LOCATION '$INPUT_AZURE_ENV_OPENAI_LOCATION' is invalid. Must contain only lowercase letters and numbers" + elif [[ ! "$INPUT_AZURE_ENV_AI_SERVICE_LOCATION" =~ ^[a-z0-9]+$ ]]; then + echo "āŒ ERROR: AZURE_ENV_AI_SERVICE_LOCATION '$INPUT_AZURE_ENV_AI_SERVICE_LOCATION' is invalid. Must contain only lowercase letters and numbers" VALIDATION_FAILED=true else - echo "āœ… AZURE_ENV_OPENAI_LOCATION: '$INPUT_AZURE_ENV_OPENAI_LOCATION' is valid" + echo "āœ… AZURE_ENV_AI_SERVICE_LOCATION: '$INPUT_AZURE_ENV_AI_SERVICE_LOCATION' is valid" fi # Validate AZURE_LOCATION (required, Azure region format) @@ -153,27 +153,27 @@ jobs: echo "āœ… WAF_ENABLED: '$INPUT_WAF_ENABLED' is valid" fi - # Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID (optional, if provided must be valid Resource ID) - if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" ]]; then - if [[ ! "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then - echo "āŒ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID is invalid. Must be a valid Azure Resource ID format:" - echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}" - echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID'" + # Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID (optional, if provided must be valid Resource ID) + if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" ]]; then + if [[ ! "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then + echo "āŒ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID is invalid. Must be a valid Azure Resource ID format:" + echo " Expected: /subscriptions/{guid}/resourceGroups/{rg}/providers/Microsoft.OperationalInsights/workspaces/{name}" + echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: Valid Resource ID format" + echo "āœ… AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: Valid Resource ID format" fi fi - # Validate AZURE_EXISTING_AI_PROJECT_RESOURCE_ID (optional, if provided must be valid Resource ID) - if [[ -n "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" ]]; then - if [[ ! "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then - echo "āŒ ERROR: AZURE_EXISTING_AI_PROJECT_RESOURCE_ID is invalid. Must be a valid Azure Resource ID format:" - echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/projects/{projectName}" - echo " Got: '$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID'" + # Validate AZURE_ENV_FOUNDRY_PROJECT_RID (optional, if provided must be valid Resource ID) + if [[ -n "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" ]]; then + if [[ ! "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then + echo "āŒ ERROR: AZURE_ENV_FOUNDRY_PROJECT_RID is invalid. Must be a valid Azure Resource ID format:" + echo " Expected: /subscriptions/{guid}/resourceGroups/{rg}/providers/Microsoft.CognitiveServices/accounts/{account}/projects/{project}" + echo " Got: '$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: Valid Resource ID format" + echo "āœ… AZURE_ENV_FOUNDRY_PROJECT_RID: Valid Resource ID format" fi fi @@ -222,14 +222,14 @@ jobs: shell: pwsh env: INPUT_ENV_NAME: ${{ inputs.ENV_NAME }} - INPUT_AZURE_ENV_OPENAI_LOCATION: ${{ inputs.AZURE_ENV_OPENAI_LOCATION }} + INPUT_AZURE_ENV_AI_SERVICE_LOCATION: ${{ inputs.AZURE_ENV_AI_SERVICE_LOCATION }} INPUT_AZURE_LOCATION: ${{ inputs.AZURE_LOCATION }} INPUT_RESOURCE_GROUP_NAME: ${{ inputs.RESOURCE_GROUP_NAME }} INPUT_IMAGE_TAG: ${{ inputs.IMAGE_TAG }} INPUT_BUILD_DOCKER_IMAGE: ${{ inputs.BUILD_DOCKER_IMAGE }} INPUT_EXP: ${{ inputs.EXP }} - INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }} - INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }} + INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} + INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} run: | $ErrorActionPreference = "Stop" Write-Host "Starting azd deployment..." @@ -243,7 +243,7 @@ jobs: # Set additional parameters azd env set AZURE_SUBSCRIPTION_ID="${{ secrets.AZURE_SUBSCRIPTION_ID }}" - azd env set AZURE_ENV_OPENAI_LOCATION="$env:INPUT_AZURE_ENV_OPENAI_LOCATION" + azd env set AZURE_ENV_AI_SERVICE_LOCATION="$env:INPUT_AZURE_ENV_AI_SERVICE_LOCATION" azd env set AZURE_LOCATION="$env:INPUT_AZURE_LOCATION" azd env set AZURE_RESOURCE_GROUP="$env:INPUT_RESOURCE_GROUP_NAME" azd env set AZURE_ENV_IMAGE_TAG="$env:INPUT_IMAGE_TAG" @@ -261,22 +261,22 @@ jobs: Write-Host "āœ… EXP ENABLED - Setting EXP parameters..." # Set EXP variables dynamically - if ($env:INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID -ne "") { - $EXP_LOG_ANALYTICS_ID = $env:INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID + if ($env:INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID -ne "") { + $EXP_LOG_ANALYTICS_ID = $env:INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID } else { - $EXP_LOG_ANALYTICS_ID = "${{ secrets.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}" + $EXP_LOG_ANALYTICS_ID = "${{ secrets.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }}" } - if ($env:INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID -ne "") { - $EXP_AI_PROJECT_ID = $env:INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID + if ($env:INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID -ne "") { + $EXP_AI_PROJECT_ID = $env:INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID } else { $EXP_AI_PROJECT_ID = "${{ secrets.AZURE_ENV_FOUNDRY_PROJECT_ID }}" } - Write-Host "AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: $EXP_LOG_ANALYTICS_ID" - Write-Host "AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: $EXP_AI_PROJECT_ID" - azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID="$EXP_LOG_ANALYTICS_ID" - azd env set AZURE_EXISTING_AI_PROJECT_RESOURCE_ID="$EXP_AI_PROJECT_ID" + Write-Host "AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: $EXP_LOG_ANALYTICS_ID" + Write-Host "AZURE_ENV_FOUNDRY_PROJECT_RID: $EXP_AI_PROJECT_ID" + azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID="$EXP_LOG_ANALYTICS_ID" + azd env set AZURE_ENV_FOUNDRY_PROJECT_RID="$EXP_AI_PROJECT_ID" } else { Write-Host "EXP DISABLED - Skipping EXP parameters" } @@ -341,7 +341,7 @@ jobs: INPUT_WAF_ENABLED: ${{ inputs.WAF_ENABLED }} INPUT_EXP: ${{ inputs.EXP }} INPUT_AZURE_LOCATION: ${{ inputs.AZURE_LOCATION }} - INPUT_AZURE_ENV_OPENAI_LOCATION: ${{ inputs.AZURE_ENV_OPENAI_LOCATION }} + INPUT_AZURE_ENV_AI_SERVICE_LOCATION: ${{ inputs.AZURE_ENV_AI_SERVICE_LOCATION }} INPUT_IMAGE_TAG: ${{ inputs.IMAGE_TAG }} run: | echo "## šŸš€ Deploy Job Summary (Windows)" >> $GITHUB_STEP_SUMMARY @@ -360,7 +360,7 @@ jobs: fi echo "| **Configuration Type** | \`$CONFIG_TYPE\` |" >> $GITHUB_STEP_SUMMARY echo "| **Azure Region (Infrastructure)** | \`$INPUT_AZURE_LOCATION\` |" >> $GITHUB_STEP_SUMMARY - echo "| **Azure OpenAI Region** | \`$INPUT_AZURE_ENV_OPENAI_LOCATION\` |" >> $GITHUB_STEP_SUMMARY + echo "| **Azure OpenAI Region** | \`$INPUT_AZURE_ENV_AI_SERVICE_LOCATION\` |" >> $GITHUB_STEP_SUMMARY echo "| **Docker Image Tag** | \`$INPUT_IMAGE_TAG\` |" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY if [[ "${{ job.status }}" == "success" ]]; then diff --git a/.github/workflows/job-deploy.yml b/.github/workflows/job-deploy.yml index 7a8f32e31..db531a5c1 100644 --- a/.github/workflows/job-deploy.yml +++ b/.github/workflows/job-deploy.yml @@ -51,12 +51,12 @@ on: required: false default: '' type: string - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: + AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: description: 'Log Analytics Workspace ID (Optional)' required: false default: '' type: string - AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: + AZURE_ENV_FOUNDRY_PROJECT_RID: description: 'AI Project Resource ID (Optional)' required: false default: '' @@ -82,9 +82,9 @@ on: AZURE_LOCATION: description: "Azure Location" value: ${{ jobs.azure-setup.outputs.AZURE_LOCATION }} - AZURE_ENV_OPENAI_LOCATION: + AZURE_ENV_AI_SERVICE_LOCATION: description: "Azure OpenAI Location" - value: ${{ jobs.azure-setup.outputs.AZURE_ENV_OPENAI_LOCATION }} + value: ${{ jobs.azure-setup.outputs.AZURE_ENV_AI_SERVICE_LOCATION }} IMAGE_TAG: description: "Docker Image Tag Used" value: ${{ jobs.azure-setup.outputs.IMAGE_TAG }} @@ -113,7 +113,7 @@ jobs: RESOURCE_GROUP_NAME: ${{ steps.check_create_rg.outputs.RESOURCE_GROUP_NAME }} ENV_NAME: ${{ steps.generate_env_name.outputs.ENV_NAME }} AZURE_LOCATION: ${{ steps.set_region.outputs.AZURE_LOCATION }} - AZURE_ENV_OPENAI_LOCATION: ${{ steps.set_region.outputs.AZURE_ENV_OPENAI_LOCATION }} + AZURE_ENV_AI_SERVICE_LOCATION: ${{ steps.set_region.outputs.AZURE_ENV_AI_SERVICE_LOCATION }} IMAGE_TAG: ${{ steps.determine_image_tag.outputs.IMAGE_TAG }} QUOTA_FAILED: ${{ steps.quota_failure_output.outputs.QUOTA_FAILED }} EXP_ENABLED: ${{ steps.configure_exp.outputs.EXP_ENABLED }} @@ -128,8 +128,8 @@ jobs: INPUT_EXP: ${{ inputs.EXP }} INPUT_CLEANUP_RESOURCES: ${{ inputs.cleanup_resources }} INPUT_RUN_E2E_TESTS: ${{ inputs.run_e2e_tests }} - INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }} - INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }} + INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} + INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} INPUT_EXISTING_WEBAPP_URL: ${{ inputs.existing_webapp_url }} INPUT_DOCKER_IMAGE_TAG: ${{ inputs.docker_image_tag }} run: | @@ -194,27 +194,27 @@ jobs: fi fi - # Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID (Azure Resource ID format) - if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" ]]; then - if [[ ! "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then - echo "āŒ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID is invalid. Must be a valid Azure Resource ID format:" + # Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID (Azure Resource ID format) + if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" ]]; then + if [[ ! "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then + echo "āŒ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID is invalid. Must be a valid Azure Resource ID format:" echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}" - echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID'" + echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: Valid Resource ID format" + echo "āœ… AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: Valid Resource ID format" fi fi - # Validate AZURE_EXISTING_AI_PROJECT_RESOURCE_ID (Azure Resource ID format) - if [[ -n "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" ]]; then - if [[ ! "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then - echo "āŒ ERROR: AZURE_EXISTING_AI_PROJECT_RESOURCE_ID is invalid. Must be a valid Azure Resource ID format:" + # Validate AZURE_ENV_FOUNDRY_PROJECT_RID (Azure Resource ID format) + if [[ -n "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" ]]; then + if [[ ! "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then + echo "āŒ ERROR: AZURE_ENV_FOUNDRY_PROJECT_RID is invalid. Must be a valid Azure Resource ID format:" echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/projects/{projectName}" - echo " Got: '$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID'" + echo " Got: '$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: Valid Resource ID format" + echo "āœ… AZURE_ENV_FOUNDRY_PROJECT_RID: Valid Resource ID format" fi fi @@ -258,8 +258,8 @@ jobs: shell: bash env: INPUT_EXP: ${{ inputs.EXP }} - INPUT_LOG_ANALYTICS_WORKSPACE_ID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }} - INPUT_AI_PROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }} + INPUT_LOG_ANALYTICS_WORKSPACE_ID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} + INPUT_AI_PROJECT_RESOURCE_ID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} run: | echo "šŸ” Validating EXP configuration..." @@ -336,8 +336,8 @@ jobs: INPUT_AZURE_LOCATION: ${{ inputs.azure_location }} run: | echo "Selected Region from Quota Check: $VALID_REGION" - echo "AZURE_ENV_OPENAI_LOCATION=$VALID_REGION" >> $GITHUB_ENV - echo "AZURE_ENV_OPENAI_LOCATION=$VALID_REGION" >> $GITHUB_OUTPUT + echo "AZURE_ENV_AI_SERVICE_LOCATION=$VALID_REGION" >> $GITHUB_ENV + echo "AZURE_ENV_AI_SERVICE_LOCATION=$VALID_REGION" >> $GITHUB_OUTPUT if [[ "$INPUT_TRIGGER_TYPE" == "workflow_dispatch" && -n "$INPUT_AZURE_LOCATION" ]]; then USER_SELECTED_LOCATION="$INPUT_AZURE_LOCATION" @@ -495,15 +495,15 @@ jobs: uses: ./.github/workflows/job-deploy-linux.yml with: ENV_NAME: ${{ needs.azure-setup.outputs.ENV_NAME }} - AZURE_ENV_OPENAI_LOCATION: ${{ needs.azure-setup.outputs.AZURE_ENV_OPENAI_LOCATION }} + AZURE_ENV_AI_SERVICE_LOCATION: ${{ needs.azure-setup.outputs.AZURE_ENV_AI_SERVICE_LOCATION }} AZURE_LOCATION: ${{ needs.azure-setup.outputs.AZURE_LOCATION }} RESOURCE_GROUP_NAME: ${{ needs.azure-setup.outputs.RESOURCE_GROUP_NAME }} IMAGE_TAG: ${{ needs.azure-setup.outputs.IMAGE_TAG }} BUILD_DOCKER_IMAGE: ${{ inputs.build_docker_image || 'false' }} EXP: ${{ needs.azure-setup.outputs.EXP_ENABLED }} WAF_ENABLED: ${{ inputs.waf_enabled == true && 'true' || 'false' }} - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }} - AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }} + AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} + AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} secrets: inherit deploy-windows: @@ -513,13 +513,13 @@ jobs: uses: ./.github/workflows/job-deploy-windows.yml with: ENV_NAME: ${{ needs.azure-setup.outputs.ENV_NAME }} - AZURE_ENV_OPENAI_LOCATION: ${{ needs.azure-setup.outputs.AZURE_ENV_OPENAI_LOCATION }} + AZURE_ENV_AI_SERVICE_LOCATION: ${{ needs.azure-setup.outputs.AZURE_ENV_AI_SERVICE_LOCATION }} AZURE_LOCATION: ${{ needs.azure-setup.outputs.AZURE_LOCATION }} RESOURCE_GROUP_NAME: ${{ needs.azure-setup.outputs.RESOURCE_GROUP_NAME }} IMAGE_TAG: ${{ needs.azure-setup.outputs.IMAGE_TAG }} BUILD_DOCKER_IMAGE: ${{ inputs.build_docker_image || 'false' }} EXP: ${{ needs.azure-setup.outputs.EXP_ENABLED }} WAF_ENABLED: ${{ inputs.waf_enabled == true && 'true' || 'false' }} - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }} - AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }} + AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} + AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} secrets: inherit diff --git a/docs/CustomizingAzdParameters.md b/docs/CustomizingAzdParameters.md index c88dedad3..1b5e895e9 100644 --- a/docs/CustomizingAzdParameters.md +++ b/docs/CustomizingAzdParameters.md @@ -10,11 +10,11 @@ By default this template will use the environment name as the prefix to prevent | ------------------------------- | ------ | ----------------- | --------------------------------------------------------------------------------------------------- | | `AZURE_ENV_NAME` | string | `macae` | Used as a prefix for all resource names to ensure uniqueness across environments. | | `AZURE_LOCATION` | string | `` | Location of the Azure resources. Controls where the infrastructure will be deployed. | -| `AZURE_ENV_OPENAI_LOCATION` | string | `` | Specifies the region for OpenAI resource deployment. | +| `AZURE_ENV_AI_SERVICE_LOCATION` | string | `` | Specifies the region for OpenAI resource deployment. | | `AZURE_ENV_MODEL_DEPLOYMENT_TYPE` | string | `GlobalStandard` | Defines the deployment type for the AI model (e.g., Standard, GlobalStandard). | -| `AZURE_ENV_MODEL_NAME` | string | `gpt-4.1-mini` | Specifies the name of the GPT model to be deployed. | -| `AZURE_ENV_MODEL_VERSION` | string | `2025-04-14` | Version of the GPT model to be used for deployment. | -| `AZURE_ENV_MODEL_CAPACITY` | int | `50` | Sets the GPT model capacity. | +| `AZURE_ENV_GPT_MODEL_NAME` | string | `gpt-4.1-mini` | Specifies the name of the GPT model to be deployed. | +| `AZURE_ENV_GPT_MODEL_VERSION` | string | `2025-04-14` | Version of the GPT model to be used for deployment. | +| `AZURE_ENV_GPT_MODEL_CAPACITY` | int | `50` | Sets the GPT model capacity. | | `AZURE_ENV_MODEL_4_1_DEPLOYMENT_TYPE` | string | `GlobalStandard` | Defines the deployment type for the AI model (e.g., Standard, GlobalStandard). | | `AZURE_ENV_MODEL_4_1_NAME` | string | `gpt-4.1` | Specifies the name of the GPT model to be deployed. | | `AZURE_ENV_MODEL_4_1_VERSION` | string | `2025-04-14` | Version of the GPT model to be used for deployment. | @@ -25,8 +25,8 @@ By default this template will use the environment name as the prefix to prevent | `AZURE_ENV_REASONING_MODEL_CAPACITY` | int | `50` | Sets the reasoning GPT model capacity. | | `AZURE_ENV_IMAGETAG` | string | `latest_v3` | Docker image tag used for container deployments. | | `AZURE_ENV_ENABLE_TELEMETRY` | bool | `true` | Enables telemetry for monitoring and diagnostics. | -| `AZURE_EXISTING_AI_PROJECT_RESOURCE_ID` | string | `` | Set this if you want to reuse an AI Foundry Project instead of creating a new one. | -| `AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID` | string | Guide to get your [Existing Workspace ID](/docs/re-use-log-analytics.md) | Set this if you want to reuse an existing Log Analytics Workspace instead of creating a new one. | +| `AZURE_ENV_FOUNDRY_PROJECT_RID` | string | `` | Set this if you want to reuse an AI Foundry Project instead of creating a new one. | +| `AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID` | string | Guide to get your [Existing Workspace ID](/docs/re-use-log-analytics.md) | Set this if you want to reuse an existing Log Analytics Workspace instead of creating a new one. | | `AZURE_ENV_VM_ADMIN_USERNAME` | string | `take(newGuid(), 20)` | The administrator username for the virtual machine. | | `AZURE_ENV_VM_ADMIN_PASSWORD` | string | `newGuid()` | The administrator password for the virtual machine. | | `AZURE_ENV_VM_SIZE` | string | `Standard_D2s_v5` | The size of the virtual machine deployed with private networking. | @@ -43,7 +43,7 @@ azd env set Set the Log Analytics Workspace Id if you need to reuse the existing workspace which is already existing ```shell -azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID '/subscriptions//resourceGroups//providers/Microsoft.OperationalInsights/workspaces/' +azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID '/subscriptions//resourceGroups//providers/Microsoft.OperationalInsights/workspaces/' ``` **Example:** diff --git a/docs/re-use-foundry-project.md b/docs/re-use-foundry-project.md index e6e4075c4..ed955f1ac 100644 --- a/docs/re-use-foundry-project.md +++ b/docs/re-use-foundry-project.md @@ -36,7 +36,7 @@ In the left-hand menu of the project blade: ### 6. Set the Foundry Project Resource ID in Your Environment Run the following command in your terminal ```bash -azd env set AZURE_EXISTING_AI_PROJECT_RESOURCE_ID '' +azd env set AZURE_ENV_FOUNDRY_PROJECT_RID '' ``` Replace `` with the value obtained from Step 5. diff --git a/docs/re-use-log-analytics.md b/docs/re-use-log-analytics.md index 1fa7a35df..7ee170faf 100644 --- a/docs/re-use-log-analytics.md +++ b/docs/re-use-log-analytics.md @@ -23,7 +23,7 @@ Copy Resource ID that is your Workspace ID ### 4. Set the Workspace ID in Your Environment Run the following command in your terminal ```bash -azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID '' +azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID '' ``` Replace `` with the value obtained from Step 3. diff --git a/infra/main.parameters.json b/infra/main.parameters.json index ed6ba532a..be6fcaa14 100644 --- a/infra/main.parameters.json +++ b/infra/main.parameters.json @@ -9,19 +9,19 @@ "value": "${AZURE_LOCATION}" }, "azureAiServiceLocation": { - "value": "${AZURE_ENV_OPENAI_LOCATION}" + "value": "${AZURE_ENV_AI_SERVICE_LOCATION}" }, "gptModelDeploymentType": { "value": "${AZURE_ENV_MODEL_DEPLOYMENT_TYPE}" }, "gptModelName": { - "value": "${AZURE_ENV_MODEL_NAME}" + "value": "${AZURE_ENV_GPT_MODEL_NAME}" }, "gptModelVersion": { - "value": "${AZURE_ENV_MODEL_VERSION}" + "value": "${AZURE_ENV_GPT_MODEL_VERSION}" }, "gptModelCapacity": { - "value": "${AZURE_ENV_MODEL_CAPACITY}" + "value": "${AZURE_ENV_GPT_MODEL_CAPACITY}" }, "gpt4_1ModelDeploymentType": { "value": "${AZURE_ENV_MODEL_4_1_DEPLOYMENT_TYPE}" @@ -60,10 +60,10 @@ "value": "${AZURE_ENV_ENABLE_TELEMETRY}" }, "existingLogAnalyticsWorkspaceId": { - "value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID}" + "value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID}" }, "existingAiFoundryAiProjectResourceId": { - "value": "${AZURE_EXISTING_AI_PROJECT_RESOURCE_ID}" + "value": "${AZURE_ENV_FOUNDRY_PROJECT_RID}" }, "backendContainerRegistryHostname": { "value": "${AZURE_ENV_CONTAINER_REGISTRY_ENDPOINT}" diff --git a/infra/main.waf.parameters.json b/infra/main.waf.parameters.json index dcdfd1e23..23e123d6a 100644 --- a/infra/main.waf.parameters.json +++ b/infra/main.waf.parameters.json @@ -9,19 +9,19 @@ "value": "${AZURE_LOCATION}" }, "azureAiServiceLocation": { - "value": "${AZURE_ENV_OPENAI_LOCATION}" + "value": "${AZURE_ENV_AI_SERVICE_LOCATION}" }, "gptModelDeploymentType": { "value": "${AZURE_ENV_MODEL_DEPLOYMENT_TYPE}" }, "gptModelName": { - "value": "${AZURE_ENV_MODEL_NAME}" + "value": "${AZURE_ENV_GPT_MODEL_NAME}" }, "gptModelVersion": { - "value": "${AZURE_ENV_MODEL_VERSION}" + "value": "${AZURE_ENV_GPT_MODEL_VERSION}" }, "gptModelCapacity": { - "value": "${AZURE_ENV_MODEL_CAPACITY}" + "value": "${AZURE_ENV_GPT_MODEL_CAPACITY}" }, "gpt4_1ModelDeploymentType": { "value": "${AZURE_ENV_MODEL_4_1_DEPLOYMENT_TYPE}" @@ -78,10 +78,10 @@ "value": "${AZURE_ENV_VM_SIZE}" }, "existingLogAnalyticsWorkspaceId": { - "value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID}" + "value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID}" }, "existingAiFoundryAiProjectResourceId": { - "value": "${AZURE_EXISTING_AI_PROJECT_RESOURCE_ID}" + "value": "${AZURE_ENV_FOUNDRY_PROJECT_RID}" }, "backendContainerRegistryHostname": { "value": "${AZURE_ENV_CONTAINER_REGISTRY_ENDPOINT}" diff --git a/infra/scripts/validate_model_quota.ps1 b/infra/scripts/validate_model_quota.ps1 index 7afe3773b..495a21456 100644 --- a/infra/scripts/validate_model_quota.ps1 +++ b/infra/scripts/validate_model_quota.ps1 @@ -97,9 +97,9 @@ if ($FallbackRegions.Count -gt 0) { } Write-Host "`nšŸ”§ To proceed, run:" - Write-Host " azd env set AZURE_ENV_OPENAI_LOCATION ''" + Write-Host " azd env set AZURE_ENV_AI_SERVICE_LOCATION ''" Write-Host "šŸ“Œ To confirm it's set correctly, run:" - Write-Host " azd env get-value AZURE_ENV_OPENAI_LOCATION" + Write-Host " azd env get-value AZURE_ENV_AI_SERVICE_LOCATION" Write-Host "ā–¶ļø Once confirmed, re-run azd up to deploy the model in the new region." exit 2 } diff --git a/infra/scripts/validate_model_quota.sh b/infra/scripts/validate_model_quota.sh index 5cf71f96a..51cc300eb 100644 --- a/infra/scripts/validate_model_quota.sh +++ b/infra/scripts/validate_model_quota.sh @@ -89,9 +89,9 @@ if [[ "${#FALLBACK_REGIONS[@]}" -gt 0 ]]; then echo " • $fallback" done echo -e "\nšŸ”§ To proceed, run:" - echo " azd env set AZURE_ENV_OPENAI_LOCATION ''" + echo " azd env set AZURE_ENV_AI_SERVICE_LOCATION ''" echo "šŸ“Œ To confirm it's set correctly, run:" - echo " azd env get-value AZURE_ENV_OPENAI_LOCATION" + echo " azd env get-value AZURE_ENV_AI_SERVICE_LOCATION" echo "ā–¶ļø Once confirmed, re-run azd up to deploy the model in the new region." exit 2 fi From e2ea72e27060c60f37eec97a02c841ae44a9184c Mon Sep 17 00:00:00 2001 From: Prachig-Microsoft Date: Mon, 23 Mar 2026 17:44:44 +0530 Subject: [PATCH 2/7] Update .github/workflows/job-deploy-linux.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/job-deploy-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/job-deploy-linux.yml b/.github/workflows/job-deploy-linux.yml index 21ddbb627..76aabd593 100644 --- a/.github/workflows/job-deploy-linux.yml +++ b/.github/workflows/job-deploy-linux.yml @@ -271,7 +271,7 @@ jobs: fi echo "AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: $EXP_LOG_ANALYTICS_ID" - echo "AZURE_ENV_FOUNDRY_PROJECT_ID: $EXP_AI_PROJECT_ID" + echo "AZURE_ENV_FOUNDRY_PROJECT_RID: $EXP_AI_PROJECT_ID" azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID="$EXP_LOG_ANALYTICS_ID" azd env set AZURE_ENV_FOUNDRY_PROJECT_RID="$EXP_AI_PROJECT_ID" else From 0511ef0cdc6c769e9268c97b0159d51cfc741e40 Mon Sep 17 00:00:00 2001 From: Prachig-Microsoft Date: Mon, 23 Mar 2026 17:45:01 +0530 Subject: [PATCH 3/7] Update .github/workflows/job-deploy-windows.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/job-deploy-windows.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/job-deploy-windows.yml b/.github/workflows/job-deploy-windows.yml index 5c2321f72..032ed9184 100644 --- a/.github/workflows/job-deploy-windows.yml +++ b/.github/workflows/job-deploy-windows.yml @@ -270,7 +270,10 @@ jobs: if ($env:INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID -ne "") { $EXP_AI_PROJECT_ID = $env:INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID } else { - $EXP_AI_PROJECT_ID = "${{ secrets.AZURE_ENV_FOUNDRY_PROJECT_ID }}" + $EXP_AI_PROJECT_ID = "${{ secrets.AZURE_ENV_FOUNDRY_PROJECT_RID }}" + if (-not $EXP_AI_PROJECT_ID) { + $EXP_AI_PROJECT_ID = "${{ secrets.AZURE_ENV_FOUNDRY_PROJECT_ID }}" + } } Write-Host "AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: $EXP_LOG_ANALYTICS_ID" From e5b8c39b7c0123e9849478446c4787c1b8124b83 Mon Sep 17 00:00:00 2001 From: Vamshi-Microsoft Date: Thu, 26 Mar 2026 14:19:47 +0530 Subject: [PATCH 4/7] Update resource group creation command to include tags and fix exp paramter in workflow --- .github/workflows/job-deploy-linux.yml | 2 +- .github/workflows/job-deploy.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/job-deploy-linux.yml b/.github/workflows/job-deploy-linux.yml index 76aabd593..e38dd226e 100644 --- a/.github/workflows/job-deploy-linux.yml +++ b/.github/workflows/job-deploy-linux.yml @@ -267,7 +267,7 @@ jobs: if [[ -n "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" ]]; then EXP_AI_PROJECT_ID="$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" else - EXP_AI_PROJECT_ID="${{ secrets.AZURE_ENV_FOUNDRY_PROJECT_ID }}" + EXP_AI_PROJECT_ID="${{ secrets.AZURE_ENV_FOUNDRY_PROJECT_RID }}" fi echo "AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: $EXP_LOG_ANALYTICS_ID" diff --git a/.github/workflows/job-deploy.yml b/.github/workflows/job-deploy.yml index db531a5c1..3510603da 100644 --- a/.github/workflows/job-deploy.yml +++ b/.github/workflows/job-deploy.yml @@ -382,7 +382,7 @@ jobs: rg_exists=$(az group exists --name $RESOURCE_GROUP_NAME) if [ "$rg_exists" = "false" ]; then echo "šŸ“¦ Resource group does not exist. Creating new resource group '$RESOURCE_GROUP_NAME' in location '$AZURE_LOCATION'..." - az group create --name $RESOURCE_GROUP_NAME --location $AZURE_LOCATION || { echo "āŒ Error creating resource group"; exit 1; } + az group create --name $RESOURCE_GROUP_NAME --location $AZURE_LOCATION --tags ${{ env.RG_TAGS }} || { echo "āŒ Error creating resource group"; exit 1; } echo "āœ… Resource group '$RESOURCE_GROUP_NAME' created successfully." else echo "āœ… Resource group '$RESOURCE_GROUP_NAME' already exists. Deploying to existing resource group." From a0095aaaaaf493524e87b69ddc4a7dcc49936aae Mon Sep 17 00:00:00 2001 From: Vamshi-Microsoft Date: Thu, 26 Mar 2026 15:28:09 +0530 Subject: [PATCH 5/7] Add RG_TAGS environment variable to deployment workflow --- .github/workflows/job-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/job-deploy.yml b/.github/workflows/job-deploy.yml index 3510603da..a3f0ef165 100644 --- a/.github/workflows/job-deploy.yml +++ b/.github/workflows/job-deploy.yml @@ -102,7 +102,7 @@ env: CLEANUP_RESOURCES: ${{ inputs.trigger_type != 'workflow_dispatch' || inputs.cleanup_resources }} RUN_E2E_TESTS: ${{ inputs.trigger_type == 'workflow_dispatch' && (inputs.run_e2e_tests || 'GoldenPath-Testing') || 'GoldenPath-Testing' }} BUILD_DOCKER_IMAGE: ${{ inputs.trigger_type == 'workflow_dispatch' && (inputs.build_docker_image || false) || false }} - + RG_TAGS: ${{ vars.RG_TAGS }} jobs: azure-setup: name: Azure Setup From c5a014aa4aff0ec27db25c441ab83fea8eb5d8c5 Mon Sep 17 00:00:00 2001 From: Prachig-Microsoft Date: Tue, 7 Apr 2026 16:53:59 +0530 Subject: [PATCH 6/7] fix: correct secret name references in workflow files - azure-dev.yml: Fix AZURE_AI_DEPLOYMENT_LOCATION -> AZURE_ENV_AI_SERVICE_LOCATION to match standardized naming - job-deploy-windows.yml: Fix AZURE_ENV_FOUNDRY_PROJECT_ID -> AZURE_ENV_FOUNDRY_PROJECT_RID typo in fallback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/azure-dev.yml | 2 +- .github/workflows/job-deploy-windows.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/azure-dev.yml b/.github/workflows/azure-dev.yml index e09a24a1d..cea698614 100644 --- a/.github/workflows/azure-dev.yml +++ b/.github/workflows/azure-dev.yml @@ -29,7 +29,7 @@ jobs: AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} AZURE_ENV_NAME: ${{ secrets.AZURE_ENV_NAME }} AZURE_LOCATION: ${{ secrets.AZURE_LOCATION }} - AZURE_ENV_AI_SERVICE_LOCATION : ${{ secrets.AZURE_AI_DEPLOYMENT_LOCATION }} + AZURE_ENV_AI_SERVICE_LOCATION: ${{ secrets.AZURE_ENV_AI_SERVICE_LOCATION }} AZURE_ENV_GPT_MODEL_CAPACITY: 1 AZURE_ENV_MODEL_4_1_CAPACITY: 1 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/job-deploy-windows.yml b/.github/workflows/job-deploy-windows.yml index 032ed9184..e296bf63a 100644 --- a/.github/workflows/job-deploy-windows.yml +++ b/.github/workflows/job-deploy-windows.yml @@ -272,7 +272,7 @@ jobs: } else { $EXP_AI_PROJECT_ID = "${{ secrets.AZURE_ENV_FOUNDRY_PROJECT_RID }}" if (-not $EXP_AI_PROJECT_ID) { - $EXP_AI_PROJECT_ID = "${{ secrets.AZURE_ENV_FOUNDRY_PROJECT_ID }}" + $EXP_AI_PROJECT_ID = "${{ secrets.AZURE_ENV_FOUNDRY_PROJECT_RID }}" } } From 1edb4739c995f6836bea87647705f169912e481e Mon Sep 17 00:00:00 2001 From: Prachig-Microsoft Date: Thu, 9 Apr 2026 13:28:12 +0530 Subject: [PATCH 7/7] Standardize environment variable names - Updated parameter naming convention --- .github/workflows/deploy-orchestrator.yml | 8 +- .github/workflows/deploy-v2.yml | 48 +- .github/workflows/job-deploy-linux.yml | 56 +- .github/workflows/job-deploy-windows.yml | 58 +- .github/workflows/job-deploy.yml | 50 +- docs/CustomizingAzdParameters.md | 6 +- docs/re-use-foundry-project.md | 2 +- docs/re-use-log-analytics.md | 2 +- infra/main.parameters.json | 4 +- infra/main.waf.parameters.json | 4 +- infra/old/00-older/deploy_ai_foundry.bicep | 313 --- infra/old/00-older/deploy_keyvault.bicep | 62 - .../00-older/deploy_managed_identity.bicep | 45 - infra/old/00-older/macae-continer-oc.json | 458 ----- infra/old/00-older/macae-continer.json | 458 ----- infra/old/00-older/macae-dev.bicep | 131 -- infra/old/00-older/macae-large.bicepparam | 11 - infra/old/00-older/macae-mini.bicepparam | 11 - infra/old/00-older/macae.bicep | 362 ---- infra/old/00-older/main.bicep | 1298 ------------- infra/old/00-older/main2.bicep | 54 - infra/old/00-older/resources.bicep | 242 --- infra/old/08-2025/abbreviations.json | 227 --- infra/old/08-2025/bicepconfig.json | 9 - infra/old/08-2025/main.bicep | 1726 ----------------- infra/old/08-2025/main.parameters.json | 102 - infra/old/08-2025/modules/account/main.bicep | 421 ---- .../account/modules/dependencies.bicep | 479 ----- .../account/modules/keyVaultExport.bicep | 43 - .../modules/account/modules/project.bicep | 61 - infra/old/08-2025/modules/ai-hub.bicep | 62 - .../modules/container-app-environment.bicep | 93 - .../modules/fetch-container-image.bicep | 8 - infra/old/08-2025/modules/role.bicep | 58 - 34 files changed, 119 insertions(+), 6853 deletions(-) delete mode 100644 infra/old/00-older/deploy_ai_foundry.bicep delete mode 100644 infra/old/00-older/deploy_keyvault.bicep delete mode 100644 infra/old/00-older/deploy_managed_identity.bicep delete mode 100644 infra/old/00-older/macae-continer-oc.json delete mode 100644 infra/old/00-older/macae-continer.json delete mode 100644 infra/old/00-older/macae-dev.bicep delete mode 100644 infra/old/00-older/macae-large.bicepparam delete mode 100644 infra/old/00-older/macae-mini.bicepparam delete mode 100644 infra/old/00-older/macae.bicep delete mode 100644 infra/old/00-older/main.bicep delete mode 100644 infra/old/00-older/main2.bicep delete mode 100644 infra/old/00-older/resources.bicep delete mode 100644 infra/old/08-2025/abbreviations.json delete mode 100644 infra/old/08-2025/bicepconfig.json delete mode 100644 infra/old/08-2025/main.bicep delete mode 100644 infra/old/08-2025/main.parameters.json delete mode 100644 infra/old/08-2025/modules/account/main.bicep delete mode 100644 infra/old/08-2025/modules/account/modules/dependencies.bicep delete mode 100644 infra/old/08-2025/modules/account/modules/keyVaultExport.bicep delete mode 100644 infra/old/08-2025/modules/account/modules/project.bicep delete mode 100644 infra/old/08-2025/modules/ai-hub.bicep delete mode 100644 infra/old/08-2025/modules/container-app-environment.bicep delete mode 100644 infra/old/08-2025/modules/fetch-container-image.bicep delete mode 100644 infra/old/08-2025/modules/role.bicep diff --git a/.github/workflows/deploy-orchestrator.yml b/.github/workflows/deploy-orchestrator.yml index cedee1934..1affc1bbd 100644 --- a/.github/workflows/deploy-orchestrator.yml +++ b/.github/workflows/deploy-orchestrator.yml @@ -42,12 +42,12 @@ on: required: false default: 'GoldenPath-Testing' type: string - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: + AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: description: 'Log Analytics Workspace ID (Optional)' required: false default: '' type: string - AZURE_ENV_FOUNDRY_PROJECT_RID: + AZURE_EXISTING_AIPROJECT_RESOURCE_ID: description: 'AI Project Resource ID (Optional)' required: false default: '' @@ -86,8 +86,8 @@ jobs: EXP: ${{ inputs.EXP }} build_docker_image: ${{ inputs.build_docker_image }} existing_webapp_url: ${{ inputs.existing_webapp_url }} - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} - AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} + AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID }} + AZURE_EXISTING_AIPROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AIPROJECT_RESOURCE_ID }} docker_image_tag: ${{ needs.docker-build.outputs.IMAGE_TAG }} run_e2e_tests: ${{ inputs.run_e2e_tests }} cleanup_resources: ${{ inputs.cleanup_resources }} diff --git a/.github/workflows/deploy-v2.yml b/.github/workflows/deploy-v2.yml index cfc617588..897914b59 100644 --- a/.github/workflows/deploy-v2.yml +++ b/.github/workflows/deploy-v2.yml @@ -75,12 +75,12 @@ on: - 'Smoke-Testing' - 'None' - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: + AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: description: 'Log Analytics Workspace ID (Optional)' required: false default: '' type: string - AZURE_ENV_FOUNDRY_PROJECT_RID: + AZURE_EXISTING_AIPROJECT_RESOURCE_ID: description: 'AI Project Resource ID (Optional)' required: false default: '' @@ -107,8 +107,8 @@ jobs: build_docker_image: ${{ steps.validate.outputs.build_docker_image }} cleanup_resources: ${{ steps.validate.outputs.cleanup_resources }} run_e2e_tests: ${{ steps.validate.outputs.run_e2e_tests }} - azure_env_log_analytics_workspace_id: ${{ steps.validate.outputs.azure_env_log_analytics_workspace_id }} - azure_env_foundry_project_rid: ${{ steps.validate.outputs.azure_env_foundry_project_rid }} + azure_env_existing_log_analytics_workspace_rid: ${{ steps.validate.outputs.azure_env_existing_log_analytics_workspace_rid }} + azure_existing_aiproject_resource_id: ${{ steps.validate.outputs.azure_existing_aiproject_resource_id }} existing_webapp_url: ${{ steps.validate.outputs.existing_webapp_url }} steps: - name: Validate Workflow Input Parameters @@ -123,8 +123,8 @@ jobs: INPUT_BUILD_DOCKER_IMAGE: ${{ github.event.inputs.build_docker_image }} INPUT_CLEANUP_RESOURCES: ${{ github.event.inputs.cleanup_resources }} INPUT_RUN_E2E_TESTS: ${{ github.event.inputs.run_e2e_tests }} - INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ github.event.inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} - INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ github.event.inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} + INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: ${{ github.event.inputs.AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID }} + INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID: ${{ github.event.inputs.AZURE_EXISTING_AIPROJECT_RESOURCE_ID }} INPUT_EXISTING_WEBAPP_URL: ${{ github.event.inputs.existing_webapp_url }} run: | echo "šŸ” Validating workflow input parameters..." @@ -214,32 +214,32 @@ jobs: echo "āœ… run_e2e_tests: '$TEST_OPTION' is valid" fi - # Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID (optional, Azure Resource ID format) - if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" ]]; then - if [[ ! "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then - echo "āŒ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID is invalid. Must be a valid Azure Resource ID format:" + # Validate AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID (optional, Azure Resource ID format) + if [[ -n "$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" ]]; then + if [[ ! "$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then + echo "āŒ ERROR: AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID is invalid. Must be a valid Azure Resource ID format:" echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}" - echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID'" + echo " Got: '$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: Valid Resource ID format" + echo "āœ… AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: Valid Resource ID format" fi else - echo "āœ… AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: Not provided (optional)" + echo "āœ… AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: Not provided (optional)" fi - # Validate AZURE_ENV_FOUNDRY_PROJECT_RID (optional, Azure Resource ID format) - if [[ -n "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" ]]; then - if [[ ! "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then - echo "āŒ ERROR: AZURE_ENV_FOUNDRY_PROJECT_RID is invalid. Must be a valid Azure Resource ID format:" + # Validate AZURE_EXISTING_AIPROJECT_RESOURCE_ID (optional, Azure Resource ID format) + if [[ -n "$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID" ]]; then + if [[ ! "$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then + echo "āŒ ERROR: AZURE_EXISTING_AIPROJECT_RESOURCE_ID is invalid. Must be a valid Azure Resource ID format:" echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/projects/{projectName}" - echo " Got: '$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID'" + echo " Got: '$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_ENV_FOUNDRY_PROJECT_RID: Valid Resource ID format" + echo "āœ… AZURE_EXISTING_AIPROJECT_RESOURCE_ID: Valid Resource ID format" fi else - echo "āœ… AZURE_ENV_FOUNDRY_PROJECT_RID: Not provided (optional)" + echo "āœ… AZURE_EXISTING_AIPROJECT_RESOURCE_ID: Not provided (optional)" fi # Validate existing_webapp_url (optional, must start with https) @@ -274,8 +274,8 @@ jobs: echo "build_docker_image=$BUILD_DOCKER" >> $GITHUB_OUTPUT echo "cleanup_resources=$CLEANUP_RESOURCES" >> $GITHUB_OUTPUT echo "run_e2e_tests=$TEST_OPTION" >> $GITHUB_OUTPUT - echo "azure_env_log_analytics_workspace_id=$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" >> $GITHUB_OUTPUT - echo "azure_env_foundry_project_rid=$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" >> $GITHUB_OUTPUT + echo "azure_env_existing_log_analytics_workspace_rid=$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" >> $GITHUB_OUTPUT + echo "azure_existing_aiproject_resource_id=$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID" >> $GITHUB_OUTPUT echo "existing_webapp_url=$INPUT_EXISTING_WEBAPP_URL" >> $GITHUB_OUTPUT Run: @@ -291,8 +291,8 @@ jobs: build_docker_image: ${{ needs.validate-inputs.outputs.build_docker_image == 'true' }} cleanup_resources: ${{ needs.validate-inputs.outputs.cleanup_resources == 'true' }} run_e2e_tests: ${{ needs.validate-inputs.outputs.run_e2e_tests || 'GoldenPath-Testing' }} - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ needs.validate-inputs.outputs.azure_env_log_analytics_workspace_id || '' }} - AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ needs.validate-inputs.outputs.azure_env_foundry_project_rid || '' }} + AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: ${{ needs.validate-inputs.outputs.azure_env_existing_log_analytics_workspace_rid || '' }} + AZURE_EXISTING_AIPROJECT_RESOURCE_ID: ${{ needs.validate-inputs.outputs.azure_existing_aiproject_resource_id || '' }} existing_webapp_url: ${{ needs.validate-inputs.outputs.existing_webapp_url || '' }} trigger_type: ${{ github.event_name }} secrets: inherit diff --git a/.github/workflows/job-deploy-linux.yml b/.github/workflows/job-deploy-linux.yml index e38dd226e..930d3768d 100644 --- a/.github/workflows/job-deploy-linux.yml +++ b/.github/workflows/job-deploy-linux.yml @@ -28,10 +28,10 @@ on: required: false type: string default: 'false' - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: + AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: required: false type: string - AZURE_ENV_FOUNDRY_PROJECT_RID: + AZURE_EXISTING_AIPROJECT_RESOURCE_ID: required: false type: string outputs: @@ -66,8 +66,8 @@ jobs: INPUT_BUILD_DOCKER_IMAGE: ${{ inputs.BUILD_DOCKER_IMAGE }} INPUT_EXP: ${{ inputs.EXP }} INPUT_WAF_ENABLED: ${{ inputs.WAF_ENABLED }} - INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} - INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} + INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID }} + INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AIPROJECT_RESOURCE_ID }} run: | echo "šŸ” Validating workflow input parameters..." VALIDATION_FAILED=false @@ -154,27 +154,27 @@ jobs: echo "āœ… WAF_ENABLED: '$INPUT_WAF_ENABLED' is valid" fi - # Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID (optional, if provided must be valid Resource ID) - if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" ]]; then - if [[ ! "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then - echo "āŒ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID is invalid. Must be a valid Azure Resource ID format:" + # Validate AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID (optional, if provided must be valid Resource ID) + if [[ -n "$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" ]]; then + if [[ ! "$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then + echo "āŒ ERROR: AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID is invalid. Must be a valid Azure Resource ID format:" echo " Expected: /subscriptions/{guid}/resourceGroups/{rg}/providers/Microsoft.OperationalInsights/workspaces/{name}" - echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID'" + echo " Got: '$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: Valid Resource ID format" + echo "āœ… AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: Valid Resource ID format" fi fi - # Validate AZURE_ENV_FOUNDRY_PROJECT_RID (optional, if provided must be valid Resource ID) - if [[ -n "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" ]]; then - if [[ ! "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then - echo "āŒ ERROR: AZURE_ENV_FOUNDRY_PROJECT_RID is invalid. Must be a valid Azure Resource ID format:" + # Validate AZURE_EXISTING_AIPROJECT_RESOURCE_ID (optional, if provided must be valid Resource ID) + if [[ -n "$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID" ]]; then + if [[ ! "$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then + echo "āŒ ERROR: AZURE_EXISTING_AIPROJECT_RESOURCE_ID is invalid. Must be a valid Azure Resource ID format:" echo " Expected: /subscriptions/{guid}/resourceGroups/{rg}/providers/Microsoft.CognitiveServices/accounts/{account}/projects/{project}" - echo " Got: '$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID'" + echo " Got: '$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_ENV_FOUNDRY_PROJECT_RID: Valid Resource ID format" + echo "āœ… AZURE_EXISTING_AIPROJECT_RESOURCE_ID: Valid Resource ID format" fi fi @@ -228,8 +228,8 @@ jobs: INPUT_IMAGE_TAG: ${{ inputs.IMAGE_TAG }} INPUT_BUILD_DOCKER_IMAGE: ${{ inputs.BUILD_DOCKER_IMAGE }} INPUT_EXP: ${{ inputs.EXP }} - INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} - INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} + INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID }} + INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AIPROJECT_RESOURCE_ID }} run: | set -e @@ -258,22 +258,22 @@ jobs: if [[ "$INPUT_EXP" == "true" ]]; then echo "āœ… EXP ENABLED - Setting EXP parameters..." - if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" ]]; then - EXP_LOG_ANALYTICS_ID="$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" + if [[ -n "$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" ]]; then + EXP_LOG_ANALYTICS_ID="$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" else - EXP_LOG_ANALYTICS_ID="${{ secrets.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }}" + EXP_LOG_ANALYTICS_ID="${{ secrets.AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID }}" fi - if [[ -n "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" ]]; then - EXP_AI_PROJECT_ID="$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" + if [[ -n "$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID" ]]; then + EXP_AI_PROJECT_ID="$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID" else - EXP_AI_PROJECT_ID="${{ secrets.AZURE_ENV_FOUNDRY_PROJECT_RID }}" + EXP_AI_PROJECT_ID="${{ secrets.AZURE_EXISTING_AIPROJECT_RESOURCE_ID }}" fi - echo "AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: $EXP_LOG_ANALYTICS_ID" - echo "AZURE_ENV_FOUNDRY_PROJECT_RID: $EXP_AI_PROJECT_ID" - azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID="$EXP_LOG_ANALYTICS_ID" - azd env set AZURE_ENV_FOUNDRY_PROJECT_RID="$EXP_AI_PROJECT_ID" + echo "AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: $EXP_LOG_ANALYTICS_ID" + echo "AZURE_EXISTING_AIPROJECT_RESOURCE_ID: $EXP_AI_PROJECT_ID" + azd env set AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID="$EXP_LOG_ANALYTICS_ID" + azd env set AZURE_EXISTING_AIPROJECT_RESOURCE_ID="$EXP_AI_PROJECT_ID" else echo "EXP DISABLED - Skipping EXP parameters" fi diff --git a/.github/workflows/job-deploy-windows.yml b/.github/workflows/job-deploy-windows.yml index e296bf63a..675ae1371 100644 --- a/.github/workflows/job-deploy-windows.yml +++ b/.github/workflows/job-deploy-windows.yml @@ -28,10 +28,10 @@ on: required: false type: string default: 'false' - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: + AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: required: false type: string - AZURE_ENV_FOUNDRY_PROJECT_RID: + AZURE_EXISTING_AIPROJECT_RESOURCE_ID: required: false type: string outputs: @@ -65,8 +65,8 @@ jobs: INPUT_BUILD_DOCKER_IMAGE: ${{ inputs.BUILD_DOCKER_IMAGE }} INPUT_EXP: ${{ inputs.EXP }} INPUT_WAF_ENABLED: ${{ inputs.WAF_ENABLED }} - INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} - INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} + INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID }} + INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AIPROJECT_RESOURCE_ID }} run: | echo "šŸ” Validating workflow input parameters..." VALIDATION_FAILED=false @@ -153,27 +153,27 @@ jobs: echo "āœ… WAF_ENABLED: '$INPUT_WAF_ENABLED' is valid" fi - # Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID (optional, if provided must be valid Resource ID) - if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" ]]; then - if [[ ! "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then - echo "āŒ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID is invalid. Must be a valid Azure Resource ID format:" + # Validate AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID (optional, if provided must be valid Resource ID) + if [[ -n "$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" ]]; then + if [[ ! "$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then + echo "āŒ ERROR: AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID is invalid. Must be a valid Azure Resource ID format:" echo " Expected: /subscriptions/{guid}/resourceGroups/{rg}/providers/Microsoft.OperationalInsights/workspaces/{name}" - echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID'" + echo " Got: '$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: Valid Resource ID format" + echo "āœ… AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: Valid Resource ID format" fi fi - # Validate AZURE_ENV_FOUNDRY_PROJECT_RID (optional, if provided must be valid Resource ID) - if [[ -n "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" ]]; then - if [[ ! "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then - echo "āŒ ERROR: AZURE_ENV_FOUNDRY_PROJECT_RID is invalid. Must be a valid Azure Resource ID format:" + # Validate AZURE_EXISTING_AIPROJECT_RESOURCE_ID (optional, if provided must be valid Resource ID) + if [[ -n "$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID" ]]; then + if [[ ! "$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then + echo "āŒ ERROR: AZURE_EXISTING_AIPROJECT_RESOURCE_ID is invalid. Must be a valid Azure Resource ID format:" echo " Expected: /subscriptions/{guid}/resourceGroups/{rg}/providers/Microsoft.CognitiveServices/accounts/{account}/projects/{project}" - echo " Got: '$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID'" + echo " Got: '$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_ENV_FOUNDRY_PROJECT_RID: Valid Resource ID format" + echo "āœ… AZURE_EXISTING_AIPROJECT_RESOURCE_ID: Valid Resource ID format" fi fi @@ -228,8 +228,8 @@ jobs: INPUT_IMAGE_TAG: ${{ inputs.IMAGE_TAG }} INPUT_BUILD_DOCKER_IMAGE: ${{ inputs.BUILD_DOCKER_IMAGE }} INPUT_EXP: ${{ inputs.EXP }} - INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} - INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} + INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID }} + INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AIPROJECT_RESOURCE_ID }} run: | $ErrorActionPreference = "Stop" Write-Host "Starting azd deployment..." @@ -261,25 +261,25 @@ jobs: Write-Host "āœ… EXP ENABLED - Setting EXP parameters..." # Set EXP variables dynamically - if ($env:INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID -ne "") { - $EXP_LOG_ANALYTICS_ID = $env:INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID + if ($env:INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID -ne "") { + $EXP_LOG_ANALYTICS_ID = $env:INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID } else { - $EXP_LOG_ANALYTICS_ID = "${{ secrets.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }}" + $EXP_LOG_ANALYTICS_ID = "${{ secrets.AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID }}" } - if ($env:INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID -ne "") { - $EXP_AI_PROJECT_ID = $env:INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID + if ($env:INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID -ne "") { + $EXP_AI_PROJECT_ID = $env:INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID } else { - $EXP_AI_PROJECT_ID = "${{ secrets.AZURE_ENV_FOUNDRY_PROJECT_RID }}" + $EXP_AI_PROJECT_ID = "${{ secrets.AZURE_EXISTING_AIPROJECT_RESOURCE_ID }}" if (-not $EXP_AI_PROJECT_ID) { - $EXP_AI_PROJECT_ID = "${{ secrets.AZURE_ENV_FOUNDRY_PROJECT_RID }}" + $EXP_AI_PROJECT_ID = "${{ secrets.AZURE_EXISTING_AIPROJECT_RESOURCE_ID }}" } } - Write-Host "AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: $EXP_LOG_ANALYTICS_ID" - Write-Host "AZURE_ENV_FOUNDRY_PROJECT_RID: $EXP_AI_PROJECT_ID" - azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID="$EXP_LOG_ANALYTICS_ID" - azd env set AZURE_ENV_FOUNDRY_PROJECT_RID="$EXP_AI_PROJECT_ID" + Write-Host "AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: $EXP_LOG_ANALYTICS_ID" + Write-Host "AZURE_EXISTING_AIPROJECT_RESOURCE_ID: $EXP_AI_PROJECT_ID" + azd env set AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID="$EXP_LOG_ANALYTICS_ID" + azd env set AZURE_EXISTING_AIPROJECT_RESOURCE_ID="$EXP_AI_PROJECT_ID" } else { Write-Host "EXP DISABLED - Skipping EXP parameters" } diff --git a/.github/workflows/job-deploy.yml b/.github/workflows/job-deploy.yml index a3f0ef165..aadbb9ecd 100644 --- a/.github/workflows/job-deploy.yml +++ b/.github/workflows/job-deploy.yml @@ -51,12 +51,12 @@ on: required: false default: '' type: string - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: + AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: description: 'Log Analytics Workspace ID (Optional)' required: false default: '' type: string - AZURE_ENV_FOUNDRY_PROJECT_RID: + AZURE_EXISTING_AIPROJECT_RESOURCE_ID: description: 'AI Project Resource ID (Optional)' required: false default: '' @@ -128,8 +128,8 @@ jobs: INPUT_EXP: ${{ inputs.EXP }} INPUT_CLEANUP_RESOURCES: ${{ inputs.cleanup_resources }} INPUT_RUN_E2E_TESTS: ${{ inputs.run_e2e_tests }} - INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} - INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} + INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID }} + INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AIPROJECT_RESOURCE_ID }} INPUT_EXISTING_WEBAPP_URL: ${{ inputs.existing_webapp_url }} INPUT_DOCKER_IMAGE_TAG: ${{ inputs.docker_image_tag }} run: | @@ -194,27 +194,27 @@ jobs: fi fi - # Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID (Azure Resource ID format) - if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" ]]; then - if [[ ! "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then - echo "āŒ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID is invalid. Must be a valid Azure Resource ID format:" + # Validate AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID (Azure Resource ID format) + if [[ -n "$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" ]]; then + if [[ ! "$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then + echo "āŒ ERROR: AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID is invalid. Must be a valid Azure Resource ID format:" echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}" - echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID'" + echo " Got: '$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: Valid Resource ID format" + echo "āœ… AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: Valid Resource ID format" fi fi - # Validate AZURE_ENV_FOUNDRY_PROJECT_RID (Azure Resource ID format) - if [[ -n "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" ]]; then - if [[ ! "$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then - echo "āŒ ERROR: AZURE_ENV_FOUNDRY_PROJECT_RID is invalid. Must be a valid Azure Resource ID format:" + # Validate AZURE_EXISTING_AIPROJECT_RESOURCE_ID (Azure Resource ID format) + if [[ -n "$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID" ]]; then + if [[ ! "$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then + echo "āŒ ERROR: AZURE_EXISTING_AIPROJECT_RESOURCE_ID is invalid. Must be a valid Azure Resource ID format:" echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/projects/{projectName}" - echo " Got: '$INPUT_AZURE_ENV_FOUNDRY_PROJECT_RID'" + echo " Got: '$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID'" VALIDATION_FAILED=true else - echo "āœ… AZURE_ENV_FOUNDRY_PROJECT_RID: Valid Resource ID format" + echo "āœ… AZURE_EXISTING_AIPROJECT_RESOURCE_ID: Valid Resource ID format" fi fi @@ -258,8 +258,8 @@ jobs: shell: bash env: INPUT_EXP: ${{ inputs.EXP }} - INPUT_LOG_ANALYTICS_WORKSPACE_ID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} - INPUT_AI_PROJECT_RESOURCE_ID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} + INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID }} + INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AIPROJECT_RESOURCE_ID }} run: | echo "šŸ” Validating EXP configuration..." @@ -268,12 +268,12 @@ jobs: if [[ "$INPUT_EXP" == "true" ]]; then EXP_ENABLED="true" echo "āœ… EXP explicitly enabled by user input" - elif [[ -n "$INPUT_LOG_ANALYTICS_WORKSPACE_ID" ]] || [[ -n "$INPUT_AI_PROJECT_RESOURCE_ID" ]]; then + elif [[ -n "$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" ]] || [[ -n "$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID" ]]; then echo "šŸ”§ AUTO-ENABLING EXP: EXP parameter values were provided but EXP was not explicitly enabled." echo "" echo "You provided values for:" - [[ -n "$INPUT_LOG_ANALYTICS_WORKSPACE_ID" ]] && echo " - Azure Log Analytics Workspace ID: '$INPUT_LOG_ANALYTICS_WORKSPACE_ID'" - [[ -n "$INPUT_AI_PROJECT_RESOURCE_ID" ]] && echo " - Azure AI Project Resource ID: '$INPUT_AI_PROJECT_RESOURCE_ID'" + [[ -n "$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" ]] && echo " - Azure Log Analytics Workspace ID: '$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID'" + [[ -n "$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID" ]] && echo " - Azure AI Project Resource ID: '$INPUT_AZURE_EXISTING_AIPROJECT_RESOURCE_ID'" echo "" echo "āœ… Automatically enabling EXP to use these values." EXP_ENABLED="true" @@ -502,8 +502,8 @@ jobs: BUILD_DOCKER_IMAGE: ${{ inputs.build_docker_image || 'false' }} EXP: ${{ needs.azure-setup.outputs.EXP_ENABLED }} WAF_ENABLED: ${{ inputs.waf_enabled == true && 'true' || 'false' }} - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} - AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} + AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID }} + AZURE_EXISTING_AIPROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AIPROJECT_RESOURCE_ID }} secrets: inherit deploy-windows: @@ -520,6 +520,6 @@ jobs: BUILD_DOCKER_IMAGE: ${{ inputs.build_docker_image || 'false' }} EXP: ${{ needs.azure-setup.outputs.EXP_ENABLED }} WAF_ENABLED: ${{ inputs.waf_enabled == true && 'true' || 'false' }} - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID }} - AZURE_ENV_FOUNDRY_PROJECT_RID: ${{ inputs.AZURE_ENV_FOUNDRY_PROJECT_RID }} + AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: ${{ inputs.AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID }} + AZURE_EXISTING_AIPROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AIPROJECT_RESOURCE_ID }} secrets: inherit diff --git a/docs/CustomizingAzdParameters.md b/docs/CustomizingAzdParameters.md index 1b5e895e9..1721bb907 100644 --- a/docs/CustomizingAzdParameters.md +++ b/docs/CustomizingAzdParameters.md @@ -25,8 +25,8 @@ By default this template will use the environment name as the prefix to prevent | `AZURE_ENV_REASONING_MODEL_CAPACITY` | int | `50` | Sets the reasoning GPT model capacity. | | `AZURE_ENV_IMAGETAG` | string | `latest_v3` | Docker image tag used for container deployments. | | `AZURE_ENV_ENABLE_TELEMETRY` | bool | `true` | Enables telemetry for monitoring and diagnostics. | -| `AZURE_ENV_FOUNDRY_PROJECT_RID` | string | `` | Set this if you want to reuse an AI Foundry Project instead of creating a new one. | -| `AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID` | string | Guide to get your [Existing Workspace ID](/docs/re-use-log-analytics.md) | Set this if you want to reuse an existing Log Analytics Workspace instead of creating a new one. | +| `AZURE_EXISTING_AIPROJECT_RESOURCE_ID` | string | `` | Set this if you want to reuse an AI Foundry Project instead of creating a new one. | +| `AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID` | string | Guide to get your [Existing Workspace ID](/docs/re-use-log-analytics.md) | Set this if you want to reuse an existing Log Analytics Workspace instead of creating a new one. | | `AZURE_ENV_VM_ADMIN_USERNAME` | string | `take(newGuid(), 20)` | The administrator username for the virtual machine. | | `AZURE_ENV_VM_ADMIN_PASSWORD` | string | `newGuid()` | The administrator password for the virtual machine. | | `AZURE_ENV_VM_SIZE` | string | `Standard_D2s_v5` | The size of the virtual machine deployed with private networking. | @@ -43,7 +43,7 @@ azd env set Set the Log Analytics Workspace Id if you need to reuse the existing workspace which is already existing ```shell -azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID '/subscriptions//resourceGroups//providers/Microsoft.OperationalInsights/workspaces/' +azd env set AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID '/subscriptions//resourceGroups//providers/Microsoft.OperationalInsights/workspaces/' ``` **Example:** diff --git a/docs/re-use-foundry-project.md b/docs/re-use-foundry-project.md index ed955f1ac..39fe86a74 100644 --- a/docs/re-use-foundry-project.md +++ b/docs/re-use-foundry-project.md @@ -36,7 +36,7 @@ In the left-hand menu of the project blade: ### 6. Set the Foundry Project Resource ID in Your Environment Run the following command in your terminal ```bash -azd env set AZURE_ENV_FOUNDRY_PROJECT_RID '' +azd env set AZURE_EXISTING_AIPROJECT_RESOURCE_ID '' ``` Replace `` with the value obtained from Step 5. diff --git a/docs/re-use-log-analytics.md b/docs/re-use-log-analytics.md index 7ee170faf..81cdea146 100644 --- a/docs/re-use-log-analytics.md +++ b/docs/re-use-log-analytics.md @@ -23,7 +23,7 @@ Copy Resource ID that is your Workspace ID ### 4. Set the Workspace ID in Your Environment Run the following command in your terminal ```bash -azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID '' +azd env set AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID '' ``` Replace `` with the value obtained from Step 3. diff --git a/infra/main.parameters.json b/infra/main.parameters.json index be6fcaa14..0a81c78f0 100644 --- a/infra/main.parameters.json +++ b/infra/main.parameters.json @@ -60,10 +60,10 @@ "value": "${AZURE_ENV_ENABLE_TELEMETRY}" }, "existingLogAnalyticsWorkspaceId": { - "value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID}" + "value": "${AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID}" }, "existingAiFoundryAiProjectResourceId": { - "value": "${AZURE_ENV_FOUNDRY_PROJECT_RID}" + "value": "${AZURE_EXISTING_AIPROJECT_RESOURCE_ID}" }, "backendContainerRegistryHostname": { "value": "${AZURE_ENV_CONTAINER_REGISTRY_ENDPOINT}" diff --git a/infra/main.waf.parameters.json b/infra/main.waf.parameters.json index 23e123d6a..ab16c38fd 100644 --- a/infra/main.waf.parameters.json +++ b/infra/main.waf.parameters.json @@ -78,10 +78,10 @@ "value": "${AZURE_ENV_VM_SIZE}" }, "existingLogAnalyticsWorkspaceId": { - "value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_RID}" + "value": "${AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID}" }, "existingAiFoundryAiProjectResourceId": { - "value": "${AZURE_ENV_FOUNDRY_PROJECT_RID}" + "value": "${AZURE_EXISTING_AIPROJECT_RESOURCE_ID}" }, "backendContainerRegistryHostname": { "value": "${AZURE_ENV_CONTAINER_REGISTRY_ENDPOINT}" diff --git a/infra/old/00-older/deploy_ai_foundry.bicep b/infra/old/00-older/deploy_ai_foundry.bicep deleted file mode 100644 index 4bb9e584c..000000000 --- a/infra/old/00-older/deploy_ai_foundry.bicep +++ /dev/null @@ -1,313 +0,0 @@ -// Creates Azure dependent resources for Azure AI studio -param solutionName string -param solutionLocation string -param keyVaultName string -param gptModelName string -param gptModelVersion string -param managedIdentityObjectId string -param aiServicesEndpoint string -param aiServicesKey string -param aiServicesId string - -// Load the abbrevations file required to name the azure resources. -var abbrs = loadJsonContent('./abbreviations.json') - -var storageName = '${abbrs.storage.storageAccount}${solutionName}hub' -var storageSkuName = 'Standard_LRS' -var aiServicesName = '${abbrs.ai.aiServices}${solutionName}' -var workspaceName = '${abbrs.managementGovernance.logAnalyticsWorkspace}${solutionName}hub' -//var keyvaultName = '${abbrs.security.keyVault}${solutionName}' -var location = solutionLocation -var aiHubName = '${abbrs.ai.aiHub}${solutionName}' -var aiHubFriendlyName = aiHubName -var aiHubDescription = 'AI Hub for MACAE template' -var aiProjectName = '${abbrs.ai.aiHubProject}${solutionName}' -var aiProjectFriendlyName = aiProjectName -var aiSearchName = '${abbrs.ai.aiSearch}${solutionName}' - -resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = { - name: keyVaultName -} - -resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2023-09-01' = { - name: workspaceName - location: location - tags: {} - properties: { - retentionInDays: 30 - sku: { - name: 'PerGB2018' - } - } -} - -var storageNameCleaned = replace(storageName, '-', '') - -resource storage 'Microsoft.Storage/storageAccounts@2022-09-01' = { - name: storageNameCleaned - location: location - sku: { - name: storageSkuName - } - kind: 'StorageV2' - identity: { - type: 'SystemAssigned' - } - properties: { - accessTier: 'Hot' - allowBlobPublicAccess: false - allowCrossTenantReplication: false - allowSharedKeyAccess: false - encryption: { - keySource: 'Microsoft.Storage' - requireInfrastructureEncryption: false - services: { - blob: { - enabled: true - keyType: 'Account' - } - file: { - enabled: true - keyType: 'Account' - } - queue: { - enabled: true - keyType: 'Service' - } - table: { - enabled: true - keyType: 'Service' - } - } - } - isHnsEnabled: false - isNfsv4Enabled: false - keyPolicy: { - keyExpirationPeriodInDays: 7 - } - largeFileSharesState: 'Disabled' - minimumTlsVersion: 'TLS1_2' - networkAcls: { - bypass: 'AzureServices' - defaultAction: 'Allow' - } - supportsHttpsTrafficOnly: true - } -} - -@description('This is the built-in Storage Blob Data Contributor.') -resource blobDataContributor 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' existing = { - scope: subscription() - name: 'ba92f5b4-2d11-453d-a403-e96b0029c9fe' -} - -resource storageroleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(resourceGroup().id, managedIdentityObjectId, blobDataContributor.id) - scope: storage - properties: { - principalId: managedIdentityObjectId - roleDefinitionId: blobDataContributor.id - principalType: 'ServicePrincipal' - } -} - -resource aiHub 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = { - name: aiHubName - location: location - identity: { - type: 'SystemAssigned' - } - properties: { - // organization - friendlyName: aiHubFriendlyName - description: aiHubDescription - - // dependent resources - keyVault: keyVault.id - storageAccount: storage.id - } - kind: 'hub' - - resource aiServicesConnection 'connections@2024-07-01-preview' = { - name: '${aiHubName}-connection-AzureOpenAI' - properties: { - category: 'AIServices' - target: aiServicesEndpoint - authType: 'AAD' - isSharedToAll: true - metadata: { - ApiType: 'Azure' - ResourceId: aiServicesId - } - } - } -} - -resource aiHubProject 'Microsoft.MachineLearningServices/workspaces@2024-01-01-preview' = { - name: aiProjectName - location: location - kind: 'Project' - identity: { - type: 'SystemAssigned' - } - properties: { - friendlyName: aiProjectFriendlyName - hubResourceId: aiHub.id - } -} - -resource aiDeveloper 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - name: '64702f94-c441-49e6-a78b-ef80e0188fee' -} - -resource aiDevelopertoAIProject 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(aiHubProject.id, aiDeveloper.id) - scope: resourceGroup() - properties: { - roleDefinitionId: aiDeveloper.id - principalId: aiHubProject.identity.principalId - principalType: 'ServicePrincipal' - } -} - -resource tenantIdEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'TENANT-ID' - properties: { - value: subscription().tenantId - } -} - -resource azureOpenAIInferenceEndpoint 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'AZURE-OPENAI-INFERENCE-ENDPOINT' - properties: { - value: '' - } -} - -resource azureOpenAIInferenceKey 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'AZURE-OPENAI-INFERENCE-KEY' - properties: { - value: '' - } -} - -resource azureOpenAIApiKeyEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'AZURE-OPENAI-KEY' - properties: { - value: aiServicesKey //aiServices_m.listKeys().key1 - } -} - -resource azureOpenAIDeploymentModel 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'AZURE-OPEN-AI-DEPLOYMENT-MODEL' - properties: { - value: gptModelName - } -} - -resource azureOpenAIApiVersionEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'AZURE-OPENAI-PREVIEW-API-VERSION' - properties: { - value: gptModelVersion //'2024-02-15-preview' - } -} - -resource azureOpenAIEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'AZURE-OPENAI-ENDPOINT' - properties: { - value: aiServicesEndpoint //aiServices_m.properties.endpoint - } -} - -resource azureAIProjectConnectionStringEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'AZURE-AI-PROJECT-CONN-STRING' - properties: { - value: '${split(aiHubProject.properties.discoveryUrl, '/')[2]};${subscription().subscriptionId};${resourceGroup().name};${aiHubProject.name}' - } -} - -resource azureOpenAICUApiVersionEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'AZURE-OPENAI-CU-VERSION' - properties: { - value: '?api-version=2024-12-01-preview' - } -} - -resource azureSearchIndexEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'AZURE-SEARCH-INDEX' - properties: { - value: 'transcripts_index' - } -} - -resource cogServiceEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'COG-SERVICES-ENDPOINT' - properties: { - value: aiServicesEndpoint - } -} - -resource cogServiceKeyEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'COG-SERVICES-KEY' - properties: { - value: aiServicesKey - } -} - -resource cogServiceNameEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'COG-SERVICES-NAME' - properties: { - value: aiServicesName - } -} - -resource azureSubscriptionIdEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'AZURE-SUBSCRIPTION-ID' - properties: { - value: subscription().subscriptionId - } -} - -resource resourceGroupNameEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'AZURE-RESOURCE-GROUP' - properties: { - value: resourceGroup().name - } -} - -resource azureLocatioEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'AZURE-LOCATION' - properties: { - value: solutionLocation - } -} - -output keyvaultName string = keyVaultName -output keyvaultId string = keyVault.id - -output aiServicesName string = aiServicesName -output aiSearchName string = aiSearchName -output aiProjectName string = aiHubProject.name - -output storageAccountName string = storageNameCleaned - -output logAnalyticsId string = logAnalytics.id -output storageAccountId string = storage.id - -output projectConnectionString string = '${split(aiHubProject.properties.discoveryUrl, '/')[2]};${subscription().subscriptionId};${resourceGroup().name};${aiHubProject.name}' diff --git a/infra/old/00-older/deploy_keyvault.bicep b/infra/old/00-older/deploy_keyvault.bicep deleted file mode 100644 index 3a5c1f761..000000000 --- a/infra/old/00-older/deploy_keyvault.bicep +++ /dev/null @@ -1,62 +0,0 @@ -param solutionLocation string -param managedIdentityObjectId string - -@description('KeyVault Name') -param keyvaultName string - -resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: keyvaultName - location: solutionLocation - properties: { - createMode: 'default' - accessPolicies: [ - { - objectId: managedIdentityObjectId - permissions: { - certificates: [ - 'all' - ] - keys: [ - 'all' - ] - secrets: [ - 'all' - ] - storage: [ - 'all' - ] - } - tenantId: subscription().tenantId - } - ] - enabledForDeployment: true - enabledForDiskEncryption: true - enabledForTemplateDeployment: true - enableRbacAuthorization: true - publicNetworkAccess: 'enabled' - sku: { - family: 'A' - name: 'standard' - } - softDeleteRetentionInDays: 7 - tenantId: subscription().tenantId - } -} - -@description('This is the built-in Key Vault Administrator role.') -resource kvAdminRole 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' existing = { - scope: resourceGroup() - name: '00482a5a-887f-4fb3-b363-3b7fe8e74483' -} - -resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(resourceGroup().id, managedIdentityObjectId, kvAdminRole.id) - properties: { - principalId: managedIdentityObjectId - roleDefinitionId:kvAdminRole.id - principalType: 'ServicePrincipal' - } -} - -output keyvaultName string = keyvaultName -output keyvaultId string = keyVault.id diff --git a/infra/old/00-older/deploy_managed_identity.bicep b/infra/old/00-older/deploy_managed_identity.bicep deleted file mode 100644 index 5288872cb..000000000 --- a/infra/old/00-older/deploy_managed_identity.bicep +++ /dev/null @@ -1,45 +0,0 @@ -// ========== Managed Identity ========== // -targetScope = 'resourceGroup' - -@description('Solution Location') -//param solutionLocation string -param managedIdentityId string -param managedIdentityPropPrin string -param managedIdentityLocation string -@description('Managed Identity Name') -param miName string - -// resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { -// name: miName -// location: solutionLocation -// tags: { -// app: solutionName -// location: solutionLocation -// } -// } - -@description('This is the built-in owner role. See https://docs.microsoft.com/azure/role-based-access-control/built-in-roles#owner') -resource ownerRoleDefinition 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' existing = { - scope: resourceGroup() - name: '8e3af657-a8ff-443c-a75c-2fe8c4bcb635' -} - -resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(resourceGroup().id, managedIdentityId, ownerRoleDefinition.id) - properties: { - principalId: managedIdentityPropPrin - roleDefinitionId: ownerRoleDefinition.id - principalType: 'ServicePrincipal' - } -} - - -output managedIdentityOutput object = { - id: managedIdentityId - objectId: managedIdentityPropPrin - resourceId: managedIdentityId - location: managedIdentityLocation - name: miName -} - -output managedIdentityId string = managedIdentityId diff --git a/infra/old/00-older/macae-continer-oc.json b/infra/old/00-older/macae-continer-oc.json deleted file mode 100644 index 40c676ebe..000000000 --- a/infra/old/00-older/macae-continer-oc.json +++ /dev/null @@ -1,458 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.33.93.31351", - "templateHash": "9524414973084491660" - } - }, - "parameters": { - "location": { - "type": "string", - "defaultValue": "EastUS2", - "metadata": { - "description": "Location for all resources." - } - }, - "azureOpenAILocation": { - "type": "string", - "defaultValue": "EastUS", - "metadata": { - "description": "Location for OpenAI resources." - } - }, - "prefix": { - "type": "string", - "defaultValue": "macae", - "metadata": { - "description": "A prefix to add to the start of all resource names. Note: A \"unique\" suffix will also be added" - } - }, - "tags": { - "type": "object", - "defaultValue": {}, - "metadata": { - "description": "Tags to apply to all deployed resources" - } - }, - "resourceSize": { - "type": "object", - "properties": { - "gpt4oCapacity": { - "type": "int" - }, - "containerAppSize": { - "type": "object", - "properties": { - "cpu": { - "type": "string" - }, - "memory": { - "type": "string" - }, - "minReplicas": { - "type": "int" - }, - "maxReplicas": { - "type": "int" - } - } - } - }, - "defaultValue": { - "gpt4oCapacity": 50, - "containerAppSize": { - "cpu": "2.0", - "memory": "4.0Gi", - "minReplicas": 1, - "maxReplicas": 1 - } - }, - "metadata": { - "description": "The size of the resources to deploy, defaults to a mini size" - } - } - }, - "variables": { - "appVersion": "latest", - "resgistryName": "biabcontainerreg", - "dockerRegistryUrl": "[format('https://{0}.azurecr.io', variables('resgistryName'))]", - "backendDockerImageURL": "[format('{0}.azurecr.io/macaebackend:{1}', variables('resgistryName'), variables('appVersion'))]", - "frontendDockerImageURL": "[format('{0}.azurecr.io/macaefrontend:{1}', variables('resgistryName'), variables('appVersion'))]", - "uniqueNameFormat": "[format('{0}-{{0}}-{1}', parameters('prefix'), uniqueString(resourceGroup().id, parameters('prefix')))]", - "aoaiApiVersion": "2024-08-01-preview" - }, - "resources": { - "openai::gpt4o": { - "type": "Microsoft.CognitiveServices/accounts/deployments", - "apiVersion": "2023-10-01-preview", - "name": "[format('{0}/{1}', format(variables('uniqueNameFormat'), 'openai'), 'gpt-4o')]", - "sku": { - "name": "GlobalStandard", - "capacity": "[parameters('resourceSize').gpt4oCapacity]" - }, - "properties": { - "model": { - "format": "OpenAI", - "name": "gpt-4o", - "version": "2024-08-06" - }, - "versionUpgradeOption": "NoAutoUpgrade" - }, - "dependsOn": [ - "openai" - ] - }, - "cosmos::autogenDb::memoryContainer": { - "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers", - "apiVersion": "2024-05-15", - "name": "[format('{0}/{1}/{2}', format(variables('uniqueNameFormat'), 'cosmos'), 'autogen', 'memory')]", - "properties": { - "resource": { - "id": "memory", - "partitionKey": { - "kind": "Hash", - "version": 2, - "paths": [ - "/session_id" - ] - } - } - }, - "dependsOn": [ - "cosmos::autogenDb" - ] - }, - "cosmos::contributorRoleDefinition": { - "existing": true, - "type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions", - "apiVersion": "2024-05-15", - "name": "[format('{0}/{1}', format(variables('uniqueNameFormat'), 'cosmos'), '00000000-0000-0000-0000-000000000002')]", - "dependsOn": [ - "cosmos" - ] - }, - "cosmos::autogenDb": { - "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases", - "apiVersion": "2024-05-15", - "name": "[format('{0}/{1}', format(variables('uniqueNameFormat'), 'cosmos'), 'autogen')]", - "properties": { - "resource": { - "id": "autogen", - "createMode": "Default" - } - }, - "dependsOn": [ - "cosmos" - ] - }, - "containerAppEnv::aspireDashboard": { - "type": "Microsoft.App/managedEnvironments/dotNetComponents", - "apiVersion": "2024-02-02-preview", - "name": "[format('{0}/{1}', format(variables('uniqueNameFormat'), 'containerapp'), 'aspire-dashboard')]", - "properties": { - "componentType": "AspireDashboard" - }, - "dependsOn": [ - "containerAppEnv" - ] - }, - "logAnalytics": { - "type": "Microsoft.OperationalInsights/workspaces", - "apiVersion": "2023-09-01", - "name": "[format(variables('uniqueNameFormat'), 'logs')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "retentionInDays": 30, - "sku": { - "name": "PerGB2018" - } - } - }, - "appInsights": { - "type": "Microsoft.Insights/components", - "apiVersion": "2020-02-02-preview", - "name": "[format(variables('uniqueNameFormat'), 'appins')]", - "location": "[parameters('location')]", - "kind": "web", - "properties": { - "Application_Type": "web", - "WorkspaceResourceId": "[resourceId('Microsoft.OperationalInsights/workspaces', format(variables('uniqueNameFormat'), 'logs'))]" - }, - "dependsOn": [ - "logAnalytics" - ] - }, - "openai": { - "type": "Microsoft.CognitiveServices/accounts", - "apiVersion": "2023-10-01-preview", - "name": "[format(variables('uniqueNameFormat'), 'openai')]", - "location": "[parameters('azureOpenAILocation')]", - "tags": "[parameters('tags')]", - "kind": "OpenAI", - "sku": { - "name": "S0" - }, - "properties": { - "customSubDomainName": "[format(variables('uniqueNameFormat'), 'openai')]" - } - }, - "aoaiUserRoleDefinition": { - "existing": true, - "type": "Microsoft.Authorization/roleDefinitions", - "apiVersion": "2022-05-01-preview", - "name": "5e0bd9bd-7b93-4f28-af87-19fc36ad61bd" - }, - "acaAoaiRoleAssignment": { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2022-04-01", - "scope": "[format('Microsoft.CognitiveServices/accounts/{0}', format(variables('uniqueNameFormat'), 'openai'))]", - "name": "[guid(resourceId('Microsoft.App/containerApps', format('{0}-backend', parameters('prefix'))), resourceId('Microsoft.CognitiveServices/accounts', format(variables('uniqueNameFormat'), 'openai')), resourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd'))]", - "properties": { - "principalId": "[reference('containerApp', '2024-03-01', 'full').identity.principalId]", - "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd')]", - "principalType": "ServicePrincipal" - }, - "dependsOn": [ - "containerApp", - "openai" - ] - }, - "cosmos": { - "type": "Microsoft.DocumentDB/databaseAccounts", - "apiVersion": "2024-05-15", - "name": "[format(variables('uniqueNameFormat'), 'cosmos')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "kind": "GlobalDocumentDB", - "properties": { - "databaseAccountOfferType": "Standard", - "enableFreeTier": false, - "locations": [ - { - "failoverPriority": 0, - "locationName": "[parameters('location')]" - } - ], - "capabilities": [ - { - "name": "EnableServerless" - } - ] - } - }, - "pullIdentity": { - "type": "Microsoft.ManagedIdentity/userAssignedIdentities", - "apiVersion": "2023-07-31-preview", - "name": "[format(variables('uniqueNameFormat'), 'containerapp-pull')]", - "location": "[parameters('location')]" - }, - "containerAppEnv": { - "type": "Microsoft.App/managedEnvironments", - "apiVersion": "2024-03-01", - "name": "[format(variables('uniqueNameFormat'), 'containerapp')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "daprAIConnectionString": "[reference('appInsights').ConnectionString]", - "appLogsConfiguration": { - "destination": "log-analytics", - "logAnalyticsConfiguration": { - "customerId": "[reference('logAnalytics').customerId]", - "sharedKey": "[listKeys(resourceId('Microsoft.OperationalInsights/workspaces', format(variables('uniqueNameFormat'), 'logs')), '2023-09-01').primarySharedKey]" - } - } - }, - "dependsOn": [ - "appInsights", - "logAnalytics" - ] - }, - "acaCosomsRoleAssignment": { - "type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments", - "apiVersion": "2024-05-15", - "name": "[format('{0}/{1}', format(variables('uniqueNameFormat'), 'cosmos'), guid(resourceId('Microsoft.App/containerApps', format('{0}-backend', parameters('prefix'))), resourceId('Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions', format(variables('uniqueNameFormat'), 'cosmos'), '00000000-0000-0000-0000-000000000002')))]", - "properties": { - "principalId": "[reference('containerApp', '2024-03-01', 'full').identity.principalId]", - "roleDefinitionId": "[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions', format(variables('uniqueNameFormat'), 'cosmos'), '00000000-0000-0000-0000-000000000002')]", - "scope": "[resourceId('Microsoft.DocumentDB/databaseAccounts', format(variables('uniqueNameFormat'), 'cosmos'))]" - }, - "dependsOn": [ - "containerApp", - "cosmos" - ] - }, - "containerApp": { - "type": "Microsoft.App/containerApps", - "apiVersion": "2024-03-01", - "name": "[format('{0}-backend', parameters('prefix'))]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "identity": { - "type": "SystemAssigned, UserAssigned", - "userAssignedIdentities": { - "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format(variables('uniqueNameFormat'), 'containerapp-pull')))]": {} - } - }, - "properties": { - "managedEnvironmentId": "[resourceId('Microsoft.App/managedEnvironments', format(variables('uniqueNameFormat'), 'containerapp'))]", - "configuration": { - "ingress": { - "targetPort": 8000, - "external": true, - "corsPolicy": { - "allowedOrigins": [ - "[format('https://{0}.azurewebsites.net', format(variables('uniqueNameFormat'), 'frontend'))]", - "[format('http://{0}.azurewebsites.net', format(variables('uniqueNameFormat'), 'frontend'))]" - ] - } - }, - "activeRevisionsMode": "Single" - }, - "template": { - "scale": { - "minReplicas": "[parameters('resourceSize').containerAppSize.minReplicas]", - "maxReplicas": "[parameters('resourceSize').containerAppSize.maxReplicas]", - "rules": [ - { - "name": "http-scaler", - "http": { - "metadata": { - "concurrentRequests": "100" - } - } - } - ] - }, - "containers": [ - { - "name": "backend", - "image": "[variables('backendDockerImageURL')]", - "resources": { - "cpu": "[json(parameters('resourceSize').containerAppSize.cpu)]", - "memory": "[parameters('resourceSize').containerAppSize.memory]" - }, - "env": [ - { - "name": "COSMOSDB_ENDPOINT", - "value": "[reference('cosmos').documentEndpoint]" - }, - { - "name": "COSMOSDB_DATABASE", - "value": "autogen" - }, - { - "name": "COSMOSDB_CONTAINER", - "value": "memory" - }, - { - "name": "AZURE_OPENAI_ENDPOINT", - "value": "[reference('openai').endpoint]" - }, - { - "name": "AZURE_OPENAI_DEPLOYMENT_NAME", - "value": "gpt-4o" - }, - { - "name": "AZURE_OPENAI_API_VERSION", - "value": "[variables('aoaiApiVersion')]" - }, - { - "name": "FRONTEND_SITE_NAME", - "value": "[format('https://{0}.azurewebsites.net', format(variables('uniqueNameFormat'), 'frontend'))]" - }, - { - "name": "APPLICATIONINSIGHTS_CONNECTION_STRING", - "value": "[reference('appInsights').ConnectionString]" - } - ] - } - ] - } - }, - "dependsOn": [ - "appInsights", - "cosmos::autogenDb", - "containerAppEnv", - "cosmos", - "openai::gpt4o", - "cosmos::autogenDb::memoryContainer", - "openai", - "pullIdentity" - ], - "metadata": { - "description": "" - } - }, - "frontendAppServicePlan": { - "type": "Microsoft.Web/serverfarms", - "apiVersion": "2021-02-01", - "name": "[format(variables('uniqueNameFormat'), 'frontend-plan')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "sku": { - "name": "P1v2", - "capacity": 1, - "tier": "PremiumV2" - }, - "properties": { - "reserved": true - }, - "kind": "linux" - }, - "frontendAppService": { - "type": "Microsoft.Web/sites", - "apiVersion": "2021-02-01", - "name": "[format(variables('uniqueNameFormat'), 'frontend')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "kind": "app,linux,container", - "properties": { - "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', format(variables('uniqueNameFormat'), 'frontend-plan'))]", - "reserved": true, - "siteConfig": { - "linuxFxVersion": "[format('DOCKER|{0}', variables('frontendDockerImageURL'))]", - "appSettings": [ - { - "name": "DOCKER_REGISTRY_SERVER_URL", - "value": "[variables('dockerRegistryUrl')]" - }, - { - "name": "WEBSITES_PORT", - "value": "3000" - }, - { - "name": "WEBSITES_CONTAINER_START_TIME_LIMIT", - "value": "1800" - }, - { - "name": "BACKEND_API_URL", - "value": "[format('https://{0}', reference('containerApp').configuration.ingress.fqdn)]" - } - ] - } - }, - "identity": { - "type": "SystemAssigned,UserAssigned", - "userAssignedIdentities": { - "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format(variables('uniqueNameFormat'), 'containerapp-pull')))]": {} - } - }, - "dependsOn": [ - "containerApp", - "frontendAppServicePlan", - "pullIdentity" - ] - } - }, - "outputs": { - "cosmosAssignCli": { - "type": "string", - "value": "[format('az cosmosdb sql role assignment create --resource-group \"{0}\" --account-name \"{1}\" --role-definition-id \"{2}\" --scope \"{3}\" --principal-id \"fill-in\"', resourceGroup().name, format(variables('uniqueNameFormat'), 'cosmos'), resourceId('Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions', format(variables('uniqueNameFormat'), 'cosmos'), '00000000-0000-0000-0000-000000000002'), resourceId('Microsoft.DocumentDB/databaseAccounts', format(variables('uniqueNameFormat'), 'cosmos')))]" - } - } -} \ No newline at end of file diff --git a/infra/old/00-older/macae-continer.json b/infra/old/00-older/macae-continer.json deleted file mode 100644 index db8539188..000000000 --- a/infra/old/00-older/macae-continer.json +++ /dev/null @@ -1,458 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.34.44.8038", - "templateHash": "8201361287909347586" - } - }, - "parameters": { - "location": { - "type": "string", - "defaultValue": "EastUS2", - "metadata": { - "description": "Location for all resources." - } - }, - "azureOpenAILocation": { - "type": "string", - "defaultValue": "EastUS", - "metadata": { - "description": "Location for OpenAI resources." - } - }, - "prefix": { - "type": "string", - "defaultValue": "macae", - "metadata": { - "description": "A prefix to add to the start of all resource names. Note: A \"unique\" suffix will also be added" - } - }, - "tags": { - "type": "object", - "defaultValue": {}, - "metadata": { - "description": "Tags to apply to all deployed resources" - } - }, - "resourceSize": { - "type": "object", - "properties": { - "gpt4oCapacity": { - "type": "int" - }, - "containerAppSize": { - "type": "object", - "properties": { - "cpu": { - "type": "string" - }, - "memory": { - "type": "string" - }, - "minReplicas": { - "type": "int" - }, - "maxReplicas": { - "type": "int" - } - } - } - }, - "defaultValue": { - "gpt4oCapacity": 50, - "containerAppSize": { - "cpu": "2.0", - "memory": "4.0Gi", - "minReplicas": 1, - "maxReplicas": 1 - } - }, - "metadata": { - "description": "The size of the resources to deploy, defaults to a mini size" - } - } - }, - "variables": { - "appVersion": "latest", - "resgistryName": "biabcontainerreg", - "dockerRegistryUrl": "[format('https://{0}.azurecr.io', variables('resgistryName'))]", - "backendDockerImageURL": "[format('{0}.azurecr.io/macaebackend:{1}', variables('resgistryName'), variables('appVersion'))]", - "frontendDockerImageURL": "[format('{0}.azurecr.io/macaefrontend:{1}', variables('resgistryName'), variables('appVersion'))]", - "uniqueNameFormat": "[format('{0}-{{0}}-{1}', parameters('prefix'), uniqueString(resourceGroup().id, parameters('prefix')))]", - "aoaiApiVersion": "2024-08-01-preview" - }, - "resources": { - "openai::gpt4o": { - "type": "Microsoft.CognitiveServices/accounts/deployments", - "apiVersion": "2023-10-01-preview", - "name": "[format('{0}/{1}', format(variables('uniqueNameFormat'), 'openai'), 'gpt-4o')]", - "sku": { - "name": "GlobalStandard", - "capacity": "[parameters('resourceSize').gpt4oCapacity]" - }, - "properties": { - "model": { - "format": "OpenAI", - "name": "gpt-4o", - "version": "2024-08-06" - }, - "versionUpgradeOption": "NoAutoUpgrade" - }, - "dependsOn": [ - "openai" - ] - }, - "cosmos::autogenDb::memoryContainer": { - "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers", - "apiVersion": "2024-05-15", - "name": "[format('{0}/{1}/{2}', format(variables('uniqueNameFormat'), 'cosmos'), 'autogen', 'memory')]", - "properties": { - "resource": { - "id": "memory", - "partitionKey": { - "kind": "Hash", - "version": 2, - "paths": [ - "/session_id" - ] - } - } - }, - "dependsOn": [ - "cosmos::autogenDb" - ] - }, - "cosmos::contributorRoleDefinition": { - "existing": true, - "type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions", - "apiVersion": "2024-05-15", - "name": "[format('{0}/{1}', format(variables('uniqueNameFormat'), 'cosmos'), '00000000-0000-0000-0000-000000000002')]", - "dependsOn": [ - "cosmos" - ] - }, - "cosmos::autogenDb": { - "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases", - "apiVersion": "2024-05-15", - "name": "[format('{0}/{1}', format(variables('uniqueNameFormat'), 'cosmos'), 'autogen')]", - "properties": { - "resource": { - "id": "autogen", - "createMode": "Default" - } - }, - "dependsOn": [ - "cosmos" - ] - }, - "containerAppEnv::aspireDashboard": { - "type": "Microsoft.App/managedEnvironments/dotNetComponents", - "apiVersion": "2024-02-02-preview", - "name": "[format('{0}/{1}', format(variables('uniqueNameFormat'), 'containerapp'), 'aspire-dashboard')]", - "properties": { - "componentType": "AspireDashboard" - }, - "dependsOn": [ - "containerAppEnv" - ] - }, - "logAnalytics": { - "type": "Microsoft.OperationalInsights/workspaces", - "apiVersion": "2023-09-01", - "name": "[format(variables('uniqueNameFormat'), 'logs')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "retentionInDays": 30, - "sku": { - "name": "PerGB2018" - } - } - }, - "appInsights": { - "type": "Microsoft.Insights/components", - "apiVersion": "2020-02-02-preview", - "name": "[format(variables('uniqueNameFormat'), 'appins')]", - "location": "[parameters('location')]", - "kind": "web", - "properties": { - "Application_Type": "web", - "WorkspaceResourceId": "[resourceId('Microsoft.OperationalInsights/workspaces', format(variables('uniqueNameFormat'), 'logs'))]" - }, - "dependsOn": [ - "logAnalytics" - ] - }, - "openai": { - "type": "Microsoft.CognitiveServices/accounts", - "apiVersion": "2023-10-01-preview", - "name": "[format(variables('uniqueNameFormat'), 'openai')]", - "location": "[parameters('azureOpenAILocation')]", - "tags": "[parameters('tags')]", - "kind": "OpenAI", - "sku": { - "name": "S0" - }, - "properties": { - "customSubDomainName": "[format(variables('uniqueNameFormat'), 'openai')]" - } - }, - "aoaiUserRoleDefinition": { - "existing": true, - "type": "Microsoft.Authorization/roleDefinitions", - "apiVersion": "2022-05-01-preview", - "name": "5e0bd9bd-7b93-4f28-af87-19fc36ad61bd" - }, - "acaAoaiRoleAssignment": { - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2022-04-01", - "scope": "[format('Microsoft.CognitiveServices/accounts/{0}', format(variables('uniqueNameFormat'), 'openai'))]", - "name": "[guid(resourceId('Microsoft.App/containerApps', format('{0}-backend', parameters('prefix'))), resourceId('Microsoft.CognitiveServices/accounts', format(variables('uniqueNameFormat'), 'openai')), resourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd'))]", - "properties": { - "principalId": "[reference('containerApp', '2024-03-01', 'full').identity.principalId]", - "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd')]", - "principalType": "ServicePrincipal" - }, - "dependsOn": [ - "containerApp", - "openai" - ] - }, - "cosmos": { - "type": "Microsoft.DocumentDB/databaseAccounts", - "apiVersion": "2024-05-15", - "name": "[format(variables('uniqueNameFormat'), 'cosmos')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "kind": "GlobalDocumentDB", - "properties": { - "databaseAccountOfferType": "Standard", - "enableFreeTier": false, - "locations": [ - { - "failoverPriority": 0, - "locationName": "[parameters('location')]" - } - ], - "capabilities": [ - { - "name": "EnableServerless" - } - ] - } - }, - "pullIdentity": { - "type": "Microsoft.ManagedIdentity/userAssignedIdentities", - "apiVersion": "2023-07-31-preview", - "name": "[format(variables('uniqueNameFormat'), 'containerapp-pull')]", - "location": "[parameters('location')]" - }, - "containerAppEnv": { - "type": "Microsoft.App/managedEnvironments", - "apiVersion": "2024-03-01", - "name": "[format(variables('uniqueNameFormat'), 'containerapp')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "daprAIConnectionString": "[reference('appInsights').ConnectionString]", - "appLogsConfiguration": { - "destination": "log-analytics", - "logAnalyticsConfiguration": { - "customerId": "[reference('logAnalytics').customerId]", - "sharedKey": "[listKeys(resourceId('Microsoft.OperationalInsights/workspaces', format(variables('uniqueNameFormat'), 'logs')), '2023-09-01').primarySharedKey]" - } - } - }, - "dependsOn": [ - "appInsights", - "logAnalytics" - ] - }, - "acaCosomsRoleAssignment": { - "type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments", - "apiVersion": "2024-05-15", - "name": "[format('{0}/{1}', format(variables('uniqueNameFormat'), 'cosmos'), guid(resourceId('Microsoft.App/containerApps', format('{0}-backend', parameters('prefix'))), resourceId('Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions', format(variables('uniqueNameFormat'), 'cosmos'), '00000000-0000-0000-0000-000000000002')))]", - "properties": { - "principalId": "[reference('containerApp', '2024-03-01', 'full').identity.principalId]", - "roleDefinitionId": "[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions', format(variables('uniqueNameFormat'), 'cosmos'), '00000000-0000-0000-0000-000000000002')]", - "scope": "[resourceId('Microsoft.DocumentDB/databaseAccounts', format(variables('uniqueNameFormat'), 'cosmos'))]" - }, - "dependsOn": [ - "containerApp", - "cosmos" - ] - }, - "containerApp": { - "type": "Microsoft.App/containerApps", - "apiVersion": "2024-03-01", - "name": "[format('{0}-backend', parameters('prefix'))]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "identity": { - "type": "SystemAssigned, UserAssigned", - "userAssignedIdentities": { - "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format(variables('uniqueNameFormat'), 'containerapp-pull')))]": {} - } - }, - "properties": { - "managedEnvironmentId": "[resourceId('Microsoft.App/managedEnvironments', format(variables('uniqueNameFormat'), 'containerapp'))]", - "configuration": { - "ingress": { - "targetPort": 8000, - "external": true, - "corsPolicy": { - "allowedOrigins": [ - "[format('https://{0}.azurewebsites.net', format(variables('uniqueNameFormat'), 'frontend'))]", - "[format('http://{0}.azurewebsites.net', format(variables('uniqueNameFormat'), 'frontend'))]" - ] - } - }, - "activeRevisionsMode": "Single" - }, - "template": { - "scale": { - "minReplicas": "[parameters('resourceSize').containerAppSize.minReplicas]", - "maxReplicas": "[parameters('resourceSize').containerAppSize.maxReplicas]", - "rules": [ - { - "name": "http-scaler", - "http": { - "metadata": { - "concurrentRequests": "100" - } - } - } - ] - }, - "containers": [ - { - "name": "backend", - "image": "[variables('backendDockerImageURL')]", - "resources": { - "cpu": "[json(parameters('resourceSize').containerAppSize.cpu)]", - "memory": "[parameters('resourceSize').containerAppSize.memory]" - }, - "env": [ - { - "name": "COSMOSDB_ENDPOINT", - "value": "[reference('cosmos').documentEndpoint]" - }, - { - "name": "COSMOSDB_DATABASE", - "value": "autogen" - }, - { - "name": "COSMOSDB_CONTAINER", - "value": "memory" - }, - { - "name": "AZURE_OPENAI_ENDPOINT", - "value": "[reference('openai').endpoint]" - }, - { - "name": "AZURE_OPENAI_DEPLOYMENT_NAME", - "value": "gpt-4o" - }, - { - "name": "AZURE_OPENAI_API_VERSION", - "value": "[variables('aoaiApiVersion')]" - }, - { - "name": "FRONTEND_SITE_NAME", - "value": "[format('https://{0}.azurewebsites.net', format(variables('uniqueNameFormat'), 'frontend'))]" - }, - { - "name": "APPLICATIONINSIGHTS_CONNECTION_STRING", - "value": "[reference('appInsights').ConnectionString]" - } - ] - } - ] - } - }, - "dependsOn": [ - "appInsights", - "containerAppEnv", - "cosmos", - "cosmos::autogenDb", - "cosmos::autogenDb::memoryContainer", - "openai", - "openai::gpt4o", - "pullIdentity" - ], - "metadata": { - "description": "" - } - }, - "frontendAppServicePlan": { - "type": "Microsoft.Web/serverfarms", - "apiVersion": "2021-02-01", - "name": "[format(variables('uniqueNameFormat'), 'frontend-plan')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "sku": { - "name": "P1v2", - "capacity": 1, - "tier": "PremiumV2" - }, - "properties": { - "reserved": true - }, - "kind": "linux" - }, - "frontendAppService": { - "type": "Microsoft.Web/sites", - "apiVersion": "2021-02-01", - "name": "[format(variables('uniqueNameFormat'), 'frontend')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "kind": "app,linux,container", - "properties": { - "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', format(variables('uniqueNameFormat'), 'frontend-plan'))]", - "reserved": true, - "siteConfig": { - "linuxFxVersion": "[format('DOCKER|{0}', variables('frontendDockerImageURL'))]", - "appSettings": [ - { - "name": "DOCKER_REGISTRY_SERVER_URL", - "value": "[variables('dockerRegistryUrl')]" - }, - { - "name": "WEBSITES_PORT", - "value": "3000" - }, - { - "name": "WEBSITES_CONTAINER_START_TIME_LIMIT", - "value": "1800" - }, - { - "name": "BACKEND_API_URL", - "value": "[format('https://{0}', reference('containerApp').configuration.ingress.fqdn)]" - } - ] - } - }, - "identity": { - "type": "SystemAssigned,UserAssigned", - "userAssignedIdentities": { - "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format(variables('uniqueNameFormat'), 'containerapp-pull')))]": {} - } - }, - "dependsOn": [ - "containerApp", - "frontendAppServicePlan", - "pullIdentity" - ] - } - }, - "outputs": { - "cosmosAssignCli": { - "type": "string", - "value": "[format('az cosmosdb sql role assignment create --resource-group \"{0}\" --account-name \"{1}\" --role-definition-id \"{2}\" --scope \"{3}\" --principal-id \"fill-in\"', resourceGroup().name, format(variables('uniqueNameFormat'), 'cosmos'), resourceId('Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions', format(variables('uniqueNameFormat'), 'cosmos'), '00000000-0000-0000-0000-000000000002'), resourceId('Microsoft.DocumentDB/databaseAccounts', format(variables('uniqueNameFormat'), 'cosmos')))]" - } - } -} \ No newline at end of file diff --git a/infra/old/00-older/macae-dev.bicep b/infra/old/00-older/macae-dev.bicep deleted file mode 100644 index 5157fa92f..000000000 --- a/infra/old/00-older/macae-dev.bicep +++ /dev/null @@ -1,131 +0,0 @@ -@description('Location for all resources.') -param location string = resourceGroup().location - -@description('location for Cosmos DB resources.') -// prompt for this as there is often quota restrictions -param cosmosLocation string - -@description('Location for OpenAI resources.') -// prompt for this as there is often quota restrictions -param azureOpenAILocation string - -@description('A prefix to add to the start of all resource names. Note: A "unique" suffix will also be added') -param prefix string = 'macae' - -@description('Tags to apply to all deployed resources') -param tags object = {} - -@description('Principal ID to assign to the Cosmos DB contributor & Azure OpenAI user role, leave empty to skip role assignment. This is your ObjectID wihtin Entra ID.') -param developerPrincipalId string - -var uniqueNameFormat = '${prefix}-{0}-${uniqueString(resourceGroup().id, prefix)}' -var aoaiApiVersion = '2024-08-01-preview' - -resource openai 'Microsoft.CognitiveServices/accounts@2023-10-01-preview' = { - name: format(uniqueNameFormat, 'openai') - location: azureOpenAILocation - tags: tags - kind: 'OpenAI' - sku: { - name: 'S0' - } - properties: { - customSubDomainName: format(uniqueNameFormat, 'openai') - } - resource gpt4o 'deployments' = { - name: 'gpt-4o' - sku: { - name: 'GlobalStandard' - capacity: 15 - } - properties: { - model: { - format: 'OpenAI' - name: 'gpt-4o' - version: '2024-08-06' - } - versionUpgradeOption: 'NoAutoUpgrade' - } - } -} - -resource aoaiUserRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-05-01-preview' existing = { - name: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' //'Cognitive Services OpenAI User' -} - -resource devAoaiRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = if(!empty(trim(developerPrincipalId))) { - name: guid(developerPrincipalId, openai.id, aoaiUserRoleDefinition.id) - scope: openai - properties: { - principalId: developerPrincipalId - roleDefinitionId: aoaiUserRoleDefinition.id - principalType: 'User' - } -} - -resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2024-05-15' = { - name: format(uniqueNameFormat, 'cosmos') - location: cosmosLocation - tags: tags - kind: 'GlobalDocumentDB' - properties: { - databaseAccountOfferType: 'Standard' - enableFreeTier: false - locations: [ - { - failoverPriority: 0 - locationName: cosmosLocation - } - ] - capabilities: [ { name: 'EnableServerless' } ] - } - - resource contributorRoleDefinition 'sqlRoleDefinitions' existing = { - name: '00000000-0000-0000-0000-000000000002' - } - - resource devRoleAssignment 'sqlRoleAssignments' = if(!empty(trim(developerPrincipalId))) { - name: guid(developerPrincipalId, contributorRoleDefinition.id) - properties: { - principalId: developerPrincipalId - roleDefinitionId: contributorRoleDefinition.id - scope: cosmos.id - } - } - - resource autogenDb 'sqlDatabases' = { - name: 'autogen' - properties: { - resource: { - id: 'autogen' - createMode: 'Default' - } - } - - resource memoryContainer 'containers' = { - name: 'memory' - properties: { - resource: { - id: 'memory' - partitionKey: { - kind: 'Hash' - version: 2 - paths: [ - '/session_id' - ] - } - } - } - } - } -} - - - -output COSMOSDB_ENDPOINT string = cosmos.properties.documentEndpoint -output COSMOSDB_DATABASE string = cosmos::autogenDb.name -output COSMOSDB_CONTAINER string = cosmos::autogenDb::memoryContainer.name -output AZURE_OPENAI_ENDPOINT string = openai.properties.endpoint -output AZURE_OPENAI_DEPLOYMENT_NAME string = openai::gpt4o.name -output AZURE_OPENAI_API_VERSION string = aoaiApiVersion - diff --git a/infra/old/00-older/macae-large.bicepparam b/infra/old/00-older/macae-large.bicepparam deleted file mode 100644 index 3e88f4452..000000000 --- a/infra/old/00-older/macae-large.bicepparam +++ /dev/null @@ -1,11 +0,0 @@ -using './macae.bicep' - -param resourceSize = { - gpt4oCapacity: 50 - containerAppSize: { - cpu: '2.0' - memory: '4.0Gi' - minReplicas: 1 - maxReplicas: 1 - } -} diff --git a/infra/old/00-older/macae-mini.bicepparam b/infra/old/00-older/macae-mini.bicepparam deleted file mode 100644 index ee3d65127..000000000 --- a/infra/old/00-older/macae-mini.bicepparam +++ /dev/null @@ -1,11 +0,0 @@ -using './macae.bicep' - -param resourceSize = { - gpt4oCapacity: 15 - containerAppSize: { - cpu: '1.0' - memory: '2.0Gi' - minReplicas: 0 - maxReplicas: 1 - } -} diff --git a/infra/old/00-older/macae.bicep b/infra/old/00-older/macae.bicep deleted file mode 100644 index bfa56c9a1..000000000 --- a/infra/old/00-older/macae.bicep +++ /dev/null @@ -1,362 +0,0 @@ -@description('Location for all resources.') -param location string = resourceGroup().location - -@description('location for Cosmos DB resources.') -// prompt for this as there is often quota restrictions -param cosmosLocation string - -@description('Location for OpenAI resources.') -// prompt for this as there is often quota restrictions -param azureOpenAILocation string - -@description('A prefix to add to the start of all resource names. Note: A "unique" suffix will also be added') -param prefix string = 'macae' - -@description('Tags to apply to all deployed resources') -param tags object = {} - -@description('The size of the resources to deploy, defaults to a mini size') -param resourceSize { - gpt4oCapacity: int - containerAppSize: { - cpu: string - memory: string - minReplicas: int - maxReplicas: int - } -} = { - gpt4oCapacity: 50 - containerAppSize: { - cpu: '2.0' - memory: '4.0Gi' - minReplicas: 1 - maxReplicas: 1 - } -} - - -// var appVersion = 'latest' -// var resgistryName = 'biabcontainerreg' -// var dockerRegistryUrl = 'https://${resgistryName}.azurecr.io' -var placeholderImage = 'hello-world:latest' - -var uniqueNameFormat = '${prefix}-{0}-${uniqueString(resourceGroup().id, prefix)}' -var uniqueShortNameFormat = '${toLower(prefix)}{0}${uniqueString(resourceGroup().id, prefix)}' -//var aoaiApiVersion = '2024-08-01-preview' - - -resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2023-09-01' = { - name: format(uniqueNameFormat, 'logs') - location: location - tags: tags - properties: { - retentionInDays: 30 - sku: { - name: 'PerGB2018' - } - } -} - -resource appInsights 'Microsoft.Insights/components@2020-02-02-preview' = { - name: format(uniqueNameFormat, 'appins') - location: location - kind: 'web' - properties: { - Application_Type: 'web' - WorkspaceResourceId: logAnalytics.id - } -} - -resource openai 'Microsoft.CognitiveServices/accounts@2023-10-01-preview' = { - name: format(uniqueNameFormat, 'openai') - location: azureOpenAILocation - tags: tags - kind: 'OpenAI' - sku: { - name: 'S0' - } - properties: { - customSubDomainName: format(uniqueNameFormat, 'openai') - } - resource gpt4o 'deployments' = { - name: 'gpt-4o' - sku: { - name: 'GlobalStandard' - capacity: resourceSize.gpt4oCapacity - } - properties: { - model: { - format: 'OpenAI' - name: 'gpt-4o' - version: '2024-08-06' - } - versionUpgradeOption: 'NoAutoUpgrade' - } - } -} - -resource aoaiUserRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-05-01-preview' existing = { - name: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' //'Cognitive Services OpenAI User' -} - -resource acaAoaiRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(containerApp.id, openai.id, aoaiUserRoleDefinition.id) - scope: openai - properties: { - principalId: containerApp.identity.principalId - roleDefinitionId: aoaiUserRoleDefinition.id - principalType: 'ServicePrincipal' - } -} - -resource acr 'Microsoft.ContainerRegistry/registries@2023-11-01-preview' = { - name: format(uniqueShortNameFormat, 'acr') - location: location - sku: { - name: 'Standard' - } - properties: { - adminUserEnabled: true // Add this line - } -} - -resource pullIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-07-31-preview' = { - name: format(uniqueNameFormat, 'containerapp-pull') - location: location -} - -resource acrPullDefinition 'Microsoft.Authorization/roleDefinitions@2022-05-01-preview' existing = { - name: '7f951dda-4ed3-4680-a7ca-43fe172d538d' //'AcrPull' -} - -resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(acr.id, pullIdentity.id, acrPullDefinition.id) - properties: { - principalId: pullIdentity.properties.principalId - principalType: 'ServicePrincipal' - roleDefinitionId: acrPullDefinition.id - } -} - -resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2024-05-15' = { - name: format(uniqueNameFormat, 'cosmos') - location: cosmosLocation - tags: tags - kind: 'GlobalDocumentDB' - properties: { - databaseAccountOfferType: 'Standard' - enableFreeTier: false - locations: [ - { - failoverPriority: 0 - locationName: cosmosLocation - } - ] - capabilities: [ { name: 'EnableServerless' } ] - } - - resource contributorRoleDefinition 'sqlRoleDefinitions' existing = { - name: '00000000-0000-0000-0000-000000000002' - } - - resource autogenDb 'sqlDatabases' = { - name: 'autogen' - properties: { - resource: { - id: 'autogen' - createMode: 'Default' - } - } - - resource memoryContainer 'containers' = { - name: 'memory' - properties: { - resource: { - id: 'memory' - partitionKey: { - kind: 'Hash' - version: 2 - paths: [ - '/session_id' - ] - } - } - } - } - } -} - -resource containerAppEnv 'Microsoft.App/managedEnvironments@2024-03-01' = { - name: format(uniqueNameFormat, 'containerapp') - location: location - tags: tags - properties: { - daprAIConnectionString: appInsights.properties.ConnectionString - appLogsConfiguration: { - destination: 'log-analytics' - logAnalyticsConfiguration: { - customerId: logAnalytics.properties.customerId - sharedKey: logAnalytics.listKeys().primarySharedKey - } - } - } - resource aspireDashboard 'dotNetComponents@2024-02-02-preview' = { - name: 'aspire-dashboard' - properties: { - componentType: 'AspireDashboard' - } - } -} - -resource acaCosomsRoleAssignment 'Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments@2024-05-15' = { - name: guid(containerApp.id, cosmos::contributorRoleDefinition.id) - parent: cosmos - properties: { - principalId: containerApp.identity.principalId - roleDefinitionId: cosmos::contributorRoleDefinition.id - scope: cosmos.id - } -} - -@description('') -resource containerApp 'Microsoft.App/containerApps@2024-03-01' = { - name: '${prefix}-backend' - location: location - tags: tags - identity: { - type: 'SystemAssigned, UserAssigned' - userAssignedIdentities: { - '${pullIdentity.id}': {} - } - } - properties: { - managedEnvironmentId: containerAppEnv.id - configuration: { - ingress: { - targetPort: 8000 - external: true - corsPolicy: { - allowedOrigins: [ - 'https://${format(uniqueNameFormat, 'frontend')}.azurewebsites.net' - 'http://${format(uniqueNameFormat, 'frontend')}.azurewebsites.net' - ] - } - } - activeRevisionsMode: 'Single' - } - template: { - scale: { - minReplicas: resourceSize.containerAppSize.minReplicas - maxReplicas: resourceSize.containerAppSize.maxReplicas - rules: [ - { - name: 'http-scaler' - http: { - metadata: { - concurrentRequests: '100' - } - } - } - ] - } - containers: [ - { - name: 'backend' - image: placeholderImage - resources: { - cpu: json(resourceSize.containerAppSize.cpu) - memory: resourceSize.containerAppSize.memory - } - } - // env: [ - // { - // name: 'COSMOSDB_ENDPOINT' - // value: cosmos.properties.documentEndpoint - // } - // { - // name: 'COSMOSDB_DATABASE' - // value: cosmos::autogenDb.name - // } - // { - // name: 'COSMOSDB_CONTAINER' - // value: cosmos::autogenDb::memoryContainer.name - // } - // { - // name: 'AZURE_OPENAI_ENDPOINT' - // value: openai.properties.endpoint - // } - // { - // name: 'AZURE_OPENAI_DEPLOYMENT_NAME' - // value: openai::gpt4o.name - // } - // { - // name: 'AZURE_OPENAI_API_VERSION' - // value: aoaiApiVersion - // } - // { - // name: 'FRONTEND_SITE_NAME' - // value: 'https://${format(uniqueNameFormat, 'frontend')}.azurewebsites.net' - // } - // ] - // } - ] - } - - } - - } -resource frontendAppServicePlan 'Microsoft.Web/serverfarms@2021-02-01' = { - name: format(uniqueNameFormat, 'frontend-plan') - location: location - tags: tags - sku: { - name: 'P1v2' - capacity: 1 - tier: 'PremiumV2' - } - properties: { - reserved: true - } - kind: 'linux' // Add this line to support Linux containers -} - -resource frontendAppService 'Microsoft.Web/sites@2021-02-01' = { - name: format(uniqueNameFormat, 'frontend') - location: location - tags: tags - kind: 'app,linux,container' // Add this line - properties: { - serverFarmId: frontendAppServicePlan.id - reserved: true - siteConfig: { - linuxFxVersion:''//'DOCKER|${frontendDockerImageURL}' - appSettings: [ - { - name: 'DOCKER_REGISTRY_SERVER_URL' - value: acr.properties.loginServer - } - { - name: 'WEBSITES_PORT' - value: '3000' - } - { - name: 'WEBSITES_CONTAINER_START_TIME_LIMIT' // Add startup time limit - value: '1800' // 30 minutes, adjust as needed - } - { - name: 'BACKEND_API_URL' - value: 'https://${containerApp.properties.configuration.ingress.fqdn}' - } - ] - } - } - dependsOn: [containerApp] - identity: { - type: 'SystemAssigned, UserAssigned' - userAssignedIdentities: { - '${pullIdentity.id}': {} - } - } -} - -output cosmosAssignCli string = 'az cosmosdb sql role assignment create --resource-group "${resourceGroup().name}" --account-name "${cosmos.name}" --role-definition-id "${cosmos::contributorRoleDefinition.id}" --scope "${cosmos.id}" --principal-id "fill-in"' diff --git a/infra/old/00-older/main.bicep b/infra/old/00-older/main.bicep deleted file mode 100644 index 22f9bcd7e..000000000 --- a/infra/old/00-older/main.bicep +++ /dev/null @@ -1,1298 +0,0 @@ -extension graphV1 -//extension graphBeta - -metadata name = '' -metadata description = '' - -@description('Required. The prefix to add in the default names given to all deployed Azure resources.') -@maxLength(19) -param solutionPrefix string - -@description('Optional. Location for all Resources.') -param solutionLocation string = resourceGroup().location - -@description('Optional. Enable/Disable usage telemetry for module.') -param enableTelemetry bool - -@description('Optional. Enable/Disable usage telemetry for module.') -param enableNetworkSecurity bool - -@description('Optional. The tags to apply to all deployed Azure resources.') -param tags object = { - app: solutionPrefix - location: solutionLocation -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Log Analytics Workspace resource.') -param logAnalyticsWorkspaceConfiguration logAnalyticsWorkspaceConfigurationType = { - enabled: true - name: '${solutionPrefix}laws' - location: solutionLocation - sku: 'PerGB2018' - tags: tags - dataRetentionInDays: 30 -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Application Insights resource.') -param applicationInsightsConfiguration applicationInsightsConfigurationType = { - enabled: true - name: '${solutionPrefix}appi' - location: solutionLocation - tags: tags - retentionInDays: 30 -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Managed Identity resource.') -param userAssignedManagedIdentityConfiguration userAssignedManagedIdentityType = { - enabled: true - name: '${solutionPrefix}mgid' - location: solutionLocation - tags: tags -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the backend subnet.') -param networkSecurityGroupBackendConfiguration networkSecurityGroupConfigurationType = { - enabled: enableNetworkSecurity - name: '${solutionPrefix}nsgr-backend' - location: solutionLocation - tags: tags - securityRules: [ - // { - // name: 'DenySshRdpOutbound' //Azure Bastion - // properties: { - // priority: 200 - // access: 'Deny' - // protocol: '*' - // direction: 'Outbound' - // sourceAddressPrefix: 'VirtualNetwork' - // sourcePortRange: '*' - // destinationAddressPrefix: '*' - // destinationPortRanges: [ - // '3389' - // '22' - // ] - // } - // } - ] -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the containers subnet.') -param networkSecurityGroupContainersConfiguration networkSecurityGroupConfigurationType = { - enabled: enableNetworkSecurity - name: '${solutionPrefix}nsgr-containers' - location: solutionLocation - tags: tags - securityRules: [ - // { - // name: 'DenySshRdpOutbound' //Azure Bastion - // properties: { - // priority: 200 - // access: 'Deny' - // protocol: '*' - // direction: 'Outbound' - // sourceAddressPrefix: 'VirtualNetwork' - // sourcePortRange: '*' - // destinationAddressPrefix: '*' - // destinationPortRanges: [ - // '3389' - // '22' - // ] - // } - // } - ] -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the Bastion subnet.') -param networkSecurityGroupBastionConfiguration networkSecurityGroupConfigurationType = { - enabled: enableNetworkSecurity - name: '${solutionPrefix}nsgr-bastion' - location: solutionLocation - tags: tags - securityRules: [ - // { - // name: 'DenySshRdpOutbound' //Azure Bastion - // properties: { - // priority: 200 - // access: 'Deny' - // protocol: '*' - // direction: 'Outbound' - // sourceAddressPrefix: 'VirtualNetwork' - // sourcePortRange: '*' - // destinationAddressPrefix: '*' - // destinationPortRanges: [ - // '3389' - // '22' - // ] - // } - // } - ] -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the administration subnet.') -param networkSecurityGroupAdministrationConfiguration networkSecurityGroupConfigurationType = { - enabled: enableNetworkSecurity - name: '${solutionPrefix}nsgr-administration' - location: solutionLocation - tags: tags - securityRules: [ - // { - // name: 'DenySshRdpOutbound' //Azure Bastion - // properties: { - // priority: 200 - // access: 'Deny' - // protocol: '*' - // direction: 'Outbound - // sourceAddressPrefix: 'VirtualNetwork' - // sourcePortRange: '*' - // destinationAddressPrefix: '*' - // destinationPortRanges: [ - // '3389' - // '22' - // ] - // } - // } - ] -} - -@description('Optional. Configuration for the virtual machine.') -param virtualMachineConfiguration virtualMachineConfigurationType = { - enabled: enableNetworkSecurity - adminUsername: 'adminuser' - adminPassword: guid(solutionPrefix, subscription().subscriptionId) -} -var virtualMachineEnabled = virtualMachineConfiguration.?enabled ?? true - -@description('Optional. Configuration for the virtual machine.') -param virtualNetworkConfiguration virtualNetworkConfigurationType = { - enabled: enableNetworkSecurity -} -var virtualNetworkEnabled = virtualNetworkConfiguration.?enabled ?? true - -@description('Optional. The configuration of the Entra ID Application used to authenticate the website.') -param entraIdApplicationConfiguration entraIdApplicationConfigurationType = { - enabled: false -} - -@description('Optional. The UTC time deployment.') -param deploymentTime string = utcNow() - -// -// Add your parameters here -// - -// ============== // -// Resources // -// ============== // - -/* #disable-next-line no-deployments-resources -resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableTelemetry) { - name: '46d3xbcp.[[REPLACE WITH TELEMETRY IDENTIFIER]].${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' - } - } - } - } -} */ - -// ========== Log Analytics Workspace ========== // -// Log Analytics configuration defaults -var logAnalyticsWorkspaceEnabled = logAnalyticsWorkspaceConfiguration.?enabled ?? true -var logAnalyticsWorkspaceResourceName = logAnalyticsWorkspaceConfiguration.?name ?? '${solutionPrefix}-laws' -var logAnalyticsWorkspaceTags = logAnalyticsWorkspaceConfiguration.?tags ?? tags -var logAnalyticsWorkspaceLocation = logAnalyticsWorkspaceConfiguration.?location ?? solutionLocation -var logAnalyticsWorkspaceSkuName = logAnalyticsWorkspaceConfiguration.?sku ?? 'PerGB2018' -var logAnalyticsWorkspaceDataRetentionInDays = logAnalyticsWorkspaceConfiguration.?dataRetentionInDays ?? 30 -module logAnalyticsWorkspace 'br/public:avm/res/operational-insights/workspace:0.11.2' = if (logAnalyticsWorkspaceEnabled) { - name: take('operational-insights.workspace.${logAnalyticsWorkspaceResourceName}', 64) - params: { - name: logAnalyticsWorkspaceResourceName - tags: logAnalyticsWorkspaceTags - location: logAnalyticsWorkspaceLocation - enableTelemetry: enableTelemetry - skuName: logAnalyticsWorkspaceSkuName - dataRetention: logAnalyticsWorkspaceDataRetentionInDays - diagnosticSettings: [{ useThisWorkspace: true }] - } -} - -// ========== Application Insights ========== // -// Application Insights configuration defaults -var applicationInsightsEnabled = applicationInsightsConfiguration.?enabled ?? true -var applicationInsightsResourceName = applicationInsightsConfiguration.?name ?? '${solutionPrefix}appi' -var applicationInsightsTags = applicationInsightsConfiguration.?tags ?? tags -var applicationInsightsLocation = applicationInsightsConfiguration.?location ?? solutionLocation -var applicationInsightsRetentionInDays = applicationInsightsConfiguration.?retentionInDays ?? 365 -module applicationInsights 'br/public:avm/res/insights/component:0.6.0' = if (applicationInsightsEnabled) { - name: take('insights.component.${applicationInsightsResourceName}', 64) - params: { - name: applicationInsightsResourceName - workspaceResourceId: logAnalyticsWorkspace.outputs.resourceId - location: applicationInsightsLocation - enableTelemetry: enableTelemetry - tags: applicationInsightsTags - retentionInDays: applicationInsightsRetentionInDays - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspace.outputs.resourceId }] - kind: 'web' - disableIpMasking: false - flowType: 'Bluefield' - } -} - -// ========== User assigned identity Web App ========== // -var userAssignedManagedIdentityEnabled = userAssignedManagedIdentityConfiguration.?enabled ?? true -var userAssignedManagedIdentityResourceName = userAssignedManagedIdentityConfiguration.?name ?? '${solutionPrefix}uaid' -var userAssignedManagedIdentityTags = userAssignedManagedIdentityConfiguration.?tags ?? tags -var userAssignedManagedIdentityLocation = userAssignedManagedIdentityConfiguration.?location ?? solutionLocation -module userAssignedIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.4.1' = if (userAssignedManagedIdentityEnabled) { - name: take('managed-identity.user-assigned-identity.${userAssignedManagedIdentityResourceName}', 64) - params: { - name: userAssignedManagedIdentityResourceName - tags: userAssignedManagedIdentityTags - location: userAssignedManagedIdentityLocation - enableTelemetry: enableTelemetry - } -} - -// ========== Network Security Groups ========== // -var networkSecurityGroupBackendEnabled = networkSecurityGroupBackendConfiguration.?enabled ?? true -var networkSecurityGroupBackendResourceName = networkSecurityGroupBackendConfiguration.?name ?? '${solutionPrefix}nsgr-backend' -var networkSecurityGroupBackendTags = networkSecurityGroupBackendConfiguration.?tags ?? tags -var networkSecurityGroupBackendLocation = networkSecurityGroupBackendConfiguration.?location ?? solutionLocation -var networkSecurityGroupBackendSecurityRules = networkSecurityGroupBackendConfiguration.?securityRules ?? [ - // { - // name: 'DenySshRdpOutbound' //Azure Bastion - // properties: { - // priority: 200 - // access: 'Deny' - // protocol: '*' - // direction: 'Outbound' - // sourceAddressPrefix: 'VirtualNetwork' - // sourcePortRange: '*' - // destinationAddressPrefix: '*' - // destinationPortRanges: [ - // '3389' - // '22' - // ] - // } - // } -] -module networkSecurityGroupBackend 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupBackendEnabled) { - name: take('network.network-security-group.${networkSecurityGroupBackendResourceName}', 64) - params: { - name: networkSecurityGroupBackendResourceName - location: networkSecurityGroupBackendLocation - tags: networkSecurityGroupBackendTags - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspace.outputs.resourceId }] - securityRules: networkSecurityGroupBackendSecurityRules - } -} - -var networkSecurityGroupContainersEnabled = networkSecurityGroupContainersConfiguration.?enabled ?? true -var networkSecurityGroupContainersResourceName = networkSecurityGroupContainersConfiguration.?name ?? '${solutionPrefix}nsgr-containers' -var networkSecurityGroupContainersTags = networkSecurityGroupContainersConfiguration.?tags ?? tags -var networkSecurityGroupContainersLocation = networkSecurityGroupContainersConfiguration.?location ?? solutionLocation -var networkSecurityGroupContainersSecurityRules = networkSecurityGroupContainersConfiguration.?securityRules ?? [ - // { - // name: 'DenySshRdpOutbound' //Azure Bastion - // properties: { - // priority: 200 - // access: 'Deny' - // protocol: '*' - // direction: 'Outbound' - // sourceAddressPrefix: 'VirtualNetwork' - // sourcePortRange: '*' - // destinationAddressPrefix: '*' - // destinationPortRanges: [ - // '3389' - // '22' - // ] - // } - // } -] -module networkSecurityGroupContainers 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupContainersEnabled) { - name: take('network.network-security-group.${networkSecurityGroupContainersResourceName}', 64) - params: { - name: networkSecurityGroupContainersResourceName - location: networkSecurityGroupContainersLocation - tags: networkSecurityGroupContainersTags - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspace.outputs.resourceId }] - securityRules: networkSecurityGroupContainersSecurityRules - } -} - -var networkSecurityGroupBastionEnabled = networkSecurityGroupBastionConfiguration.?enabled ?? true -var networkSecurityGroupBastionResourceName = networkSecurityGroupBastionConfiguration.?name ?? '${solutionPrefix}nsgr-bastion' -var networkSecurityGroupBastionTags = networkSecurityGroupBastionConfiguration.?tags ?? tags -var networkSecurityGroupBastionLocation = networkSecurityGroupBastionConfiguration.?location ?? solutionLocation -var networkSecurityGroupBastionSecurityRules = networkSecurityGroupBastionConfiguration.?securityRules ?? [ - // { - // name: 'DenySshRdpOutbound' //Azure Bastion - // properties: { - // priority: 200 - // access: 'Deny' - // protocol: '*' - // direction: 'Outbound' - // sourceAddressPrefix: 'VirtualNetwork' - // sourcePortRange: '*' - // destinationAddressPrefix: '*' - // destinationPortRanges: [ - // '3389' - // '22' - // ] - // } - // } -] -module networkSecurityGroupBastion 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupBastionEnabled) { - name: take('network.network-security-group.${networkSecurityGroupBastionResourceName}', 64) - params: { - name: networkSecurityGroupBastionResourceName - location: networkSecurityGroupBastionLocation - tags: networkSecurityGroupBastionTags - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspace.outputs.resourceId }] - securityRules: networkSecurityGroupBastionSecurityRules - } -} - -var networkSecurityGroupAdministrationEnabled = networkSecurityGroupAdministrationConfiguration.?enabled ?? true -var networkSecurityGroupAdministrationResourceName = networkSecurityGroupAdministrationConfiguration.?name ?? '${solutionPrefix}nsgr-administration' -var networkSecurityGroupAdministrationTags = networkSecurityGroupAdministrationConfiguration.?tags ?? tags -var networkSecurityGroupAdministrationLocation = networkSecurityGroupAdministrationConfiguration.?location ?? solutionLocation -var networkSecurityGroupAdministrationSecurityRules = networkSecurityGroupAdministrationConfiguration.?securityRules ?? [ - // { - // name: 'DenySshRdpOutbound' //Azure Bastion - // properties: { - // priority: 200 - // access: 'Deny' - // protocol: '*' - // direction: 'Outbound' - // sourceAddressPrefix: 'VirtualNetwork' - // sourcePortRange: '*' - // destinationAddressPrefix: '*' - // destinationPortRanges: [ - // '3389' - // '22' - // ] - // } - // } -] -module networkSecurityGroupAdministration 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupAdministrationEnabled) { - name: take('network.network-security-group.${networkSecurityGroupAdministrationResourceName}', 64) - params: { - name: networkSecurityGroupAdministrationResourceName - location: networkSecurityGroupAdministrationLocation - tags: networkSecurityGroupAdministrationTags - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspace.outputs.resourceId }] - securityRules: networkSecurityGroupAdministrationSecurityRules - } -} - -// ========== Virtual Network ========== // - -module virtualNetwork 'br/public:avm/res/network/virtual-network:0.6.1' = if (virtualNetworkEnabled) { - name: 'network-virtual-network' - params: { - name: '${solutionPrefix}vnet' - location: solutionLocation - tags: tags - enableTelemetry: enableTelemetry - addressPrefixes: ['10.0.0.0/8'] - subnets: [ - // The default subnet **must** be the first in the subnets array - { - name: 'backend' - addressPrefix: '10.0.0.0/27' - //defaultOutboundAccess: false TODO: check this configuration for a more restricted outbound access - networkSecurityGroupResourceId: networkSecurityGroupBackend.outputs.resourceId - } - { - name: 'administration' - addressPrefix: '10.0.0.32/27' - networkSecurityGroupResourceId: networkSecurityGroupAdministration.outputs.resourceId - //defaultOutboundAccess: false TODO: check this configuration for a more restricted outbound access - //natGatewayResourceId: natGateway.outputs.resourceId - } - { - // For Azure Bastion resources deployed on or after November 2, 2021, the minimum AzureBastionSubnet size is /26 or larger (/25, /24, etc.). - // https://learn.microsoft.com/en-us/azure/bastion/configuration-settings#subnet - name: 'AzureBastionSubnet' //This exact name is required for Azure Bastion - addressPrefix: '10.0.0.64/26' - networkSecurityGroupResourceId: networkSecurityGroupBastion.outputs.resourceId - } - { - // If you use your own VNet, you need to provide a subnet that is dedicated exclusively to the Container App environment you deploy. This subnet isn't available to other services - // https://learn.microsoft.com/en-us/azure/container-apps/networking?tabs=workload-profiles-env%2Cazure-cli#custom-vnet-configuration - name: 'containers' - addressPrefix: '10.0.1.0/23' //subnet of size /23 is required for container app - //defaultOutboundAccess: false TODO: check this configuration for a more restricted outbound access - delegation: 'Microsoft.App/environments' - networkSecurityGroupResourceId: networkSecurityGroupContainers.outputs.resourceId - privateEndpointNetworkPolicies: 'Disabled' - privateLinkServiceNetworkPolicies: 'Enabled' - } - ] - } -} - -// ========== Bastion host ========== // - -module bastionHost 'br/public:avm/res/network/bastion-host:0.6.1' = if (virtualNetworkEnabled) { - name: 'network-dns-zone-bastion-host' - params: { - name: '${solutionPrefix}bstn' - location: solutionLocation - skuName: 'Standard' - enableTelemetry: enableTelemetry - tags: tags - virtualNetworkResourceId: virtualNetwork.outputs.resourceId - publicIPAddressObject: { - name: '${solutionPrefix}pbipbstn' - } - disableCopyPaste: false - enableFileCopy: false - enableIpConnect: true - //enableKerberos: bastionConfiguration.?enableKerberos - enableShareableLink: true - //scaleUnits: bastionConfiguration.?scaleUnits - } -} - -// ========== Virtual machine ========== // - -module virtualMachine 'br/public:avm/res/compute/virtual-machine:0.13.0' = if (virtualNetworkEnabled && virtualMachineEnabled) { - name: 'compute-virtual-machine' - params: { - name: '${solutionPrefix}vmws' - computerName: take('${solutionPrefix}vmws', 15) - location: solutionLocation - tags: tags - enableTelemetry: enableTelemetry - adminUsername: virtualMachineConfiguration.?adminUsername! - adminPassword: virtualMachineConfiguration.?adminPassword! - nicConfigurations: [ - { - //networkSecurityGroupResourceId: virtualMachineConfiguration.?nicConfigurationConfiguration.networkSecurityGroupResourceId - nicSuffix: 'nic01' - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspace.outputs.resourceId }] - ipConfigurations: [ - { - name: 'ipconfig01' - subnetResourceId: virtualNetwork.outputs.subnetResourceIds[1] - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspace.outputs.resourceId }] - } - ] - } - ] - imageReference: { - publisher: 'microsoft-dsvm' - offer: 'dsvm-win-2022' - sku: 'winserver-2022' - version: 'latest' - } - osDisk: { - createOption: 'FromImage' - managedDisk: { - storageAccountType: 'Premium_ZRS' - } - diskSizeGB: 128 - caching: 'ReadWrite' - } - //patchMode: virtualMachineConfiguration.?patchMode - osType: 'Windows' - encryptionAtHost: false //The property 'securityProfile.encryptionAtHost' is not valid because the 'Microsoft.Compute/EncryptionAtHost' feature is not enabled for this subscription. - vmSize: 'Standard_D2s_v4' - zone: 0 - extensionAadJoinConfig: { - enabled: true - typeHandlerVersion: '1.0' - } - // extensionMonitoringAgentConfig: { - // enabled: true - // } - // maintenanceConfigurationResourceId: virtualMachineConfiguration.?maintenanceConfigurationResourceId - } -} -// ========== DNS Zone for AI Foundry: Open AI ========== // -var openAiSubResource = 'account' -var openAiPrivateDnsZones = { - 'privatelink.cognitiveservices.azure.com': openAiSubResource - 'privatelink.openai.azure.com': openAiSubResource - 'privatelink.services.ai.azure.com': openAiSubResource -} - -module privateDnsZonesAiServices 'br/public:avm/res/network/private-dns-zone:0.7.1' = [ - for zone in objectKeys(openAiPrivateDnsZones): if (virtualNetworkEnabled) { - name: 'network-dns-zone-${uniqueString(deployment().name, zone)}' - params: { - name: zone - tags: tags - enableTelemetry: enableTelemetry - virtualNetworkLinks: [{ virtualNetworkResourceId: virtualNetwork.outputs.resourceId }] - } - } -] - -// ========== AI Foundry: AI Services ========== -// NOTE: Required version 'Microsoft.CognitiveServices/accounts@2024-04-01-preview' not available in AVM -var aiFoundryAiServicesModelDeployment = { - format: 'OpenAI' - name: 'gpt-4o' - version: '2024-08-06' - sku: { - name: 'GlobalStandard' - capacity: 50 - } - raiPolicyName: 'Microsoft.Default' -} - -var aiFoundryAiServicesAccountName = '${solutionPrefix}aifdaisv' -module aiFoundryAiServices 'br/public:avm/res/cognitive-services/account:0.10.2' = { - name: 'cognitive-services-account' - params: { - name: aiFoundryAiServicesAccountName - tags: tags - location: solutionLocation - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspace.outputs.resourceId }] - sku: 'S0' - kind: 'AIServices' - disableLocalAuth: false //Should be set to true for WAF aligned configuration - customSubDomainName: aiFoundryAiServicesAccountName - apiProperties: { - //staticsEnabled: false - } - //publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled' - publicNetworkAccess: 'Enabled' //TODO: connection via private endpoint is not working from containers network. Change this when fixed - privateEndpoints: virtualNetworkEnabled - ? ([ - { - subnetResourceId: virtualNetwork.outputs.subnetResourceIds[0] - privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: map(objectKeys(openAiPrivateDnsZones), zone => { - name: replace(zone, '.', '-') - privateDnsZoneResourceId: resourceId('Microsoft.Network/privateDnsZones', zone) - }) - } - } - ]) - : [] - roleAssignments: [ - // { - // principalId: userAssignedIdentity.outputs.principalId - // principalType: 'ServicePrincipal' - // roleDefinitionIdOrName: 'Cognitive Services OpenAI User' - // } - { - principalId: containerApp.outputs.?systemAssignedMIPrincipalId! - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'Cognitive Services OpenAI User' - } - ] - deployments: [ - { - name: aiFoundryAiServicesModelDeployment.name - model: { - format: aiFoundryAiServicesModelDeployment.format - name: aiFoundryAiServicesModelDeployment.name - version: aiFoundryAiServicesModelDeployment.version - } - raiPolicyName: aiFoundryAiServicesModelDeployment.raiPolicyName - sku: { - name: aiFoundryAiServicesModelDeployment.sku.name - capacity: aiFoundryAiServicesModelDeployment.sku.capacity - } - } - ] - } -} - -// AI Foundry: storage account - -var storageAccountPrivateDnsZones = { - 'privatelink.blob.${environment().suffixes.storage}': 'blob' - 'privatelink.file.${environment().suffixes.storage}': 'file' -} - -module privateDnsZonesAiFoundryStorageAccount 'br/public:avm/res/network/private-dns-zone:0.3.1' = [ - for zone in objectKeys(storageAccountPrivateDnsZones): if (virtualNetworkEnabled) { - name: 'network-dns-zone-aifd-stac-${zone}' - params: { - name: zone - tags: tags - enableTelemetry: enableTelemetry - virtualNetworkLinks: [ - { - virtualNetworkResourceId: virtualNetwork.outputs.resourceId - } - ] - } - } -] - -var aiFoundryStorageAccountName = '${solutionPrefix}aifdstrg' -module aiFoundryStorageAccount 'br/public:avm/res/storage/storage-account:0.18.2' = { - name: 'storage-storage-account' - dependsOn: [ - privateDnsZonesAiFoundryStorageAccount - ] - params: { - name: aiFoundryStorageAccountName - location: solutionLocation - tags: tags - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspace.outputs.resourceId }] - skuName: 'Standard_LRS' - allowSharedKeyAccess: false - networkAcls: { - bypass: 'AzureServices' - defaultAction: 'Allow' - } - blobServices: { - deleteRetentionPolicyEnabled: false - containerDeleteRetentionPolicyDays: 7 - containerDeleteRetentionPolicyEnabled: false - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspace.outputs.resourceId }] - } - publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled' - allowBlobPublicAccess: virtualNetworkEnabled ? false : true - privateEndpoints: virtualNetworkEnabled - ? map(items(storageAccountPrivateDnsZones), zone => { - name: 'pep-${zone.value}-${aiFoundryStorageAccountName}' - customNetworkInterfaceName: 'nic-${zone.value}-${aiFoundryStorageAccountName}' - service: zone.value - subnetResourceId: virtualNetwork.outputs.subnetResourceIds[0] ?? '' - privateDnsZoneResourceIds: [resourceId('Microsoft.Network/privateDnsZones', zone.key)] - }) - : null - roleAssignments: [ - { - principalId: userAssignedIdentity.outputs.principalId - roleDefinitionIdOrName: 'Storage Blob Data Contributor' - principalType: 'ServicePrincipal' - } - ] - } -} - -// AI Foundry: AI Hub -var mlTargetSubResource = 'amlworkspace' -var mlPrivateDnsZones = { - 'privatelink.api.azureml.ms': mlTargetSubResource - 'privatelink.notebooks.azure.net': mlTargetSubResource -} -module privateDnsZonesAiFoundryWorkspaceHub 'br/public:avm/res/network/private-dns-zone:0.3.1' = [ - for zone in objectKeys(mlPrivateDnsZones): if (virtualNetworkEnabled) { - name: 'network-dns-zone-${zone}' - params: { - name: zone - enableTelemetry: enableTelemetry - tags: tags - virtualNetworkLinks: [ - { - virtualNetworkResourceId: virtualNetwork.outputs.resourceId - } - ] - } - } -] -var aiFoundryAiHubName = '${solutionPrefix}aifdaihb' -module aiFoundryAiHub 'modules/ai-hub.bicep' = { - name: 'modules-ai-hub' - dependsOn: [ - privateDnsZonesAiFoundryWorkspaceHub - ] - params: { - name: aiFoundryAiHubName - location: solutionLocation - tags: tags - aiFoundryAiServicesName: aiFoundryAiServices.outputs.name - applicationInsightsResourceId: applicationInsights.outputs.resourceId - enableTelemetry: enableTelemetry - logAnalyticsWorkspaceResourceId: logAnalyticsWorkspace.outputs.resourceId - storageAccountResourceId: aiFoundryStorageAccount.outputs.resourceId - virtualNetworkEnabled: virtualNetworkEnabled - privateEndpoints: virtualNetworkEnabled - ? [ - { - name: 'pep-${mlTargetSubResource}-${aiFoundryAiHubName}' - customNetworkInterfaceName: 'nic-${mlTargetSubResource}-${aiFoundryAiHubName}' - service: mlTargetSubResource - subnetResourceId: virtualNetworkEnabled ? virtualNetwork.?outputs.?subnetResourceIds[0] : null - privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: map(objectKeys(mlPrivateDnsZones), zone => { - name: replace(zone, '.', '-') - privateDnsZoneResourceId: resourceId('Microsoft.Network/privateDnsZones', zone) - }) - } - } - ] - : [] - } -} - -// AI Foundry: AI Project -var aiFoundryAiProjectName = '${solutionPrefix}aifdaipj' - -module aiFoundryAiProject 'br/public:avm/res/machine-learning-services/workspace:0.12.0' = { - name: 'machine-learning-services-workspace-project' - params: { - name: aiFoundryAiProjectName - location: solutionLocation - tags: tags - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspace.outputs.resourceId }] - sku: 'Basic' - kind: 'Project' - hubResourceId: aiFoundryAiHub.outputs.resourceId - roleAssignments: [ - { - principalId: containerApp.outputs.?systemAssignedMIPrincipalId! - // Assigning the role with the role name instead of the role ID freezes the deployment at this point - roleDefinitionIdOrName: '64702f94-c441-49e6-a78b-ef80e0188fee' //'Azure AI Developer' - principalType: 'ServicePrincipal' - } - ] - } -} - -// ========== DNS Zone for Cosmos DB ========== // -module privateDnsZonesCosmosDb 'br/public:avm/res/network/private-dns-zone:0.7.0' = if (virtualNetworkEnabled) { - name: 'network-dns-zone-cosmos-db' - params: { - name: 'privatelink.documents.azure.com' - enableTelemetry: enableTelemetry - virtualNetworkLinks: [{ virtualNetworkResourceId: virtualNetwork.outputs.resourceId }] - tags: tags - } -} - -// ========== Cosmos DB ========== // -var cosmosDbName = '${solutionPrefix}csdb' -var cosmosDbDatabaseName = 'autogen' -var cosmosDbDatabaseMemoryContainerName = 'memory' -module cosmosDb 'br/public:avm/res/document-db/database-account:0.12.0' = { - name: 'cosmos-db' - params: { - // Required parameters - name: cosmosDbName - tags: tags - location: solutionLocation - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspace.outputs.resourceId }] - databaseAccountOfferType: 'Standard' - enableFreeTier: false - networkRestrictions: { - networkAclBypass: 'None' - publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled' - } - privateEndpoints: virtualNetworkEnabled - ? [ - { - privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: [{ privateDnsZoneResourceId: privateDnsZonesCosmosDb.outputs.resourceId }] - } - service: 'Sql' - subnetResourceId: virtualNetwork.outputs.subnetResourceIds[0] - } - ] - : [] - sqlDatabases: [ - { - name: cosmosDbDatabaseName - containers: [ - { - name: cosmosDbDatabaseMemoryContainerName - paths: [ - '/session_id' - ] - kind: 'Hash' - version: 2 - } - ] - } - ] - locations: [ - { - locationName: solutionLocation - failoverPriority: 0 - } - ] - capabilitiesToAdd: [ - 'EnableServerless' - ] - sqlRoleAssignmentsPrincipalIds: [ - //userAssignedIdentity.outputs.principalId - containerApp.outputs.?systemAssignedMIPrincipalId - ] - sqlRoleDefinitions: [ - { - // Replace this with built-in role definition Cosmos DB Built-in Data Contributor: https://docs.azure.cn/en-us/cosmos-db/nosql/security/reference-data-plane-roles#cosmos-db-built-in-data-contributor - roleType: 'CustomRole' - roleName: 'Cosmos DB SQL Data Contributor' - name: 'cosmos-db-sql-data-contributor' - dataAction: [ - 'Microsoft.DocumentDB/databaseAccounts/readMetadata' - 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*' - 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*' - ] - } - ] - } -} - -// ========== Backend Container App Environment ========== // - -module containerAppEnvironment 'modules/container-app-environment.bicep' = { - name: 'modules-container-app-environment' - params: { - name: '${solutionPrefix}cenv' - tags: tags - location: solutionLocation - logAnalyticsResourceName: logAnalyticsWorkspace.outputs.name - publicNetworkAccess: 'Enabled' - zoneRedundant: virtualNetworkEnabled ? true : false - aspireDashboardEnabled: !virtualNetworkEnabled - vnetConfiguration: virtualNetworkEnabled - ? { - internal: false - infrastructureSubnetId: virtualNetwork.?outputs.?subnetResourceIds[2] ?? '' - } - : {} - } -} - -// module containerAppEnvironment 'br/public:avm/res/app/managed-environment:0.11.0' = { -// name: 'container-app-environment' -// params: { -// name: '${solutionPrefix}cenv' -// location: solutionLocation -// tags: tags -// enableTelemetry: enableTelemetry -// //daprAIConnectionString: applicationInsights.outputs.connectionString //Troubleshoot: ContainerAppsConfiguration.DaprAIConnectionString is invalid. DaprAIConnectionString can not be set when AppInsightsConfiguration has been set, please set DaprAIConnectionString to null. (Code:InvalidRequestParameterWithDetails -// appLogsConfiguration: { -// destination: 'log-analytics' -// logAnalyticsConfiguration: { -// customerId: logAnalyticsWorkspace.outputs.logAnalyticsWorkspaceId -// sharedKey: listKeys( -// '${resourceGroup().id}/providers/Microsoft.OperationalInsights/workspaces/${logAnalyticsWorkspaceName}', -// '2023-09-01' -// ).primarySharedKey -// } -// } -// appInsightsConnectionString: applicationInsights.outputs.connectionString -// publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled' //TODO: use Azure Front Door WAF or Application Gateway WAF instead -// zoneRedundant: true //TODO: make it zone redundant for waf aligned -// infrastructureSubnetResourceId: virtualNetworkEnabled -// ? virtualNetwork.outputs.subnetResourceIds[1] -// : null -// internal: false -// } -// } - -// ========== Backend Container App Service ========== // -module containerApp 'br/public:avm/res/app/container-app:0.14.2' = { - name: 'container-app' - params: { - name: '${solutionPrefix}capp' - tags: tags - location: solutionLocation - enableTelemetry: enableTelemetry - //environmentResourceId: containerAppEnvironment.outputs.resourceId - environmentResourceId: containerAppEnvironment.outputs.resourceId - managedIdentities: { - systemAssigned: true //Replace with user assigned identity - userAssignedResourceIds: [userAssignedIdentity.outputs.resourceId] - } - ingressTargetPort: 8000 - ingressExternal: true - activeRevisionsMode: 'Single' - corsPolicy: { - allowedOrigins: [ - 'https://${webSiteName}.azurewebsites.net' - 'http://${webSiteName}.azurewebsites.net' - ] - } - scaleSettings: { - //TODO: Make maxReplicas and minReplicas parameterized - maxReplicas: 1 - minReplicas: 1 - rules: [ - { - name: 'http-scaler' - http: { - metadata: { - concurrentRequests: '100' - } - } - } - ] - } - containers: [ - { - name: 'backend' - //TODO: Make image parameterized for the registry name and the appversion - image: 'biabcontainerreg.azurecr.io/macaebackend:fnd01' - resources: { - //TODO: Make cpu and memory parameterized - cpu: '2.0' - memory: '4.0Gi' - } - env: [ - { - name: 'COSMOSDB_ENDPOINT' - value: 'https://${cosmosDbName}.documents.azure.com:443/' - } - { - name: 'COSMOSDB_DATABASE' - value: cosmosDbDatabaseName - } - { - name: 'COSMOSDB_CONTAINER' - value: cosmosDbDatabaseMemoryContainerName - } - { - name: 'AZURE_OPENAI_ENDPOINT' - value: 'https://${aiFoundryAiServicesAccountName}.openai.azure.com/' - } - { - name: 'AZURE_OPENAI_MODEL_NAME' - value: aiFoundryAiServicesModelDeployment.name - } - { - name: 'AZURE_OPENAI_DEPLOYMENT_NAME' - value: aiFoundryAiServicesModelDeployment.name - } - { - name: 'AZURE_OPENAI_API_VERSION' - value: '2025-01-01-preview' //TODO: set parameter/variable - } - { - name: 'APPLICATIONINSIGHTS_INSTRUMENTATION_KEY' - value: applicationInsights.outputs.instrumentationKey - } - { - name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' - value: applicationInsights.outputs.connectionString - } - { - name: 'AZURE_AI_AGENT_PROJECT_CONNECTION_STRING' - value: '${toLower(replace(solutionLocation,' ',''))}.api.azureml.ms;${subscription().subscriptionId};${resourceGroup().name};${aiFoundryAiProjectName}' - //Location should be the AI Foundry AI Project location - } - { - name: 'AZURE_AI_SUBSCRIPTION_ID' - value: subscription().subscriptionId - } - { - name: 'AZURE_AI_RESOURCE_GROUP' - value: resourceGroup().name - } - { - name: 'AZURE_AI_PROJECT_NAME' - value: aiFoundryAiProjectName - } - { - name: 'FRONTEND_SITE_NAME' - value: 'https://${webSiteName}.azurewebsites.net' - } - ] - } - ] - } -} - -// ========== Frontend server farm ========== // -module webServerfarm 'br/public:avm/res/web/serverfarm:0.4.1' = { - name: 'web-server-farm' - params: { - tags: tags - location: solutionLocation - name: '${solutionPrefix}sfrm' - skuName: 'P1v2' - skuCapacity: 1 - reserved: true - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspace.outputs.resourceId }] - kind: 'linux' - zoneRedundant: false //TODO: make it zone redundant for waf aligned - } -} - -// ========== Entra ID Application ========== // -resource entraIdApplication 'Microsoft.Graph/applications@v1.0' = if (entraIdApplicationConfiguration.?enabled!) { - displayName: '${webSiteName}-app' - uniqueName: '${webSiteName}-app-${uniqueString(resourceGroup().id, webSiteName)}' - description: 'EntraId Application for ${webSiteName} authentication' - passwordCredentials: [ - { - displayName: 'Credential for website ${webSiteName}' - endDateTime: dateTimeAdd(deploymentTime, 'P180D') - // keyId: 'string' - // startDateTime: 'string' - } - ] -} - -var graphAppId = '00000003-0000-0000-c000-000000000000' //Microsoft Graph ID -// Get the Microsoft Graph service principal so that the scope names can be looked up and mapped to a permission ID -resource msGraphSP 'Microsoft.Graph/servicePrincipals@v1.0' existing = { - appId: graphAppId -} - -// ========== Entra ID Service Principal ========== // -resource entraIdServicePrincipal 'Microsoft.Graph/servicePrincipals@v1.0' = if (entraIdApplicationConfiguration.?enabled!) { - appId: entraIdApplication.appId -} - -// Grant the OAuth2.0 scopes (requested in parameters) to the basic app, for all users in the tenant -resource graphScopesAssignment 'Microsoft.Graph/oauth2PermissionGrants@v1.0' = if (entraIdApplicationConfiguration.?enabled!) { - clientId: entraIdServicePrincipal.id - resourceId: msGraphSP.id - consentType: 'AllPrincipals' - scope: 'User.Read' -} - -// ========== Frontend web site ========== // -var webSiteName = '${solutionPrefix}wapp' -var entraIdApplicationCredentialSecretSettingName = 'MICROSOFT_PROVIDER_AUTHENTICATION_SECRET' -module webSite 'br/public:avm/res/web/site:0.15.1' = { - name: 'web-site' - params: { - tags: tags - kind: 'app,linux,container' - name: webSiteName - location: solutionLocation - serverFarmResourceId: webServerfarm.outputs.resourceId - appInsightResourceId: applicationInsights.outputs.resourceId - siteConfig: { - linuxFxVersion: 'DOCKER|biabcontainerreg.azurecr.io/macaefrontend:fnd01' - } - publicNetworkAccess: 'Enabled' //TODO: use Azure Front Door WAF or Application Gateway WAF instead - //privateEndpoints: [{ subnetResourceId: virtualNetwork.outputs.subnetResourceIds[0] }] - //Not required, this resource only serves a static website - appSettingsKeyValuePairs: union( - { - SCM_DO_BUILD_DURING_DEPLOYMENT: 'true' - DOCKER_REGISTRY_SERVER_URL: 'https://biabcontainerreg.azurecr.io' - WEBSITES_PORT: '3000' - WEBSITES_CONTAINER_START_TIME_LIMIT: '1800' // 30 minutes, adjust as needed - BACKEND_API_URL: 'https://${containerApp.outputs.fqdn}' - AUTH_ENABLED: 'false' - }, - (entraIdApplicationConfiguration.?enabled! - ? { '${entraIdApplicationCredentialSecretSettingName}': entraIdApplication.passwordCredentials[0].secretText } - : {}) - ) - authSettingV2Configuration: { - platform: { - enabled: entraIdApplicationConfiguration.?enabled! - runtimeVersion: '~1' - } - login: { - cookieExpiration: { - convention: 'FixedTime' - timeToExpiration: '08:00:00' - } - nonce: { - nonceExpirationInterval: '00:05:00' - validateNonce: true - } - preserveUrlFragmentsForLogins: false - routes: {} - tokenStore: { - azureBlobStorage: {} - enabled: true - fileSystem: {} - tokenRefreshExtensionHours: 72 - } - } - globalValidation: { - requireAuthentication: true - unauthenticatedClientAction: 'RedirectToLoginPage' - redirectToProvider: 'azureactivedirectory' - } - httpSettings: { - forwardProxy: { - convention: 'NoProxy' - } - requireHttps: true - routes: { - apiPrefix: '/.auth' - } - } - identityProviders: { - azureActiveDirectory: entraIdApplicationConfiguration.?enabled! - ? { - isAutoProvisioned: true - enabled: true - login: { - disableWWWAuthenticate: false - } - registration: { - clientId: entraIdApplication.appId //create application in AAD - clientSecretSettingName: entraIdApplicationCredentialSecretSettingName - openIdIssuer: 'https://sts.windows.net/${tenant().tenantId}/v2.0/' - } - validation: { - allowedAudiences: [ - 'api://${entraIdApplication.appId}' - ] - defaultAuthorizationPolicy: { - allowedPrincipals: {} - allowedApplications: ['86e2d249-6832-461f-8888-cfa0394a5f8c'] - } - jwtClaimChecks: {} - } - } - : {} - } - } - } -} - -// ============ // -// Outputs // -// ============ // - -// Add your outputs here - -// @description('The resource ID of the resource.') -// output resourceId string = .id - -// @description('The name of the resource.') -// output name string = .name - -// @description('The location the resource was deployed into.') -// output location string = .location - -// ================ // -// Definitions // -// ================ // -// -// Add your User-defined-types here, if any -// - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Log Analytics Workspace resource configuration.') -type logAnalyticsWorkspaceConfigurationType = { - @description('Optional. If the Log Analytics Workspace resource should be enabled or not.') - enabled: bool? - - @description('Optional. The name of the Log Analytics Workspace resource.') - @maxLength(63) - name: string? - - @description('Optional. Location for the Log Analytics Workspace resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to for the Log Analytics Workspace resource.') - tags: object? - - @description('Optional. The SKU for the Log Analytics Workspace resource.') - sku: ('CapacityReservation' | 'Free' | 'LACluster' | 'PerGB2018' | 'PerNode' | 'Premium' | 'Standalone' | 'Standard')? - - @description('Optional. The number of days to retain the data in the Log Analytics Workspace. If empty, it will be set to 30 days.') - @maxValue(730) - dataRetentionInDays: int? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Application Insights resource configuration.') -type applicationInsightsConfigurationType = { - @description('Optional. If the Application Insights resource should be enabled or not.') - enabled: bool? - - @description('Optional. The name of the Application Insights resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the Application Insights resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Application Insights resource.') - tags: object? - - @description('Optional. The retention of Application Insights data in days. If empty, Standard will be used.') - retentionInDays: (120 | 180 | 270 | 30 | 365 | 550 | 60 | 730 | 90)? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Application User Assigned Managed Identity resource configuration.') -type userAssignedManagedIdentityType = { - @description('Optional. If the User Assigned Managed Identity resource should be enabled or not.') - enabled: bool? - - @description('Optional. The name of the User Assigned Managed Identity resource.') - @maxLength(128) - name: string? - - @description('Optional. Location for the User Assigned Managed Identity resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the User Assigned Managed Identity resource.') - tags: object? -} - -@export() -import { securityRuleType } from 'br/public:avm/res/network/network-security-group:0.5.1' -@description('The type for the Multi-Agent Custom Automation Engine Network Security Group resource configuration.') -type networkSecurityGroupConfigurationType = { - @description('Optional. If the Network Security Group resource should be enabled or not.') - enabled: bool? - - @description('Optional. The name of the Network Security Group resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the Network Security Group resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Network Security Group resource.') - tags: object? - - @description('Optional. The security rules to set for the Network Security Group resource.') - securityRules: securityRuleType[]? -} - -@export() -@description('The type for the Multi-Agent Custom Automation virtual machine resource configuration.') -type virtualMachineConfigurationType = { - @description('Optional. If the Virtual Machine resource should be enabled or not.') - enabled: bool? - - @description('Required. The username for the administrator account on the virtual machine. Required if a virtual machine is created as part of the module.') - adminUsername: string? - - @description('Required. The password for the administrator account on the virtual machine. Required if a virtual machine is created as part of the module.') - @secure() - adminPassword: string? -} - -@export() -@description('The type for the Multi-Agent Custom Automation virtual network resource configuration.') -type virtualNetworkConfigurationType = { - @description('Optional. If the Virtual Network resource should be enabled or not.') - enabled: bool? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Entra ID Application resource configuration.') -type entraIdApplicationConfigurationType = { - @description('Optional. If the Entra ID Application for website authentication should be enabled or not.') - enabled: bool? -} diff --git a/infra/old/00-older/main2.bicep b/infra/old/00-older/main2.bicep deleted file mode 100644 index 9d9f3f1ca..000000000 --- a/infra/old/00-older/main2.bicep +++ /dev/null @@ -1,54 +0,0 @@ -targetScope = 'subscription' - -@minLength(1) -@maxLength(64) -@description('Name of the environment that can be used as part of naming resource convention') -param environmentName string - -@minLength(1) -@description('Primary location for all resources') -param location string - -param backendExists bool -@secure() -param backendDefinition object -param frontendExists bool -@secure() -param frontendDefinition object - -@description('Id of the user or app to assign application roles') -param principalId string - -// Tags that should be applied to all resources. -// -// Note that 'azd-service-name' tags should be applied separately to service host resources. -// Example usage: -// tags: union(tags, { 'azd-service-name': }) -var tags = { - 'azd-env-name': environmentName -} - -// Organize resources in a resource group -resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: 'rg-${environmentName}' - location: location - tags: tags -} - -module resources 'resources.bicep' = { - scope: rg - name: 'resources' - params: { - location: location - tags: tags - principalId: principalId - backendExists: backendExists - backendDefinition: backendDefinition - frontendExists: frontendExists - frontendDefinition: frontendDefinition - } -} - -output AZURE_CONTAINER_REGISTRY_ENDPOINT string = resources.outputs.AZURE_CONTAINER_REGISTRY_ENDPOINT -output AZURE_RESOURCE_BACKEND_ID string = resources.outputs.AZURE_RESOURCE_BACKEND_ID -output AZURE_RESOURCE_FRONTEND_ID string = resources.outputs.AZURE_RESOURCE_FRONTEND_ID diff --git a/infra/old/00-older/resources.bicep b/infra/old/00-older/resources.bicep deleted file mode 100644 index 3c9a580c2..000000000 --- a/infra/old/00-older/resources.bicep +++ /dev/null @@ -1,242 +0,0 @@ -@description('The location used for all deployed resources') -param location string = resourceGroup().location - -@description('Tags that will be applied to all resources') -param tags object = {} - - -param backendExists bool -@secure() -param backendDefinition object -param frontendExists bool -@secure() -param frontendDefinition object - -@description('Id of the user or app to assign application roles') -param principalId string - -var abbrs = loadJsonContent('./abbreviations.json') -var resourceToken = uniqueString(subscription().id, resourceGroup().id, location) - -// Monitor application with Azure Monitor -module monitoring 'br/public:avm/ptn/azd/monitoring:0.1.0' = { - name: 'monitoring' - params: { - logAnalyticsName: '${abbrs.operationalInsightsWorkspaces}${resourceToken}' - applicationInsightsName: '${abbrs.insightsComponents}${resourceToken}' - applicationInsightsDashboardName: '${abbrs.portalDashboards}${resourceToken}' - location: location - tags: tags - } -} - -// Container registry -module containerRegistry 'br/public:avm/res/container-registry/registry:0.1.1' = { - name: 'registry' - params: { - name: '${abbrs.containerRegistryRegistries}${resourceToken}' - location: location - tags: tags - publicNetworkAccess: 'Enabled' - roleAssignments:[ - { - principalId: backendIdentity.outputs.principalId - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - } - { - principalId: frontendIdentity.outputs.principalId - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - } - ] - } -} - -// Container apps environment -module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.4.5' = { - name: 'container-apps-environment' - params: { - logAnalyticsWorkspaceResourceId: monitoring.outputs.logAnalyticsWorkspaceResourceId - name: '${abbrs.appManagedEnvironments}${resourceToken}' - location: location - zoneRedundant: false - } -} - -module backendIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.2.1' = { - name: 'backendidentity' - params: { - name: '${abbrs.managedIdentityUserAssignedIdentities}backend-${resourceToken}' - location: location - } -} - -module backendFetchLatestImage './modules/fetch-container-image.bicep' = { - name: 'backend-fetch-image' - params: { - exists: backendExists - name: 'backend' - } -} - -var backendAppSettingsArray = filter(array(backendDefinition.settings), i => i.name != '') -var backendSecrets = map(filter(backendAppSettingsArray, i => i.?secret != null), i => { - name: i.name - value: i.value - secretRef: i.?secretRef ?? take(replace(replace(toLower(i.name), '_', '-'), '.', '-'), 32) -}) -var backendEnv = map(filter(backendAppSettingsArray, i => i.?secret == null), i => { - name: i.name - value: i.value -}) - -module backend 'br/public:avm/res/app/container-app:0.8.0' = { - name: 'backend' - params: { - name: 'backend' - ingressTargetPort: 8000 - scaleMinReplicas: 1 - scaleMaxReplicas: 10 - secrets: { - secureList: union([ - ], - map(backendSecrets, secret => { - name: secret.secretRef - value: secret.value - })) - } - containers: [ - { - image: backendFetchLatestImage.outputs.?containers[?0].?image ?? 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest' - name: 'main' - resources: { - cpu: json('0.5') - memory: '1.0Gi' - } - env: union([ - { - name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' - value: monitoring.outputs.applicationInsightsConnectionString - } - { - name: 'AZURE_CLIENT_ID' - value: backendIdentity.outputs.clientId - } - { - name: 'PORT' - value: '8000' - } - ], - backendEnv, - map(backendSecrets, secret => { - name: secret.name - secretRef: secret.secretRef - })) - } - ] - managedIdentities:{ - systemAssigned: false - userAssignedResourceIds: [backendIdentity.outputs.resourceId] - } - registries:[ - { - server: containerRegistry.outputs.loginServer - identity: backendIdentity.outputs.resourceId - } - ] - environmentResourceId: containerAppsEnvironment.outputs.resourceId - location: location - tags: union(tags, { 'azd-service-name': 'backend' }) - } -} - -module frontendIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.2.1' = { - name: 'frontendidentity' - params: { - name: '${abbrs.managedIdentityUserAssignedIdentities}frontend-${resourceToken}' - location: location - } -} - -module frontendFetchLatestImage './modules/fetch-container-image.bicep' = { - name: 'frontend-fetch-image' - params: { - exists: frontendExists - name: 'frontend' - } -} - -var frontendAppSettingsArray = filter(array(frontendDefinition.settings), i => i.name != '') -var frontendSecrets = map(filter(frontendAppSettingsArray, i => i.?secret != null), i => { - name: i.name - value: i.value - secretRef: i.?secretRef ?? take(replace(replace(toLower(i.name), '_', '-'), '.', '-'), 32) -}) -var frontendEnv = map(filter(frontendAppSettingsArray, i => i.?secret == null), i => { - name: i.name - value: i.value -}) - -module frontend 'br/public:avm/res/app/container-app:0.8.0' = { - name: 'frontend' - params: { - name: 'frontend' - ingressTargetPort: 3000 - scaleMinReplicas: 1 - scaleMaxReplicas: 10 - secrets: { - secureList: union([ - ], - map(frontendSecrets, secret => { - name: secret.secretRef - value: secret.value - })) - } - containers: [ - { - image: frontendFetchLatestImage.outputs.?containers[?0].?image ?? 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest' - name: 'main' - resources: { - cpu: json('0.5') - memory: '1.0Gi' - } - env: union([ - { - name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' - value: monitoring.outputs.applicationInsightsConnectionString - } - { - name: 'AZURE_CLIENT_ID' - value: frontendIdentity.outputs.clientId - } - { - name: 'PORT' - value: '3000' - } - ], - frontendEnv, - map(frontendSecrets, secret => { - name: secret.name - secretRef: secret.secretRef - })) - } - ] - managedIdentities:{ - systemAssigned: false - userAssignedResourceIds: [frontendIdentity.outputs.resourceId] - } - registries:[ - { - server: containerRegistry.outputs.loginServer - identity: frontendIdentity.outputs.resourceId - } - ] - environmentResourceId: containerAppsEnvironment.outputs.resourceId - location: location - tags: union(tags, { 'azd-service-name': 'frontend' }) - } -} -output AZURE_CONTAINER_REGISTRY_ENDPOINT string = containerRegistry.outputs.loginServer -output AZURE_RESOURCE_BACKEND_ID string = backend.outputs.resourceId -output AZURE_RESOURCE_FRONTEND_ID string = frontend.outputs.resourceId diff --git a/infra/old/08-2025/abbreviations.json b/infra/old/08-2025/abbreviations.json deleted file mode 100644 index 93b95656b..000000000 --- a/infra/old/08-2025/abbreviations.json +++ /dev/null @@ -1,227 +0,0 @@ -{ - "ai": { - "aiSearch": "srch-", - "aiServices": "aisa-", - "aiVideoIndexer": "avi-", - "machineLearningWorkspace": "mlw-", - "openAIService": "oai-", - "botService": "bot-", - "computerVision": "cv-", - "contentModerator": "cm-", - "contentSafety": "cs-", - "customVisionPrediction": "cstv-", - "customVisionTraining": "cstvt-", - "documentIntelligence": "di-", - "faceApi": "face-", - "healthInsights": "hi-", - "immersiveReader": "ir-", - "languageService": "lang-", - "speechService": "spch-", - "translator": "trsl-", - "aiHub": "aih-", - "aiHubProject": "aihp-" - }, - "analytics": { - "analysisServicesServer": "as", - "databricksWorkspace": "dbw-", - "dataExplorerCluster": "dec", - "dataExplorerClusterDatabase": "dedb", - "dataFactory": "adf-", - "digitalTwin": "dt-", - "streamAnalytics": "asa-", - "synapseAnalyticsPrivateLinkHub": "synplh-", - "synapseAnalyticsSQLDedicatedPool": "syndp", - "synapseAnalyticsSparkPool": "synsp", - "synapseAnalyticsWorkspaces": "synw", - "dataLakeStoreAccount": "dls", - "dataLakeAnalyticsAccount": "dla", - "eventHubsNamespace": "evhns-", - "eventHub": "evh-", - "eventGridDomain": "evgd-", - "eventGridSubscriptions": "evgs-", - "eventGridTopic": "evgt-", - "eventGridSystemTopic": "egst-", - "hdInsightHadoopCluster": "hadoop-", - "hdInsightHBaseCluster": "hbase-", - "hdInsightKafkaCluster": "kafka-", - "hdInsightSparkCluster": "spark-", - "hdInsightStormCluster": "storm-", - "hdInsightMLServicesCluster": "mls-", - "iotHub": "iot-", - "provisioningServices": "provs-", - "provisioningServicesCertificate": "pcert-", - "powerBIEmbedded": "pbi-", - "timeSeriesInsightsEnvironment": "tsi-" - }, - "compute": { - "appServiceEnvironment": "ase-", - "appServicePlan": "asp-", - "loadTesting": "lt-", - "availabilitySet": "avail-", - "arcEnabledServer": "arcs-", - "arcEnabledKubernetesCluster": "arck", - "batchAccounts": "ba-", - "cloudService": "cld-", - "communicationServices": "acs-", - "diskEncryptionSet": "des", - "functionApp": "func-", - "gallery": "gal", - "hostingEnvironment": "host-", - "imageTemplate": "it-", - "managedDiskOS": "osdisk", - "managedDiskData": "disk", - "notificationHubs": "ntf-", - "notificationHubsNamespace": "ntfns-", - "proximityPlacementGroup": "ppg-", - "restorePointCollection": "rpc-", - "snapshot": "snap-", - "staticWebApp": "stapp-", - "virtualMachine": "vm", - "virtualMachineScaleSet": "vmss-", - "virtualMachineMaintenanceConfiguration": "mc-", - "virtualMachineStorageAccount": "stvm", - "webApp": "app-" - }, - "containers": { - "aksCluster": "aks-", - "aksSystemNodePool": "npsystem-", - "aksUserNodePool": "np-", - "containerApp": "ca-", - "containerAppsEnvironment": "cae-", - "containerRegistry": "cr", - "containerInstance": "ci", - "serviceFabricCluster": "sf-", - "serviceFabricManagedCluster": "sfmc-" - }, - "databases": { - "cosmosDBDatabase": "cosmos-", - "cosmosDBApacheCassandra": "coscas-", - "cosmosDBMongoDB": "cosmon-", - "cosmosDBNoSQL": "cosno-", - "cosmosDBTable": "costab-", - "cosmosDBGremlin": "cosgrm-", - "cosmosDBPostgreSQL": "cospos-", - "cacheForRedis": "redis-", - "sqlDatabaseServer": "sql-", - "sqlDatabase": "sqldb-", - "sqlElasticJobAgent": "sqlja-", - "sqlElasticPool": "sqlep-", - "mariaDBServer": "maria-", - "mariaDBDatabase": "mariadb-", - "mySQLDatabase": "mysql-", - "postgreSQLDatabase": "psql-", - "sqlServerStretchDatabase": "sqlstrdb-", - "sqlManagedInstance": "sqlmi-" - }, - "developerTools": { - "appConfigurationStore": "appcs-", - "mapsAccount": "map-", - "signalR": "sigr", - "webPubSub": "wps-" - }, - "devOps": { - "managedGrafana": "amg-" - }, - "integration": { - "apiManagementService": "apim-", - "integrationAccount": "ia-", - "logicApp": "logic-", - "serviceBusNamespace": "sbns-", - "serviceBusQueue": "sbq-", - "serviceBusTopic": "sbt-", - "serviceBusTopicSubscription": "sbts-" - }, - "managementGovernance": { - "automationAccount": "aa-", - "applicationInsights": "appi-", - "monitorActionGroup": "ag-", - "monitorDataCollectionRules": "dcr-", - "monitorAlertProcessingRule": "apr-", - "blueprint": "bp-", - "blueprintAssignment": "bpa-", - "dataCollectionEndpoint": "dce-", - "logAnalyticsWorkspace": "log-", - "logAnalyticsQueryPacks": "pack-", - "managementGroup": "mg-", - "purviewInstance": "pview-", - "resourceGroup": "rg-", - "templateSpecsName": "ts-" - }, - "migration": { - "migrateProject": "migr-", - "databaseMigrationService": "dms-", - "recoveryServicesVault": "rsv-" - }, - "networking": { - "applicationGateway": "agw-", - "applicationSecurityGroup": "asg-", - "cdnProfile": "cdnp-", - "cdnEndpoint": "cdne-", - "connections": "con-", - "dnsForwardingRuleset": "dnsfrs-", - "dnsPrivateResolver": "dnspr-", - "dnsPrivateResolverInboundEndpoint": "in-", - "dnsPrivateResolverOutboundEndpoint": "out-", - "firewall": "afw-", - "firewallPolicy": "afwp-", - "expressRouteCircuit": "erc-", - "expressRouteGateway": "ergw-", - "frontDoorProfile": "afd-", - "frontDoorEndpoint": "fde-", - "frontDoorFirewallPolicy": "fdfp-", - "ipGroups": "ipg-", - "loadBalancerInternal": "lbi-", - "loadBalancerExternal": "lbe-", - "loadBalancerRule": "rule-", - "localNetworkGateway": "lgw-", - "natGateway": "ng-", - "networkInterface": "nic-", - "networkSecurityGroup": "nsg-", - "networkSecurityGroupSecurityRules": "nsgsr-", - "networkWatcher": "nw-", - "privateLink": "pl-", - "privateEndpoint": "pep-", - "publicIPAddress": "pip-", - "publicIPAddressPrefix": "ippre-", - "routeFilter": "rf-", - "routeServer": "rtserv-", - "routeTable": "rt-", - "serviceEndpointPolicy": "se-", - "trafficManagerProfile": "traf-", - "userDefinedRoute": "udr-", - "virtualNetwork": "vnet-", - "virtualNetworkGateway": "vgw-", - "virtualNetworkManager": "vnm-", - "virtualNetworkPeering": "peer-", - "virtualNetworkSubnet": "snet-", - "virtualWAN": "vwan-", - "virtualWANHub": "vhub-" - }, - "security": { - "bastion": "bas-", - "keyVault": "kv-", - "keyVaultManagedHSM": "kvmhsm-", - "managedIdentity": "id-", - "sshKey": "sshkey-", - "vpnGateway": "vpng-", - "vpnConnection": "vcn-", - "vpnSite": "vst-", - "webApplicationFirewallPolicy": "waf", - "webApplicationFirewallPolicyRuleGroup": "wafrg" - }, - "storage": { - "storSimple": "ssimp", - "backupVault": "bvault-", - "backupVaultPolicy": "bkpol-", - "fileShare": "share-", - "storageAccount": "st", - "storageSyncService": "sss-" - }, - "virtualDesktop": { - "labServicesPlan": "lp-", - "virtualDesktopHostPool": "vdpool-", - "virtualDesktopApplicationGroup": "vdag-", - "virtualDesktopWorkspace": "vdws-", - "virtualDesktopScalingPlan": "vdscaling-" - } - } \ No newline at end of file diff --git a/infra/old/08-2025/bicepconfig.json b/infra/old/08-2025/bicepconfig.json deleted file mode 100644 index 7d7839f72..000000000 --- a/infra/old/08-2025/bicepconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "experimentalFeaturesEnabled": { - "extensibility": true - }, - "extensions": { - "graphV1": "br:mcr.microsoft.com/bicep/extensions/microsoftgraph/v1.0:0.2.0-preview" // , - // "graphBeta": "br:mcr.microsoft.com/bicep/extensions/microsoftgraph/beta:0.2.0-preview" - } - } \ No newline at end of file diff --git a/infra/old/08-2025/main.bicep b/infra/old/08-2025/main.bicep deleted file mode 100644 index a23b5bc8e..000000000 --- a/infra/old/08-2025/main.bicep +++ /dev/null @@ -1,1726 +0,0 @@ -metadata name = 'Multi-Agent Custom Automation Engine' -metadata description = 'This module contains the resources required to deploy the Multi-Agent Custom Automation Engine solution accelerator for both Sandbox environments and WAF aligned environments.' - -@description('Set to true if you want to deploy WAF-aligned infrastructure.') -param useWafAlignedArchitecture bool - -@description('Use this parameter to use an existing AI project resource ID') -param existingFoundryProjectResourceId string = '' - -@description('Required. Name of the environment to deploy the solution into.') -param environmentName string - -@description('Required. Location for all Resources except AI Foundry.') -param solutionLocation string = resourceGroup().location - -@description('Optional. Enable/Disable usage telemetry for module.') -param enableTelemetry bool = true - -param existingLogAnalyticsWorkspaceId string = '' - -// Restricting deployment to only supported Azure OpenAI regions validated with GPT-4o model -@metadata({ - azd: { - type: 'location' - usageName: [ - 'OpenAI.GlobalStandard.gpt-4o, 150' - ] - } -}) -@allowed(['australiaeast', 'eastus2', 'francecentral', 'japaneast', 'norwayeast', 'swedencentral', 'uksouth', 'westus']) -@description('Azure OpenAI Location') -param aiDeploymentsLocation string - -@minLength(1) -@description('Name of the GPT model to deploy:') -param gptModelName string = 'gpt-4o' - -param gptModelVersion string = '2024-08-06' - -@minLength(1) -@description('GPT model deployment type:') -param modelDeploymentType string = 'GlobalStandard' - -@description('Optional. AI model deployment token capacity.') -param gptModelCapacity int = 150 - -@description('Set the image tag for the container images used in the solution. Default is "latest".') -param imageTag string = 'latest' - -param solutionPrefix string = 'macae-${padLeft(take(toLower(uniqueString(subscription().id, environmentName, resourceGroup().location, resourceGroup().name)), 12), 12, '0')}' - -@description('Optional. The tags to apply to all deployed Azure resources.') -param tags object = { - app: solutionPrefix - location: solutionLocation -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Log Analytics Workspace resource.') -param logAnalyticsWorkspaceConfiguration logAnalyticsWorkspaceConfigurationType = { - enabled: true - name: 'log-${solutionPrefix}' - location: solutionLocation - sku: 'PerGB2018' - tags: tags - dataRetentionInDays: useWafAlignedArchitecture ? 365 : 30 - existingWorkspaceResourceId: existingLogAnalyticsWorkspaceId -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Application Insights resource.') -param applicationInsightsConfiguration applicationInsightsConfigurationType = { - enabled: true - name: 'appi-${solutionPrefix}' - location: solutionLocation - tags: tags - retentionInDays: useWafAlignedArchitecture ? 365 : 30 -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Managed Identity resource.') -param userAssignedManagedIdentityConfiguration userAssignedManagedIdentityType = { - enabled: true - name: 'id-${solutionPrefix}' - location: solutionLocation - tags: tags -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the backend subnet.') -param networkSecurityGroupBackendConfiguration networkSecurityGroupConfigurationType = { - enabled: true - name: 'nsg-backend-${solutionPrefix}' - location: solutionLocation - tags: tags - securityRules: null //Default value set on module configuration -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the containers subnet.') -param networkSecurityGroupContainersConfiguration networkSecurityGroupConfigurationType = { - enabled: true - name: 'nsg-containers-${solutionPrefix}' - location: solutionLocation - tags: tags - securityRules: null //Default value set on module configuration -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the Bastion subnet.') -param networkSecurityGroupBastionConfiguration networkSecurityGroupConfigurationType = { - enabled: true - name: 'nsg-bastion-${solutionPrefix}' - location: solutionLocation - tags: tags - securityRules: null //Default value set on module configuration -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the administration subnet.') -param networkSecurityGroupAdministrationConfiguration networkSecurityGroupConfigurationType = { - enabled: true - name: 'nsg-administration-${solutionPrefix}' - location: solutionLocation - tags: tags - securityRules: null //Default value set on module configuration -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine virtual network resource.') -param virtualNetworkConfiguration virtualNetworkConfigurationType = { - enabled: useWafAlignedArchitecture ? true : false - name: 'vnet-${solutionPrefix}' - location: solutionLocation - tags: tags - addressPrefixes: null //Default value set on module configuration - subnets: null //Default value set on module configuration -} - -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine bastion resource.') -param bastionConfiguration bastionConfigurationType = { - enabled: true - name: 'bas-${solutionPrefix}' - location: solutionLocation - tags: tags - sku: 'Standard' - virtualNetworkResourceId: null //Default value set on module configuration - publicIpResourceName: 'pip-bas${solutionPrefix}' -} - -@description('Optional. Configuration for the Windows virtual machine.') -param virtualMachineConfiguration virtualMachineConfigurationType = { - enabled: true - name: 'vm${solutionPrefix}' - location: solutionLocation - tags: tags - adminUsername: 'adminuser' - adminPassword: useWafAlignedArchitecture ? 'P@ssw0rd1234' : guid(solutionPrefix, subscription().subscriptionId) - vmSize: 'Standard_D2s_v4' - subnetResourceId: null //Default value set on module configuration -} - -@description('Optional. The configuration to apply for the AI Foundry AI Services resource.') -param aiFoundryAiServicesConfiguration aiServicesConfigurationType = { - enabled: true - name: 'aisa-${solutionPrefix}' - location: aiDeploymentsLocation - sku: 'S0' - deployments: null //Default value set on module configuration - subnetResourceId: null //Default value set on module configuration - modelCapacity: gptModelCapacity -} - -@description('Optional. The configuration to apply for the AI Foundry AI Project resource.') -param aiFoundryAiProjectConfiguration aiProjectConfigurationType = { - enabled: true - name: 'aifp-${solutionPrefix}' - location: aiDeploymentsLocation - sku: 'Basic' - tags: tags -} - -@description('Optional. The configuration to apply for the Cosmos DB Account resource.') -param cosmosDbAccountConfiguration cosmosDbAccountConfigurationType = { - enabled: true - name: 'cosmos-${solutionPrefix}' - location: solutionLocation - tags: tags - subnetResourceId: null //Default value set on module configuration - sqlDatabases: null //Default value set on module configuration -} - -@description('Optional. The configuration to apply for the Container App Environment resource.') -param containerAppEnvironmentConfiguration containerAppEnvironmentConfigurationType = { - enabled: true - name: 'cae-${solutionPrefix}' - location: solutionLocation - tags: tags - subnetResourceId: null //Default value set on module configuration -} - -@description('Optional. The configuration to apply for the Container App resource.') -param containerAppConfiguration containerAppConfigurationType = { - enabled: true - name: 'ca-${solutionPrefix}' - location: solutionLocation - tags: tags - environmentResourceId: null //Default value set on module configuration - concurrentRequests: '100' - containerCpu: '2.0' - containerMemory: '4.0Gi' - containerImageRegistryDomain: 'biabcontainerreg.azurecr.io' - containerImageName: 'macaebackend' - containerImageTag: imageTag - containerName: 'backend' - ingressTargetPort: 8000 - maxReplicas: 1 - minReplicas: 1 -} - -@description('Optional. The configuration to apply for the Web Server Farm resource.') -param webServerFarmConfiguration webServerFarmConfigurationType = { - enabled: true - name: 'asp-${solutionPrefix}' - location: solutionLocation - skuName: useWafAlignedArchitecture ? 'P1v4' : 'B2' - skuCapacity: useWafAlignedArchitecture ? 3 : 1 - tags: tags -} - -@description('Optional. The configuration to apply for the Web Server Farm resource.') -param webSiteConfiguration webSiteConfigurationType = { - enabled: true - name: 'app-${solutionPrefix}' - location: solutionLocation - containerImageRegistryDomain: 'biabcontainerreg.azurecr.io' - containerImageName: 'macaefrontend' - containerImageTag: imageTag - containerName: 'backend' - tags: tags - environmentResourceId: null //Default value set on module configuration -} - -// ========== Resource Group Tag ========== // -resource resourceGroupTags 'Microsoft.Resources/tags@2021-04-01' = { - name: 'default' - properties: { - tags: { - ...tags - TemplateName: 'Macae' - } - } -} - -// ========== Log Analytics Workspace ========== // -// WAF best practices for Log Analytics: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-log-analytics -// Log Analytics configuration defaults -var logAnalyticsWorkspaceEnabled = logAnalyticsWorkspaceConfiguration.?enabled ?? true -var logAnalyticsWorkspaceResourceName = logAnalyticsWorkspaceConfiguration.?name ?? 'log-${solutionPrefix}' -var existingWorkspaceResourceId = logAnalyticsWorkspaceConfiguration.?existingWorkspaceResourceId ?? '' -var useExistingWorkspace = existingWorkspaceResourceId != '' - -module logAnalyticsWorkspace 'br/public:avm/res/operational-insights/workspace:0.11.2' = if (logAnalyticsWorkspaceEnabled && !useExistingWorkspace) { - name: take('avm.res.operational-insights.workspace.${logAnalyticsWorkspaceResourceName}', 64) - params: { - name: logAnalyticsWorkspaceResourceName - tags: logAnalyticsWorkspaceConfiguration.?tags ?? tags - location: logAnalyticsWorkspaceConfiguration.?location ?? solutionLocation - enableTelemetry: enableTelemetry - skuName: logAnalyticsWorkspaceConfiguration.?sku ?? 'PerGB2018' - dataRetention: logAnalyticsWorkspaceConfiguration.?dataRetentionInDays ?? 365 - diagnosticSettings: [{ useThisWorkspace: true }] - } -} - -var logAnalyticsWorkspaceId = useExistingWorkspace - ? existingWorkspaceResourceId - : logAnalyticsWorkspace.outputs.resourceId - -// ========== Application Insights ========== // -// WAF best practices for Application Insights: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/application-insights -// Application Insights configuration defaults -var applicationInsightsEnabled = applicationInsightsConfiguration.?enabled ?? true -var applicationInsightsResourceName = applicationInsightsConfiguration.?name ?? 'appi-${solutionPrefix}' -module applicationInsights 'br/public:avm/res/insights/component:0.6.0' = if (applicationInsightsEnabled) { - name: take('avm.res.insights.component.${applicationInsightsResourceName}', 64) - params: { - name: applicationInsightsResourceName - workspaceResourceId: logAnalyticsWorkspaceId - location: applicationInsightsConfiguration.?location ?? solutionLocation - enableTelemetry: enableTelemetry - tags: applicationInsightsConfiguration.?tags ?? tags - retentionInDays: applicationInsightsConfiguration.?retentionInDays ?? 365 - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - kind: 'web' - disableIpMasking: false - flowType: 'Bluefield' - } -} - -// ========== User assigned identity Web Site ========== // -// WAF best practices for identity and access management: https://learn.microsoft.com/en-us/azure/well-architected/security/identity-access -var userAssignedManagedIdentityEnabled = userAssignedManagedIdentityConfiguration.?enabled ?? true -var userAssignedManagedIdentityResourceName = userAssignedManagedIdentityConfiguration.?name ?? 'id-${solutionPrefix}' -module userAssignedIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.4.1' = if (userAssignedManagedIdentityEnabled) { - name: take('avm.res.managed-identity.user-assigned-identity.${userAssignedManagedIdentityResourceName}', 64) - params: { - name: userAssignedManagedIdentityResourceName - tags: userAssignedManagedIdentityConfiguration.?tags ?? tags - location: userAssignedManagedIdentityConfiguration.?location ?? solutionLocation - enableTelemetry: enableTelemetry - } -} - -// ========== Network Security Groups ========== // -// WAF best practices for virtual networks: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/virtual-network -// WAF recommendations for networking and connectivity: https://learn.microsoft.com/en-us/azure/well-architected/security/networking -var networkSecurityGroupBackendEnabled = networkSecurityGroupBackendConfiguration.?enabled ?? true -var networkSecurityGroupBackendResourceName = networkSecurityGroupBackendConfiguration.?name ?? 'nsg-backend-${solutionPrefix}' -module networkSecurityGroupBackend 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupBackendEnabled) { - name: take('avm.res.network.network-security-group.${networkSecurityGroupBackendResourceName}', 64) - params: { - name: networkSecurityGroupBackendResourceName - location: networkSecurityGroupBackendConfiguration.?location ?? solutionLocation - tags: networkSecurityGroupBackendConfiguration.?tags ?? tags - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - securityRules: networkSecurityGroupBackendConfiguration.?securityRules ?? [ - // { - // name: 'DenySshRdpOutbound' //Azure Bastion - // properties: { - // priority: 200 - // access: 'Deny' - // protocol: '*' - // direction: 'Outbound' - // sourceAddressPrefix: 'VirtualNetwork' - // sourcePortRange: '*' - // destinationAddressPrefix: '*' - // destinationPortRanges: [ - // '3389' - // '22' - // ] - // } - // } - ] - } -} - -var networkSecurityGroupContainersEnabled = networkSecurityGroupContainersConfiguration.?enabled ?? true -var networkSecurityGroupContainersResourceName = networkSecurityGroupContainersConfiguration.?name ?? 'nsg-containers-${solutionPrefix}' -module networkSecurityGroupContainers 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupContainersEnabled) { - name: take('avm.res.network.network-security-group.${networkSecurityGroupContainersResourceName}', 64) - params: { - name: networkSecurityGroupContainersResourceName - location: networkSecurityGroupContainersConfiguration.?location ?? solutionLocation - tags: networkSecurityGroupContainersConfiguration.?tags ?? tags - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - securityRules: networkSecurityGroupContainersConfiguration.?securityRules ?? [ - // { - // name: 'DenySshRdpOutbound' //Azure Bastion - // properties: { - // priority: 200 - // access: 'Deny' - // protocol: '*' - // direction: 'Outbound' - // sourceAddressPrefix: 'VirtualNetwork' - // sourcePortRange: '*' - // destinationAddressPrefix: '*' - // destinationPortRanges: [ - // '3389' - // '22' - // ] - // } - // } - ] - } -} - -var networkSecurityGroupBastionEnabled = networkSecurityGroupBastionConfiguration.?enabled ?? true -var networkSecurityGroupBastionResourceName = networkSecurityGroupBastionConfiguration.?name ?? 'nsg-bastion-${solutionPrefix}' -module networkSecurityGroupBastion 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupBastionEnabled) { - name: take('avm.res.network.network-security-group.${networkSecurityGroupBastionResourceName}', 64) - params: { - name: networkSecurityGroupBastionResourceName - location: networkSecurityGroupBastionConfiguration.?location ?? solutionLocation - tags: networkSecurityGroupBastionConfiguration.?tags ?? tags - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - securityRules: networkSecurityGroupBastionConfiguration.?securityRules ?? [ - { - name: 'AllowHttpsInBound' - properties: { - protocol: 'Tcp' - sourcePortRange: '*' - sourceAddressPrefix: 'Internet' - destinationPortRange: '443' - destinationAddressPrefix: '*' - access: 'Allow' - priority: 100 - direction: 'Inbound' - } - } - { - name: 'AllowGatewayManagerInBound' - properties: { - protocol: 'Tcp' - sourcePortRange: '*' - sourceAddressPrefix: 'GatewayManager' - destinationPortRange: '443' - destinationAddressPrefix: '*' - access: 'Allow' - priority: 110 - direction: 'Inbound' - } - } - { - name: 'AllowLoadBalancerInBound' - properties: { - protocol: 'Tcp' - sourcePortRange: '*' - sourceAddressPrefix: 'AzureLoadBalancer' - destinationPortRange: '443' - destinationAddressPrefix: '*' - access: 'Allow' - priority: 120 - direction: 'Inbound' - } - } - { - name: 'AllowBastionHostCommunicationInBound' - properties: { - protocol: '*' - sourcePortRange: '*' - sourceAddressPrefix: 'VirtualNetwork' - destinationPortRanges: [ - '8080' - '5701' - ] - destinationAddressPrefix: 'VirtualNetwork' - access: 'Allow' - priority: 130 - direction: 'Inbound' - } - } - { - name: 'DenyAllInBound' - properties: { - protocol: '*' - sourcePortRange: '*' - sourceAddressPrefix: '*' - destinationPortRange: '*' - destinationAddressPrefix: '*' - access: 'Deny' - priority: 1000 - direction: 'Inbound' - } - } - { - name: 'AllowSshRdpOutBound' - properties: { - protocol: 'Tcp' - sourcePortRange: '*' - sourceAddressPrefix: '*' - destinationPortRanges: [ - '22' - '3389' - ] - destinationAddressPrefix: 'VirtualNetwork' - access: 'Allow' - priority: 100 - direction: 'Outbound' - } - } - { - name: 'AllowAzureCloudCommunicationOutBound' - properties: { - protocol: 'Tcp' - sourcePortRange: '*' - sourceAddressPrefix: '*' - destinationPortRange: '443' - destinationAddressPrefix: 'AzureCloud' - access: 'Allow' - priority: 110 - direction: 'Outbound' - } - } - { - name: 'AllowBastionHostCommunicationOutBound' - properties: { - protocol: '*' - sourcePortRange: '*' - sourceAddressPrefix: 'VirtualNetwork' - destinationPortRanges: [ - '8080' - '5701' - ] - destinationAddressPrefix: 'VirtualNetwork' - access: 'Allow' - priority: 120 - direction: 'Outbound' - } - } - { - name: 'AllowGetSessionInformationOutBound' - properties: { - protocol: '*' - sourcePortRange: '*' - sourceAddressPrefix: '*' - destinationAddressPrefix: 'Internet' - destinationPortRanges: [ - '80' - '443' - ] - access: 'Allow' - priority: 130 - direction: 'Outbound' - } - } - { - name: 'DenyAllOutBound' - properties: { - protocol: '*' - sourcePortRange: '*' - destinationPortRange: '*' - sourceAddressPrefix: '*' - destinationAddressPrefix: '*' - access: 'Deny' - priority: 1000 - direction: 'Outbound' - } - } - ] - } -} - -var networkSecurityGroupAdministrationEnabled = networkSecurityGroupAdministrationConfiguration.?enabled ?? true -var networkSecurityGroupAdministrationResourceName = networkSecurityGroupAdministrationConfiguration.?name ?? 'nsg-administration-${solutionPrefix}' -module networkSecurityGroupAdministration 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupAdministrationEnabled) { - name: take('avm.res.network.network-security-group.${networkSecurityGroupAdministrationResourceName}', 64) - params: { - name: networkSecurityGroupAdministrationResourceName - location: networkSecurityGroupAdministrationConfiguration.?location ?? solutionLocation - tags: networkSecurityGroupAdministrationConfiguration.?tags ?? tags - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - securityRules: networkSecurityGroupAdministrationConfiguration.?securityRules ?? [ - // { - // name: 'DenySshRdpOutbound' //Azure Bastion - // properties: { - // priority: 200 - // access: 'Deny' - // protocol: '*' - // direction: 'Outbound' - // sourceAddressPrefix: 'VirtualNetwork' - // sourcePortRange: '*' - // destinationAddressPrefix: '*' - // destinationPortRanges: [ - // '3389' - // '22' - // ] - // } - // } - ] - } -} - -// ========== Virtual Network ========== // -// WAF best practices for virtual networks: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/virtual-network -// WAF recommendations for networking and connectivity: https://learn.microsoft.com/en-us/azure/well-architected/security/networking -var virtualNetworkEnabled = virtualNetworkConfiguration.?enabled ?? true -var virtualNetworkResourceName = virtualNetworkConfiguration.?name ?? 'vnet-${solutionPrefix}' -module virtualNetwork 'br/public:avm/res/network/virtual-network:0.6.1' = if (virtualNetworkEnabled) { - name: take('avm.res.network.virtual-network.${virtualNetworkResourceName}', 64) - params: { - name: virtualNetworkResourceName - location: virtualNetworkConfiguration.?location ?? solutionLocation - tags: virtualNetworkConfiguration.?tags ?? tags - enableTelemetry: enableTelemetry - addressPrefixes: virtualNetworkConfiguration.?addressPrefixes ?? ['10.0.0.0/8'] - subnets: virtualNetworkConfiguration.?subnets ?? [ - { - name: 'backend' - addressPrefix: '10.0.0.0/27' - //defaultOutboundAccess: false TODO: check this configuration for a more restricted outbound access - networkSecurityGroupResourceId: networkSecurityGroupBackend.outputs.resourceId - } - { - name: 'administration' - addressPrefix: '10.0.0.32/27' - networkSecurityGroupResourceId: networkSecurityGroupAdministration.outputs.resourceId - } - { - // For Azure Bastion resources deployed on or after November 2, 2021, the minimum AzureBastionSubnet size is /26 or larger (/25, /24, etc.). - // https://learn.microsoft.com/en-us/azure/bastion/configuration-settings#subnet - name: 'AzureBastionSubnet' //This exact name is required for Azure Bastion - addressPrefix: '10.0.0.64/26' - networkSecurityGroupResourceId: networkSecurityGroupBastion.outputs.resourceId - } - { - // If you use your own vnw, you need to provide a subnet that is dedicated exclusively to the Container App environment you deploy. This subnet isn't available to other services - // https://learn.microsoft.com/en-us/azure/container-apps/networking?tabs=workload-profiles-env%2Cazure-cli#custom-vnw-configuration - name: 'containers' - addressPrefix: '10.0.2.0/23' //subnet of size /23 is required for container app - delegation: 'Microsoft.App/environments' - networkSecurityGroupResourceId: networkSecurityGroupContainers.outputs.resourceId - privateEndpointNetworkPolicies: 'Disabled' - privateLinkServiceNetworkPolicies: 'Enabled' - } - ] - } -} -var bastionEnabled = bastionConfiguration.?enabled ?? true -var bastionResourceName = bastionConfiguration.?name ?? 'bas-${solutionPrefix}' - -// ========== Bastion host ========== // -// WAF best practices for virtual networks: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/virtual-network -// WAF recommendations for networking and connectivity: https://learn.microsoft.com/en-us/azure/well-architected/security/networking -module bastionHost 'br/public:avm/res/network/bastion-host:0.6.1' = if (virtualNetworkEnabled && bastionEnabled) { - name: take('avm.res.network.bastion-host.${bastionResourceName}', 64) - params: { - name: bastionResourceName - location: bastionConfiguration.?location ?? solutionLocation - skuName: bastionConfiguration.?sku ?? 'Standard' - enableTelemetry: enableTelemetry - tags: bastionConfiguration.?tags ?? tags - virtualNetworkResourceId: bastionConfiguration.?virtualNetworkResourceId ?? virtualNetwork.?outputs.?resourceId - publicIPAddressObject: { - name: bastionConfiguration.?publicIpResourceName ?? 'pip-bas${solutionPrefix}' - zones: [] - } - disableCopyPaste: false - enableFileCopy: false - enableIpConnect: true - enableShareableLink: true - } -} - -// ========== Virtual machine ========== // -// WAF best practices for virtual machines: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/virtual-machines -var virtualMachineEnabled = virtualMachineConfiguration.?enabled ?? true -var virtualMachineResourceName = virtualMachineConfiguration.?name ?? 'vm${solutionPrefix}' -module virtualMachine 'br/public:avm/res/compute/virtual-machine:0.13.0' = if (virtualNetworkEnabled && virtualMachineEnabled) { - name: take('avm.res.compute.virtual-machine.${virtualMachineResourceName}', 64) - params: { - name: virtualMachineResourceName - computerName: take(virtualMachineResourceName, 15) - location: virtualMachineConfiguration.?location ?? solutionLocation - tags: virtualMachineConfiguration.?tags ?? tags - enableTelemetry: enableTelemetry - vmSize: virtualMachineConfiguration.?vmSize ?? 'Standard_D2s_v4' - adminUsername: virtualMachineConfiguration.?adminUsername ?? 'adminuser' - adminPassword: virtualMachineConfiguration.?adminPassword ?? guid(solutionPrefix, subscription().subscriptionId) - nicConfigurations: [ - { - name: 'nic-${virtualMachineResourceName}' - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - ipConfigurations: [ - { - name: '${virtualMachineResourceName}-nic01-ipconfig01' - subnetResourceId: virtualMachineConfiguration.?subnetResourceId ?? virtualNetwork.outputs.subnetResourceIds[1] - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - } - ] - } - ] - imageReference: { - publisher: 'microsoft-dsvm' - offer: 'dsvm-win-2022' - sku: 'winserver-2022' - version: 'latest' - } - osDisk: { - name: 'osdisk-${virtualMachineResourceName}' - createOption: 'FromImage' - managedDisk: { - storageAccountType: 'Standard_LRS' - } - diskSizeGB: 128 - caching: 'ReadWrite' - } - osType: 'Windows' - encryptionAtHost: false //The property 'securityProfile.encryptionAtHost' is not valid because the 'Microsoft.Compute/EncryptionAtHost' feature is not enabled for this subscription. - zone: 0 - extensionAadJoinConfig: { - enabled: true - typeHandlerVersion: '1.0' - } - } -} - -// ========== AI Foundry: AI Services ========== // -// WAF best practices for Open AI: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-openai -var openAiSubResource = 'account' -var openAiPrivateDnsZones = { - 'privatelink.cognitiveservices.azure.com': openAiSubResource - 'privatelink.openai.azure.com': openAiSubResource - 'privatelink.services.ai.azure.com': openAiSubResource -} - -module privateDnsZonesAiServices 'br/public:avm/res/network/private-dns-zone:0.7.1' = [ - for zone in objectKeys(openAiPrivateDnsZones): if (virtualNetworkEnabled && aiFoundryAIservicesEnabled) { - name: take( - 'avm.res.network.private-dns-zone.ai-services.${uniqueString(aiFoundryAiServicesResourceName,zone)}.${solutionPrefix}', - 64 - ) - params: { - name: zone - tags: tags - enableTelemetry: enableTelemetry - virtualNetworkLinks: [ - { - name: 'vnetlink-${split(zone, '.')[1]}' - virtualNetworkResourceId: virtualNetwork.outputs.resourceId - } - ] - } - } -] - -// NOTE: Required version 'Microsoft.CognitiveServices/accounts@2024-04-01-preview' not available in AVM -var useExistingFoundryProject = !empty(existingFoundryProjectResourceId) -var existingAiFoundryName = useExistingFoundryProject ? split(existingFoundryProjectResourceId, '/')[8] : '' -var aiFoundryAiServicesResourceName = useExistingFoundryProject - ? existingAiFoundryName - : aiFoundryAiServicesConfiguration.?name ?? 'aisa-${solutionPrefix}' -var aiFoundryAIservicesEnabled = aiFoundryAiServicesConfiguration.?enabled ?? true -var aiFoundryAiServicesModelDeployment = { - format: 'OpenAI' - name: gptModelName - version: gptModelVersion - sku: { - name: modelDeploymentType - //Curently the capacity is set to 140 for opinanal performance. - capacity: aiFoundryAiServicesConfiguration.?modelCapacity ?? gptModelCapacity - } - raiPolicyName: 'Microsoft.Default' -} - -module aiFoundryAiServices 'modules/account/main.bicep' = if (aiFoundryAIservicesEnabled) { - name: take('avm.res.cognitive-services.account.${aiFoundryAiServicesResourceName}', 64) - params: { - name: aiFoundryAiServicesResourceName - tags: aiFoundryAiServicesConfiguration.?tags ?? tags - location: aiFoundryAiServicesConfiguration.?location ?? aiDeploymentsLocation - enableTelemetry: enableTelemetry - projectName: 'aifp-${solutionPrefix}' - projectDescription: 'aifp-${solutionPrefix}' - existingFoundryProjectResourceId: existingFoundryProjectResourceId - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - sku: aiFoundryAiServicesConfiguration.?sku ?? 'S0' - kind: 'AIServices' - disableLocalAuth: true //Should be set to true for WAF aligned configuration - customSubDomainName: aiFoundryAiServicesResourceName - apiProperties: { - //staticsEnabled: false - } - allowProjectManagement: true - managedIdentities: { - systemAssigned: true - } - publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled' - networkAcls: { - bypass: 'AzureServices' - defaultAction: (virtualNetworkEnabled) ? 'Deny' : 'Allow' - } - privateEndpoints: virtualNetworkEnabled && !useExistingFoundryProject - ? ([ - { - name: 'pep-${aiFoundryAiServicesResourceName}' - customNetworkInterfaceName: 'nic-${aiFoundryAiServicesResourceName}' - subnetResourceId: aiFoundryAiServicesConfiguration.?subnetResourceId ?? virtualNetwork.outputs.subnetResourceIds[0] - privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: map(objectKeys(openAiPrivateDnsZones), zone => { - name: replace(zone, '.', '-') - privateDnsZoneResourceId: resourceId('Microsoft.Network/privateDnsZones', zone) - }) - } - } - ]) - : [] - deployments: aiFoundryAiServicesConfiguration.?deployments ?? [ - { - name: aiFoundryAiServicesModelDeployment.name - model: { - format: aiFoundryAiServicesModelDeployment.format - name: aiFoundryAiServicesModelDeployment.name - version: aiFoundryAiServicesModelDeployment.version - } - raiPolicyName: aiFoundryAiServicesModelDeployment.raiPolicyName - sku: { - name: aiFoundryAiServicesModelDeployment.sku.name - capacity: aiFoundryAiServicesModelDeployment.sku.capacity - } - } - ] - } -} - -// AI Foundry: AI Project -// WAF best practices for Open AI: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-openai -var existingAiFounryProjectName = useExistingFoundryProject ? last(split(existingFoundryProjectResourceId, '/')) : '' -var aiFoundryAiProjectName = useExistingFoundryProject - ? existingAiFounryProjectName - : aiFoundryAiProjectConfiguration.?name ?? 'aifp-${solutionPrefix}' - -var useExistingResourceId = !empty(existingFoundryProjectResourceId) - -module cogServiceRoleAssignmentsNew './modules/role.bicep' = if (!useExistingResourceId) { - params: { - name: 'new-${guid(containerApp.name, aiFoundryAiServices.outputs.resourceId)}' - principalId: containerApp.outputs.?systemAssignedMIPrincipalId! - aiServiceName: aiFoundryAiServices.outputs.name - } - scope: resourceGroup(subscription().subscriptionId, resourceGroup().name) -} - -module cogServiceRoleAssignmentsExisting './modules/role.bicep' = if (useExistingResourceId) { - params: { - name: 'reuse-${guid(containerApp.name, aiFoundryAiServices.outputs.aiProjectInfo.resourceId)}' - principalId: containerApp.outputs.?systemAssignedMIPrincipalId! - aiServiceName: aiFoundryAiServices.outputs.name - } - scope: resourceGroup(split(existingFoundryProjectResourceId, '/')[2], split(existingFoundryProjectResourceId, '/')[4]) -} - -// ========== Cosmos DB ========== // -// WAF best practices for Cosmos DB: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/cosmos-db -module privateDnsZonesCosmosDb 'br/public:avm/res/network/private-dns-zone:0.7.0' = if (virtualNetworkEnabled) { - name: take('avm.res.network.private-dns-zone.cosmos-db.${solutionPrefix}', 64) - params: { - name: 'privatelink.documents.azure.com' - enableTelemetry: enableTelemetry - virtualNetworkLinks: [ - { - name: 'vnetlink-cosmosdb' - virtualNetworkResourceId: virtualNetwork.outputs.resourceId - } - ] - tags: tags - } -} - -var cosmosDbAccountEnabled = cosmosDbAccountConfiguration.?enabled ?? true -var cosmosDbResourceName = cosmosDbAccountConfiguration.?name ?? 'cosmos-${solutionPrefix}' -var cosmosDbDatabaseName = 'macae' -var cosmosDbDatabaseMemoryContainerName = 'memory' -module cosmosDb 'br/public:avm/res/document-db/database-account:0.12.0' = if (cosmosDbAccountEnabled) { - name: take('avm.res.document-db.database-account.${cosmosDbResourceName}', 64) - params: { - // Required parameters - name: cosmosDbAccountConfiguration.?name ?? 'cosmos-${solutionPrefix}' - location: cosmosDbAccountConfiguration.?location ?? solutionLocation - tags: cosmosDbAccountConfiguration.?tags ?? tags - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - databaseAccountOfferType: 'Standard' - enableFreeTier: false - networkRestrictions: { - networkAclBypass: 'None' - publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled' - } - privateEndpoints: virtualNetworkEnabled - ? [ - { - name: 'pep-${cosmosDbResourceName}' - customNetworkInterfaceName: 'nic-${cosmosDbResourceName}' - privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: [{ privateDnsZoneResourceId: privateDnsZonesCosmosDb.outputs.resourceId }] - } - service: 'Sql' - subnetResourceId: cosmosDbAccountConfiguration.?subnetResourceId ?? virtualNetwork.outputs.subnetResourceIds[0] - } - ] - : [] - sqlDatabases: concat(cosmosDbAccountConfiguration.?sqlDatabases ?? [], [ - { - name: cosmosDbDatabaseName - containers: [ - { - name: cosmosDbDatabaseMemoryContainerName - paths: [ - '/session_id' - ] - kind: 'Hash' - version: 2 - } - ] - } - ]) - locations: [ - { - locationName: cosmosDbAccountConfiguration.?location ?? solutionLocation - failoverPriority: 0 - isZoneRedundant: false - } - ] - capabilitiesToAdd: [ - 'EnableServerless' - ] - sqlRoleAssignmentsPrincipalIds: [ - containerApp.outputs.?systemAssignedMIPrincipalId - ] - sqlRoleDefinitions: [ - { - // Replace this with built-in role definition Cosmos DB Built-in Data Contributor: https://docs.azure.cn/en-us/cosmos-db/nosql/security/reference-data-plane-roles#cosmos-db-built-in-data-contributor - roleType: 'CustomRole' - roleName: 'Cosmos DB SQL Data Contributor' - name: 'cosmos-db-sql-data-contributor' - dataAction: [ - 'Microsoft.DocumentDB/databaseAccounts/readMetadata' - 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*' - 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*' - ] - } - ] - } -} - -// ========== Backend Container App Environment ========== // -// WAF best practices for container apps: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-container-apps -var containerAppEnvironmentEnabled = containerAppEnvironmentConfiguration.?enabled ?? true -var containerAppEnvironmentResourceName = containerAppEnvironmentConfiguration.?name ?? 'cae-${solutionPrefix}' -module containerAppEnvironment 'modules/container-app-environment.bicep' = if (containerAppEnvironmentEnabled) { - name: take('module.container-app-environment.${containerAppEnvironmentResourceName}', 64) - params: { - name: containerAppEnvironmentResourceName - tags: containerAppEnvironmentConfiguration.?tags ?? tags - location: containerAppEnvironmentConfiguration.?location ?? solutionLocation - logAnalyticsResourceId: logAnalyticsWorkspaceId - publicNetworkAccess: 'Enabled' - zoneRedundant: false - applicationInsightsConnectionString: applicationInsights.outputs.connectionString - enableTelemetry: enableTelemetry - subnetResourceId: virtualNetworkEnabled - ? containerAppEnvironmentConfiguration.?subnetResourceId ?? virtualNetwork.?outputs.?subnetResourceIds[3] ?? '' - : '' - } -} - -// ========== Backend Container App Service ========== // -// WAF best practices for container apps: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-container-apps -var containerAppEnabled = containerAppConfiguration.?enabled ?? true -var containerAppResourceName = containerAppConfiguration.?name ?? 'ca-${solutionPrefix}' -module containerApp 'br/public:avm/res/app/container-app:0.14.2' = if (containerAppEnabled) { - name: take('avm.res.app.container-app.${containerAppResourceName}', 64) - params: { - name: containerAppResourceName - tags: containerAppConfiguration.?tags ?? tags - location: containerAppConfiguration.?location ?? solutionLocation - enableTelemetry: enableTelemetry - environmentResourceId: containerAppConfiguration.?environmentResourceId ?? containerAppEnvironment.outputs.resourceId - managedIdentities: { - systemAssigned: true //Replace with user assigned identity - userAssignedResourceIds: [userAssignedIdentity.outputs.resourceId] - } - ingressTargetPort: containerAppConfiguration.?ingressTargetPort ?? 8000 - ingressExternal: true - activeRevisionsMode: 'Single' - corsPolicy: { - allowedOrigins: [ - 'https://${webSiteName}.azurewebsites.net' - 'http://${webSiteName}.azurewebsites.net' - ] - } - scaleSettings: { - //TODO: Make maxReplicas and minReplicas parameterized - maxReplicas: containerAppConfiguration.?maxReplicas ?? 1 - minReplicas: containerAppConfiguration.?minReplicas ?? 1 - rules: [ - { - name: 'http-scaler' - http: { - metadata: { - concurrentRequests: containerAppConfiguration.?concurrentRequests ?? '100' - } - } - } - ] - } - containers: [ - { - name: containerAppConfiguration.?containerName ?? 'backend' - image: '${containerAppConfiguration.?containerImageRegistryDomain ?? 'biabcontainerreg.azurecr.io'}/${containerAppConfiguration.?containerImageName ?? 'macaebackend'}:${containerAppConfiguration.?containerImageTag ?? 'latest'}' - resources: { - //TODO: Make cpu and memory parameterized - cpu: containerAppConfiguration.?containerCpu ?? '2.0' - memory: containerAppConfiguration.?containerMemory ?? '4.0Gi' - } - env: [ - { - name: 'COSMOSDB_ENDPOINT' - value: 'https://${cosmosDbResourceName}.documents.azure.com:443/' - } - { - name: 'COSMOSDB_DATABASE' - value: cosmosDbDatabaseName - } - { - name: 'COSMOSDB_CONTAINER' - value: cosmosDbDatabaseMemoryContainerName - } - { - name: 'AZURE_OPENAI_ENDPOINT' - value: 'https://${aiFoundryAiServicesResourceName}.openai.azure.com/' - } - { - name: 'AZURE_OPENAI_MODEL_NAME' - value: aiFoundryAiServicesModelDeployment.name - } - { - name: 'AZURE_OPENAI_DEPLOYMENT_NAME' - value: aiFoundryAiServicesModelDeployment.name - } - { - name: 'AZURE_OPENAI_API_VERSION' - value: '2025-01-01-preview' //TODO: set parameter/variable - } - { - name: 'APPLICATIONINSIGHTS_INSTRUMENTATION_KEY' - value: applicationInsights.outputs.instrumentationKey - } - { - name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' - value: applicationInsights.outputs.connectionString - } - { - name: 'AZURE_AI_SUBSCRIPTION_ID' - value: subscription().subscriptionId - } - { - name: 'AZURE_AI_RESOURCE_GROUP' - value: resourceGroup().name - } - { - name: 'AZURE_AI_PROJECT_NAME' - value: aiFoundryAiProjectName - } - { - name: 'FRONTEND_SITE_NAME' - value: 'https://${webSiteName}.azurewebsites.net' - } - { - name: 'AZURE_AI_AGENT_ENDPOINT' - value: aiFoundryAiServices.outputs.aiProjectInfo.apiEndpoint - } - { - name: 'AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME' - value: aiFoundryAiServicesModelDeployment.name - } - { - name: 'APP_ENV' - value: 'Prod' - } - ] - } - ] - } -} - -var webServerFarmEnabled = webServerFarmConfiguration.?enabled ?? true -var webServerFarmResourceName = webServerFarmConfiguration.?name ?? 'asp-${solutionPrefix}' - -// ========== Frontend server farm ========== // -// WAF best practices for web app service: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/app-service-web-apps -module webServerFarm 'br/public:avm/res/web/serverfarm:0.4.1' = if (webServerFarmEnabled) { - name: take('avm.res.web.serverfarm.${webServerFarmResourceName}', 64) - params: { - name: webServerFarmResourceName - tags: tags - location: webServerFarmConfiguration.?location ?? solutionLocation - skuName: webServerFarmConfiguration.?skuName ?? 'P1v4' - skuCapacity: webServerFarmConfiguration.?skuCapacity ?? 3 - reserved: true - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - kind: 'linux' - zoneRedundant: false //TODO: make it zone redundant for waf aligned - } -} - -// ========== Frontend web site ========== // -// WAF best practices for web app service: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/app-service-web-apps -var webSiteEnabled = webSiteConfiguration.?enabled ?? true - -var webSiteName = 'app-${solutionPrefix}' -module webSite 'br/public:avm/res/web/site:0.15.1' = if (webSiteEnabled) { - name: take('avm.res.web.site.${webSiteName}', 64) - params: { - name: webSiteName - tags: webSiteConfiguration.?tags ?? tags - location: webSiteConfiguration.?location ?? solutionLocation - kind: 'app,linux,container' - enableTelemetry: enableTelemetry - serverFarmResourceId: webSiteConfiguration.?environmentResourceId ?? webServerFarm.?outputs.resourceId - appInsightResourceId: applicationInsights.outputs.resourceId - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - publicNetworkAccess: 'Enabled' //TODO: use Azure Front Door WAF or Application Gateway WAF instead - siteConfig: { - linuxFxVersion: 'DOCKER|${webSiteConfiguration.?containerImageRegistryDomain ?? 'biabcontainerreg.azurecr.io'}/${webSiteConfiguration.?containerImageName ?? 'macaefrontend'}:${webSiteConfiguration.?containerImageTag ?? 'latest'}' - } - appSettingsKeyValuePairs: { - SCM_DO_BUILD_DURING_DEPLOYMENT: 'true' - DOCKER_REGISTRY_SERVER_URL: 'https://${webSiteConfiguration.?containerImageRegistryDomain ?? 'biabcontainerreg.azurecr.io'}' - WEBSITES_PORT: '3000' - WEBSITES_CONTAINER_START_TIME_LIMIT: '1800' // 30 minutes, adjust as needed - BACKEND_API_URL: 'https://${containerApp.outputs.fqdn}' - AUTH_ENABLED: 'false' - APP_ENV: 'Prod' - } - } -} - -// ============ // -// Outputs // -// ============ // - -// Add your outputs here - -@description('The default url of the website to connect to the Multi-Agent Custom Automation Engine solution.') -output webSiteDefaultHostname string = webSite.outputs.defaultHostname - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Log Analytics Workspace resource configuration.') -type logAnalyticsWorkspaceConfigurationType = { - @description('Optional. If the Log Analytics Workspace resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Log Analytics Workspace resource.') - @maxLength(63) - name: string? - - @description('Optional. Location for the Log Analytics Workspace resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to for the Log Analytics Workspace resource.') - tags: object? - - @description('Optional. The SKU for the Log Analytics Workspace resource.') - sku: ('CapacityReservation' | 'Free' | 'LACluster' | 'PerGB2018' | 'PerNode' | 'Premium' | 'Standalone' | 'Standard')? - - @description('Optional. The number of days to retain the data in the Log Analytics Workspace. If empty, it will be set to 365 days.') - @maxValue(730) - dataRetentionInDays: int? - - @description('Optional: Existing Log Analytics Workspace Resource ID') - existingWorkspaceResourceId: string? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Application Insights resource configuration.') -type applicationInsightsConfigurationType = { - @description('Optional. If the Application Insights resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Application Insights resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the Application Insights resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Application Insights resource.') - tags: object? - - @description('Optional. The retention of Application Insights data in days. If empty, Standard will be used.') - retentionInDays: (120 | 180 | 270 | 30 | 365 | 550 | 60 | 730 | 90)? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Application User Assigned Managed Identity resource configuration.') -type userAssignedManagedIdentityType = { - @description('Optional. If the User Assigned Managed Identity resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the User Assigned Managed Identity resource.') - @maxLength(128) - name: string? - - @description('Optional. Location for the User Assigned Managed Identity resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the User Assigned Managed Identity resource.') - tags: object? -} - -@export() -import { securityRuleType } from 'br/public:avm/res/network/network-security-group:0.5.1' -@description('The type for the Multi-Agent Custom Automation Engine Network Security Group resource configuration.') -type networkSecurityGroupConfigurationType = { - @description('Optional. If the Network Security Group resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Network Security Group resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the Network Security Group resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Network Security Group resource.') - tags: object? - - @description('Optional. The security rules to set for the Network Security Group resource.') - securityRules: securityRuleType[]? -} - -@export() -@description('The type for the Multi-Agent Custom Automation virtual network resource configuration.') -type virtualNetworkConfigurationType = { - @description('Optional. If the Virtual Network resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Virtual Network resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the Virtual Network resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Virtual Network resource.') - tags: object? - - @description('Optional. An array of 1 or more IP Addresses prefixes for the Virtual Network resource.') - addressPrefixes: string[]? - - @description('Optional. An array of 1 or more subnets for the Virtual Network resource.') - subnets: subnetType[]? -} - -import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -type subnetType = { - @description('Optional. The Name of the subnet resource.') - name: string - - @description('Conditional. The address prefix for the subnet. Required if `addressPrefixes` is empty.') - addressPrefix: string? - - @description('Conditional. List of address prefixes for the subnet. Required if `addressPrefix` is empty.') - addressPrefixes: string[]? - - @description('Optional. Application gateway IP configurations of virtual network resource.') - applicationGatewayIPConfigurations: object[]? - - @description('Optional. The delegation to enable on the subnet.') - delegation: string? - - @description('Optional. The resource ID of the NAT Gateway to use for the subnet.') - natGatewayResourceId: string? - - @description('Optional. The resource ID of the network security group to assign to the subnet.') - networkSecurityGroupResourceId: string? - - @description('Optional. enable or disable apply network policies on private endpoint in the subnet.') - privateEndpointNetworkPolicies: ('Disabled' | 'Enabled' | 'NetworkSecurityGroupEnabled' | 'RouteTableEnabled')? - - @description('Optional. enable or disable apply network policies on private link service in the subnet.') - privateLinkServiceNetworkPolicies: ('Disabled' | 'Enabled')? - - @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType[]? - - @description('Optional. The resource ID of the route table to assign to the subnet.') - routeTableResourceId: string? - - @description('Optional. An array of service endpoint policies.') - serviceEndpointPolicies: object[]? - - @description('Optional. The service endpoints to enable on the subnet.') - serviceEndpoints: string[]? - - @description('Optional. Set this property to false to disable default outbound connectivity for all VMs in the subnet. This property can only be set at the time of subnet creation and cannot be updated for an existing subnet.') - defaultOutboundAccess: bool? - - @description('Optional. Set this property to Tenant to allow sharing subnet with other subscriptions in your AAD tenant. This property can only be set if defaultOutboundAccess is set to false, both properties can only be set if subnet is empty.') - sharingScope: ('DelegatedServices' | 'Tenant')? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Bastion resource configuration.') -type bastionConfigurationType = { - @description('Optional. If the Bastion resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Bastion resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the Bastion resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Bastion resource.') - tags: object? - - @description('Optional. The SKU for the Bastion resource.') - sku: ('Basic' | 'Developer' | 'Premium' | 'Standard')? - - @description('Optional. The Virtual Network resource id where the Bastion resource should be deployed.') - virtualNetworkResourceId: string? - - @description('Optional. The name of the Public Ip resource created to connect to Bastion.') - publicIpResourceName: string? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine virtual machine resource configuration.') -type virtualMachineConfigurationType = { - @description('Optional. If the Virtual Machine resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Virtual Machine resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the Virtual Machine resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Virtual Machine resource.') - tags: object? - - @description('Optional. Specifies the size for the Virtual Machine resource.') - vmSize: ( - | 'Basic_A0' - | 'Basic_A1' - | 'Basic_A2' - | 'Basic_A3' - | 'Basic_A4' - | 'Standard_A0' - | 'Standard_A1' - | 'Standard_A2' - | 'Standard_A3' - | 'Standard_A4' - | 'Standard_A5' - | 'Standard_A6' - | 'Standard_A7' - | 'Standard_A8' - | 'Standard_A9' - | 'Standard_A10' - | 'Standard_A11' - | 'Standard_A1_v2' - | 'Standard_A2_v2' - | 'Standard_A4_v2' - | 'Standard_A8_v2' - | 'Standard_A2m_v2' - | 'Standard_A4m_v2' - | 'Standard_A8m_v2' - | 'Standard_B1s' - | 'Standard_B1ms' - | 'Standard_B2s' - | 'Standard_B2ms' - | 'Standard_B4ms' - | 'Standard_B8ms' - | 'Standard_D1' - | 'Standard_D2' - | 'Standard_D3' - | 'Standard_D4' - | 'Standard_D11' - | 'Standard_D12' - | 'Standard_D13' - | 'Standard_D14' - | 'Standard_D1_v2' - | 'Standard_D2_v2' - | 'Standard_D3_v2' - | 'Standard_D4_v2' - | 'Standard_D5_v2' - | 'Standard_D2_v4' - | 'Standard_D4_v4' - | 'Standard_D8_v4' - | 'Standard_D16_v4' - | 'Standard_D32_v4' - | 'Standard_D64_v4' - | 'Standard_D2s_v4' - | 'Standard_D4s_v4' - | 'Standard_D8s_v4' - | 'Standard_D16s_v4' - | 'Standard_D32s_v4' - | 'Standard_D64s_v4' - | 'Standard_D11_v2' - | 'Standard_D12_v2' - | 'Standard_D13_v2' - | 'Standard_D14_v2' - | 'Standard_D15_v2' - | 'Standard_DS1' - | 'Standard_DS2' - | 'Standard_DS3' - | 'Standard_DS4' - | 'Standard_DS11' - | 'Standard_DS12' - | 'Standard_DS13' - | 'Standard_DS14' - | 'Standard_DS1_v2' - | 'Standard_DS2_v2' - | 'Standard_DS3_v2' - | 'Standard_DS4_v2' - | 'Standard_DS5_v2' - | 'Standard_DS11_v2' - | 'Standard_DS12_v2' - | 'Standard_DS13_v2' - | 'Standard_DS14_v2' - | 'Standard_DS15_v2' - | 'Standard_DS13-4_v2' - | 'Standard_DS13-2_v2' - | 'Standard_DS14-8_v2' - | 'Standard_DS14-4_v2' - | 'Standard_E2_v4' - | 'Standard_E4_v4' - | 'Standard_E8_v4' - | 'Standard_E16_v4' - | 'Standard_E32_v4' - | 'Standard_E64_v4' - | 'Standard_E2s_v4' - | 'Standard_E4s_v4' - | 'Standard_E8s_v4' - | 'Standard_E16s_v4' - | 'Standard_E32s_v4' - | 'Standard_E64s_v4' - | 'Standard_E32-16_v4' - | 'Standard_E32-8s_v4' - | 'Standard_E64-32s_v4' - | 'Standard_E64-16s_v4' - | 'Standard_F1' - | 'Standard_F2' - | 'Standard_F4' - | 'Standard_F8' - | 'Standard_F16' - | 'Standard_F1s' - | 'Standard_F2s' - | 'Standard_F4s' - | 'Standard_F8s' - | 'Standard_F16s' - | 'Standard_F2s_v2' - | 'Standard_F4s_v2' - | 'Standard_F8s_v2' - | 'Standard_F16s_v2' - | 'Standard_F32s_v2' - | 'Standard_F64s_v2' - | 'Standard_F72s_v2' - | 'Standard_G1' - | 'Standard_G2' - | 'Standard_G3' - | 'Standard_G4' - | 'Standard_G5' - | 'Standard_GS1' - | 'Standard_GS2' - | 'Standard_GS3' - | 'Standard_GS4' - | 'Standard_GS5' - | 'Standard_GS4-8' - | 'Standard_GS4-4' - | 'Standard_GS5-16' - | 'Standard_GS5-8' - | 'Standard_H8' - | 'Standard_H16' - | 'Standard_H8m' - | 'Standard_H16m' - | 'Standard_H16r' - | 'Standard_H16mr' - | 'Standard_L4s' - | 'Standard_L8s' - | 'Standard_L16s' - | 'Standard_L32s' - | 'Standard_M64s' - | 'Standard_M64ms' - | 'Standard_M128s' - | 'Standard_M128ms' - | 'Standard_M64-32ms' - | 'Standard_M64-16ms' - | 'Standard_M128-64ms' - | 'Standard_M128-32ms' - | 'Standard_NC6' - | 'Standard_NC12' - | 'Standard_NC24' - | 'Standard_NC24r' - | 'Standard_NC6s_v2' - | 'Standard_NC12s_v2' - | 'Standard_NC24s_v2' - | 'Standard_NC24rs_v2' - | 'Standard_NC6s_v4' - | 'Standard_NC12s_v4' - | 'Standard_NC24s_v4' - | 'Standard_NC24rs_v4' - | 'Standard_ND6s' - | 'Standard_ND12s' - | 'Standard_ND24s' - | 'Standard_ND24rs' - | 'Standard_NV6' - | 'Standard_NV12' - | 'Standard_NV24')? - - @description('Optional. The username for the administrator account on the virtual machine. Required if a virtual machine is created as part of the module.') - adminUsername: string? - - @description('Optional. The password for the administrator account on the virtual machine. Required if a virtual machine is created as part of the module.') - @secure() - adminPassword: string? - - @description('Optional. The resource ID of the subnet where the Virtual Machine resource should be deployed.') - subnetResourceId: string? -} - -@export() -import { deploymentType } from 'br/public:avm/res/cognitive-services/account:0.10.2' -@description('The type for the Multi-Agent Custom Automation Engine AI Services resource configuration.') -type aiServicesConfigurationType = { - @description('Optional. If the AI Services resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the AI Services resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the AI Services resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the AI Services resource.') - tags: object? - - @description('Optional. The SKU of the AI Services resource. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'SKU\' for your Azure region.') - sku: ( - | 'C2' - | 'C3' - | 'C4' - | 'F0' - | 'F1' - | 'S' - | 'S0' - | 'S1' - | 'S10' - | 'S2' - | 'S3' - | 'S4' - | 'S5' - | 'S6' - | 'S7' - | 'S8' - | 'S9')? - - @description('Optional. The resource Id of the subnet where the AI Services private endpoint should be created.') - subnetResourceId: string? - - @description('Optional. The model deployments to set for the AI Services resource.') - deployments: deploymentType[]? - - @description('Optional. The capacity to set for AI Services GTP model.') - modelCapacity: int? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine AI Foundry AI Project resource configuration.') -type aiProjectConfigurationType = { - @description('Optional. If the AI Project resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the AI Project resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the AI Project resource deployment.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The SKU of the AI Project resource.') - sku: ('Basic' | 'Free' | 'Standard' | 'Premium')? - - @description('Optional. The tags to set for the AI Project resource.') - tags: object? -} - -import { sqlDatabaseType } from 'br/public:avm/res/document-db/database-account:0.13.0' -@export() -@description('The type for the Multi-Agent Custom Automation Engine Cosmos DB Account resource configuration.') -type cosmosDbAccountConfigurationType = { - @description('Optional. If the Cosmos DB Account resource should be deployed or not.') - enabled: bool? - @description('Optional. The name of the Cosmos DB Account resource.') - @maxLength(60) - name: string? - - @description('Optional. Location for the Cosmos DB Account resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Cosmos DB Account resource.') - tags: object? - - @description('Optional. The resource Id of the subnet where the Cosmos DB Account private endpoint should be created.') - subnetResourceId: string? - - @description('Optional. The SQL databases configuration for the Cosmos DB Account resource.') - sqlDatabases: sqlDatabaseType[]? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Container App Environment resource configuration.') -type containerAppEnvironmentConfigurationType = { - @description('Optional. If the Container App Environment resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Container App Environment resource.') - @maxLength(60) - name: string? - - @description('Optional. Location for the Container App Environment resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Container App Environment resource.') - tags: object? - - @description('Optional. The resource Id of the subnet where the Container App Environment private endpoint should be created.') - subnetResourceId: string? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Container App resource configuration.') -type containerAppConfigurationType = { - @description('Optional. If the Container App resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Container App resource.') - @maxLength(60) - name: string? - - @description('Optional. Location for the Container App resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Container App resource.') - tags: object? - - @description('Optional. The resource Id of the Container App Environment where the Container App should be created.') - environmentResourceId: string? - - @description('Optional. The maximum number of replicas of the Container App.') - maxReplicas: int? - - @description('Optional. The minimum number of replicas of the Container App.') - minReplicas: int? - - @description('Optional. The ingress target port of the Container App.') - ingressTargetPort: int? - - @description('Optional. The concurrent requests allowed for the Container App.') - concurrentRequests: string? - - @description('Optional. The name given to the Container App.') - containerName: string? - - @description('Optional. The container registry domain of the container image to be used by the Container App. Default to `biabcontainerreg.azurecr.io`') - containerImageRegistryDomain: string? - - @description('Optional. The name of the container image to be used by the Container App.') - containerImageName: string? - - @description('Optional. The tag of the container image to be used by the Container App.') - containerImageTag: string? - - @description('Optional. The CPU reserved for the Container App. Defaults to 2.0') - containerCpu: string? - - @description('Optional. The Memory reserved for the Container App. Defaults to 4.0Gi') - containerMemory: string? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Entra ID Application resource configuration.') -type entraIdApplicationConfigurationType = { - @description('Optional. If the Entra ID Application for website authentication should be deployed or not.') - enabled: bool? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Web Server Farm resource configuration.') -type webServerFarmConfigurationType = { - @description('Optional. If the Web Server Farm resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Web Server Farm resource.') - @maxLength(60) - name: string? - - @description('Optional. Location for the Web Server Farm resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Web Server Farm resource.') - tags: object? - - @description('Optional. The name of th SKU that will determine the tier, size and family for the Web Server Farm resource. This defaults to P1v4 to leverage availability zones.') - skuName: string? - - @description('Optional. Number of workers associated with the App Service Plan. This defaults to 3, to leverage availability zones.') - skuCapacity: int? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Web Site resource configuration.') -type webSiteConfigurationType = { - @description('Optional. If the Web Site resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Web Site resource.') - @maxLength(60) - name: string? - - @description('Optional. Location for the Web Site resource deployment.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Web Site resource.') - tags: object? - - @description('Optional. The resource Id of the Web Site Environment where the Web Site should be created.') - environmentResourceId: string? - - @description('Optional. The name given to the Container App.') - containerName: string? - - @description('Optional. The container registry domain of the container image to be used by the Web Site. Default to `biabcontainerreg.azurecr.io`') - containerImageRegistryDomain: string? - - @description('Optional. The name of the container image to be used by the Web Site.') - containerImageName: string? - - @description('Optional. The tag of the container image to be used by the Web Site.') - containerImageTag: string? -} diff --git a/infra/old/08-2025/main.parameters.json b/infra/old/08-2025/main.parameters.json deleted file mode 100644 index efab1db7f..000000000 --- a/infra/old/08-2025/main.parameters.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "aiModelDeployments": { - "value": [ - { - "name": "gpt", - "model": { - "name": "gpt-4o", - "version": "2024-08-06", - "format": "OpenAI" - }, - "sku": { - "name": "GlobalStandard", - "capacity": 140 - } - } - ] - }, - "environmentName": { - "value": "${AZURE_ENV_NAME}" - }, - "solutionLocation": { - "value": "${AZURE_LOCATION}" - }, - "aiDeploymentsLocation": { - "value": "${AZURE_ENV_OPENAI_LOCATION}" - }, - "modelDeploymentType": { - "value": "${AZURE_ENV_MODEL_DEPLOYMENT_TYPE}" - }, - "gptModelName": { - "value": "${AZURE_ENV_MODEL_NAME}" - }, - "gptModelVersion": { - "value": "${AZURE_ENV_MODEL_VERSION}" - }, - "gptModelCapacity": { - "value": "${AZURE_ENV_MODEL_CAPACITY}" - }, - "existingFoundryProjectResourceId": { - "value": "${AZURE_EXISTING_AI_PROJECT_RESOURCE_ID}" - }, - "imageTag": { - "value": "${AZURE_ENV_IMAGE_TAG}" - }, - "enableTelemetry": { - "value": "${AZURE_ENV_ENABLE_TELEMETRY}" - }, - "existingLogAnalyticsWorkspaceId": { - "value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID}" - }, - "backendExists": { - "value": "${SERVICE_BACKEND_RESOURCE_EXISTS=false}" - }, - "backendDefinition": { - "value": { - "settings": [ - { - "name": "", - "value": "${VAR}", - "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.", - "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR} to use the value of 'VAR' from the current environment." - }, - { - "name": "", - "value": "${VAR_S}", - "secret": true, - "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.", - "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR_S} to use the value of 'VAR_S' from the current environment." - } - ] - } - }, - "frontendExists": { - "value": "${SERVICE_FRONTEND_RESOURCE_EXISTS=false}" - }, - "frontendDefinition": { - "value": { - "settings": [ - { - "name": "", - "value": "${VAR}", - "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.", - "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR} to use the value of 'VAR' from the current environment." - }, - { - "name": "", - "value": "${VAR_S}", - "secret": true, - "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.", - "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR_S} to use the value of 'VAR_S' from the current environment." - } - ] - } - }, - "principalId": { - "value": "${AZURE_PRINCIPAL_ID}" - } - } -} \ No newline at end of file diff --git a/infra/old/08-2025/modules/account/main.bicep b/infra/old/08-2025/modules/account/main.bicep deleted file mode 100644 index b1fad4456..000000000 --- a/infra/old/08-2025/modules/account/main.bicep +++ /dev/null @@ -1,421 +0,0 @@ -metadata name = 'Cognitive Services' -metadata description = 'This module deploys a Cognitive Service.' - -@description('Required. The name of Cognitive Services account.') -param name string - -@description('Optional: Name for the project which needs to be created.') -param projectName string - -@description('Optional: Description for the project which needs to be created.') -param projectDescription string - -param existingFoundryProjectResourceId string = '' - -@description('Required. Kind of the Cognitive Services account. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'SKU\' for your Azure region.') -@allowed([ - 'AIServices' - 'AnomalyDetector' - 'CognitiveServices' - 'ComputerVision' - 'ContentModerator' - 'ContentSafety' - 'ConversationalLanguageUnderstanding' - 'CustomVision.Prediction' - 'CustomVision.Training' - 'Face' - 'FormRecognizer' - 'HealthInsights' - 'ImmersiveReader' - 'Internal.AllInOne' - 'LUIS' - 'LUIS.Authoring' - 'LanguageAuthoring' - 'MetricsAdvisor' - 'OpenAI' - 'Personalizer' - 'QnAMaker.v2' - 'SpeechServices' - 'TextAnalytics' - 'TextTranslation' -]) -param kind string - -@description('Optional. SKU of the Cognitive Services account. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'SKU\' for your Azure region.') -@allowed([ - 'C2' - 'C3' - 'C4' - 'F0' - 'F1' - 'S' - 'S0' - 'S1' - 'S10' - 'S2' - 'S3' - 'S4' - 'S5' - 'S6' - 'S7' - 'S8' - 'S9' -]) -param sku string = 'S0' - -@description('Optional. Location for all Resources.') -param location string = resourceGroup().location - -import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingFullType[]? - -@description('Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set and networkAcls are not set.') -@allowed([ - 'Enabled' - 'Disabled' -]) -param publicNetworkAccess string? - -@description('Conditional. Subdomain name used for token-based authentication. Required if \'networkAcls\' or \'privateEndpoints\' are set.') -param customSubDomainName string? - -@description('Optional. A collection of rules governing the accessibility from specific network locations.') -param networkAcls object? - -import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') -param privateEndpoints privateEndpointSingleServiceType[]? - -import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. The lock settings of the service.') -param lock lockType? - -import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType[]? - -@description('Optional. Tags of the resource.') -param tags object? - -@description('Optional. List of allowed FQDN.') -param allowedFqdnList array? - -@description('Optional. The API properties for special APIs.') -param apiProperties object? - -@description('Optional. Allow only Azure AD authentication. Should be enabled for security reasons.') -param disableLocalAuth bool = true - -import { customerManagedKeyType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. The customer managed key definition.') -param customerManagedKey customerManagedKeyType? - -@description('Optional. The flag to enable dynamic throttling.') -param dynamicThrottlingEnabled bool = false - -@secure() -@description('Optional. Resource migration token.') -param migrationToken string? - -@description('Optional. Restore a soft-deleted cognitive service at deployment time. Will fail if no such soft-deleted resource exists.') -param restore bool = false - -@description('Optional. Restrict outbound network access.') -param restrictOutboundNetworkAccess bool = true - -@description('Optional. The storage accounts for this resource.') -param userOwnedStorage array? - -import { managedIdentityAllType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. The managed identity definition for this resource.') -param managedIdentities managedIdentityAllType? - -@description('Optional. Enable/Disable usage telemetry for module.') -param enableTelemetry bool = true - -@description('Optional. Array of deployments about cognitive service accounts to create.') -param deployments deploymentType[]? - -@description('Optional. Key vault reference and secret settings for the module\'s secrets export.') -param secretsExportConfiguration secretsExportConfigurationType? - -@description('Optional. Enable/Disable project management feature for AI Foundry.') -param allowProjectManagement bool? - -var formattedUserAssignedIdentities = reduce( - map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), - {}, - (cur, next) => union(cur, next) -) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } - -var identity = !empty(managedIdentities) - ? { - type: (managedIdentities.?systemAssigned ?? false) - ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned, UserAssigned' : 'SystemAssigned') - : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null) - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null - } - : null - -#disable-next-line no-deployments-resources -resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableTelemetry) { - name: '46d3xbcp.res.cognitiveservices-account.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' - } - } - } - } -} - -resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-07-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { - name: last(split(customerManagedKey.?keyVaultResourceId!, '/')) - scope: resourceGroup( - split(customerManagedKey.?keyVaultResourceId!, '/')[2], - split(customerManagedKey.?keyVaultResourceId!, '/')[4] - ) - - resource cMKKey 'keys@2023-07-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { - name: customerManagedKey.?keyName! - } -} - -resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2025-01-31-preview' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { - name: last(split(customerManagedKey.?userAssignedIdentityResourceId!, '/')) - scope: resourceGroup( - split(customerManagedKey.?userAssignedIdentityResourceId!, '/')[2], - split(customerManagedKey.?userAssignedIdentityResourceId!, '/')[4] - ) -} - -var useExistingService = !empty(existingFoundryProjectResourceId) - -resource cognitiveServiceNew 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = if(!useExistingService) { - name: name - kind: kind - identity: identity - location: location - tags: tags - sku: { - name: sku - } - properties: { - allowProjectManagement: allowProjectManagement // allows project management for Cognitive Services accounts in AI Foundry - FDP updates - customSubDomainName: customSubDomainName - networkAcls: !empty(networkAcls ?? {}) - ? { - defaultAction: networkAcls.?defaultAction - virtualNetworkRules: networkAcls.?virtualNetworkRules ?? [] - ipRules: networkAcls.?ipRules ?? [] - } - : null - publicNetworkAccess: publicNetworkAccess != null - ? publicNetworkAccess - : (!empty(networkAcls) ? 'Enabled' : 'Disabled') - allowedFqdnList: allowedFqdnList - apiProperties: apiProperties - disableLocalAuth: disableLocalAuth - encryption: !empty(customerManagedKey) - ? { - keySource: 'Microsoft.KeyVault' - keyVaultProperties: { - identityClientId: !empty(customerManagedKey.?userAssignedIdentityResourceId ?? '') - ? cMKUserAssignedIdentity.properties.clientId - : null - keyVaultUri: cMKKeyVault.properties.vaultUri - keyName: customerManagedKey!.keyName - keyVersion: !empty(customerManagedKey.?keyVersion ?? '') - ? customerManagedKey!.?keyVersion - : last(split(cMKKeyVault::cMKKey.properties.keyUriWithVersion, '/')) - } - } - : null - migrationToken: migrationToken - restore: restore - restrictOutboundNetworkAccess: restrictOutboundNetworkAccess - userOwnedStorage: userOwnedStorage - dynamicThrottlingEnabled: dynamicThrottlingEnabled - } -} - -var existingCognitiveServiceDetails = split(existingFoundryProjectResourceId, '/') - -resource cognitiveServiceExisting 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing = if(useExistingService) { - name: existingCognitiveServiceDetails[8] - scope: resourceGroup(existingCognitiveServiceDetails[2], existingCognitiveServiceDetails[4]) -} - -module cognigive_service_dependencies 'modules/dependencies.bicep' = if(!useExistingService) { - params: { - projectName: projectName - projectDescription: projectDescription - name: cognitiveServiceNew.name - location: location - deployments: deployments - diagnosticSettings: diagnosticSettings - lock: lock - privateEndpoints: privateEndpoints - roleAssignments: roleAssignments - secretsExportConfiguration: secretsExportConfiguration - sku: sku - tags: tags - } -} - -module existing_cognigive_service_dependencies 'modules/dependencies.bicep' = if(useExistingService) { - params: { - name: cognitiveServiceExisting.name - projectName: projectName - projectDescription: projectDescription - azureExistingAIProjectResourceId: existingFoundryProjectResourceId - location: location - deployments: deployments - diagnosticSettings: diagnosticSettings - lock: lock - privateEndpoints: privateEndpoints - roleAssignments: roleAssignments - secretsExportConfiguration: secretsExportConfiguration - sku: sku - tags: tags - } - scope: resourceGroup(existingCognitiveServiceDetails[2], existingCognitiveServiceDetails[4]) -} - -var cognitiveService = useExistingService ? cognitiveServiceExisting : cognitiveServiceNew - -@description('The name of the cognitive services account.') -output name string = useExistingService ? cognitiveServiceExisting.name : cognitiveServiceNew.name - -@description('The resource ID of the cognitive services account.') -output resourceId string = useExistingService ? cognitiveServiceExisting.id : cognitiveServiceNew.id - -@description('The resource group the cognitive services account was deployed into.') -output subscriptionId string = useExistingService ? existingCognitiveServiceDetails[2] : subscription().subscriptionId - -@description('The resource group the cognitive services account was deployed into.') -output resourceGroupName string = useExistingService ? existingCognitiveServiceDetails[4] : resourceGroup().name - -@description('The service endpoint of the cognitive services account.') -output endpoint string = useExistingService ? cognitiveServiceExisting.properties.endpoint : cognitiveService.properties.endpoint - -@description('All endpoints available for the cognitive services account, types depends on the cognitive service kind.') -output endpoints endpointType = useExistingService ? cognitiveServiceExisting.properties.endpoints : cognitiveService.properties.endpoints - -@description('The principal ID of the system assigned identity.') -output systemAssignedMIPrincipalId string? = useExistingService ? cognitiveServiceExisting.identity.principalId : cognitiveService.?identity.?principalId - -@description('The location the resource was deployed into.') -output location string = useExistingService ? cognitiveServiceExisting.location : cognitiveService.location - -import { secretsOutputType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('A hashtable of references to the secrets exported to the provided Key Vault. The key of each reference is each secret\'s name.') -output exportedSecrets secretsOutputType = useExistingService ? existing_cognigive_service_dependencies.outputs.exportedSecrets : cognigive_service_dependencies.outputs.exportedSecrets - -@description('The private endpoints of the congitive services account.') -output privateEndpoints privateEndpointOutputType[] = useExistingService ? existing_cognigive_service_dependencies.outputs.privateEndpoints : cognigive_service_dependencies.outputs.privateEndpoints - -import { aiProjectOutputType } from './modules/project.bicep' -output aiProjectInfo aiProjectOutputType = useExistingService ? existing_cognigive_service_dependencies.outputs.aiProjectInfo : cognigive_service_dependencies.outputs.aiProjectInfo - -// ================ // -// Definitions // -// ================ // - -@export() -@description('The type for the private endpoint output.') -type privateEndpointOutputType = { - @description('The name of the private endpoint.') - name: string - - @description('The resource ID of the private endpoint.') - resourceId: string - - @description('The group Id for the private endpoint Group.') - groupId: string? - - @description('The custom DNS configurations of the private endpoint.') - customDnsConfigs: { - @description('FQDN that resolves to private endpoint IP address.') - fqdn: string? - - @description('A list of private IP addresses of the private endpoint.') - ipAddresses: string[] - }[] - - @description('The IDs of the network interfaces associated with the private endpoint.') - networkInterfaceResourceIds: string[] -} - -@export() -@description('The type for a cognitive services account deployment.') -type deploymentType = { - @description('Optional. Specify the name of cognitive service account deployment.') - name: string? - - @description('Required. Properties of Cognitive Services account deployment model.') - model: { - @description('Required. The name of Cognitive Services account deployment model.') - name: string - - @description('Required. The format of Cognitive Services account deployment model.') - format: string - - @description('Required. The version of Cognitive Services account deployment model.') - version: string - } - - @description('Optional. The resource model definition representing SKU.') - sku: { - @description('Required. The name of the resource model definition representing SKU.') - name: string - - @description('Optional. The capacity of the resource model definition representing SKU.') - capacity: int? - - @description('Optional. The tier of the resource model definition representing SKU.') - tier: string? - - @description('Optional. The size of the resource model definition representing SKU.') - size: string? - - @description('Optional. The family of the resource model definition representing SKU.') - family: string? - }? - - @description('Optional. The name of RAI policy.') - raiPolicyName: string? - - @description('Optional. The version upgrade option.') - versionUpgradeOption: string? -} - -@export() -@description('The type for a cognitive services account endpoint.') -type endpointType = { - @description('Type of the endpoint.') - name: string? - @description('The endpoint URI.') - endpoint: string? -} - -@export() -@description('The type of the secrets exported to the provided Key Vault.') -type secretsExportConfigurationType = { - @description('Required. The key vault name where to store the keys and connection strings generated by the modules.') - keyVaultResourceId: string - - @description('Optional. The name for the accessKey1 secret to create.') - accessKey1Name: string? - - @description('Optional. The name for the accessKey2 secret to create.') - accessKey2Name: string? -} diff --git a/infra/old/08-2025/modules/account/modules/dependencies.bicep b/infra/old/08-2025/modules/account/modules/dependencies.bicep deleted file mode 100644 index c2d7de6f8..000000000 --- a/infra/old/08-2025/modules/account/modules/dependencies.bicep +++ /dev/null @@ -1,479 +0,0 @@ -@description('Required. The name of Cognitive Services account.') -param name string - -@description('Optional. SKU of the Cognitive Services account. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'SKU\' for your Azure region.') -@allowed([ - 'C2' - 'C3' - 'C4' - 'F0' - 'F1' - 'S' - 'S0' - 'S1' - 'S10' - 'S2' - 'S3' - 'S4' - 'S5' - 'S6' - 'S7' - 'S8' - 'S9' -]) -param sku string = 'S0' - -@description('Optional. Location for all Resources.') -param location string = resourceGroup().location - -@description('Optional. Tags of the resource.') -param tags object? - -@description('Optional. Array of deployments about cognitive service accounts to create.') -param deployments deploymentType[]? - -@description('Optional. Key vault reference and secret settings for the module\'s secrets export.') -param secretsExportConfiguration secretsExportConfigurationType? - -import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') -param privateEndpoints privateEndpointSingleServiceType[]? - -import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. The lock settings of the service.') -param lock lockType? - -import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType[]? - -import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingFullType[]? - -@description('Optional: Name for the project which needs to be created.') -param projectName string - -@description('Optional: Description for the project which needs to be created.') -param projectDescription string - -@description('Optional: Provide the existing project resource id in case if it needs to be reused') -param azureExistingAIProjectResourceId string = '' - -var builtInRoleNames = { - 'Cognitive Services Contributor': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' - ) - 'Cognitive Services Custom Vision Contributor': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' - ) - 'Cognitive Services Custom Vision Deployment': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '5c4089e1-6d96-4d2f-b296-c1bc7137275f' - ) - 'Cognitive Services Custom Vision Labeler': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '88424f51-ebe7-446f-bc41-7fa16989e96c' - ) - 'Cognitive Services Custom Vision Reader': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '93586559-c37d-4a6b-ba08-b9f0940c2d73' - ) - 'Cognitive Services Custom Vision Trainer': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' - ) - 'Cognitive Services Data Reader (Preview)': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'b59867f0-fa02-499b-be73-45a86b5b3e1c' - ) - 'Cognitive Services Face Recognizer': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '9894cab4-e18a-44aa-828b-cb588cd6f2d7' - ) - 'Cognitive Services Immersive Reader User': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'b2de6794-95db-4659-8781-7e080d3f2b9d' - ) - 'Cognitive Services Language Owner': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f07febfe-79bc-46b1-8b37-790e26e6e498' - ) - 'Cognitive Services Language Reader': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '7628b7b8-a8b2-4cdc-b46f-e9b35248918e' - ) - 'Cognitive Services Language Writer': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f2310ca1-dc64-4889-bb49-c8e0fa3d47a8' - ) - 'Cognitive Services LUIS Owner': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f72c8140-2111-481c-87ff-72b910f6e3f8' - ) - 'Cognitive Services LUIS Reader': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '18e81cdc-4e98-4e29-a639-e7d10c5a6226' - ) - 'Cognitive Services LUIS Writer': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '6322a993-d5c9-4bed-b113-e49bbea25b27' - ) - 'Cognitive Services Metrics Advisor Administrator': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'cb43c632-a144-4ec5-977c-e80c4affc34a' - ) - 'Cognitive Services Metrics Advisor User': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '3b20f47b-3825-43cb-8114-4bd2201156a8' - ) - 'Cognitive Services OpenAI Contributor': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'a001fd3d-188f-4b5d-821b-7da978bf7442' - ) - 'Cognitive Services OpenAI User': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' - ) - 'Cognitive Services QnA Maker Editor': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f4cc2bf9-21be-47a1-bdf1-5c5804381025' - ) - 'Cognitive Services QnA Maker Reader': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '466ccd10-b268-4a11-b098-b4849f024126' - ) - 'Cognitive Services Speech Contributor': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '0e75ca1e-0464-4b4d-8b93-68208a576181' - ) - 'Cognitive Services Speech User': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f2dc8367-1007-4938-bd23-fe263f013447' - ) - 'Cognitive Services User': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'a97b65f3-24c7-4388-baec-2e87135dc908' - ) - 'Azure AI Developer': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '64702f94-c441-49e6-a78b-ef80e0188fee' - ) - Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') - Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - 'Role Based Access Control Administrator': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' - ) - 'User Access Administrator': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' - ) -} - -var formattedRoleAssignments = [ - for (roleAssignment, index) in (roleAssignments ?? []): union(roleAssignment, { - roleDefinitionId: builtInRoleNames[?roleAssignment.roleDefinitionIdOrName] ?? (contains( - roleAssignment.roleDefinitionIdOrName, - '/providers/Microsoft.Authorization/roleDefinitions/' - ) - ? roleAssignment.roleDefinitionIdOrName - : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName)) - }) -] - -var enableReferencedModulesTelemetry = false - -resource cognitiveService 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing = { - name: name -} - -@batchSize(1) -resource cognitiveService_deployments 'Microsoft.CognitiveServices/accounts/deployments@2025-04-01-preview' = [ - for (deployment, index) in (deployments ?? []): { - parent: cognitiveService - name: deployment.?name ?? '${name}-deployments' - properties: { - model: deployment.model - raiPolicyName: deployment.?raiPolicyName - versionUpgradeOption: deployment.?versionUpgradeOption - } - sku: deployment.?sku ?? { - name: sku - capacity: sku.?capacity - tier: sku.?tier - size: sku.?size - family: sku.?family - } - } -] - -resource cognitiveService_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { - name: lock.?name ?? 'lock-${name}' - properties: { - level: lock.?kind ?? '' - notes: lock.?kind == 'CanNotDelete' - ? 'Cannot delete resource or child resources.' - : 'Cannot delete or modify the resource or child resources.' - } - scope: cognitiveService -} - -resource cognitiveService_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ - for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [ - for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - } - ] - logs: [ - for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - } - ] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType - } - scope: cognitiveService - } -] - -module cognitiveService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.11.0' = [ - for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-cognitiveService-PrivateEndpoint-${index}' - scope: resourceGroup( - split(privateEndpoint.?resourceGroupResourceId ?? resourceGroup().id, '/')[2], - split(privateEndpoint.?resourceGroupResourceId ?? resourceGroup().id, '/')[4] - ) - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - privateLinkServiceConnections: privateEndpoint.?isManualConnection != true - ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - properties: { - privateLinkServiceId: cognitiveService.id - groupIds: [ - privateEndpoint.?service ?? 'account' - ] - } - } - ] - : null - manualPrivateLinkServiceConnections: privateEndpoint.?isManualConnection == true - ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - properties: { - privateLinkServiceId: cognitiveService.id - groupIds: [ - privateEndpoint.?service ?? 'account' - ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] - : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: enableReferencedModulesTelemetry - location: privateEndpoint.?location ?? reference( - split(privateEndpoint.subnetResourceId, '/subnets/')[0], - '2020-06-01', - 'Full' - ).location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroup: privateEndpoint.?privateDnsZoneGroup - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName - } - } -] - -resource cognitiveService_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ - for (roleAssignment, index) in (formattedRoleAssignments ?? []): { - name: roleAssignment.?name ?? guid(cognitiveService.id, roleAssignment.principalId, roleAssignment.roleDefinitionId) - properties: { - roleDefinitionId: roleAssignment.roleDefinitionId - principalId: roleAssignment.principalId - description: roleAssignment.?description - principalType: roleAssignment.?principalType - condition: roleAssignment.?condition - conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set - delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId - } - scope: cognitiveService - } -] - -module secretsExport './keyVaultExport.bicep' = if (secretsExportConfiguration != null) { - name: '${uniqueString(deployment().name, location)}-secrets-kv' - scope: resourceGroup( - split(secretsExportConfiguration.?keyVaultResourceId!, '/')[2], - split(secretsExportConfiguration.?keyVaultResourceId!, '/')[4] - ) - params: { - keyVaultName: last(split(secretsExportConfiguration.?keyVaultResourceId!, '/')) - secretsToSet: union( - [], - contains(secretsExportConfiguration!, 'accessKey1Name') - ? [ - { - name: secretsExportConfiguration!.?accessKey1Name - value: cognitiveService.listKeys().key1 - } - ] - : [], - contains(secretsExportConfiguration!, 'accessKey2Name') - ? [ - { - name: secretsExportConfiguration!.?accessKey2Name - value: cognitiveService.listKeys().key2 - } - ] - : [] - ) - } -} - -module aiProject 'project.bicep' = if(!empty(projectName) || !empty(azureExistingAIProjectResourceId)) { - name: take('${name}-ai-project-${projectName}-deployment', 64) - params: { - name: projectName - desc: projectDescription - aiServicesName: cognitiveService.name - location: location - tags: tags - azureExistingAIProjectResourceId: azureExistingAIProjectResourceId - } -} - -import { secretsOutputType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('A hashtable of references to the secrets exported to the provided Key Vault. The key of each reference is each secret\'s name.') -output exportedSecrets secretsOutputType = (secretsExportConfiguration != null) - ? toObject(secretsExport.outputs.secretsSet, secret => last(split(secret.secretResourceId, '/')), secret => secret) - : {} - -@description('The private endpoints of the congitive services account.') -output privateEndpoints privateEndpointOutputType[] = [ - for (pe, index) in (privateEndpoints ?? []): { - name: cognitiveService_privateEndpoints[index].outputs.name - resourceId: cognitiveService_privateEndpoints[index].outputs.resourceId - groupId: cognitiveService_privateEndpoints[index].outputs.?groupId! - customDnsConfigs: cognitiveService_privateEndpoints[index].outputs.customDnsConfigs - networkInterfaceResourceIds: cognitiveService_privateEndpoints[index].outputs.networkInterfaceResourceIds - } -] - -import { aiProjectOutputType } from 'project.bicep' -output aiProjectInfo aiProjectOutputType = aiProject.outputs.aiProjectInfo - -// ================ // -// Definitions // -// ================ // - -@export() -@description('The type for the private endpoint output.') -type privateEndpointOutputType = { - @description('The name of the private endpoint.') - name: string - - @description('The resource ID of the private endpoint.') - resourceId: string - - @description('The group Id for the private endpoint Group.') - groupId: string? - - @description('The custom DNS configurations of the private endpoint.') - customDnsConfigs: { - @description('FQDN that resolves to private endpoint IP address.') - fqdn: string? - - @description('A list of private IP addresses of the private endpoint.') - ipAddresses: string[] - }[] - - @description('The IDs of the network interfaces associated with the private endpoint.') - networkInterfaceResourceIds: string[] -} - -@export() -@description('The type for a cognitive services account deployment.') -type deploymentType = { - @description('Optional. Specify the name of cognitive service account deployment.') - name: string? - - @description('Required. Properties of Cognitive Services account deployment model.') - model: { - @description('Required. The name of Cognitive Services account deployment model.') - name: string - - @description('Required. The format of Cognitive Services account deployment model.') - format: string - - @description('Required. The version of Cognitive Services account deployment model.') - version: string - } - - @description('Optional. The resource model definition representing SKU.') - sku: { - @description('Required. The name of the resource model definition representing SKU.') - name: string - - @description('Optional. The capacity of the resource model definition representing SKU.') - capacity: int? - - @description('Optional. The tier of the resource model definition representing SKU.') - tier: string? - - @description('Optional. The size of the resource model definition representing SKU.') - size: string? - - @description('Optional. The family of the resource model definition representing SKU.') - family: string? - }? - - @description('Optional. The name of RAI policy.') - raiPolicyName: string? - - @description('Optional. The version upgrade option.') - versionUpgradeOption: string? -} - -@export() -@description('The type for a cognitive services account endpoint.') -type endpointType = { - @description('Type of the endpoint.') - name: string? - @description('The endpoint URI.') - endpoint: string? -} - -@export() -@description('The type of the secrets exported to the provided Key Vault.') -type secretsExportConfigurationType = { - @description('Required. The key vault name where to store the keys and connection strings generated by the modules.') - keyVaultResourceId: string - - @description('Optional. The name for the accessKey1 secret to create.') - accessKey1Name: string? - - @description('Optional. The name for the accessKey2 secret to create.') - accessKey2Name: string? -} diff --git a/infra/old/08-2025/modules/account/modules/keyVaultExport.bicep b/infra/old/08-2025/modules/account/modules/keyVaultExport.bicep deleted file mode 100644 index a54cc5576..000000000 --- a/infra/old/08-2025/modules/account/modules/keyVaultExport.bicep +++ /dev/null @@ -1,43 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. The name of the Key Vault to set the ecrets in.') -param keyVaultName string - -import { secretToSetType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Required. The secrets to set in the Key Vault.') -param secretsToSet secretToSetType[] - -// ============= // -// Resources // -// ============= // - -resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' existing = { - name: keyVaultName -} - -resource secrets 'Microsoft.KeyVault/vaults/secrets@2023-07-01' = [ - for secret in secretsToSet: { - name: secret.name - parent: keyVault - properties: { - value: secret.value - } - } -] - -// =========== // -// Outputs // -// =========== // - -import { secretSetOutputType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('The references to the secrets exported to the provided Key Vault.') -output secretsSet secretSetOutputType[] = [ - #disable-next-line outputs-should-not-contain-secrets // Only returning the references, not a secret value - for index in range(0, length(secretsToSet ?? [])): { - secretResourceId: secrets[index].id - secretUri: secrets[index].properties.secretUri - secretUriWithVersion: secrets[index].properties.secretUriWithVersion - } -] diff --git a/infra/old/08-2025/modules/account/modules/project.bicep b/infra/old/08-2025/modules/account/modules/project.bicep deleted file mode 100644 index 8ca346546..000000000 --- a/infra/old/08-2025/modules/account/modules/project.bicep +++ /dev/null @@ -1,61 +0,0 @@ -@description('Required. Name of the AI Services project.') -param name string - -@description('Required. The location of the Project resource.') -param location string = resourceGroup().location - -@description('Optional. The description of the AI Foundry project to create. Defaults to the project name.') -param desc string = name - -@description('Required. Name of the existing Cognitive Services resource to create the AI Foundry project in.') -param aiServicesName string - -@description('Optional. Tags to be applied to the resources.') -param tags object = {} - -@description('Optional. Use this parameter to use an existing AI project resource ID from different resource group') -param azureExistingAIProjectResourceId string = '' - -// // Extract components from existing AI Project Resource ID if provided -var useExistingProject = !empty(azureExistingAIProjectResourceId) -var existingProjName = useExistingProject ? last(split(azureExistingAIProjectResourceId, '/')) : '' -var existingProjEndpoint = useExistingProject ? format('https://{0}.services.ai.azure.com/api/projects/{1}', aiServicesName, existingProjName) : '' -// Reference to cognitive service in current resource group for new projects -resource cogServiceReference 'Microsoft.CognitiveServices/accounts@2024-10-01' existing = { - name: aiServicesName -} - -// Create new AI project only if not reusing existing one -resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' = if(!useExistingProject) { - parent: cogServiceReference - name: name - tags: tags - location: location - identity: { - type: 'SystemAssigned' - } - properties: { - description: desc - displayName: name - } -} - -@description('AI Project metadata including name, resource ID, and API endpoint.') -output aiProjectInfo aiProjectOutputType = { - name: useExistingProject ? existingProjName : aiProject.name - resourceId: useExistingProject ? azureExistingAIProjectResourceId : aiProject.id - apiEndpoint: useExistingProject ? existingProjEndpoint : aiProject.properties.endpoints['AI Foundry API'] -} - -@export() -@description('Output type representing AI project information.') -type aiProjectOutputType = { - @description('Required. Name of the AI project.') - name: string - - @description('Required. Resource ID of the AI project.') - resourceId: string - - @description('Required. API endpoint for the AI project.') - apiEndpoint: string -} diff --git a/infra/old/08-2025/modules/ai-hub.bicep b/infra/old/08-2025/modules/ai-hub.bicep deleted file mode 100644 index c92acff92..000000000 --- a/infra/old/08-2025/modules/ai-hub.bicep +++ /dev/null @@ -1,62 +0,0 @@ -param name string -param tags object -param location string -param sku string -param storageAccountResourceId string -param logAnalyticsWorkspaceResourceId string -param applicationInsightsResourceId string -param aiFoundryAiServicesName string -param enableTelemetry bool -param virtualNetworkEnabled bool -import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.4.0' -param privateEndpoints privateEndpointSingleServiceType[] - -resource aiServices 'Microsoft.CognitiveServices/accounts@2023-05-01' existing = { - name: aiFoundryAiServicesName -} - -module aiFoundryAiHub 'br/public:avm/res/machine-learning-services/workspace:0.10.1' = { - name: take('avm.res.machine-learning-services.workspace.${name}', 64) - params: { - name: name - tags: tags - location: location - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] - kind: 'Hub' - sku: sku - description: 'AI Hub for Multi Agent Custom Automation Engine Solution Accelerator template' - //associatedKeyVaultResourceId: keyVaultResourceId - associatedStorageAccountResourceId: storageAccountResourceId - associatedApplicationInsightsResourceId: applicationInsightsResourceId - connections: [ - { - name: 'connection-AzureOpenAI' - category: 'AIServices' - target: aiServices.properties.endpoint - isSharedToAll: true - metadata: { - ApiType: 'Azure' - ResourceId: aiServices.id - } - connectionProperties: { - authType: 'ApiKey' - credentials: { - key: aiServices.listKeys().key1 - } - } - } - ] - //publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled' - publicNetworkAccess: 'Enabled' //TODO: connection via private endpoint is not working from containers network. Change this when fixed - managedNetworkSettings: virtualNetworkEnabled - ? { - isolationMode: 'AllowInternetOutbound' - outboundRules: null //TODO: Refine this - } - : null - privateEndpoints: privateEndpoints - } -} - -output resourceId string = aiFoundryAiHub.outputs.resourceId diff --git a/infra/old/08-2025/modules/container-app-environment.bicep b/infra/old/08-2025/modules/container-app-environment.bicep deleted file mode 100644 index 0fc2721f2..000000000 --- a/infra/old/08-2025/modules/container-app-environment.bicep +++ /dev/null @@ -1,93 +0,0 @@ -param name string -param location string -param logAnalyticsResourceId string -param tags object -param publicNetworkAccess string -//param vnetConfiguration object -param zoneRedundant bool -//param aspireDashboardEnabled bool -param enableTelemetry bool -param subnetResourceId string -param applicationInsightsConnectionString string - -var logAnalyticsSubscription = split(logAnalyticsResourceId, '/')[2] -var logAnalyticsResourceGroup = split(logAnalyticsResourceId, '/')[4] -var logAnalyticsName = split(logAnalyticsResourceId, '/')[8] - -resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-08-01' existing = { - name: logAnalyticsName - scope: resourceGroup(logAnalyticsSubscription, logAnalyticsResourceGroup) -} - -// resource containerAppEnvironment 'Microsoft.App/managedEnvironments@2024-08-02-preview' = { -// name: name -// location: location -// tags: tags -// properties: { -// //daprAIConnectionString: appInsights.properties.ConnectionString -// //daprAIConnectionString: applicationInsights.outputs.connectionString -// appLogsConfiguration: { -// destination: 'log-analytics' -// logAnalyticsConfiguration: { -// customerId: logAnalyticsWorkspace.properties.customerId -// #disable-next-line use-secure-value-for-secure-inputs -// sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey -// } -// } -// workloadProfiles: [ -// //THIS IS REQUIRED TO ADD PRIVATE ENDPOINTS -// { -// name: 'Consumption' -// workloadProfileType: 'Consumption' -// } -// ] -// publicNetworkAccess: publicNetworkAccess -// vnetConfiguration: vnetConfiguration -// zoneRedundant: zoneRedundant -// } -// } - -module containerAppEnvironment 'br/public:avm/res/app/managed-environment:0.11.1' = { - name: take('avm.res.app.managed-environment.${name}', 64) - params: { - name: name - location: location - tags: tags - enableTelemetry: enableTelemetry - //daprAIConnectionString: applicationInsights.outputs.connectionString //Troubleshoot: ContainerAppsConfiguration.DaprAIConnectionString is invalid. DaprAIConnectionString can not be set when AppInsightsConfiguration has been set, please set DaprAIConnectionString to null. (Code:InvalidRequestParameterWithDetails - appLogsConfiguration: { - destination: 'log-analytics' - logAnalyticsConfiguration: { - customerId: logAnalyticsWorkspace.properties.customerId - #disable-next-line use-secure-value-for-secure-inputs - sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey - } - } - workloadProfiles: [ - //THIS IS REQUIRED TO ADD PRIVATE ENDPOINTS - { - name: 'Consumption' - workloadProfileType: 'Consumption' - } - ] - publicNetworkAccess: publicNetworkAccess - appInsightsConnectionString: applicationInsightsConnectionString - zoneRedundant: zoneRedundant - infrastructureSubnetResourceId: subnetResourceId - internal: false - } -} - -//TODO: FIX when deployed to vnet. This needs access to Azure to work -// resource aspireDashboard 'Microsoft.App/managedEnvironments/dotNetComponents@2024-10-02-preview' = if (aspireDashboardEnabled) { -// parent: containerAppEnvironment -// name: 'aspire-dashboard' -// properties: { -// componentType: 'AspireDashboard' -// } -// } - -//output resourceId string = containerAppEnvironment.id -output resourceId string = containerAppEnvironment.outputs.resourceId -//output location string = containerAppEnvironment.location -output location string = containerAppEnvironment.outputs.location diff --git a/infra/old/08-2025/modules/fetch-container-image.bicep b/infra/old/08-2025/modules/fetch-container-image.bicep deleted file mode 100644 index 78d1e7eeb..000000000 --- a/infra/old/08-2025/modules/fetch-container-image.bicep +++ /dev/null @@ -1,8 +0,0 @@ -param exists bool -param name string - -resource existingApp 'Microsoft.App/containerApps@2023-05-02-preview' existing = if (exists) { - name: name -} - -output containers array = exists ? existingApp.properties.template.containers : [] diff --git a/infra/old/08-2025/modules/role.bicep b/infra/old/08-2025/modules/role.bicep deleted file mode 100644 index cf8251635..000000000 --- a/infra/old/08-2025/modules/role.bicep +++ /dev/null @@ -1,58 +0,0 @@ -@description('The name of the role assignment resource. Typically generated using `guid()` for uniqueness.') -param name string - -@description('The object ID of the principal (user, group, or service principal) to whom the role will be assigned.') -param principalId string - -@description('The name of the existing Azure Cognitive Services account.') -param aiServiceName string - - -@allowed(['Device', 'ForeignGroup', 'Group', 'ServicePrincipal', 'User']) -param principalType string = 'ServicePrincipal' - -resource cognitiveServiceExisting 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing = { - name: aiServiceName -} - -resource aiUser 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - name: '53ca6127-db72-4b80-b1b0-d745d6d5456d' -} - -resource aiDeveloper 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - name: '64702f94-c441-49e6-a78b-ef80e0188fee' -} - -resource cognitiveServiceOpenAIUser 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - name: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' -} - -resource aiUserAccessFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(name, 'aiUserAccessFoundry') - scope: cognitiveServiceExisting - properties: { - roleDefinitionId: aiUser.id - principalId: principalId - principalType: principalType - } -} - -resource aiDeveloperAccessFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(name, 'aiDeveloperAccessFoundry') - scope: cognitiveServiceExisting - properties: { - roleDefinitionId: aiDeveloper.id - principalId: principalId - principalType: principalType - } -} - -resource cognitiveServiceOpenAIUserAccessFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(name, 'cognitiveServiceOpenAIUserAccessFoundry') - scope: cognitiveServiceExisting - properties: { - roleDefinitionId: cognitiveServiceOpenAIUser.id - principalId: principalId - principalType: principalType - } -}