Skip to content

Commit 548b8dd

Browse files
committed
feat(infra): Add private networking ACI deployment with managed identity
Infrastructure: - Add skipContainerDeployment parameter for 2-phase ACI deployment - Add container-instance.bicep module with UserAssigned identity - Add virtualNetwork.bicep module with NSGs and subnet config - Add main.parameters.json for azd env variable mapping - Update azure.yaml with workflow for automatic image build/push Scripts: - Add assign_aci_roles.sh for ACI role assignments - Add local_dev.sh/ps1 for local development - Add product_ingestion.py for data loading - Add scripts/README.md documentation Frontend: - Remove unused components (BriefConfirmation, ProductSelector) - Fix scroll behavior in ChatPanel - Update frontend build assets Backend: - Clean up unused models and imports - Remove debug logging Deployment flow: 1. First provision creates ACR, skips ACI (no image yet) 2. postprovision hook builds/pushes image to ACR 3. Re-runs provision to deploy ACI with image
1 parent 5ac9a80 commit 548b8dd

25 files changed

Lines changed: 3049 additions & 1124 deletions

content-gen/.env.template

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
# Azure Authentication
66
# =============================================================================
77
AZURE_CLIENT_ID=
8-
AZURE_TENANT_ID=
9-
AZURE_SUBSCRIPTION_ID=
108

119
# =============================================================================
1210
# Azure OpenAI Configuration
@@ -32,13 +30,6 @@ AZURE_OPENAI_PREVIEW_API_VERSION=2024-02-01
3230
AZURE_OPENAI_TEMPERATURE=0.7
3331
AZURE_OPENAI_MAX_TOKENS=2000
3432

35-
# =============================================================================
36-
# Azure AI Foundry (Agent Framework)
37-
# =============================================================================
38-
AZURE_AI_AGENT_ENDPOINT=https://your-project.services.ai.azure.com/api/projects/your-project
39-
AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME=gpt-5.1
40-
AZURE_AI_AGENT_API_VERSION=2024-12-01-preview
41-
4233
# =============================================================================
4334
# Azure Cosmos DB
4435
# =============================================================================
@@ -47,10 +38,6 @@ AZURE_COSMOS_DATABASE_NAME=content-generation
4738
AZURE_COSMOS_PRODUCTS_CONTAINER=products
4839
AZURE_COSMOS_CONVERSATIONS_CONTAINER=conversations
4940

50-
# For local development with emulator (optional)
51-
# AZURE_COSMOS_ENDPOINT=https://localhost:8081
52-
# AZURE_COSMOSDB_ACCOUNT_KEY=your-emulator-key
53-
5441
# =============================================================================
5542
# Azure Blob Storage
5643
# =============================================================================
@@ -64,7 +51,6 @@ AZURE_BLOB_GENERATED_IMAGES_CONTAINER=generated-images
6451
AZURE_AI_SEARCH_ENDPOINT=https://your-search.search.windows.net
6552
AZURE_AI_SEARCH_PRODUCTS_INDEX=products
6653
AZURE_AI_SEARCH_IMAGE_INDEX=product-images
67-
AZURE_OPENAI_EMBEDDING_MODEL=text-embedding-ada-002
6854

6955
# =============================================================================
7056
# UI Configuration
@@ -103,17 +89,7 @@ BRAND_REQUIRED_DISCLOSURES=
10389
# Server configuration
10490
PORT=5000
10591
WORKERS=4
106-
LOG_LEVEL=info
10792

10893
# Feature flags
10994
AUTH_ENABLED=false
11095
SANITIZE_ANSWER=false
111-
112-
# =============================================================================
113-
# Development Settings
114-
# =============================================================================
115-
# Set to true for verbose logging
116-
DEBUG=true
117-
118-
# Python path (usually set automatically)
119-
PYTHONPATH=.

content-gen/aci-deployment.yaml

Lines changed: 0 additions & 61 deletions
This file was deleted.

