diff --git a/azure.yaml b/azure.yaml index e187df3..25df14c 100644 --- a/azure.yaml +++ b/azure.yaml @@ -1,21 +1,15 @@ # yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json -name: llama-index-nextjs +name: llama-index-javascript metadata: - template: llama-index-javascript + template: llama-index-javascript@1.15.1 services: - llama-index-nextjs: + llama-index-javascript: project: . host: containerapp language: js docker: path: Dockerfile - # hooks: - # predeploy: - # shell: sh - # continueOnError: false - # interactive: false - # run: npm run generate hooks: postprovision: windows: diff --git a/infra/abbreviations.json b/infra/abbreviations.json index dc62141..1533dee 100644 --- a/infra/abbreviations.json +++ b/infra/abbreviations.json @@ -37,6 +37,7 @@ "devicesProvisioningServices": "provs-", "devicesProvisioningServicesCertificates": "pcert-", "documentDBDatabaseAccounts": "cosmos-", + "documentDBMongoDatabaseAccounts": "cosmon-", "eventGridDomains": "evgd-", "eventGridDomainsTopics": "evgt-", "eventGridEventSubscriptions": "evgs-", diff --git a/infra/app/llama-index-nextjs.bicep b/infra/app/llama-index-nextjs.bicep deleted file mode 100644 index 3c38f8a..0000000 --- a/infra/app/llama-index-nextjs.bicep +++ /dev/null @@ -1,151 +0,0 @@ -param name string -param location string = resourceGroup().location -param tags object = {} - -param identityName string -param containerRegistryName string -param containerAppsEnvironmentName string -param applicationInsightsName string -param exists bool - -@description('Whether the deployment is running on GitHub Actions') -param runningOnGh string = '' - -@description('Id of the user or app to assign application roles') -param principalId string = '' - -@secure() -param appDefinition object - -var appSettingsArray = filter(array(appDefinition.settings), i => i.name != '') -var secrets = map(filter(appSettingsArray, i => i.?secret != null), i => { - name: i.name - value: i.value - secretRef: i.?secretRef ?? take(replace(replace(toLower(i.name), '_', '-'), '.', '-'), 32) -}) -var env = map(filter(appSettingsArray, i => i.?secret == null), i => { - name: i.name - value: i.value -}) - -resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: identityName - location: location -} - -resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2023-05-01' existing = { - name: containerAppsEnvironmentName -} - -resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = { - name: applicationInsightsName -} - -// Roles - -// User roles -module openAiRoleUser '../shared/role.bicep' = if (empty(runningOnGh)) { - name: guid(subscription().id, resourceGroup().id, identity.id, 'openaiUserRole') - params: { - principalId: principalId - // Cognitive Services OpenAI User - roleDefinitionId: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' - principalType: 'User' - } -} - -// System roles -module openAiRoleBackend '../shared/role.bicep' = { - name: guid(subscription().id, resourceGroup().id, identity.id, 'openaiServicePrincipalRole') - params: { - principalId: app.identity.principalId - // Cognitive Services OpenAI User - roleDefinitionId: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' - principalType: 'ServicePrincipal' - } -} -module acrPullRole '../shared/role.bicep' = { - name: guid(subscription().id, resourceGroup().id, identity.id, 'acrPullRole') - params: { - principalId: identity.properties.principalId - roleDefinitionId: '7f951dda-4ed3-4680-a7ca-43fe172d538d' - principalType: 'ServicePrincipal' - } -} - -module fetchLatestImage '../modules/fetch-container-image.bicep' = { - name: '${name}-fetch-image' - params: { - exists: exists - name: name - } -} - -resource app 'Microsoft.App/containerApps@2023-05-02-preview' = { - name: name - location: location - tags: union(tags, {'azd-service-name': 'llama-index-nextjs' }) - dependsOn: [ acrPullRole ] - identity: { - type: 'SystemAssigned,UserAssigned' - userAssignedIdentities: { '${identity.id}': {} } - } - properties: { - managedEnvironmentId: containerAppsEnvironment.id - configuration: { - ingress: { - external: true - targetPort: 3000 - transport: 'auto' - } - registries: [ - { - server: '${containerRegistryName}.azurecr.io' - identity: identity.id - } - ] - secrets: union([ - ], - map(secrets, secret => { - name: secret.secretRef - value: secret.value - })) - } - template: { - containers: [ - { - image: fetchLatestImage.outputs.?containers[?0].?image ?? 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest' - name: 'main' - env: union([ - { - name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' - value: applicationInsights.properties.ConnectionString - } - { - name: 'PORT' - value: '3000' - } - ], - env, - map(secrets, secret => { - name: secret.name - secretRef: secret.secretRef - })) - resources: { - cpu: json('1.0') - memory: '2.0Gi' - } - } - ] - scale: { - minReplicas: 1 - maxReplicas: 10 - } - } - } -} - -output defaultDomain string = containerAppsEnvironment.properties.defaultDomain -output name string = app.name -output uri string = 'https://${app.properties.configuration.ingress.fqdn}' -output id string = app.id diff --git a/infra/main.bicep b/infra/main.bicep index 0f4357c..d5d6926 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -9,246 +9,70 @@ param environmentName string @description('Primary location for all resources') param location string -@description('Whether the deployment is running on GitHub Actions') -param runningOnGh string = '' - -param llamaIndexNextjsExists bool -@secure() -param llamaIndexNextjsDefinition object - @description('Id of the user or app to assign application roles') param principalId string -param openAiLocation string // Set in main.parameters.json -param openAiSkuName string = 'S0' // Set in main.parameters.json -param openAiUrl string = '' // Set in main.parameters.json -param openAiApiVersion string // Set in main.parameters.json +// 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 +} -var finalOpenAiUrl = empty(openAiUrl) ? 'https://${openAi.outputs.name}.openai.azure.com' : openAiUrl +param llamaIndexJavascriptExists bool +param isContinuousIntegration bool // Set in main.parameters.json var llamaIndexConfig = { chat: { - model: 'gpt-35-turbo' - deployment: 'gpt-35-turbo' - version: '1106' - capacity: '10' + model: 'gpt-4o-mini' + deployment: 'gpt-4o-mini' + version: '2024-07-18' + capacity: 10 } embedding: { model: 'text-embedding-3-large' deployment: 'text-embedding-3-large' + version: '1' dim: '1024' - capacity: '10' + capacity: 10 } model_provider: 'openai' openai_api_key: '' llm_temperature: '0.7' llm_max_tokens: '100' + openai_api_version: '2024-02-15-preview' top_k: '3' fileserver_url_prefix: 'http://localhost/api/files' system_prompt: 'You are a helpful assistant who helps users with their questions.' } -// 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 -} - -var abbrs = loadJsonContent('./abbreviations.json') -var resourceToken = toLower(uniqueString(subscription().id, environmentName, location)) - -resource rg 'Microsoft.Resources/resourceGroups@2022-09-01' = { +// Organize resources in a resource group +resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { name: 'rg-${environmentName}' location: location tags: tags } -module monitoring './shared/monitoring.bicep' = { - name: 'monitoring' - params: { - location: location - tags: tags - logAnalyticsName: '${abbrs.operationalInsightsWorkspaces}${resourceToken}' - applicationInsightsName: '${abbrs.insightsComponents}${resourceToken}' - } +module resources 'resources.bicep' = { scope: rg -} - -module dashboard './shared/dashboard-web.bicep' = { - name: 'dashboard' + name: 'resources' params: { - name: '${abbrs.portalDashboards}${resourceToken}' - applicationInsightsName: monitoring.outputs.applicationInsightsName location: location tags: tags - } - scope: rg -} - -module registry './shared/registry.bicep' = { - name: 'registry' - params: { - location: location - tags: tags - name: '${abbrs.containerRegistryRegistries}${resourceToken}' - } - scope: rg -} - -module keyVault './shared/keyvault.bicep' = { - name: 'keyvault' - params: { - location: location - tags: tags - name: '${abbrs.keyVaultVaults}${resourceToken}' principalId: principalId + llamaIndexJavascriptExists: llamaIndexJavascriptExists + llamaIndexConfig: llamaIndexConfig + isContinuousIntegration: isContinuousIntegration } - scope: rg -} - -module appsEnv './shared/apps-env.bicep' = { - name: 'apps-env' - params: { - name: '${abbrs.appManagedEnvironments}${resourceToken}' - location: location - tags: tags - applicationInsightsName: monitoring.outputs.applicationInsightsName - logAnalyticsWorkspaceName: monitoring.outputs.logAnalyticsWorkspaceName - } - scope: rg } +output AZURE_CONTAINER_REGISTRY_ENDPOINT string = resources.outputs.AZURE_CONTAINER_REGISTRY_ENDPOINT +output AZURE_RESOURCE_LLAMA_INDEX_JAVASCRIPT_ID string = resources.outputs.AZURE_RESOURCE_LLAMA_INDEX_JAVASCRIPT_ID -module openAi './shared/cognitiveservices.bicep' = if (empty(openAiUrl)) { - name: 'openai' - scope: rg - params: { - name: '${abbrs.cognitiveServicesAccounts}${resourceToken}' - location: openAiLocation - tags: tags - sku: { - name: openAiSkuName - } - disableLocalAuth: true - deployments: [ - { - name: llamaIndexConfig.chat.deployment - model: { - format: 'OpenAI' - name: llamaIndexConfig.chat.model - version: llamaIndexConfig.chat.version - } - sku: { - name: 'Standard' - capacity: llamaIndexConfig.chat.capacity - } - } - { - name: llamaIndexConfig.embedding.model - model: { - format: 'OpenAI' - name: llamaIndexConfig.embedding.deployment - } - capacity: llamaIndexConfig.embedding.capacity - } - ] - } -} - -module llamaIndexNextjs './app/llama-index-nextjs.bicep' = { - name: 'llama-index-nextjs' - params: { - name: '${abbrs.appContainerApps}llama-index-${resourceToken}' - location: location - tags: tags - runningOnGh: runningOnGh - identityName: '${abbrs.managedIdentityUserAssignedIdentities}llama-index-${resourceToken}' - applicationInsightsName: monitoring.outputs.applicationInsightsName - containerAppsEnvironmentName: appsEnv.outputs.name - containerRegistryName: registry.outputs.name - exists: llamaIndexNextjsExists - principalId: principalId - appDefinition: union(llamaIndexNextjsDefinition, { - settings: [ - { - name: 'AZURE_KEY_VAULT_NAME' - value: keyVault.outputs.name - } - { - name: 'AZURE_KEY_VAULT_ENDPOINT' - value: keyVault.outputs.endpoint - } - { - name: 'AZURE_OPENAI_ENDPOINT' - value: finalOpenAiUrl - } - { - name: 'AZURE_DEPLOYMENT_NAME' - value: llamaIndexConfig.chat.deployment - } - { - name: 'OPENAI_API_VERSION' - value: openAiApiVersion - } - { - name: 'MODEL_PROVIDER' - value: llamaIndexConfig.model_provider - } - { - name: 'MODEL' - value: llamaIndexConfig.chat.model - } - { - name: 'EMBEDDING_MODEL' - value: llamaIndexConfig.embedding.model - } - { - name: 'EMBEDDING_DIM' - value: llamaIndexConfig.embedding.dim - } - { - name: 'LLM_TEMPERATURE' - value: llamaIndexConfig.llm_temperature - } - { - name: 'LLM_MAX_TOKENS' - value: llamaIndexConfig.llm_max_tokens - } - { - name: 'TOP_K' - value: llamaIndexConfig.top_k - } - { - name: 'FILESERVER_URL_PREFIX' - value: llamaIndexConfig.fileserver_url_prefix - } - { - name: 'SYSTEM_PROMPT' - value: llamaIndexConfig.system_prompt - } - { - name: 'OPENAI_API_TYPE' - value: 'AzureOpenAI' - } - { - name: 'STORAGE_CACHE_DIR' - value: './cache' - } - ] - }) - } - scope: rg -} - -output AZURE_CONTAINER_REGISTRY_ENDPOINT string = registry.outputs.loginServer -output AZURE_KEY_VAULT_NAME string = keyVault.outputs.name -output AZURE_KEY_VAULT_ENDPOINT string = keyVault.outputs.endpoint - -output AZURE_OPENAI_ENDPOINT string = finalOpenAiUrl +output AZURE_OPENAI_ENDPOINT string = resources.outputs.AZURE_OPENAI_ENDPOINT output AZURE_DEPLOYMENT_NAME string = llamaIndexConfig.chat.deployment -output OPENAI_API_VERSION string = openAiApiVersion +output AZURE_OPENAI_API_VERSION string = llamaIndexConfig.openai_api_version // LlamaIndex configuration output MODEL_PROVIDER string = llamaIndexConfig.model_provider diff --git a/infra/main.parameters.json b/infra/main.parameters.json index b543649..bcc240f 100644 --- a/infra/main.parameters.json +++ b/infra/main.parameters.json @@ -8,28 +8,14 @@ "location": { "value": "${AZURE_LOCATION}" }, - "llamaIndexNextjsExists": { - "value": "${SERVICE_LLAMA_INDEX_NEXTJS_RESOURCE_EXISTS=false}" - }, - "llamaIndexNextjsDefinition": { - "value": { - "settings": [] - } + "llamaIndexJavascriptExists": { + "value": "${SERVICE_LLAMA_INDEX_JAVASCRIPT_RESOURCE_EXISTS=false}" }, "principalId": { "value": "${AZURE_PRINCIPAL_ID}" }, - "openAiLocation": { - "value": "${AZURE_OPENAI_LOCATION=swedencentral}" - }, - "openAiApiVersion": { - "value": "${AZURE_OPENAI_API_VERSION=2024-02-15-preview}" - }, - "runningOnGh": { + "isContinuousIntegration": { "value": "${GITHUB_ACTIONS}" - }, - "azureDeploymentName": { - "value": "${AZURE_DEPLOYMENT_NAME=gpt-35-turbo}" } } -} \ No newline at end of file +} diff --git a/infra/resources.bicep b/infra/resources.bicep new file mode 100644 index 0000000..9b97d11 --- /dev/null +++ b/infra/resources.bicep @@ -0,0 +1,237 @@ +@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 = {} + +@description('The configuration for the LlamaIndex application') +param llamaIndexConfig object = {} + + +var principalType = isContinuousIntegration ? 'ServicePrincipal' : 'User' + +param isContinuousIntegration bool +param llamaIndexJavascriptExists bool + +@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: llamaIndexJavascriptIdentity.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 llamaIndexJavascriptIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.2.1' = { + name: 'llamaIndexJavascriptidentity' + params: { + name: '${abbrs.managedIdentityUserAssignedIdentities}llamaIndexJavascript-${resourceToken}' + location: location + } +} +module llamaIndexJavascriptFetchLatestImage './modules/fetch-container-image.bicep' = { + name: 'llamaIndexJavascript-fetch-image' + params: { + exists: llamaIndexJavascriptExists + name: 'llama-index-javascript' + } +} + +module llamaIndexJavascript 'br/public:avm/res/app/container-app:0.8.0' = { + name: 'llamaIndexJavascript' + params: { + name: 'llama-index-javascript' + ingressTargetPort: 3000 + scaleMinReplicas: 1 + scaleMaxReplicas: 10 + secrets: { + secureList: [ + ] + } + containers: [ + { + image: llamaIndexJavascriptFetchLatestImage.outputs.?containers[?0].?image ?? 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest' + name: 'main' + resources: { + cpu: json('0.5') + memory: '1.0Gi' + } + env: [ + { + name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' + value: monitoring.outputs.applicationInsightsConnectionString + } + { + name: 'AZURE_CLIENT_ID' + value: llamaIndexJavascriptIdentity.outputs.clientId + } + { + name: 'PORT' + value: '3000' + } + { + name: 'AZURE_OPENAI_ENDPOINT' + value: openAi.outputs.endpoint + } + { + name: 'AZURE_DEPLOYMENT_NAME' + value: llamaIndexConfig.chat.deployment + } + { + name: 'AZURE_OPENAI_API_VERSION' + value: llamaIndexConfig.openai_api_version + } + { + name: 'MODEL_PROVIDER' + value: llamaIndexConfig.model_provider + } + { + name: 'MODEL' + value: llamaIndexConfig.chat.model + } + { + name: 'EMBEDDING_MODEL' + value: llamaIndexConfig.embedding.model + } + { + name: 'EMBEDDING_DIM' + value: llamaIndexConfig.embedding.dim + } + { + name: 'LLM_TEMPERATURE' + value: llamaIndexConfig.llm_temperature + } + { + name: 'LLM_MAX_TOKENS' + value: llamaIndexConfig.llm_max_tokens + } + { + name: 'TOP_K' + value: llamaIndexConfig.top_k + } + { + name: 'FILESERVER_URL_PREFIX' + value: llamaIndexConfig.fileserver_url_prefix + } + { + name: 'SYSTEM_PROMPT' + value: llamaIndexConfig.system_prompt + } + { + name: 'OPENAI_API_TYPE' + value: 'AzureOpenAI' + } + { + name: 'STORAGE_CACHE_DIR' + value: './cache' + } + ] + } + ] + managedIdentities:{ + systemAssigned: false + userAssignedResourceIds: [llamaIndexJavascriptIdentity.outputs.resourceId] + } + registries:[ + { + server: containerRegistry.outputs.loginServer + identity: llamaIndexJavascriptIdentity.outputs.resourceId + } + ] + environmentResourceId: containerAppsEnvironment.outputs.resourceId + location: location + tags: union(tags, { 'azd-service-name': 'llama-index-javascript' }) + } +} + +module openAi 'br/public:avm/res/cognitive-services/account:0.10.2' = { + name: 'openai' + params: { + name: '${abbrs.cognitiveServicesAccounts}${resourceToken}' + tags: tags + location: location + kind: 'OpenAI' + disableLocalAuth: true + customSubDomainName: '${abbrs.cognitiveServicesAccounts}${resourceToken}' + publicNetworkAccess: 'Enabled' + deployments: [ + { + name: llamaIndexConfig.chat.deployment + model: { + format: 'OpenAI' + name: llamaIndexConfig.chat.model + version: llamaIndexConfig.chat.version + } + sku: { + capacity: llamaIndexConfig.chat.capacity + name: 'GlobalStandard' + } + } + { + name: llamaIndexConfig.embedding.deployment + model: { + format: 'OpenAI' + name: llamaIndexConfig.embedding.model + version: llamaIndexConfig.embedding.version + } + sku: { + capacity: llamaIndexConfig.embedding.capacity + name: 'Standard' + } + } + ] + roleAssignments: [ + { + principalId: principalId + principalType: principalType + roleDefinitionIdOrName: 'Cognitive Services OpenAI User' + } + { + principalId: llamaIndexJavascriptIdentity.outputs.principalId + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Cognitive Services OpenAI User' + } + ] + } +} + +output AZURE_CONTAINER_REGISTRY_ENDPOINT string = containerRegistry.outputs.loginServer +output AZURE_RESOURCE_LLAMA_INDEX_JAVASCRIPT_ID string = llamaIndexJavascript.outputs.resourceId +output AZURE_OPENAI_ENDPOINT string = openAi.outputs.endpoint diff --git a/infra/shared/apps-env.bicep b/infra/shared/apps-env.bicep deleted file mode 100644 index 030b823..0000000 --- a/infra/shared/apps-env.bicep +++ /dev/null @@ -1,33 +0,0 @@ -param name string -param location string = resourceGroup().location -param tags object = {} - -param logAnalyticsWorkspaceName string -param applicationInsightsName string = '' - -resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2022-10-01' = { - name: name - location: location - tags: tags - properties: { - appLogsConfiguration: { - destination: 'log-analytics' - logAnalyticsConfiguration: { - customerId: logAnalyticsWorkspace.properties.customerId - sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey - } - } - daprAIConnectionString: applicationInsights.properties.ConnectionString - } -} - -resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' existing = { - name: logAnalyticsWorkspaceName -} - -resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = { - name: applicationInsightsName -} - -output name string = containerAppsEnvironment.name -output domain string = containerAppsEnvironment.properties.defaultDomain diff --git a/infra/shared/cognitiveservices.bicep b/infra/shared/cognitiveservices.bicep deleted file mode 100644 index 1781e2f..0000000 --- a/infra/shared/cognitiveservices.bicep +++ /dev/null @@ -1,59 +0,0 @@ -metadata description = 'Creates an Azure Cognitive Services instance.' -param name string -param location string = resourceGroup().location -param tags object = {} -@description('The custom subdomain name used to access the API. Defaults to the value of the name parameter.') -param customSubDomainName string = name -param deployments array = [] -param kind string = 'OpenAI' - -@allowed([ 'Enabled', 'Disabled' ]) -param publicNetworkAccess string = 'Enabled' -param sku object = { - name: 'S0' -} - -param allowedIpRules array = [] -param networkAcls object = empty(allowedIpRules) ? { - defaultAction: 'Allow' -} : { - ipRules: allowedIpRules - defaultAction: 'Deny' -} -param disableLocalAuth bool = false - -resource account 'Microsoft.CognitiveServices/accounts@2023-05-01' = { - name: name - location: location - tags: tags - kind: kind - identity: { - type: 'SystemAssigned' - } - properties: { - customSubDomainName: customSubDomainName - publicNetworkAccess: publicNetworkAccess - networkAcls: networkAcls - disableLocalAuth: disableLocalAuth - } - sku: sku -} - -@batchSize(1) -resource deployment 'Microsoft.CognitiveServices/accounts/deployments@2023-05-01' = [for deployment in deployments: { - parent: account - name: deployment.name - properties: { - model: deployment.model - raiPolicyName: contains(deployment, 'raiPolicyName') ? deployment.raiPolicyName : null - } - sku: contains(deployment, 'sku') ? deployment.sku : { - name: 'Standard' - capacity: 20 - } -}] - -output endpoint string = account.properties.endpoint -output id string = account.id -output name string = account.name -output identityPrincipalId string = account.identity.principalId diff --git a/infra/shared/dashboard-web.bicep b/infra/shared/dashboard-web.bicep deleted file mode 100644 index eccce0d..0000000 --- a/infra/shared/dashboard-web.bicep +++ /dev/null @@ -1,1231 +0,0 @@ -param name string -param applicationInsightsName string -param location string = resourceGroup().location -param tags object = {} - -// 2020-09-01-preview because that is the latest valid version -resource applicationInsightsDashboard 'Microsoft.Portal/dashboards@2020-09-01-preview' = { - name: name - location: location - tags: tags - properties: { - lenses: [ - { - order: 0 - parts: [ - { - position: { - x: 0 - y: 0 - colSpan: 2 - rowSpan: 1 - } - metadata: { - inputs: [ - { - name: 'id' - value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - { - name: 'Version' - value: '1.0' - } - ] - #disable-next-line BCP036 - type: 'Extension/AppInsightsExtension/PartType/AspNetOverviewPinnedPart' - asset: { - idInputName: 'id' - type: 'ApplicationInsights' - } - defaultMenuItemId: 'overview' - } - } - { - position: { - x: 2 - y: 0 - colSpan: 1 - rowSpan: 1 - } - metadata: { - inputs: [ - { - name: 'ComponentId' - value: { - Name: applicationInsightsName - SubscriptionId: subscription().subscriptionId - ResourceGroup: resourceGroup().name - } - } - { - name: 'Version' - value: '1.0' - } - ] - #disable-next-line BCP036 - type: 'Extension/AppInsightsExtension/PartType/ProactiveDetectionAsyncPart' - asset: { - idInputName: 'ComponentId' - type: 'ApplicationInsights' - } - defaultMenuItemId: 'ProactiveDetection' - } - } - { - position: { - x: 3 - y: 0 - colSpan: 1 - rowSpan: 1 - } - metadata: { - inputs: [ - { - name: 'ComponentId' - value: { - Name: applicationInsightsName - SubscriptionId: subscription().subscriptionId - ResourceGroup: resourceGroup().name - } - } - { - name: 'ResourceId' - value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - ] - #disable-next-line BCP036 - type: 'Extension/AppInsightsExtension/PartType/QuickPulseButtonSmallPart' - asset: { - idInputName: 'ComponentId' - type: 'ApplicationInsights' - } - } - } - { - position: { - x: 4 - y: 0 - colSpan: 1 - rowSpan: 1 - } - metadata: { - inputs: [ - { - name: 'ComponentId' - value: { - Name: applicationInsightsName - SubscriptionId: subscription().subscriptionId - ResourceGroup: resourceGroup().name - } - } - { - name: 'TimeContext' - value: { - durationMs: 86400000 - endTime: null - createdTime: '2018-05-04T01:20:33.345Z' - isInitialTime: true - grain: 1 - useDashboardTimeRange: false - } - } - { - name: 'Version' - value: '1.0' - } - ] - #disable-next-line BCP036 - type: 'Extension/AppInsightsExtension/PartType/AvailabilityNavButtonPart' - asset: { - idInputName: 'ComponentId' - type: 'ApplicationInsights' - } - } - } - { - position: { - x: 5 - y: 0 - colSpan: 1 - rowSpan: 1 - } - metadata: { - inputs: [ - { - name: 'ComponentId' - value: { - Name: applicationInsightsName - SubscriptionId: subscription().subscriptionId - ResourceGroup: resourceGroup().name - } - } - { - name: 'TimeContext' - value: { - durationMs: 86400000 - endTime: null - createdTime: '2018-05-08T18:47:35.237Z' - isInitialTime: true - grain: 1 - useDashboardTimeRange: false - } - } - { - name: 'ConfigurationId' - value: '78ce933e-e864-4b05-a27b-71fd55a6afad' - } - ] - #disable-next-line BCP036 - type: 'Extension/AppInsightsExtension/PartType/AppMapButtonPart' - asset: { - idInputName: 'ComponentId' - type: 'ApplicationInsights' - } - } - } - { - position: { - x: 0 - y: 1 - colSpan: 3 - rowSpan: 1 - } - metadata: { - inputs: [] - type: 'Extension/HubsExtension/PartType/MarkdownPart' - settings: { - content: { - settings: { - content: '# Usage' - title: '' - subtitle: '' - } - } - } - } - } - { - position: { - x: 3 - y: 1 - colSpan: 1 - rowSpan: 1 - } - metadata: { - inputs: [ - { - name: 'ComponentId' - value: { - Name: applicationInsightsName - SubscriptionId: subscription().subscriptionId - ResourceGroup: resourceGroup().name - } - } - { - name: 'TimeContext' - value: { - durationMs: 86400000 - endTime: null - createdTime: '2018-05-04T01:22:35.782Z' - isInitialTime: true - grain: 1 - useDashboardTimeRange: false - } - } - ] - #disable-next-line BCP036 - type: 'Extension/AppInsightsExtension/PartType/UsageUsersOverviewPart' - asset: { - idInputName: 'ComponentId' - type: 'ApplicationInsights' - } - } - } - { - position: { - x: 4 - y: 1 - colSpan: 3 - rowSpan: 1 - } - metadata: { - inputs: [] - type: 'Extension/HubsExtension/PartType/MarkdownPart' - settings: { - content: { - settings: { - content: '# Reliability' - title: '' - subtitle: '' - } - } - } - } - } - { - position: { - x: 7 - y: 1 - colSpan: 1 - rowSpan: 1 - } - metadata: { - inputs: [ - { - name: 'ResourceId' - value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - { - name: 'DataModel' - value: { - version: '1.0.0' - timeContext: { - durationMs: 86400000 - createdTime: '2018-05-04T23:42:40.072Z' - isInitialTime: false - grain: 1 - useDashboardTimeRange: false - } - } - isOptional: true - } - { - name: 'ConfigurationId' - value: '8a02f7bf-ac0f-40e1-afe9-f0e72cfee77f' - isOptional: true - } - ] - #disable-next-line BCP036 - type: 'Extension/AppInsightsExtension/PartType/CuratedBladeFailuresPinnedPart' - isAdapter: true - asset: { - idInputName: 'ResourceId' - type: 'ApplicationInsights' - } - defaultMenuItemId: 'failures' - } - } - { - position: { - x: 8 - y: 1 - colSpan: 3 - rowSpan: 1 - } - metadata: { - inputs: [] - type: 'Extension/HubsExtension/PartType/MarkdownPart' - settings: { - content: { - settings: { - content: '# Responsiveness\r\n' - title: '' - subtitle: '' - } - } - } - } - } - { - position: { - x: 11 - y: 1 - colSpan: 1 - rowSpan: 1 - } - metadata: { - inputs: [ - { - name: 'ResourceId' - value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - { - name: 'DataModel' - value: { - version: '1.0.0' - timeContext: { - durationMs: 86400000 - createdTime: '2018-05-04T23:43:37.804Z' - isInitialTime: false - grain: 1 - useDashboardTimeRange: false - } - } - isOptional: true - } - { - name: 'ConfigurationId' - value: '2a8ede4f-2bee-4b9c-aed9-2db0e8a01865' - isOptional: true - } - ] - #disable-next-line BCP036 - type: 'Extension/AppInsightsExtension/PartType/CuratedBladePerformancePinnedPart' - isAdapter: true - asset: { - idInputName: 'ResourceId' - type: 'ApplicationInsights' - } - defaultMenuItemId: 'performance' - } - } - { - position: { - x: 12 - y: 1 - colSpan: 3 - rowSpan: 1 - } - metadata: { - inputs: [] - type: 'Extension/HubsExtension/PartType/MarkdownPart' - settings: { - content: { - settings: { - content: '# Browser' - title: '' - subtitle: '' - } - } - } - } - } - { - position: { - x: 15 - y: 1 - colSpan: 1 - rowSpan: 1 - } - metadata: { - inputs: [ - { - name: 'ComponentId' - value: { - Name: applicationInsightsName - SubscriptionId: subscription().subscriptionId - ResourceGroup: resourceGroup().name - } - } - { - name: 'MetricsExplorerJsonDefinitionId' - value: 'BrowserPerformanceTimelineMetrics' - } - { - name: 'TimeContext' - value: { - durationMs: 86400000 - createdTime: '2018-05-08T12:16:27.534Z' - isInitialTime: false - grain: 1 - useDashboardTimeRange: false - } - } - { - name: 'CurrentFilter' - value: { - eventTypes: [ - 4 - 1 - 3 - 5 - 2 - 6 - 13 - ] - typeFacets: {} - isPermissive: false - } - } - { - name: 'id' - value: { - Name: applicationInsightsName - SubscriptionId: subscription().subscriptionId - ResourceGroup: resourceGroup().name - } - } - { - name: 'Version' - value: '1.0' - } - ] - #disable-next-line BCP036 - type: 'Extension/AppInsightsExtension/PartType/MetricsExplorerBladePinnedPart' - asset: { - idInputName: 'ComponentId' - type: 'ApplicationInsights' - } - defaultMenuItemId: 'browser' - } - } - { - position: { - x: 0 - y: 2 - colSpan: 4 - rowSpan: 3 - } - metadata: { - inputs: [ - { - name: 'options' - value: { - chart: { - metrics: [ - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'sessions/count' - aggregationType: 5 - namespace: 'microsoft.insights/components/kusto' - metricVisualization: { - displayName: 'Sessions' - color: '#47BDF5' - } - } - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'users/count' - aggregationType: 5 - namespace: 'microsoft.insights/components/kusto' - metricVisualization: { - displayName: 'Users' - color: '#7E58FF' - } - } - ] - title: 'Unique sessions and users' - visualization: { - chartType: 2 - legendVisualization: { - isVisible: true - position: 2 - hideSubtitle: false - } - axisVisualization: { - x: { - isVisible: true - axisType: 2 - } - y: { - isVisible: true - axisType: 1 - } - } - } - openBladeOnClick: { - openBlade: true - destinationBlade: { - extensionName: 'HubsExtension' - bladeName: 'ResourceMenuBlade' - parameters: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - menuid: 'segmentationUsers' - } - } - } - } - } - } - { - name: 'sharedTimeRange' - isOptional: true - } - ] - #disable-next-line BCP036 - type: 'Extension/HubsExtension/PartType/MonitorChartPart' - settings: {} - } - } - { - position: { - x: 4 - y: 2 - colSpan: 4 - rowSpan: 3 - } - metadata: { - inputs: [ - { - name: 'options' - value: { - chart: { - metrics: [ - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'requests/failed' - aggregationType: 7 - namespace: 'microsoft.insights/components' - metricVisualization: { - displayName: 'Failed requests' - color: '#EC008C' - } - } - ] - title: 'Failed requests' - visualization: { - chartType: 3 - legendVisualization: { - isVisible: true - position: 2 - hideSubtitle: false - } - axisVisualization: { - x: { - isVisible: true - axisType: 2 - } - y: { - isVisible: true - axisType: 1 - } - } - } - openBladeOnClick: { - openBlade: true - destinationBlade: { - extensionName: 'HubsExtension' - bladeName: 'ResourceMenuBlade' - parameters: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - menuid: 'failures' - } - } - } - } - } - } - { - name: 'sharedTimeRange' - isOptional: true - } - ] - #disable-next-line BCP036 - type: 'Extension/HubsExtension/PartType/MonitorChartPart' - settings: {} - } - } - { - position: { - x: 8 - y: 2 - colSpan: 4 - rowSpan: 3 - } - metadata: { - inputs: [ - { - name: 'options' - value: { - chart: { - metrics: [ - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'requests/duration' - aggregationType: 4 - namespace: 'microsoft.insights/components' - metricVisualization: { - displayName: 'Server response time' - color: '#00BCF2' - } - } - ] - title: 'Server response time' - visualization: { - chartType: 2 - legendVisualization: { - isVisible: true - position: 2 - hideSubtitle: false - } - axisVisualization: { - x: { - isVisible: true - axisType: 2 - } - y: { - isVisible: true - axisType: 1 - } - } - } - openBladeOnClick: { - openBlade: true - destinationBlade: { - extensionName: 'HubsExtension' - bladeName: 'ResourceMenuBlade' - parameters: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - menuid: 'performance' - } - } - } - } - } - } - { - name: 'sharedTimeRange' - isOptional: true - } - ] - #disable-next-line BCP036 - type: 'Extension/HubsExtension/PartType/MonitorChartPart' - settings: {} - } - } - { - position: { - x: 12 - y: 2 - colSpan: 4 - rowSpan: 3 - } - metadata: { - inputs: [ - { - name: 'options' - value: { - chart: { - metrics: [ - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'browserTimings/networkDuration' - aggregationType: 4 - namespace: 'microsoft.insights/components' - metricVisualization: { - displayName: 'Page load network connect time' - color: '#7E58FF' - } - } - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'browserTimings/processingDuration' - aggregationType: 4 - namespace: 'microsoft.insights/components' - metricVisualization: { - displayName: 'Client processing time' - color: '#44F1C8' - } - } - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'browserTimings/sendDuration' - aggregationType: 4 - namespace: 'microsoft.insights/components' - metricVisualization: { - displayName: 'Send request time' - color: '#EB9371' - } - } - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'browserTimings/receiveDuration' - aggregationType: 4 - namespace: 'microsoft.insights/components' - metricVisualization: { - displayName: 'Receiving response time' - color: '#0672F1' - } - } - ] - title: 'Average page load time breakdown' - visualization: { - chartType: 3 - legendVisualization: { - isVisible: true - position: 2 - hideSubtitle: false - } - axisVisualization: { - x: { - isVisible: true - axisType: 2 - } - y: { - isVisible: true - axisType: 1 - } - } - } - } - } - } - { - name: 'sharedTimeRange' - isOptional: true - } - ] - #disable-next-line BCP036 - type: 'Extension/HubsExtension/PartType/MonitorChartPart' - settings: {} - } - } - { - position: { - x: 0 - y: 5 - colSpan: 4 - rowSpan: 3 - } - metadata: { - inputs: [ - { - name: 'options' - value: { - chart: { - metrics: [ - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'availabilityResults/availabilityPercentage' - aggregationType: 4 - namespace: 'microsoft.insights/components' - metricVisualization: { - displayName: 'Availability' - color: '#47BDF5' - } - } - ] - title: 'Average availability' - visualization: { - chartType: 3 - legendVisualization: { - isVisible: true - position: 2 - hideSubtitle: false - } - axisVisualization: { - x: { - isVisible: true - axisType: 2 - } - y: { - isVisible: true - axisType: 1 - } - } - } - openBladeOnClick: { - openBlade: true - destinationBlade: { - extensionName: 'HubsExtension' - bladeName: 'ResourceMenuBlade' - parameters: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - menuid: 'availability' - } - } - } - } - } - } - { - name: 'sharedTimeRange' - isOptional: true - } - ] - #disable-next-line BCP036 - type: 'Extension/HubsExtension/PartType/MonitorChartPart' - settings: {} - } - } - { - position: { - x: 4 - y: 5 - colSpan: 4 - rowSpan: 3 - } - metadata: { - inputs: [ - { - name: 'options' - value: { - chart: { - metrics: [ - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'exceptions/server' - aggregationType: 7 - namespace: 'microsoft.insights/components' - metricVisualization: { - displayName: 'Server exceptions' - color: '#47BDF5' - } - } - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'dependencies/failed' - aggregationType: 7 - namespace: 'microsoft.insights/components' - metricVisualization: { - displayName: 'Dependency failures' - color: '#7E58FF' - } - } - ] - title: 'Server exceptions and Dependency failures' - visualization: { - chartType: 2 - legendVisualization: { - isVisible: true - position: 2 - hideSubtitle: false - } - axisVisualization: { - x: { - isVisible: true - axisType: 2 - } - y: { - isVisible: true - axisType: 1 - } - } - } - } - } - } - { - name: 'sharedTimeRange' - isOptional: true - } - ] - #disable-next-line BCP036 - type: 'Extension/HubsExtension/PartType/MonitorChartPart' - settings: {} - } - } - { - position: { - x: 8 - y: 5 - colSpan: 4 - rowSpan: 3 - } - metadata: { - inputs: [ - { - name: 'options' - value: { - chart: { - metrics: [ - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'performanceCounters/processorCpuPercentage' - aggregationType: 4 - namespace: 'microsoft.insights/components' - metricVisualization: { - displayName: 'Processor time' - color: '#47BDF5' - } - } - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'performanceCounters/processCpuPercentage' - aggregationType: 4 - namespace: 'microsoft.insights/components' - metricVisualization: { - displayName: 'Process CPU' - color: '#7E58FF' - } - } - ] - title: 'Average processor and process CPU utilization' - visualization: { - chartType: 2 - legendVisualization: { - isVisible: true - position: 2 - hideSubtitle: false - } - axisVisualization: { - x: { - isVisible: true - axisType: 2 - } - y: { - isVisible: true - axisType: 1 - } - } - } - } - } - } - { - name: 'sharedTimeRange' - isOptional: true - } - ] - #disable-next-line BCP036 - type: 'Extension/HubsExtension/PartType/MonitorChartPart' - settings: {} - } - } - { - position: { - x: 12 - y: 5 - colSpan: 4 - rowSpan: 3 - } - metadata: { - inputs: [ - { - name: 'options' - value: { - chart: { - metrics: [ - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'exceptions/browser' - aggregationType: 7 - namespace: 'microsoft.insights/components' - metricVisualization: { - displayName: 'Browser exceptions' - color: '#47BDF5' - } - } - ] - title: 'Browser exceptions' - visualization: { - chartType: 2 - legendVisualization: { - isVisible: true - position: 2 - hideSubtitle: false - } - axisVisualization: { - x: { - isVisible: true - axisType: 2 - } - y: { - isVisible: true - axisType: 1 - } - } - } - } - } - } - { - name: 'sharedTimeRange' - isOptional: true - } - ] - #disable-next-line BCP036 - type: 'Extension/HubsExtension/PartType/MonitorChartPart' - settings: {} - } - } - { - position: { - x: 0 - y: 8 - colSpan: 4 - rowSpan: 3 - } - metadata: { - inputs: [ - { - name: 'options' - value: { - chart: { - metrics: [ - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'availabilityResults/count' - aggregationType: 7 - namespace: 'microsoft.insights/components' - metricVisualization: { - displayName: 'Availability test results count' - color: '#47BDF5' - } - } - ] - title: 'Availability test results count' - visualization: { - chartType: 2 - legendVisualization: { - isVisible: true - position: 2 - hideSubtitle: false - } - axisVisualization: { - x: { - isVisible: true - axisType: 2 - } - y: { - isVisible: true - axisType: 1 - } - } - } - } - } - } - { - name: 'sharedTimeRange' - isOptional: true - } - ] - #disable-next-line BCP036 - type: 'Extension/HubsExtension/PartType/MonitorChartPart' - settings: {} - } - } - { - position: { - x: 4 - y: 8 - colSpan: 4 - rowSpan: 3 - } - metadata: { - inputs: [ - { - name: 'options' - value: { - chart: { - metrics: [ - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'performanceCounters/processIOBytesPerSecond' - aggregationType: 4 - namespace: 'microsoft.insights/components' - metricVisualization: { - displayName: 'Process IO rate' - color: '#47BDF5' - } - } - ] - title: 'Average process I/O rate' - visualization: { - chartType: 2 - legendVisualization: { - isVisible: true - position: 2 - hideSubtitle: false - } - axisVisualization: { - x: { - isVisible: true - axisType: 2 - } - y: { - isVisible: true - axisType: 1 - } - } - } - } - } - } - { - name: 'sharedTimeRange' - isOptional: true - } - ] - #disable-next-line BCP036 - type: 'Extension/HubsExtension/PartType/MonitorChartPart' - settings: {} - } - } - { - position: { - x: 8 - y: 8 - colSpan: 4 - rowSpan: 3 - } - metadata: { - inputs: [ - { - name: 'options' - value: { - chart: { - metrics: [ - { - resourceMetadata: { - id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}' - } - name: 'performanceCounters/memoryAvailableBytes' - aggregationType: 4 - namespace: 'microsoft.insights/components' - metricVisualization: { - displayName: 'Available memory' - color: '#47BDF5' - } - } - ] - title: 'Average available memory' - visualization: { - chartType: 2 - legendVisualization: { - isVisible: true - position: 2 - hideSubtitle: false - } - axisVisualization: { - x: { - isVisible: true - axisType: 2 - } - y: { - isVisible: true - axisType: 1 - } - } - } - } - } - } - { - name: 'sharedTimeRange' - isOptional: true - } - ] - #disable-next-line BCP036 - type: 'Extension/HubsExtension/PartType/MonitorChartPart' - settings: {} - } - } - ] - } - ] - } -} diff --git a/infra/shared/keyvault.bicep b/infra/shared/keyvault.bicep deleted file mode 100644 index f84f750..0000000 --- a/infra/shared/keyvault.bicep +++ /dev/null @@ -1,31 +0,0 @@ -param name string -param location string = resourceGroup().location -param tags object = {} - -@description('Service principal that should be granted read access to the KeyVault. If unset, no service principal is granted access by default') -param principalId string = '' - -var defaultAccessPolicies = !empty(principalId) ? [ - { - objectId: principalId - permissions: { secrets: [ 'get', 'list' ] } - tenantId: subscription().tenantId - } -] : [] - -resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: name - location: location - tags: tags - properties: { - tenantId: subscription().tenantId - sku: { family: 'A', name: 'standard' } - enabledForTemplateDeployment: true - accessPolicies: union(defaultAccessPolicies, [ - // define access policies here - ]) - } -} - -output endpoint string = keyVault.properties.vaultUri -output name string = keyVault.name diff --git a/infra/shared/monitoring.bicep b/infra/shared/monitoring.bicep deleted file mode 100644 index 4ae9796..0000000 --- a/infra/shared/monitoring.bicep +++ /dev/null @@ -1,34 +0,0 @@ -param logAnalyticsName string -param applicationInsightsName string -param location string = resourceGroup().location -param tags object = {} - -resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2021-12-01-preview' = { - name: logAnalyticsName - location: location - tags: tags - properties: any({ - retentionInDays: 30 - features: { - searchVersion: 1 - } - sku: { - name: 'PerGB2018' - } - }) -} - -resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = { - name: applicationInsightsName - location: location - tags: tags - kind: 'web' - properties: { - Application_Type: 'web' - WorkspaceResourceId: logAnalytics.id - } -} - -output applicationInsightsName string = applicationInsights.name -output logAnalyticsWorkspaceId string = logAnalytics.id -output logAnalyticsWorkspaceName string = logAnalytics.name diff --git a/infra/shared/registry.bicep b/infra/shared/registry.bicep deleted file mode 100644 index d6629f8..0000000 --- a/infra/shared/registry.bicep +++ /dev/null @@ -1,36 +0,0 @@ -param name string -param location string = resourceGroup().location -param tags object = {} - -param adminUserEnabled bool = true -param anonymousPullEnabled bool = false -param dataEndpointEnabled bool = false -param encryption object = { - status: 'disabled' -} -param networkRuleBypassOptions string = 'AzureServices' -param publicNetworkAccess string = 'Enabled' -param sku object = { - name: 'Standard' -} -param zoneRedundancy string = 'Disabled' - -// 2023-01-01-preview needed for anonymousPullEnabled -resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' = { - name: name - location: location - tags: tags - sku: sku - properties: { - adminUserEnabled: adminUserEnabled - anonymousPullEnabled: anonymousPullEnabled - dataEndpointEnabled: dataEndpointEnabled - encryption: encryption - networkRuleBypassOptions: networkRuleBypassOptions - publicNetworkAccess: publicNetworkAccess - zoneRedundancy: zoneRedundancy - } -} - -output loginServer string = containerRegistry.properties.loginServer -output name string = containerRegistry.name diff --git a/infra/shared/role.bicep b/infra/shared/role.bicep deleted file mode 100644 index 0b30cfd..0000000 --- a/infra/shared/role.bicep +++ /dev/null @@ -1,21 +0,0 @@ -metadata description = 'Creates a role assignment for a service principal.' -param principalId string - -@allowed([ - 'Device' - 'ForeignGroup' - 'Group' - 'ServicePrincipal' - 'User' -]) -param principalType string = 'ServicePrincipal' -param roleDefinitionId string - -resource role 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(subscription().id, resourceGroup().id, principalId, roleDefinitionId) - properties: { - principalId: principalId - principalType: principalType - roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId) - } -} diff --git a/next-steps.md b/next-steps.md new file mode 100644 index 0000000..ab0b16e --- /dev/null +++ b/next-steps.md @@ -0,0 +1,93 @@ +# Next Steps after `azd init` + +## Table of Contents + +1. [Next Steps](#next-steps) +2. [What was added](#what-was-added) +3. [Billing](#billing) +4. [Troubleshooting](#troubleshooting) + +## Next Steps + +### Provision infrastructure and deploy application code + +Run `azd up` to provision your infrastructure and deploy to Azure (or run `azd provision` then `azd deploy` to accomplish the tasks separately). Visit the service endpoints listed to see your application up-and-running! + +To troubleshoot any issues, see [troubleshooting](#troubleshooting). + +### Configure environment variables for running services + +Environment variables can be configured by modifying the `env` settings in [resources.bicep](./infra/resources.bicep). +To define a secret, add the variable as a `secretRef` pointing to a `secrets` entry or a stored KeyVault secret. + +### Configure CI/CD pipeline + +Run `azd pipeline config` to configure the deployment pipeline to connect securely to Azure. + +- Deploying with `GitHub Actions`: Select `GitHub` when prompted for a provider. If your project lacks the `azure-dev.yml` file, accept the prompt to add it and proceed with pipeline configuration. + +- Deploying with `Azure DevOps Pipeline`: Select `Azure DevOps` when prompted for a provider. If your project lacks the `azure-dev.yml` file, accept the prompt to add it and proceed with pipeline configuration. + +## What was added + +### Infrastructure configuration + +To describe the infrastructure and application, `azure.yaml` along with Infrastructure as Code files using Bicep were added with the following directory structure: + +```yaml +- azure.yaml # azd project configuration +- infra/ # Infrastructure-as-code Bicep files + - main.bicep # Subscription level resources + - resources.bicep # Primary resource group resources + - modules/ # Library modules +``` + +The resources declared in [resources.bicep](./infra/resources.bicep) are provisioned when running `azd up` or `azd provision`. +This includes: + + +- Azure Container App to host the 'llama-index-javascript' service. + +More information about [Bicep](https://aka.ms/bicep) language. + +### Build from source (no Dockerfile) + +#### Build with Buildpacks using Oryx + +If your project does not contain a Dockerfile, we will use [Buildpacks](https://buildpacks.io/) using [Oryx](https://github.com/microsoft/Oryx/blob/main/doc/README.md) to create an image for the services in `azure.yaml` and get your containerized app onto Azure. + +To produce and run the docker image locally: + +1. Run `azd package` to build the image. +2. Copy the *Image Tag* shown. +3. Run `docker run -it ` to run the image locally. + +#### Exposed port + +Oryx will automatically set `PORT` to a default value of `80` (port `8080` for Java). Additionally, it will auto-configure supported web servers such as `gunicorn` and `ASP .NET Core` to listen to the target `PORT`. If your application already listens to the port specified by the `PORT` variable, the application will work out-of-the-box. Otherwise, you may need to perform one of the steps below: + +1. Update your application code or configuration to listen to the port specified by the `PORT` variable +1. (Alternatively) Search for `targetPort` in a .bicep file under the `infra/app` folder, and update the variable to match the port used by the application. + +## Billing + +Visit the *Cost Management + Billing* page in Azure Portal to track current spend. For more information about how you're billed, and how you can monitor the costs incurred in your Azure subscriptions, visit [billing overview](https://learn.microsoft.com/azure/developer/intro/azure-developer-billing). + +## Troubleshooting + +Q: I visited the service endpoint listed, and I'm seeing a blank page, a generic welcome page, or an error page. + +A: Your service may have failed to start, or it may be missing some configuration settings. To investigate further: + +1. Run `azd show`. Click on the link under "View in Azure Portal" to open the resource group in Azure Portal. +2. Navigate to the specific Container App service that is failing to deploy. +3. Click on the failing revision under "Revisions with Issues". +4. Review "Status details" for more information about the type of failure. +5. Observe the log outputs from Console log stream and System log stream to identify any errors. +6. If logs are written to disk, use *Console* in the navigation to connect to a shell within the running container. + +For more troubleshooting information, visit [Container Apps troubleshooting](https://learn.microsoft.com/azure/container-apps/troubleshooting). + +### Additional information + +For additional information about setting up your `azd` project, visit our official [docs](https://learn.microsoft.com/azure/developer/azure-developer-cli/make-azd-compatible?pivots=azd-convert).