From d3c43b6216051c3e73452b418b20282b7b69b20d Mon Sep 17 00:00:00 2001 From: MD Ashique Date: Wed, 20 Sep 2023 08:45:34 +0530 Subject: [PATCH] Adding bicep script to deploy azure function Dapr extension samples in ACA (#150) * Adding bicep script to deply azure functions with dapr ext in ACA Signed-off-by: MD Ashique * Adding bicep script to deply azure functions with dapr ext in ACA Signed-off-by: MD Ashique * Fixed csproj file which causing docker image to fail in ACA Signed-off-by: MD Ashique * Fixed csproj file which causing docker image to fail in ACA Signed-off-by: MD Ashique * Fixed csproj file which causing docker image to fail in ACA Signed-off-by: MD Ashique * Update samples/sample-infra/README.md Co-authored-by: Shubham Sharma * creating bicep templates Signed-off-by: MD Ashique * creating bicep templates Signed-off-by: MD Ashique * Update samples/sample-infra/dapr-components.bicep Co-authored-by: Shubham Sharma * creating bicep templates Signed-off-by: MD Ashique --------- Signed-off-by: MD Ashique Co-authored-by: Shubham Sharma --- samples/dotnet-azurefunction/Startup.cs | 21 --- .../dotnet-azurefunction.csproj | 6 +- samples/sample-infra/README.md | 29 ++++ samples/sample-infra/azure-function.bicep | 59 ++++++++ samples/sample-infra/azure-services.bicep | 141 ++++++++++++++++++ samples/sample-infra/dapr-components.bicep | 106 +++++++++++++ samples/sample-infra/deploy-samples.bicep | 50 +++++++ 7 files changed, 386 insertions(+), 26 deletions(-) delete mode 100644 samples/dotnet-azurefunction/Startup.cs create mode 100644 samples/sample-infra/README.md create mode 100644 samples/sample-infra/azure-function.bicep create mode 100644 samples/sample-infra/azure-services.bicep create mode 100644 samples/sample-infra/dapr-components.bicep create mode 100644 samples/sample-infra/deploy-samples.bicep diff --git a/samples/dotnet-azurefunction/Startup.cs b/samples/dotnet-azurefunction/Startup.cs deleted file mode 100644 index 6f158aa6..00000000 --- a/samples/dotnet-azurefunction/Startup.cs +++ /dev/null @@ -1,21 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// ------------------------------------------------------------ - -using Microsoft.Azure.Functions.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Console; - -[assembly: FunctionsStartup(typeof(Microsoft.Azure.WebJobs.Extensions.Dapr.Services.Startup))] -namespace Microsoft.Azure.WebJobs.Extensions.Dapr.Services -{ - public class Startup : FunctionsStartup - { - public override void Configure(IFunctionsHostBuilder builder) - { - builder.Services.AddSingleton(); - } - } -} \ No newline at end of file diff --git a/samples/dotnet-azurefunction/dotnet-azurefunction.csproj b/samples/dotnet-azurefunction/dotnet-azurefunction.csproj index b06d4486..db6a7a53 100644 --- a/samples/dotnet-azurefunction/dotnet-azurefunction.csproj +++ b/samples/dotnet-azurefunction/dotnet-azurefunction.csproj @@ -5,11 +5,7 @@ dotnet_azurefunction - - - - - + diff --git a/samples/sample-infra/README.md b/samples/sample-infra/README.md new file mode 100644 index 00000000..84332e5d --- /dev/null +++ b/samples/sample-infra/README.md @@ -0,0 +1,29 @@ +# azure-functions-dapr-aca-deployment +Steps to deploy the Azure Function with Dapr extension in ACA. + +## Create resource group +``` +az group create --name {resourceGroupName} --location eastasia +``` + +## Deploy azure function samples with Dapr extension in ACA +``` +az deployment group create --resource-group {resourceGroupName} --template-file deploy-samples.bicep +``` + +## List of resources bicep will create + +1. Azure Storage Account +2. Blob Service +3. Blob Container +4. Log Analytics Workspace +5. Application Insights +6. Managed Environment +7. Redis Cache +8. Event Hub Namespace +9. Event Hub Authorization Rule +10. Event Hub +11. Dapr Component for State Management +12. Dapr Component for Message Bus +13. Dapr Component for Event Hub +14. Azure Function App \ No newline at end of file diff --git a/samples/sample-infra/azure-function.bicep b/samples/sample-infra/azure-function.bicep new file mode 100644 index 00000000..6b8754d2 --- /dev/null +++ b/samples/sample-infra/azure-function.bicep @@ -0,0 +1,59 @@ +param envResourceNamePrefix string +param azStorageConnectionString string +param appInsightsConnectionString string +param environmentId string +param stateStoreName string + +resource daprComponentStateManagement 'Microsoft.App/managedEnvironments/daprComponents@2023-05-01' existing = { + name: stateStoreName +} + +/* ###################################################################### */ +// Create Azure Function +/* ###################################################################### */ +resource azfunctionapp 'Microsoft.Web/sites@2022-09-01' = { + name: '${envResourceNamePrefix}-funcapp' + location: 'East Asia (Stage)' + kind: 'functionapp,linux,container,azurecontainerapps' + properties: { + name: '${envResourceNamePrefix}-funcapp' + siteConfig: { + appSettings: [ + { + name: 'AzureWebJobsStorage' + value: azStorageConnectionString + } + { + name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' + value: appInsightsConnectionString + } + { + name: 'PubSubName' + value: 'messagebus' + } + { + name: 'StateStoreName' + value: 'statestore' + } + { + name: 'KafkaBindingName' + value: 'sample-topic' + } + ] + linuxFxVersion: 'Docker|mcr.microsoft.com/daprio/samples/dotnet-azurefunction:edge' + } + DaprConfig: { + enabled: true + appId: '${envResourceNamePrefix}-funcapp' + appPort: 3001 + httpReadBufferSize: '' + httpMaxRequestSize: '' + logLevel: '' + enableApiLogging: true + } + managedEnvironmentId: environmentId + } + dependsOn: [ + daprComponentStateManagement + ] +} diff --git a/samples/sample-infra/azure-services.bicep b/samples/sample-infra/azure-services.bicep new file mode 100644 index 00000000..55454682 --- /dev/null +++ b/samples/sample-infra/azure-services.bicep @@ -0,0 +1,141 @@ +param location string +param redisCacheName string +param eventHubNamespace string +param eventHubName string +param eventHubSku string +param containerName string +param envResourceNamePrefix string + +/* ###################################################################### */ +// Create storage account for function app prereq +/* ###################################################################### */ +resource azStorageAccount 'Microsoft.Storage/storageAccounts@2021-08-01' = { + name: '${envResourceNamePrefix}storage' + location: location + kind: 'StorageV2' + sku: { + name: 'Standard_LRS' + } +} + +var azStorageConnectionString = 'DefaultEndpointsProtocol=https;AccountName=${azStorageAccount.name};EndpointSuffix=${az.environment().suffixes.storage};AccountKey=${azStorageAccount.listKeys().keys[0].value}' + +// Create blob service +resource blobService 'Microsoft.Storage/storageAccounts/blobServices@2019-06-01' = { + name: 'default' + parent: azStorageAccount +} + +// Create container +resource container 'Microsoft.Storage/storageAccounts/blobServices/containers@2019-06-01' = { + name: containerName + parent: blobService + properties: { + publicAccess: 'None' + metadata: {} + } +} + +/* ###################################################################### */ +// Create managed ACA environment +/* ###################################################################### */ +resource logAnalyticsWorkspace'Microsoft.OperationalInsights/workspaces@2021-06-01' = { + name: '${envResourceNamePrefix}-la' + location: location + properties: any({ + retentionInDays: 30 + features: { + searchVersion: 1 + } + sku: { + name: 'PerGB2018' + } + }) +} + +resource appInsights 'Microsoft.Insights/components@2020-02-02' = { + name: '${envResourceNamePrefix}-ai' + location: location + kind: 'web' + properties: { + Application_Type: 'web' + WorkspaceResourceId: logAnalyticsWorkspace.id + } +} + +resource environment 'Microsoft.App/managedEnvironments@2022-10-01' = { + name: '${envResourceNamePrefix}-env' + location: location + properties: { + daprAIInstrumentationKey: appInsights.properties.InstrumentationKey + appLogsConfiguration: { + destination: 'log-analytics' + logAnalyticsConfiguration: { + customerId: logAnalyticsWorkspace.properties.customerId + sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey + } + } + } +} + +/* ###################################################################### */ +// Create Redis Cache +/* ###################################################################### */ +resource redisCache 'Microsoft.Cache/Redis@2020-06-01' = { + name: redisCacheName + location: location + properties: { + enableNonSslPort: true + minimumTlsVersion: '1.2' + sku: { + capacity: 1 + family: 'C' + name: 'Standard' + } + } +} + +/* ###################################################################### */ +// Create Azure EventHub +/* ###################################################################### */ +resource eventHubNamespaceResource 'Microsoft.EventHub/namespaces@2021-11-01' = { + name: eventHubNamespace + location: location + sku: { + name: eventHubSku + tier: eventHubSku + capacity: 1 + } + properties: { + isAutoInflateEnabled: false + maximumThroughputUnits: 0 + kafkaEnabled: true + } +} + +resource eventHubAuth 'Microsoft.EventHub/namespaces/authorizationRules@2022-10-01-preview' = { + name: '${envResourceNamePrefix}-eventHubAuth' + parent: eventHubNamespaceResource + properties: { + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } +} + +resource eventHub 'Microsoft.EventHub/namespaces/eventhubs@2021-11-01' = { + parent: eventHubNamespaceResource + name: eventHubName + properties: { + messageRetentionInDays: 7 + partitionCount: 1 + } +} + +output azStorageConnectionString string = azStorageConnectionString +output appInsightsConnectionString string = appInsights.properties.ConnectionString +output environmentId string = environment.id +output eventHubName string = eventHubName +output azStorageAccountName string = azStorageAccount.name diff --git a/samples/sample-infra/dapr-components.bicep b/samples/sample-infra/dapr-components.bicep new file mode 100644 index 00000000..ae8ae548 --- /dev/null +++ b/samples/sample-infra/dapr-components.bicep @@ -0,0 +1,106 @@ +param azStorageConnectionString string +param envResourceNamePrefix string +param redisCacheName string +param eventHubName string +param azStorageAccountName string +param containerName string +param eventHubNamespace string + +resource environment 'Microsoft.App/managedEnvironments@2022-10-01' existing = { + name: '${envResourceNamePrefix}-env' +} + +resource redisCache 'Microsoft.Cache/Redis@2020-06-01' existing = { + name: redisCacheName +} + +resource eventHubAuth 'Microsoft.EventHub/namespaces/authorizationRules@2022-10-01-preview' existing = { + name: '${eventHubNamespace}/${envResourceNamePrefix}-eventHubAuth' +} + +/* ###################################################################### */ +// Setup Dapr componet Redis state store in ACA +/* ###################################################################### */ +resource daprComponentStateManagement 'Microsoft.App/managedEnvironments/daprComponents@2023-05-01' = { + parent: environment + name: 'statestore' + properties: { + componentType: 'state.redis' + version: 'v1' + metadata: [ + { + name: 'redisHost' + value: '${redisCacheName}.redis.cache.windows.net:6379' + } + { + name: 'redisPassword' + value: redisCache.listKeys().primaryKey + } + ] + scopes: [] + } +} + +/* ###################################################################### */ +// Setup Dapr componet Redis message bus in ACA +/* ###################################################################### */ +resource daprComponentMessagebus 'Microsoft.App/managedEnvironments/daprComponents@2023-05-01' = { + parent: environment + name: 'messagebus' + properties: { + componentType: 'pubsub.redis' + version: 'v1' + metadata: [ + { + name: 'redisHost' + value: '${redisCacheName}.redis.cache.windows.net:6379' + } + { + name: 'redisPassword' + value: redisCache.listKeys().primaryKey + } + ] + scopes: [] + } +} + +/* ###################################################################### */ +// Setup Dapr component Eventhub in ACA +/* ###################################################################### */ +resource daprComponentEventHub 'Microsoft.App/managedEnvironments/daprComponents@2023-05-01' = { + parent: environment + name: 'sample-topic' + properties: { + componentType: 'bindings.azure.eventhubs' + version: 'v1' + metadata: [ + { + name: 'connectionString' + value: '${eventHubAuth.listKeys().primaryConnectionString};EntityPath=${eventHubName}' + } + { + name: 'storageConnectionString' + value: azStorageConnectionString + } + { + name: 'eventHub' + value: eventHubName + } + { + name: 'consumerGroup' + value: '$Default' + } + { + name: 'storageAccountName' + value: azStorageAccountName + } + { + name: 'storageContainerName' + value: containerName + } + ] + scopes: [] + } +} + +output stateStoreName string = 'statestore' diff --git a/samples/sample-infra/deploy-samples.bicep b/samples/sample-infra/deploy-samples.bicep new file mode 100644 index 00000000..303ee42e --- /dev/null +++ b/samples/sample-infra/deploy-samples.bicep @@ -0,0 +1,50 @@ +param location string = resourceGroup().location +param redisCacheName string = 'redisCacheDaprStateStore-${uniqueString(resourceGroup().id)}' +param eventHubNamespace string = 'daprEventHubNamespace-${uniqueString(resourceGroup().id)}' +param eventHubName string = 'daprEventHub-${uniqueString(resourceGroup().id)}' +param eventHubSku string = 'Standard' +param containerName string = 'daprazurefunctionseventhubstoragecontainer' + +@description('Resource name prefix') +param resourceNamePrefix string +var envResourceNamePrefix = toLower(resourceNamePrefix) + +module azureServices 'azure-services.bicep' = { + name: 'azure-services' + scope: resourceGroup() + params:{ + containerName:containerName + envResourceNamePrefix: envResourceNamePrefix + eventHubName:eventHubName + eventHubNamespace: eventHubNamespace + eventHubSku: eventHubSku + location: location + redisCacheName: redisCacheName + } +} + +module daprComponents 'dapr-components.bicep' = { + name: 'dapr-components' + scope: resourceGroup() + params:{ + containerName:containerName + envResourceNamePrefix: envResourceNamePrefix + eventHubName:eventHubName + redisCacheName: redisCacheName + azStorageAccountName: azureServices.outputs.azStorageAccountName + azStorageConnectionString: azureServices.outputs.azStorageConnectionString + eventHubNamespace: eventHubNamespace + } +} + +module azureFunction 'azure-function.bicep' = { + name: 'azure-function' + scope: resourceGroup() + params:{ + envResourceNamePrefix: envResourceNamePrefix + azStorageConnectionString: azureServices.outputs.azStorageConnectionString + appInsightsConnectionString: azureServices.outputs.appInsightsConnectionString + environmentId: azureServices.outputs.environmentId + stateStoreName: daprComponents.outputs.stateStoreName + } +}