content-gen/azure.yaml

Lines changed: 204 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ environment:
44

55
name: content-generation
66
metadata:
7-
template: content-generation@1.0
7+
template: content-generation@1.22
88

99
requiredVersions:
1010
azd: '>= 1.18.0'
@@ -13,39 +13,223 @@ parameters:
1313
solutionPrefix:
1414
type: string
1515
default: contentgen
16-
otherLocation:
16+
displayName: Solution Prefix
17+
description: A unique prefix for all resources (3-15 chars)
18+
azureAiServiceLocation:
1719
type: string
18-
default: eastus2
19-
baseUrl:
20-
type: string
21-
default: 'https://github.com/microsoft/content-generation-solution-accelerator'
20+
default: eastus
21+
displayName: AI Services Location
22+
description: Location for Azure AI Services deployments
23+
enableMonitoring:
24+
type: boolean
25+
default: false
26+
displayName: Enable Monitoring (WAF)
27+
description: Enable Log Analytics and Application Insights
28+
enableScalability:
29+
type: boolean
30+
default: false
31+
displayName: Enable Scalability (WAF)
32+
description: Enable auto-scaling and higher SKUs
33+
enableRedundancy:
34+
type: boolean
35+
default: false
36+
displayName: Enable Redundancy (WAF)
37+
description: Enable zone redundancy and geo-replication
38+
enablePrivateNetworking:
39+
type: boolean
40+
default: false
41+
displayName: Enable Private Networking (WAF)
42+
description: Enable VNet integration and private endpoints
43+
44+
infra:
45+
provider: bicep
46+
path: ./infra
47+
module: main
2248

23-
deployment:
24-
mode: Incremental
25-
template: ./infra/main.bicep
26-
parameters:
27-
solutionPrefix: ${parameters.solutionPrefix}
28-
otherLocation: ${parameters.otherLocation}
29-
baseUrl: ${parameters.baseUrl}
49+
# Custom workflow:
50+
# 1. First provision creates infrastructure (skips ACI for private networking)
51+
# 2. Build container image to ACR
52+
# 3. Second provision creates ACI with the now-available image
53+
workflows:
54+
up:
55+
steps:
56+
- azd: provision
3057

3158
hooks:
59+
preprovision:
60+
windows:
61+
run: |
62+
Write-Host "Preparing Content Generation Solution Accelerator deployment..." -ForegroundColor Cyan
63+
Write-Host "Checking Azure CLI authentication..."
64+
az account show --query "{name:name, id:id}" -o table
65+
66+
# For private networking on first run, skip ACI (image not yet in ACR)
67+
$currentSkip = azd env get-value skipContainerDeployment 2>$null
68+
if ($env:enablePrivateNetworking -eq 'true' -and -not $env:ACR_NAME -and $currentSkip -ne 'false') {
69+
Write-Host "Private networking enabled - skipping container deployment until image is built" -ForegroundColor Yellow
70+
azd env set skipContainerDeployment true
71+
}
72+
shell: pwsh
73+
continueOnError: false
74+
posix:
75+
run: |
76+
echo "Preparing Content Generation Solution Accelerator deployment..."
77+
echo "Checking Azure CLI authentication..."
78+
az account show --query "{name:name, id:id}" -o table
79+
80+
# For private networking on first run, skip ACI (image not yet in ACR)
81+
current_skip=$(azd env get-value skipContainerDeployment 2>/dev/null || echo "")
82+
if [ "$enablePrivateNetworking" = "true" ] && [ -z "$ACR_NAME" ] && [ "$current_skip" != "false" ]; then
83+
echo "Private networking enabled - skipping container deployment until image is built"
84+
azd env set skipContainerDeployment true
85+
fi
86+
shell: sh
87+
continueOnError: false
88+
3289
postprovision:
3390
windows:
3491
run: |
35-
Write-Host "Web app URL: "
92+
Write-Host "===== Provision Complete =====" -ForegroundColor Green
93+
Write-Host ""
94+
Write-Host "Web App URL: " -NoNewline
3695
Write-Host "$env:WEB_APP_URL" -ForegroundColor Cyan
37-
Write-Host "`nTo upload product data, run:"
38-
Write-Host "python ./scripts/product_ingestion.py" -ForegroundColor Cyan
96+
Write-Host "Storage Account: " -NoNewline
97+
Write-Host "$env:STORAGE_ACCOUNT_NAME" -ForegroundColor Cyan
98+
Write-Host "AI Search Service: " -NoNewline
99+
Write-Host "$env:AI_SEARCH_SERVICE_NAME" -ForegroundColor Cyan
100+
Write-Host "AI Search Index: " -NoNewline
101+
Write-Host "$env:AI_SEARCH_INDEX" -ForegroundColor Cyan
102+
Write-Host "AI Service Location: " -NoNewline
103+
Write-Host "$env:AI_SERVICE_LOCATION" -ForegroundColor Cyan
104+
105+
# Run post-deployment role assignments
106+
Write-Host ""
107+
Write-Host "===== Running Post-Deployment Configuration =====" -ForegroundColor Yellow
108+
109+
# Assign Cosmos DB role to current user
110+
Write-Host "Assigning Cosmos DB Data Contributor role..."
111+
$signedUserId = az ad signed-in-user show --query id -o tsv
112+
az cosmosdb sql role assignment create --resource-group $env:RESOURCE_GROUP_NAME --account-name $env:COSMOSDB_ACCOUNT_NAME --role-definition-id "00000000-0000-0000-0000-000000000002" --principal-id $signedUserId --scope "/" 2>$null
113+
if ($LASTEXITCODE -eq 0) {
114+
Write-Host " Cosmos DB role assigned successfully" -ForegroundColor Green
115+
} else {
116+
Write-Host " Cosmos DB role may already be assigned" -ForegroundColor Yellow
117+
}
118+
119+
# Build container image and deploy ACI if ACR exists and ACI was skipped
120+
$skipContainer = azd env get-value skipContainerDeployment 2>$null
121+
if ($env:ACR_NAME -and $skipContainer -eq 'true') {
122+
Write-Host ""
123+
Write-Host "===== Building Container Image =====" -ForegroundColor Yellow
124+
Write-Host "Building and pushing image to ACR: $env:ACR_NAME" -ForegroundColor Cyan
125+
126+
az acr build --registry $env:ACR_NAME --image content-gen-app:latest ./src
127+
128+
if ($LASTEXITCODE -eq 0) {
129+
Write-Host "Container image built and pushed successfully!" -ForegroundColor Green
130+
131+
# Enable container deployment and re-provision
132+
Write-Host ""
133+
Write-Host "===== Deploying Container Instance =====" -ForegroundColor Yellow
134+
azd env set skipContainerDeployment false
135+
136+
Write-Host "Re-running provision to deploy ACI..." -ForegroundColor Cyan
137+
azd provision --no-prompt
138+
139+
if ($LASTEXITCODE -eq 0) {
140+
Write-Host "Container Instance deployed successfully!" -ForegroundColor Green
141+
} else {
142+
Write-Host "Container Instance deployment failed" -ForegroundColor Red
143+
}
144+
} else {
145+
Write-Host "Failed to build container image" -ForegroundColor Red
146+
}
147+
} elseif ($env:CONTAINER_INSTANCE_NAME) {
148+
Write-Host ""
149+
Write-Host "Container Instance: " -NoNewline
150+
Write-Host "$env:CONTAINER_INSTANCE_NAME" -ForegroundColor Cyan
151+
Write-Host "Container Private IP: " -NoNewline
152+
Write-Host "$env:CONTAINER_INSTANCE_PRIVATE_IP" -ForegroundColor Cyan
153+
} elseif ($env:ACR_NAME) {
154+
Write-Host ""
155+
Write-Host "Container Registry: " -NoNewline
156+
Write-Host "$env:ACR_NAME" -ForegroundColor Cyan
157+
}
158+
159+
Write-Host ""
160+
Write-Host "===== Next Steps =====" -ForegroundColor Yellow
161+
Write-Host "1. Upload product data:"
162+
Write-Host " python ./scripts/product_ingestion.py --data-path ./sample_data" -ForegroundColor Cyan
163+
Write-Host ""
164+
Write-Host "2. Access the web application:"
165+
Write-Host " $env:WEB_APP_URL" -ForegroundColor Cyan
39166
shell: pwsh
40167
continueOnError: false
41168
interactive: true
42169
posix:
43170
run: |
44-
echo "Web app URL: "
45-
echo $WEB_APP_URL
171+
echo "===== Provision Complete ====="
172+
echo ""
173+
echo "Web App URL: $WEB_APP_URL"
174+
echo "Storage Account: $STORAGE_ACCOUNT_NAME"
175+
echo "AI Search Service: $AI_SEARCH_SERVICE_NAME"
176+
echo "AI Search Index: $AI_SEARCH_INDEX"
177+
echo "AI Service Location: $AI_SERVICE_LOCATION"
178+
179+
# Run post-deployment role assignments
180+
echo ""
181+
echo "===== Running Post-Deployment Configuration ====="
182+
183+
# Assign Cosmos DB role to current user
184+
echo "Assigning Cosmos DB Data Contributor role..."
185+
signed_user_id=$(az ad signed-in-user show --query id -o tsv)
186+
az cosmosdb sql role assignment create \
187+
--resource-group "$RESOURCE_GROUP_NAME" \
188+
--account-name "$COSMOSDB_ACCOUNT_NAME" \
189+
--role-definition-id "00000000-0000-0000-0000-000000000002" \
190+
--principal-id "$signed_user_id" \
191+
--scope "/" 2>/dev/null && echo " Cosmos DB role assigned successfully" || echo " Cosmos DB role may already be assigned"
192+
193+
# Build container image and deploy ACI if ACR exists and ACI was skipped
194+
skip_container=$(azd env get-value skipContainerDeployment 2>/dev/null || echo "")
195+
if [ -n "$ACR_NAME" ] && [ "$skip_container" = "true" ]; then
196+
echo ""
197+
echo "===== Building Container Image ====="
198+
echo "Building and pushing image to ACR: $ACR_NAME"
199+
200+
if az acr build --registry "$ACR_NAME" --image content-gen-app:latest ./src; then
201+
echo "Container image built and pushed successfully!"
202+
203+
# Enable container deployment and re-provision
204+
echo ""
205+
echo "===== Deploying Container Instance ====="
206+
azd env set skipContainerDeployment false
207+
208+
echo "Re-running provision to deploy ACI..."
209+
if azd provision --no-prompt; then
210+
echo "Container Instance deployed successfully!"
211+
else
212+
echo "Container Instance deployment failed"
213+
fi
214+
else
215+
echo "Failed to build container image"
216+
fi
217+
elif [ -n "$CONTAINER_INSTANCE_NAME" ]; then
218+
echo ""
219+
echo "Container Instance: $CONTAINER_INSTANCE_NAME"
220+
echo "Container Private IP: $CONTAINER_INSTANCE_PRIVATE_IP"
221+
elif [ -n "$ACR_NAME" ]; then
222+
echo ""
223+
echo "Container Registry: $ACR_NAME"
224+
fi
225+
226+
echo ""
227+
echo "===== Next Steps ====="
228+
echo "1. Upload product data:"
229+
echo " python ./scripts/product_ingestion.py --data-path ./sample_data"
46230
echo ""
47-
echo "To upload product data, run:"
48-
echo "python ./scripts/product_ingestion.py"
231+
echo "2. Access the web application:"
232+
echo " $WEB_APP_URL"
49233
shell: sh
50234
continueOnError: false
51235
interactive: true

0 commit comments

Comments
 (0)