From 16cc6b54dd18ccf1a395a7b344ecc5ff94b09b4c Mon Sep 17 00:00:00 2001 From: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com> Date: Thu, 2 May 2024 06:09:41 +0200 Subject: [PATCH 01/10] feat: remove functions worker project option in az func servicebus topic --- .../.template.config/template.json | 59 +------------- ...tes.AzureFunctions.ServiceBus.Topic.csproj | 14 ++-- .../OrderFunction.cs | 57 +------------- .../Program.cs | 2 - .../Startup.cs | 77 ------------------- .../local.settings.json | 4 - .../AzureFunctionsServiceBusProjectOptions.cs | 6 +- .../ServiceBus/Logging/SerilogLoggingTests.cs | 6 -- .../OrderMessageHandlerTests.cs | 6 -- 9 files changed, 14 insertions(+), 217 deletions(-) delete mode 100644 src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/Startup.cs diff --git a/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/.template.config/template.json b/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/.template.config/template.json index fcc931c1..197f26cf 100644 --- a/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/.template.config/template.json +++ b/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/.template.config/template.json @@ -28,20 +28,6 @@ "**/*.filelist", "**/*.user", "**/*.lock.json" - ], - "modifiers": [ - { - "condition": "Isolated", - "exclude": [ - "Startup.cs" - ] - }, - { - "condition": "InProcess", - "exclude": [ - "Program.cs" - ] - } ] } ], @@ -77,30 +63,6 @@ }, "replaces": "//#error" }, - "functions-worker": { - "type": "parameter", - "datatype": "choice", - "choices": [ - { - "choice": "inProcess", - "description": "Uses Azure Functions in-process worker template" - }, - { - "choice": "isolated", - "description": "Uses Azure Functions isolated worker template" - } - ], - "defaultValue": "isolated", - "description": "Chooses the kind of Azure Functions worker template" - }, - "InProcess": { - "type": "computed", - "value": "(functions-worker == \"inProcess\")" - }, - "Isolated": { - "type": "computed", - "value": "(functions-worker == \"isolated\")" - }, "exclude-serilog": { "type": "parameter", "datatype": "bool", @@ -111,24 +73,5 @@ "type": "computed", "value": "!(exclude-serilog)" } - }, - "postActions": [ - { - "description": "Adding Reference to Microsoft.NET.Sdk.Functions NuGet package", - "actionId": "B17581D1-C5C9-4489-8F0A-004BE667B814", - "continueOnError": false, - "manualInstructions": [ - { - "text": "Manually add the reference to Microsoft.NET.Sdk.Functions to your project file" - } - ], - "condition": "InProcess", - "args": { - "referenceType": "package", - "reference": "Microsoft.NET.Sdk.Functions", - "version": "4.1.3", - "projectFileExtensions": ".csproj" - } - } - ] + } } diff --git a/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/Arcus.Templates.AzureFunctions.ServiceBus.Topic.csproj b/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/Arcus.Templates.AzureFunctions.ServiceBus.Topic.csproj index 325129bb..d2e81787 100644 --- a/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/Arcus.Templates.AzureFunctions.ServiceBus.Topic.csproj +++ b/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/Arcus.Templates.AzureFunctions.ServiceBus.Topic.csproj @@ -1,7 +1,7 @@  net6.0 - Exe + Exe v4 Linux @@ -34,9 +34,7 @@ - $(DefineConstants);Serilog_AppInsights;InProcess - true - false + $(DefineConstants);Serilog_AppInsights true /home/site/wwwroot @@ -58,11 +56,9 @@ - - - - - + + + diff --git a/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/OrderFunction.cs b/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/OrderFunction.cs index 8c248e48..2d20661c 100644 --- a/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/OrderFunction.cs +++ b/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/OrderFunction.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Arcus.Messaging.Abstractions; @@ -8,15 +9,7 @@ using Arcus.Templates.AzureFunctions.ServiceBus.Topic.Model; using Azure.Messaging.ServiceBus; using GuardNet; -using Arcus.Observability.Correlation; -#if Isolated -using System.Text.Json; using Microsoft.Azure.Functions.Worker; -#endif -#if InProcess -using Arcus.Messaging.AzureFunctions.ServiceBus; -using Microsoft.Azure.WebJobs; -#endif using Microsoft.Extensions.Logging; namespace Arcus.Templates.AzureFunctions.ServiceBus.Topic @@ -28,50 +21,7 @@ public class OrderFunction { private readonly string _jobId; private readonly IAzureServiceBusMessageRouter _messageRouter; -#if InProcess - private readonly AzureFunctionsInProcessMessageCorrelation _messageCorrelation; - - /// - /// Initializes a new instance of the class. - /// - /// The message router instance to route the Azure Service Bus topic messages through the order processing. - /// The message correlation instance to W3C correlate the Azure Service Bus topic messages. - /// Thrown when the or the is null. - public OrderFunction( - IAzureServiceBusMessageRouter messageRouter, - AzureFunctionsInProcessMessageCorrelation messageCorrelation) - { - Guard.NotNull(messageRouter, nameof(messageRouter), "Requires a message router instance to route the incoming Azure Service Bus topic message through the order processing"); - Guard.NotNull(messageCorrelation, nameof(messageCorrelation), "Requires a message correlation instance to W3C correlate incoming Azure Service Bus topic messages"); - - _messageRouter = messageRouter; - _messageCorrelation = messageCorrelation; - _jobId = Guid.NewGuid().ToString(); - } - - /// - /// Process an Azure Service Bus topic as an . - /// - /// The incoming message on the Azure Service Bus topic, representing an . - /// The logger instance to write informational messages during the message processing. - /// The token to cancel the message processing. - [FunctionName("order-processing")] - public async Task Run( - [ServiceBusTrigger("order-topic", "order-subscription", Connection = "ServiceBusConnectionString")] ServiceBusReceivedMessage message, - ILogger log, - CancellationToken cancellationToken) - { - log.LogInformation($"C# ServiceBus topic trigger function processed message: {message.MessageId}"); - - AzureServiceBusMessageContext messageContext = message.GetMessageContext(_jobId); - using (MessageCorrelationResult result = _messageCorrelation.CorrelateMessage(message)) - { - await _messageRouter.RouteMessageAsync(message, messageContext, result.CorrelationInfo, cancellationToken); - } - } -#endif -#if Isolated - + /// /// Initializes a new instance of the class. /// @@ -97,7 +47,7 @@ public async Task Run( { ServiceBusReceivedMessage message = ConvertToServiceBusMessage(messageBody, executionContext); var logger = executionContext.GetLogger>(); - logger.LogInformation($"C# ServiceBus topic trigger function processed message: {message.MessageId}"); + logger.LogInformation("C# ServiceBus topic trigger function processed message: {MessageId}", message.MessageId); AzureServiceBusMessageContext messageContext = message.GetMessageContext(_jobId); using (MessageCorrelationResult result = executionContext.GetCorrelationInfo()) @@ -125,6 +75,5 @@ private static ServiceBusReceivedMessage ConvertToServiceBusMessage(byte[] messa return message; } -#endif } } diff --git a/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/Program.cs b/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/Program.cs index b52c752a..3cf0e5a3 100644 --- a/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/Program.cs +++ b/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/Program.cs @@ -58,13 +58,11 @@ private static IHostBuilder CreateHostBuilder(string[] args) services.AddAssemblyAppVersion(); }) #endif -#if Isolated .ConfigureFunctionsWorkerDefaults((context, builder) => { builder.Services.AddServiceBusMessageRouting() .WithServiceBusMessageHandler(); }) -#endif .ConfigureSecretStore((config, stores) => { //[#if DEBUG] diff --git a/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/Startup.cs b/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/Startup.cs deleted file mode 100644 index 13d800e4..00000000 --- a/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/Startup.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using Arcus.Security.Core.Caching.Configuration; -using Arcus.Templates.AzureFunctions.ServiceBus.Topic; -using Arcus.Templates.AzureFunctions.ServiceBus.Topic.Model; -using Microsoft.Azure.Functions.Extensions.DependencyInjection; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -#if Serilog_AppInsights -using Serilog; -using Serilog.Configuration; -using Serilog.Events; -#endif - -[assembly: FunctionsStartup(typeof(Startup))] - -namespace Arcus.Templates.AzureFunctions.ServiceBus.Topic -{ - public class Startup : FunctionsStartup - { - // This method gets called by the runtime. Use this method to configure the app configuration. - public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder) - { - builder.ConfigurationBuilder.AddEnvironmentVariables(); - } - - // This method gets called by the runtime. Use this method to add services to the container. - public override void Configure(IFunctionsHostBuilder builder) - { - builder.ConfigureSecretStore((context, config, stores) => - { -//[#if DEBUG] - stores.AddConfiguration(config); -//[#endif] - - //#error Please provide a valid secret provider, for example Azure Key Vault: https://security.arcus-azure.net/features/secret-store/provider/key-vault - stores.AddAzureKeyVaultWithManagedIdentity("https://your-keyvault.vault.azure.net/", CacheConfiguration.Default); - }); - - builder.AddServiceBusMessageRouting() - .WithServiceBusMessageHandler(); -#if Serilog_AppInsights - - builder.Services.AddAppName("Service Bus Topic Trigger"); - builder.Services.AddAssemblyAppVersion(); - builder.Services.AddLogging(logging => - { - logging.RemoveMicrosoftApplicationInsightsLoggerProvider() - .AddSerilog(provider => CreateLoggerConfiguration(provider).CreateLogger()); - }); -#endif - } -#if Serilog_AppInsights - - private static LoggerConfiguration CreateLoggerConfiguration(IServiceProvider provider) - { - IConfiguration appConfig = provider.GetRequiredService(); - var logConfig = new LoggerConfiguration() - .MinimumLevel.Information() - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) - .Enrich.FromLogContext() - .Enrich.WithComponentName(provider) - .Enrich.WithVersion(provider) - .WriteTo.Console(); - - var connectionString = appConfig.GetValue("APPLICATIONINSIGHTS_CONNECTION_STRING"); - if (!string.IsNullOrWhiteSpace(connectionString)) - { - logConfig.WriteTo.AzureApplicationInsightsWithConnectionString(provider, connectionString); - } - - return logConfig; - } -#endif - } -} \ No newline at end of file diff --git a/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/local.settings.json b/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/local.settings.json index 7880f7f0..ee03af9f 100644 --- a/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/local.settings.json +++ b/src/Arcus.Templates.AzureFunctions.ServiceBus.Topic/local.settings.json @@ -1,11 +1,7 @@ { "IsEncrypted": false, "Values": { - //#if(Isolated) "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", - //#else - "FUNCTIONS_WORKER_RUNTIME": "dotnet", - //#endif "AzureWebJobsStorage": "UseDevelopmentStorage=true" } } diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/AzureFunctionsServiceBusProjectOptions.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/AzureFunctionsServiceBusProjectOptions.cs index 54f8f3d2..36461bce 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/AzureFunctionsServiceBusProjectOptions.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/AzureFunctionsServiceBusProjectOptions.cs @@ -23,7 +23,11 @@ public AzureFunctionsServiceBusProjectOptions(ServiceBusEntityType entityType) /// The Azure Functions worker type the project should target. public AzureFunctionsServiceBusProjectOptions WithFunctionWorker(FunctionsWorker workerType) { - SetFunctionsWorker(workerType); + if (_entityType != ServiceBusEntityType.Topic) + { + SetFunctionsWorker(workerType); + } + return this; } diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/Logging/SerilogLoggingTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/Logging/SerilogLoggingTests.cs index 18dce057..449fb243 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/Logging/SerilogLoggingTests.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/Logging/SerilogLoggingTests.cs @@ -26,12 +26,6 @@ public async Task ServiceBusTopicProjectIsolated_WithoutSerilog_CorrectlyProcess await TestServiceBusProjectWithoutSerilogCorrectlyProcessesMessage(ServiceBusEntityType.Topic, FunctionsWorker.Isolated); } - [Fact] - public async Task ServiceBusTopicProjectInProcess_WithoutSerilog_CorrectlyProcessesMessage() - { - await TestServiceBusProjectWithoutSerilogCorrectlyProcessesMessage(ServiceBusEntityType.Topic, FunctionsWorker.InProcess); - } - [Fact] public async Task ServiceBusQueueProjectInProcess_WithoutSerilog_CorrectlyProcessesMessage() { diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/MessageHandling/OrderMessageHandlerTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/MessageHandling/OrderMessageHandlerTests.cs index 9a745a5a..911a7639 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/MessageHandling/OrderMessageHandlerTests.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/MessageHandling/OrderMessageHandlerTests.cs @@ -26,12 +26,6 @@ public async Task ServiceBusTopicProject_AsIsolated_CorrectlyProcessesMessage() await TestServiceBusProjectWithWorkerTypeCorrectlyProcessesMessageAsync(ServiceBusEntityType.Topic, FunctionsWorker.Isolated); } - [Fact] - public async Task ServiceBusTopicProject_AsInProcess_CorrectlyProcessesMessage() - { - await TestServiceBusProjectWithWorkerTypeCorrectlyProcessesMessageAsync(ServiceBusEntityType.Topic, FunctionsWorker.InProcess); - } - [Fact] public async Task ServiceBusQueueProject_AsInProcess_CorrectlyProcessesMessage() { From 107fbaaa0c11720c1065012428addac42ce1408c Mon Sep 17 00:00:00 2001 From: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com> Date: Thu, 2 May 2024 06:18:51 +0200 Subject: [PATCH 02/10] feat: remove functions worker project option in az func servicebus queue --- .../.template.config/template.json | 59 +------------- ...tes.AzureFunctions.ServiceBus.Queue.csproj | 14 ++-- .../OrderFunction.cs | 52 ------------- .../Program.cs | 2 - .../Startup.cs | 77 ------------------- .../local.settings.json | 4 - .../AzureFunctionsServiceBusProject.cs | 2 +- .../AzureFunctionsServiceBusProjectOptions.cs | 24 ------ .../Configuration/LaunchSettingsTests.cs | 2 +- .../ServiceBus/Logging/SerilogLoggingTests.cs | 41 +++------- .../OrderMessageHandlerTests.cs | 36 ++------- 11 files changed, 27 insertions(+), 286 deletions(-) delete mode 100644 src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/Startup.cs diff --git a/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/.template.config/template.json b/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/.template.config/template.json index 7c3909cf..fd1c3397 100644 --- a/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/.template.config/template.json +++ b/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/.template.config/template.json @@ -28,20 +28,6 @@ "**/*.filelist", "**/*.user", "**/*.lock.json" - ], - "modifiers": [ - { - "condition": "Isolated", - "exclude": [ - "Startup.cs" - ] - }, - { - "condition": "InProcess", - "exclude": [ - "Program.cs" - ] - } ] } ], @@ -77,30 +63,6 @@ }, "replaces": "//#error" }, - "functions-worker": { - "type": "parameter", - "datatype": "choice", - "choices": [ - { - "choice": "inProcess", - "description": "Uses Azure Functions in-process worker template" - }, - { - "choice": "isolated", - "description": "Uses Azure Functions isolated worker template" - } - ], - "defaultValue": "isolated", - "description": "Chooses the kind of Azure Functions worker template" - }, - "InProcess": { - "type": "computed", - "value": "(functions-worker == \"inProcess\")" - }, - "Isolated": { - "type": "computed", - "value": "(functions-worker == \"isolated\")" - }, "exclude-serilog": { "type": "parameter", "datatype": "bool", @@ -111,24 +73,5 @@ "type": "computed", "value": "!(exclude-serilog)" } - }, - "postActions": [ - { - "description": "Adding Reference to Microsoft.NET.Sdk.Functions NuGet package", - "actionId": "B17581D1-C5C9-4489-8F0A-004BE667B814", - "continueOnError": false, - "manualInstructions": [ - { - "text": "Manually add the reference to Microsoft.NET.Sdk.Functions to your project file" - } - ], - "condition": "InProcess", - "args": { - "referenceType": "package", - "reference": "Microsoft.NET.Sdk.Functions", - "version": "4.1.3", - "projectFileExtensions": ".csproj" - } - } - ] + } } diff --git a/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/Arcus.Templates.AzureFunctions.ServiceBus.Queue.csproj b/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/Arcus.Templates.AzureFunctions.ServiceBus.Queue.csproj index d357c97e..fe096bde 100644 --- a/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/Arcus.Templates.AzureFunctions.ServiceBus.Queue.csproj +++ b/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/Arcus.Templates.AzureFunctions.ServiceBus.Queue.csproj @@ -1,7 +1,7 @@  net6.0 - Exe + Exe v4 Linux @@ -35,9 +35,7 @@ - $(DefineConstants);Serilog_AppInsights;InProcess - true - false + $(DefineConstants);Serilog_AppInsights true /home/site/wwwroot @@ -59,11 +57,9 @@ - - - - - + + + diff --git a/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/OrderFunction.cs b/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/OrderFunction.cs index 1c910f92..47cb3f46 100644 --- a/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/OrderFunction.cs +++ b/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/OrderFunction.cs @@ -8,15 +8,8 @@ using Arcus.Templates.AzureFunctions.ServiceBus.Queue.Model; using Azure.Messaging.ServiceBus; using GuardNet; -using Arcus.Observability.Correlation; -#if Isolated using System.Text.Json; using Microsoft.Azure.Functions.Worker; -#endif -#if InProcess -using Arcus.Messaging.AzureFunctions.ServiceBus; -using Microsoft.Azure.WebJobs; -#endif using Microsoft.Extensions.Logging; namespace Arcus.Templates.AzureFunctions.ServiceBus.Queue @@ -28,50 +21,6 @@ public class OrderFunction { private readonly string _jobId; private readonly IAzureServiceBusMessageRouter _messageRouter; -#if InProcess - private readonly AzureFunctionsInProcessMessageCorrelation _messageCorrelation; - - /// - /// Initializes a new instance of the class. - /// - /// The message router instance to route the Azure Service Bus queue messages through the order processing. - /// The message correlation instance to W3C correlate the Azure Service Bus topic messages. - /// Thrown when the or the is null. - public OrderFunction( - IAzureServiceBusMessageRouter messageRouter, - AzureFunctionsInProcessMessageCorrelation messageCorrelation) - { - Guard.NotNull(messageRouter, nameof(messageRouter), "Requires an message router instance to route the incoming Azure Service Bus queue message through the order processing"); - Guard.NotNull(messageCorrelation, nameof(messageCorrelation), "Requires a message correlation instance to W3C correlate incoming Azure Service Bus topic messages"); - - _messageRouter = messageRouter; - _messageCorrelation = messageCorrelation; - _jobId = Guid.NewGuid().ToString(); - } - - /// - /// Process an Azure Service Bus queue as an . - /// - /// The incoming message on the Azure Service Bus queue, representing an . - /// The logger instance to write informational messages during the message processing. - /// The token to cancel the message processing. - [FunctionName("order-processing")] - public async Task Run( - [ServiceBusTrigger("orders", Connection = "ServiceBusConnectionString")] - ServiceBusReceivedMessage message, - ILogger log, - CancellationToken cancellationToken) - { - log.LogInformation("C# ServiceBus queue trigger function processed message: {MessageId}", message.MessageId); - - AzureServiceBusMessageContext messageContext = message.GetMessageContext(_jobId); - using (MessageCorrelationResult result = _messageCorrelation.CorrelateMessage(message)) - { - await _messageRouter.RouteMessageAsync(message, messageContext, result.CorrelationInfo, cancellationToken); - } - } -#endif -#if Isolated /// /// Initializes a new instance of the class. @@ -126,6 +75,5 @@ private static ServiceBusReceivedMessage ConvertToServiceBusMessage(byte[] messa return message; } -#endif } } diff --git a/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/Program.cs b/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/Program.cs index b4f92232..c411095e 100644 --- a/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/Program.cs +++ b/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/Program.cs @@ -58,13 +58,11 @@ private static IHostBuilder CreateHostBuilder(string[] args) services.AddAssemblyAppVersion(); }) #endif -#if Isolated .ConfigureFunctionsWorkerDefaults((context, builder) => { builder.Services.AddServiceBusMessageRouting() .WithServiceBusMessageHandler(); }) -#endif .ConfigureSecretStore((config, stores) => { //[#if DEBUG] diff --git a/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/Startup.cs b/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/Startup.cs deleted file mode 100644 index 06575434..00000000 --- a/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/Startup.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using Arcus.Security.Core.Caching.Configuration; -using Arcus.Templates.AzureFunctions.ServiceBus.Queue; -using Arcus.Templates.AzureFunctions.ServiceBus.Queue.Model; -using Microsoft.Azure.Functions.Extensions.DependencyInjection; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -#if Serilog_AppInsights -using Serilog; -using Serilog.Configuration; -using Serilog.Events; -#endif - -[assembly: FunctionsStartup(typeof(Startup))] - -namespace Arcus.Templates.AzureFunctions.ServiceBus.Queue -{ - public class Startup : FunctionsStartup - { - // This method gets called by the runtime. Use this method to configure the app configuration. - public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder) - { - builder.ConfigurationBuilder.AddEnvironmentVariables(); - } - - // This method gets called by the runtime. Use this method to add services to the container. - public override void Configure(IFunctionsHostBuilder builder) - { - builder.ConfigureSecretStore((context, config, stores) => - { -//[#if DEBUG] - stores.AddConfiguration(config); -//[#endif] - - //#error Please provide a valid secret provider, for example Azure Key Vault: https://security.arcus-azure.net/features/secret-store/provider/key-vault - stores.AddAzureKeyVaultWithManagedIdentity("https://your-keyvault.vault.azure.net/", CacheConfiguration.Default); - }); - - builder.AddServiceBusMessageRouting() - .WithServiceBusMessageHandler(); -#if Serilog_AppInsights - - builder.Services.AddAppName("Service Bus Queue Trigger"); - builder.Services.AddAssemblyAppVersion(); - builder.Services.AddLogging(logging => - { - logging.RemoveMicrosoftApplicationInsightsLoggerProvider() - .AddSerilog(provider => CreateLoggerConfiguration(provider).CreateLogger()); - }); -#endif - } -#if Serilog_AppInsights - - private static LoggerConfiguration CreateLoggerConfiguration(IServiceProvider provider) - { - IConfiguration appConfig = provider.GetRequiredService(); - var logConfig = new LoggerConfiguration() - .MinimumLevel.Information() - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) - .Enrich.FromLogContext() - .Enrich.WithComponentName(provider) - .Enrich.WithVersion(provider) - .WriteTo.Console(); - - var connectionString = appConfig.GetValue("APPLICATIONINSIGHTS_CONNECTION_STRING"); - if (!string.IsNullOrWhiteSpace(connectionString)) - { - logConfig.WriteTo.AzureApplicationInsightsWithConnectionString(provider, connectionString); - } - - return logConfig; - } -#endif - } -} \ No newline at end of file diff --git a/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/local.settings.json b/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/local.settings.json index 7880f7f0..ee03af9f 100644 --- a/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/local.settings.json +++ b/src/Arcus.Templates.AzureFunctions.ServiceBus.Queue/local.settings.json @@ -1,11 +1,7 @@ { "IsEncrypted": false, "Values": { - //#if(Isolated) "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", - //#else - "FUNCTIONS_WORKER_RUNTIME": "dotnet", - //#endif "AzureWebJobsStorage": "UseDevelopmentStorage=true" } } diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/AzureFunctionsServiceBusProject.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/AzureFunctionsServiceBusProject.cs index f6d78527..c066da38 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/AzureFunctionsServiceBusProject.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/AzureFunctionsServiceBusProject.cs @@ -69,7 +69,7 @@ public static async Task StartNewProjectAsync( Guard.NotNull(configuration, nameof(configuration), "Requires a configuration instance to retrieve the configuration values to pass along to the to-be-created project"); Guard.NotNull(outputWriter, nameof(outputWriter), "Requires a test logger to write diagnostic information during the creation and startup process"); - return await StartNewProjectAsync(entityType, new AzureFunctionsServiceBusProjectOptions(entityType), configuration, outputWriter); + return await StartNewProjectAsync(entityType, new AzureFunctionsServiceBusProjectOptions(), configuration, outputWriter); } /// diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/AzureFunctionsServiceBusProjectOptions.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/AzureFunctionsServiceBusProjectOptions.cs index 36461bce..5072ac92 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/AzureFunctionsServiceBusProjectOptions.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/AzureFunctionsServiceBusProjectOptions.cs @@ -7,30 +7,6 @@ namespace Arcus.Templates.Tests.Integration.AzureFunctions.ServiceBus /// public class AzureFunctionsServiceBusProjectOptions : AzureFunctionsProjectOptions { - private readonly ServiceBusEntityType _entityType; - - /// - /// Initializes a new instance of the class. - /// - public AzureFunctionsServiceBusProjectOptions(ServiceBusEntityType entityType) - { - _entityType = entityType; - } - - /// - /// Sets the Azure Functions worker type to the project options when running the project template. - /// - /// The Azure Functions worker type the project should target. - public AzureFunctionsServiceBusProjectOptions WithFunctionWorker(FunctionsWorker workerType) - { - if (_entityType != ServiceBusEntityType.Topic) - { - SetFunctionsWorker(workerType); - } - - return this; - } - /// /// Adds the 'exclude Serilog' project options when running the project template. /// diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/Configuration/LaunchSettingsTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/Configuration/LaunchSettingsTests.cs index 82298524..b3cb203d 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/Configuration/LaunchSettingsTests.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/Configuration/LaunchSettingsTests.cs @@ -25,7 +25,7 @@ public LaunchSettingsTests(ITestOutputHelper outputWriter) public void ServiceBusTriggerTemplate_WithDefault_ConfiguresLaunchSettings(ServiceBusEntityType entityType) { // Arrange - var options = new AzureFunctionsServiceBusProjectOptions(entityType); + var options = new AzureFunctionsServiceBusProjectOptions(); var config = TestConfig.Create(); // Act diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/Logging/SerilogLoggingTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/Logging/SerilogLoggingTests.cs index 449fb243..a688317a 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/Logging/SerilogLoggingTests.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/Logging/SerilogLoggingTests.cs @@ -20,40 +20,21 @@ public SerilogLoggingTests(ITestOutputHelper outputWriter) _outputWriter = outputWriter; } - [Fact] - public async Task ServiceBusTopicProjectIsolated_WithoutSerilog_CorrectlyProcessesMessage() - { - await TestServiceBusProjectWithoutSerilogCorrectlyProcessesMessage(ServiceBusEntityType.Topic, FunctionsWorker.Isolated); - } - - [Fact] - public async Task ServiceBusQueueProjectInProcess_WithoutSerilog_CorrectlyProcessesMessage() - { - await TestServiceBusProjectWithoutSerilogCorrectlyProcessesMessage(ServiceBusEntityType.Queue, FunctionsWorker.InProcess); - } - - [Fact] - public async Task ServiceBusQueueProjectIsolated_WithoutSerilog_CorrectlyProcessesMessage() - { - await TestServiceBusProjectWithoutSerilogCorrectlyProcessesMessage(ServiceBusEntityType.Queue, FunctionsWorker.Isolated); - } - - private async Task TestServiceBusProjectWithoutSerilogCorrectlyProcessesMessage(ServiceBusEntityType entityType, FunctionsWorker workerType) + [Theory] + [InlineData(ServiceBusEntityType.Topic)] + [InlineData(ServiceBusEntityType.Queue)] + public async Task ServiceBusTopicProject_WithoutSerilog_CorrectlyProcessesMessage(ServiceBusEntityType entityType) { // Arrange var config = TestConfig.Create(); - var options = - new AzureFunctionsServiceBusProjectOptions(entityType) - .WithFunctionWorker(workerType) - .WithExcludeSerilog(); + var options = new AzureFunctionsServiceBusProjectOptions().WithExcludeSerilog(); - await using (var project = await AzureFunctionsServiceBusProject.StartNewProjectAsync(entityType, options, config, _outputWriter)) - { - // Act / Assert - await project.Messaging.SimulateMessageProcessingAsync(); - Assert.DoesNotContain("Serilog", project.GetFileContentsOfProjectFile()); - Assert.DoesNotContain("Serilog", project.GetFileContentsInProject(project.RuntimeFileName)); - } + await using var project = await AzureFunctionsServiceBusProject.StartNewProjectAsync(entityType, options, config, _outputWriter); + + // Act / Assert + await project.Messaging.SimulateMessageProcessingAsync(); + Assert.DoesNotContain("Serilog", project.GetFileContentsOfProjectFile()); + Assert.DoesNotContain("Serilog", project.GetFileContentsInProject(project.RuntimeFileName)); } } } diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/MessageHandling/OrderMessageHandlerTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/MessageHandling/OrderMessageHandlerTests.cs index 911a7639..03cc0007 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/MessageHandling/OrderMessageHandlerTests.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/ServiceBus/MessageHandling/OrderMessageHandlerTests.cs @@ -20,37 +20,17 @@ public OrderMessageHandlerTests(ITestOutputHelper outputWriter) _outputWriter = outputWriter; } - [Fact] - public async Task ServiceBusTopicProject_AsIsolated_CorrectlyProcessesMessage() - { - await TestServiceBusProjectWithWorkerTypeCorrectlyProcessesMessageAsync(ServiceBusEntityType.Topic, FunctionsWorker.Isolated); - } - - [Fact] - public async Task ServiceBusQueueProject_AsInProcess_CorrectlyProcessesMessage() - { - await TestServiceBusProjectWithWorkerTypeCorrectlyProcessesMessageAsync(ServiceBusEntityType.Queue, FunctionsWorker.InProcess); - } - - [Fact] - public async Task ServiceBusQueueProject_AsIsolated_CorrectlyProcessesMessage() - { - await TestServiceBusProjectWithWorkerTypeCorrectlyProcessesMessageAsync(ServiceBusEntityType.Queue, FunctionsWorker.Isolated); - } - - private async Task TestServiceBusProjectWithWorkerTypeCorrectlyProcessesMessageAsync(ServiceBusEntityType entityType, FunctionsWorker workerType) + [Theory] + [InlineData(ServiceBusEntityType.Topic)] + [InlineData(ServiceBusEntityType.Queue)] + public async Task ServiceBusProject_WithDefault_CorrectlyProcessesMessage(ServiceBusEntityType entityType) { // Arrange var config = TestConfig.Create(); - var options = - new AzureFunctionsServiceBusProjectOptions(entityType) - .WithFunctionWorker(workerType); - - await using (var project = await AzureFunctionsServiceBusProject.StartNewProjectAsync(entityType, options, config, _outputWriter)) - { - // Act / Assert - await project.Messaging.SimulateMessageProcessingAsync(); - } + await using var project = await AzureFunctionsServiceBusProject.StartNewProjectAsync(entityType, config, _outputWriter); + + // Act / Assert + await project.Messaging.SimulateMessageProcessingAsync(); } } } From f613bcd30517f25e2e719cc035402770bf30c0f6 Mon Sep 17 00:00:00 2001 From: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com> Date: Thu, 2 May 2024 06:32:02 +0200 Subject: [PATCH 03/10] feat: remove functions worker project option in az func http --- .../.template.config/template.json | 58 +---- ...Arcus.Templates.AzureFunctions.Http.csproj | 19 +- .../HealthFunction.cs | 101 +------- .../HttpBasedAzureFunction.cs | 225 ------------------ .../OrderFunction.cs | 101 +------- .../Program.cs | 8 +- .../Startup.cs | 89 ------- .../local.settings.json | 6 +- .../Http/AzureFunctionsHttpProjectOptions.cs | 15 +- .../Http/Fix/OrderBatchTests.cs | 73 ------ .../Http/Health/HealthChecksTests.cs | 30 +-- .../Http/Logging/SerilogLoggingTests.cs | 17 +- .../Http/Swagger/SwaggerOpenApiTests.cs | 70 ++---- 13 files changed, 52 insertions(+), 760 deletions(-) delete mode 100644 src/Arcus.Templates.AzureFunctions.Http/HttpBasedAzureFunction.cs delete mode 100644 src/Arcus.Templates.AzureFunctions.Http/Startup.cs delete mode 100644 src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Fix/OrderBatchTests.cs diff --git a/src/Arcus.Templates.AzureFunctions.Http/.template.config/template.json b/src/Arcus.Templates.AzureFunctions.Http/.template.config/template.json index a0740e06..245b33b7 100644 --- a/src/Arcus.Templates.AzureFunctions.Http/.template.config/template.json +++ b/src/Arcus.Templates.AzureFunctions.Http/.template.config/template.json @@ -40,19 +40,6 @@ "HttpCorrelationOpenApiResponseHeaders.cs", "OpenApiConfigurationOptions.cs" ] - }, - { - "condition": "Isolated", - "exclude": [ - "Startup.cs", - "HttpBasedAzureFunction.cs" - ] - }, - { - "condition": "InProcess", - "exclude": [ - "Program.cs" - ] } ] } @@ -97,30 +84,6 @@ }, "replaces": "//#error" }, - "functions-worker": { - "type": "parameter", - "datatype": "choice", - "choices": [ - { - "choice": "inProcess", - "description": "Uses Azure Functions in-process project template" - }, - { - "choice": "isolated", - "description": "Uses Azure Functions isolated project template" - } - ], - "defaultValue": "isolated", - "description": "Chooses the kind of Azure Functions project template" - }, - "InProcess": { - "type": "computed", - "value": "(functions-worker == \"inProcess\")" - }, - "Isolated": { - "type": "computed", - "value": "(functions-worker == \"isolated\")" - }, "include-healthchecks": { "type": "parameter", "datatype": "bool", @@ -151,24 +114,5 @@ "type": "computed", "value": "!(exclude-serilog)" } - }, - "postActions": [ - { - "condition": "InProcess", - "description": "Adding Reference to Microsoft.NET.Sdk.Functions Nuget package", - "actionId": "B17581D1-C5C9-4489-8F0A-004BE667B814", - "continueOnError": false, - "manualInstructions": [ - { - "text": "Manually add the reference to Microsoft.NET.Sdk.Functions to your project file" - } - ], - "args": { - "referenceType": "package", - "reference": "Microsoft.NET.Sdk.Functions", - "version": "4.1.3", - "projectFileExtensions": ".csproj" - } - } - ] + } } diff --git a/src/Arcus.Templates.AzureFunctions.Http/Arcus.Templates.AzureFunctions.Http.csproj b/src/Arcus.Templates.AzureFunctions.Http/Arcus.Templates.AzureFunctions.Http.csproj index 7b4f1d3d..bffc1893 100644 --- a/src/Arcus.Templates.AzureFunctions.Http/Arcus.Templates.AzureFunctions.Http.csproj +++ b/src/Arcus.Templates.AzureFunctions.Http/Arcus.Templates.AzureFunctions.Http.csproj @@ -3,7 +3,7 @@ net6.0 v4 Linux - Exe + Exe Arcus Arcus @@ -37,9 +37,7 @@ - $(DefineConstants);OpenApi;Serilog_AppInsights;InProcess - false - true + $(DefineConstants);OpenApi;Serilog_AppInsights true true /home/site/wwwroot @@ -71,15 +69,12 @@ - + - - - - - - - + + + + diff --git a/src/Arcus.Templates.AzureFunctions.Http/HealthFunction.cs b/src/Arcus.Templates.AzureFunctions.Http/HealthFunction.cs index 300ff8b4..da6ee473 100644 --- a/src/Arcus.Templates.AzureFunctions.Http/HealthFunction.cs +++ b/src/Arcus.Templates.AzureFunctions.Http/HealthFunction.cs @@ -1,27 +1,11 @@ using System; -using System.Linq; using System.Net; -using System.Text.Json; -using System.Text.Json.Serialization; -using System.Threading; using System.Threading.Tasks; using Arcus.Templates.AzureFunctions.Http.Model; -using Arcus.WebApi.Logging.Core.Correlation; -using Arcus.WebApi.Logging.Correlation; using Azure.Core.Serialization; using GuardNet; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -#if Isolated -using System.Collections.Generic; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; -#endif -#if InProcess -using Arcus.WebApi.Logging.AzureFunctions.Correlation; -using Microsoft.Azure.WebJobs; -using Microsoft.Azure.WebJobs.Extensions.Http; -#endif #if OpenApi using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes; using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums; @@ -37,95 +21,17 @@ namespace Arcus.Templates.AzureFunctions.Http /// /// Represents the health check Azure Function to verify if the running Azure Function is healthy. /// -#if InProcess - public class HealthFunction : HttpBasedAzureFunction -#endif -#if Isolated public class HealthFunction -#endif { private readonly HealthCheckService _healthCheckService; -#if InProcess - private readonly AzureFunctionsInProcessHttpCorrelation _httpCorrelation; - - /// - /// Initializes a new instance of the class. - /// - /// The service to check the current health of the running Azure Function. - /// The instance to handle the HTTP request correlation. - /// The instance to access the HTTP correlation throughout the application. - /// The logger instance to write diagnostic trace messages while handling the HTTP request. - /// Thrown when the is null. - public HealthFunction( - HealthCheckService healthCheckService, - AzureFunctionsInProcessHttpCorrelation httpCorrelation, - IHttpCorrelationInfoAccessor correlationInfoAccessor, - ILogger logger) - : base(httpCorrelation, correlationInfoAccessor, logger) - { - Guard.NotNull(healthCheckService, nameof(healthCheckService), "Requires a health check service to check the current health of the running Azure Function"); - _healthCheckService = healthCheckService; - _httpCorrelation = httpCorrelation; - } - - [FunctionName("health")] -#if OpenApi - [OpenApiOperation("Health_Get", tags: new[] { "health" }, Summary = "Gets the health report", Description = "Gets the current health report of the running Azure Function", Visibility = OpenApiVisibilityType.Important)] - [OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Header)] - [OpenApiParameter("traceparent", In = ParameterLocation.Header, Type = typeof(string), Required = false, Summary = "The correlation header", Description = "The correlation header is used to correlate multiple operation calls")] - [OpenApiResponseWithBody(HttpStatusCode.OK, "application/json", typeof(string), Summary = "The health report summary", Description = "The health report summary of all the run health checks", CustomHeaderType = typeof(HttpCorrelationOpenApiResponseHeaders))] - [OpenApiResponseWithBody(HttpStatusCode.UnsupportedMediaType, "text/plain", typeof(string), Summary = "The faulted response for non-JSON requests", Description = "The faulted response (415) when the request doesn't accept JSON")] - [OpenApiResponseWithBody(HttpStatusCode.BadRequest, "text/plain", typeof(string), Summary = "The faulted response for invalid correlation requests", Description = "The faulted response (400) when the request doesn't correlate correctly")] - [OpenApiResponseWithBody(HttpStatusCode.InternalServerError, "text/plain", typeof(string), Summary = "The faulted response for general failures", Description = "The faulted response (500) for any general and unexpected server-related failure")] - [OpenApiResponseWithBody(HttpStatusCode.ServiceUnavailable, "application/json", typeof(string), Summary = "The faulted response for unhealthy reports", Description = "The faulted response (503) when the health checks results in an unhealthy report", CustomHeaderType = typeof(HttpCorrelationOpenApiResponseHeaders))] -#endif - public async Task Run( - [HttpTrigger(AuthorizationLevel.Function, "get", Route = "v1/health")] HttpRequest request, - CancellationToken cancellation) - { - using (EnrichWithHttpCorrelation()) - { - try - { - Logger.LogInformation("C# HTTP trigger 'health' function processed a request"); - if (AcceptsJson(request) == false) - { - string accept = string.Join(", ", GetAcceptMediaTypes(request)); - Logger.LogError("Could not process current request because the response could not accept JSON (Accept: {Accept})", accept); - - return UnsupportedMediaType("Could not process current request because the response could not accept JSON"); - } - - HealthReport healthReport = await _healthCheckService.CheckHealthAsync(cancellation); - ApiHealthReport apiHealthReport = ApiHealthReport.FromHealthReport(healthReport); - - if (healthReport?.Status == HealthStatus.Healthy) - { - return Json(apiHealthReport); - } - - return Json(apiHealthReport, statusCode: StatusCodes.Status503ServiceUnavailable); - } - catch (Exception exception) - { - Logger.LogCritical(exception, exception.Message); - return InternalServerError("Could not process the current request due to an unexpected exception"); - } - finally - { - AddCorrelationResponseHeaders(request.HttpContext); - } - } - } -#endif -#if Isolated private readonly JsonObjectSerializer _jsonSerializer; - + /// /// Initializes a new instance of the class. /// /// The service to check the current health of the running Azure Function. - /// Thrown when the is null. + /// The configured serializer in the application services that controls how JSON responses are serialized. + /// Thrown when the or the is null. public HealthFunction(HealthCheckService healthCheckService, JsonObjectSerializer jsonSerializer) { Guard.NotNull(healthCheckService, nameof(healthCheckService), "Requires a health check service to check the current health of the running Azure Function"); @@ -172,6 +78,5 @@ private static HttpStatusCode DetermineStatusCode(HealthReport healthReport) return HttpStatusCode.ServiceUnavailable; } -#endif } } diff --git a/src/Arcus.Templates.AzureFunctions.Http/HttpBasedAzureFunction.cs b/src/Arcus.Templates.AzureFunctions.Http/HttpBasedAzureFunction.cs deleted file mode 100644 index a4e56d96..00000000 --- a/src/Arcus.Templates.AzureFunctions.Http/HttpBasedAzureFunction.cs +++ /dev/null @@ -1,225 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.IO; -using System.Linq; -using System.Text.Json; -using System.Text.Json.Serialization; -using System.Threading.Tasks; -using Arcus.Observability.Correlation; -using Arcus.Observability.Telemetry.Core; -using Arcus.Observability.Telemetry.Serilog.Enrichers; -using Arcus.WebApi.Logging.AzureFunctions.Correlation; -using Arcus.WebApi.Logging.Core.Correlation; -using Arcus.WebApi.Logging.Correlation; -using GuardNet; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Formatters; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Net.Http.Headers; -#if Serilog_AppInsights -using Serilog.Context; -#endif - -namespace Arcus.Templates.AzureFunctions.Http -{ - /// - /// Represents the base HTTP web API functionality for an Azure Function implementation. - /// - public abstract class HttpBasedAzureFunction - { - private readonly AzureFunctionsInProcessHttpCorrelation _httpCorrelation; - private readonly IHttpCorrelationInfoAccessor _correlationInfoAccessor; - - /// - /// Initializes a new instance of the class. - /// - /// The correlation service to provide information of related requests. - /// The instance to access the HTTP correlation throughout the application. - /// The logger instance to write diagnostic messages throughout the execution of the HTTP trigger. - /// Thrown when the is null - protected HttpBasedAzureFunction( - AzureFunctionsInProcessHttpCorrelation httpCorrelation, - IHttpCorrelationInfoAccessor correlationInfoAccessor, - ILogger logger) - { - Guard.NotNull(httpCorrelation, nameof(httpCorrelation), "Requires an HTTP correlation instance"); - Guard.NotNull(correlationInfoAccessor, nameof(correlationInfoAccessor), "Requires "); - _httpCorrelation = httpCorrelation; - _correlationInfoAccessor = correlationInfoAccessor; - - Logger = logger ?? NullLogger.Instance; - - var options = new JsonSerializerOptions(); - options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; - options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; - options.Converters.Add(new JsonStringEnumConverter()); - JsonOptions = options; - OutputFormatters = new FormatterCollection { new SystemTextJsonOutputFormatter(JsonOptions) }; - } - - /// - /// Gets the serializer options that's being used when incoming requests are being serialized or deserialized into JSON. - /// - protected JsonSerializerOptions JsonOptions { get; } - - /// - /// Gets the set of formatters that's being used when an outgoing response is being sent back to the sender. - /// - protected FormatterCollection OutputFormatters { get; } - - /// - /// Gets the logger instance used throughout this Azure Function. - /// - protected ILogger Logger { get; } - - /// - /// Enrich the preceding functionality with the available HTTP correlation. - /// - protected IDisposable EnrichWithHttpCorrelation() - { -#if Serilog_AppInsights - return LogContext.Push(new CorrelationInfoEnricher(_correlationInfoAccessor)); -#else - return null; -#endif - } - /// - /// Add the HTTP correlation information to the HTTP response. - /// - protected void AddCorrelationResponseHeaders(HttpContext context) - { - _httpCorrelation.AddCorrelationResponseHeaders(context); - } - - /// - /// Reads the body of the incoming request as JSON to deserialize it into a given type. - /// - /// The type of the request's body that's being deserialized. - /// The incoming request which body will be deserialized. - /// The deserialized request body into the model. - /// Thrown when the is null - /// Thrown when the deserialization of the request body to a JSON representation fails. - /// Thrown when the deserialized request body didn't correspond to the required validation rules. - protected async Task GetJsonBodyAsync(HttpRequest request) - { - var message = await request.ReadFromJsonAsync(JsonOptions); - Validator.ValidateObject(message, new ValidationContext(message), validateAllProperties: true); - - return message; - } - - /// - /// Determines whether the incoming 's body can be considered as JSON or not. - /// - /// The incoming HTTP request to verify. - /// - /// [true] if the 's body is considered JSON; [false] otherwise. - /// - /// Thrown when the is null. - protected bool IsJson(HttpRequest request) - { - Guard.NotNull(request, nameof(request), "Requires a HTTP request to verify if the request's body can be considered as JSON"); - return request.ContentType == "application/json"; - } - - /// - /// Determines if the incoming accepts a JSON response. - /// - /// The incoming HTTP request to verify. - /// - /// [true] if the incoming accepts a JSON response; [false] otherwise. - /// - /// Thrown when the is null. - protected bool AcceptsJson(HttpRequest request) - { - Guard.NotNull(request, nameof(request), "Requires a HTTP request to verify if the request accepts a JSON response"); - return GetAcceptMediaTypes(request).Any(mediaType => mediaType == "application/json" || mediaType == "*/*"); - } - - /// - /// Gets all the media types in the incoming 's 'Accept' header. - /// - /// The incoming request to extract the media types from.. - /// Thrown when the is null. - protected IEnumerable GetAcceptMediaTypes(HttpRequest request) - { - Guard.NotNull(request, nameof(request), "Requires a HTTP request to retrieve the media types from the Accept header"); - IList acceptHeaders = request.GetTypedHeaders().Accept ?? new List(); - return acceptHeaders.Select(header => header.MediaType.ToString()); - } - - /// - /// Creates an instance with a JSON response . - /// - /// The response JSON body. - /// The HTTP status code of the response; default 200 OK. - /// Thrown when the is null. - protected IActionResult Json(object body, int statusCode = StatusCodes.Status200OK) - { - Guard.NotNull(body, nameof(body), "Requires a JSON body for the response body"); - return new ObjectResult(body) - { - StatusCode = statusCode, - Formatters = OutputFormatters, - ContentTypes = { "application/json" } - }; - } - - /// - /// Creates an instance for a '415 Unsupported Media Type' failure with an accompanied . - /// - /// The error message to describe the failure. - /// Throw when the is blank. - protected IActionResult UnsupportedMediaType(string errorMessage) - { - Guard.NotNullOrWhitespace(errorMessage, nameof(errorMessage), "Requires a non-blank error message to accompany the 415 Unsupported Media Type failure"); - return new ObjectResult(errorMessage) - { - StatusCode = StatusCodes.Status415UnsupportedMediaType - }; - } - - /// - /// Creates an instance for a '400 Bad Request' failure with an accompanied model to describe the failure. - /// - /// The error model to describe the failure. - /// Thrown when the is null. - protected IActionResult BadRequest(object error) - { - Guard.NotNull(error, nameof(error), "Requires an error model to describe the 400 Bad Request failure"); - return new BadRequestObjectResult(error); - } - - /// - /// Creates an instance for a '500 Internal Server Error' failure with an accompanied . - /// - /// The error message to describe the failure. - /// Thrown when the is blank. - protected IActionResult InternalServerError(string errorMessage) - { - Guard.NotNullOrWhitespace(errorMessage, nameof(errorMessage), "Requires an non-blank error message to accompany the 500 Internal Server Error failure"); - return new ObjectResult(errorMessage) - { - StatusCode = StatusCodes.Status500InternalServerError, - ContentTypes = { "text/plain" } - }; - } - - /// - /// creates an instance for a failure with an accompanied . - /// - /// The status code representing the failure. - /// The error result that is sent back to the user. - protected IActionResult Error(int statusCode, object errorResult, string contentType = "text/plain") - { - return new ObjectResult(errorResult) - { - StatusCode = statusCode, - ContentTypes = { contentType } - }; - } - } -} diff --git a/src/Arcus.Templates.AzureFunctions.Http/OrderFunction.cs b/src/Arcus.Templates.AzureFunctions.Http/OrderFunction.cs index 3a8827fa..20746c08 100644 --- a/src/Arcus.Templates.AzureFunctions.Http/OrderFunction.cs +++ b/src/Arcus.Templates.AzureFunctions.Http/OrderFunction.cs @@ -1,31 +1,12 @@ using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.Net; -using System.Text.Json; using System.Threading.Tasks; -using Arcus.Observability.Correlation; -using Arcus.Observability.Telemetry.Core; -using Arcus.Observability.Telemetry.Serilog.Enrichers; using Arcus.Security.Core; -using Arcus.WebApi.Logging.Correlation; using GuardNet; -using Microsoft.AspNetCore.Mvc; -#if InProcess -using Arcus.WebApi.Logging.AzureFunctions.Correlation; -using Arcus.WebApi.Logging.Core.Correlation; -using Microsoft.Azure.WebJobs; -using Microsoft.Azure.WebJobs.Extensions.Http; -using Serilog.Context; -#endif -using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Arcus.Templates.AzureFunctions.Http.Model; -#if Isolated using Microsoft.Azure.Functions.Worker; -using Microsoft.Azure.Functions.Worker.Http; -#endif -using Microsoft.AspNetCore.Routing; +using Microsoft.Azure.Functions.Worker.Http; #if OpenApi using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes; using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums; @@ -37,87 +18,10 @@ namespace Arcus.Templates.AzureFunctions.Http /// /// Represents the root endpoint of the Azure Function. /// -#if InProcess - public class OrderFunction : HttpBasedAzureFunction -#endif -#if Isolated public class OrderFunction -#endif { private readonly ISecretProvider _secretProvider; - -#if InProcess - /// - /// Initializes a new instance of the class. - /// - /// The instance that provides secrets to the HTTP trigger. - /// The instance to handle the HTTP request correlation. - /// The instance to access the HTTP correlation throughout the application. - /// The logger instance to write diagnostic trace messages while handling the HTTP request. - /// Thrown when the or is null. - public OrderFunction( - ISecretProvider secretProvider, - AzureFunctionsInProcessHttpCorrelation httpCorrelation, - IHttpCorrelationInfoAccessor correlationInfoAccessor, - ILogger logger) : base(httpCorrelation, correlationInfoAccessor, logger) - { - Guard.NotNull(secretProvider, nameof(secretProvider), "Requires a secret provider instance"); - _secretProvider = secretProvider; - } - - [FunctionName("order")] -#if OpenApi - [OpenApiOperation("Order_Get", tags: new[] { "order" }, Summary = "Gets the order", Description = "Gets the order from the request", Visibility = OpenApiVisibilityType.Important)] - [OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Header)] - [OpenApiRequestBody("application/json", typeof(Order), Description = "The to-be-processed order")] - [OpenApiParameter("traceparent", In = ParameterLocation.Header, Type = typeof(string), Required = false, Summary = "The correlation header", Description = "The correlation header is used to correlate multiple operation calls")] - [OpenApiResponseWithBody(HttpStatusCode.OK, "application/json", typeof(Order), Summary = "The processed order", Description = "The processed order result", CustomHeaderType = typeof(HttpCorrelationOpenApiResponseHeaders))] - [OpenApiResponseWithBody(HttpStatusCode.UnsupportedMediaType, "text/plain", typeof(string), Summary = "The faulted response for non-JSON requests", Description = "The faulted response (415) when the request doesn't accept JSON")] - [OpenApiResponseWithBody(HttpStatusCode.BadRequest, "text/plain", typeof(string), Summary = "The faulted response for invalid correlation requests", Description = "The faulted response (400) when the request doesn't correlate correctly")] - [OpenApiResponseWithBody(HttpStatusCode.InternalServerError, "text/plain", typeof(string), Summary = "The faulted response for general failures", Description = "The faulted response (500) for any general and unexpected server-related failure")] -#endif - public async Task Run( - [HttpTrigger(AuthorizationLevel.Function, "post", Route = "v1/order")] HttpRequest request) - { - using (EnrichWithHttpCorrelation()) - { - try - { - Logger.LogInformation("C# HTTP trigger 'order' function processed a request"); - if (IsJson(request) == false || AcceptsJson(request) == false) - { - string accept = string.Join(", ", GetAcceptMediaTypes(request)); - Logger.LogError("Could not process current request because the request body is not JSON and/or could not accept JSON as response (Content-Type: {ContentType}, Accept: {Accept})", request.ContentType, accept); - - return Error(StatusCodes.Status415UnsupportedMediaType, "Could not process current request because the request body is not JSON and/or could not accept JSON as response"); - } - - var order = await GetJsonBodyAsync(request); - return Json(order); - } - catch (JsonException exception) - { - Logger.LogError(exception, exception.Message); - return Error(StatusCodes.Status400BadRequest, "Could not process the current request due to an JSON deserialization failure"); - } - catch (ValidationException exception) - { - Logger.LogError(exception, exception.Message); - return Error(StatusCodes.Status400BadRequest, exception.ValidationResult.ToString()); - } - catch (Exception exception) - { - Logger.LogCritical(exception, exception.Message); - return Error(StatusCodes.Status500InternalServerError, "Could not process the current request due to an unexpected exception"); - } - finally - { - AddCorrelationResponseHeaders(request.HttpContext); - } - } - } -#endif -#if Isolated + /// /// Initializes a new instance of the class. /// @@ -153,6 +57,5 @@ public async Task Run( return response; } -#endif } } \ No newline at end of file diff --git a/src/Arcus.Templates.AzureFunctions.Http/Program.cs b/src/Arcus.Templates.AzureFunctions.Http/Program.cs index ea1b45d0..e10b813f 100644 --- a/src/Arcus.Templates.AzureFunctions.Http/Program.cs +++ b/src/Arcus.Templates.AzureFunctions.Http/Program.cs @@ -8,11 +8,9 @@ using Arcus.Security.Core.Caching.Configuration; using Arcus.Security.Core; using Arcus.WebApi.Logging.AzureFunctions; -#if Isolated using Arcus.WebApi.Hosting.AzureFunctions.Formatting; -#endif using Azure.Core.Serialization; -#if OpenApi && Isolated +#if OpenApi using Microsoft.Azure.Functions.Worker.Extensions.OpenApi.Extensions; #endif using Microsoft.Extensions.DependencyInjection; @@ -70,7 +68,6 @@ private static IHostBuilder CreateHostBuilder(string[] args) services.AddAssemblyAppVersion(); }) #endif -#if Isolated .ConfigureFunctionsWorkerDefaults((context, builder) => { #if IncludeHealthChecks @@ -85,7 +82,7 @@ private static IHostBuilder CreateHostBuilder(string[] args) builder.UseOnlyJsonFormatting() .UseFunctionContext() .UseHttpCorrelation() - .UseRequestTracking(options => + .UseRequestTracking(options => { options.OmittedRoutes.Add("/"); #if IncludeHealthChecks @@ -98,7 +95,6 @@ private static IHostBuilder CreateHostBuilder(string[] args) }) .UseExceptionHandling(); }) -#endif .ConfigureSecretStore((config, stores) => { //[#if DEBUG] diff --git a/src/Arcus.Templates.AzureFunctions.Http/Startup.cs b/src/Arcus.Templates.AzureFunctions.Http/Startup.cs deleted file mode 100644 index da089150..00000000 --- a/src/Arcus.Templates.AzureFunctions.Http/Startup.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using Arcus.Security.Core.Caching.Configuration; -using Arcus.Templates.AzureFunctions.Http; -using Microsoft.Azure.Functions.Extensions.DependencyInjection; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -#if Serilog_AppInsights -using Serilog; -using Serilog.Configuration; -using Serilog.Events; -#endif - -[assembly: FunctionsStartup(typeof(Startup))] - -namespace Arcus.Templates.AzureFunctions.Http -{ - public class Startup : FunctionsStartup - { - // This method gets called by the runtime. Use this method to configure the app configuration. - public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder) - { -#if OpenApi -//[#if DEBUG] - Environment.SetEnvironmentVariable("OpenApi__HideSwaggerUI", "false"); -//[#else] - Environment.SetEnvironmentVariable("OpenApi__HideSwaggerUI", "true"); -//[#endif] -#endif - builder.ConfigurationBuilder.AddEnvironmentVariables(); - } - - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection - public override void Configure(IFunctionsHostBuilder builder) - { - builder.AddHttpCorrelation(); -#if IncludeHealthChecks - builder.Services.AddHealthChecks(); -#endif - - builder.ConfigureSecretStore((context, config, stores) => - { -//[#if DEBUG] - stores.AddConfiguration(config); -//[#endif] - - stores.AddEnvironmentVariables(); - - //#error Please provide a valid secret provider, for example Azure Key Vault: https://security.arcus-azure.net/features/secret-store/provider/key-vault - stores.AddAzureKeyVaultWithManagedIdentity("https://your-keyvault.vault.azure.net/", CacheConfiguration.Default); - }); -#if Serilog_AppInsights - - builder.Services.AddAppName("Azure HTTP trigger"); - builder.Services.AddAssemblyAppVersion(); - builder.Services.AddLogging(logging => - { - logging.RemoveMicrosoftApplicationInsightsLoggerProvider() - .AddSerilog(provider => CreateLoggerConfiguration(provider).CreateLogger()); - }); -#endif - } -#if Serilog_AppInsights - - private static LoggerConfiguration CreateLoggerConfiguration(IServiceProvider provider) - { - var appConfig = provider.GetRequiredService(); - var connectionString = appConfig.GetValue("APPLICATIONINSIGHTS_CONNECTION_STRING"); - - var configuration = new LoggerConfiguration() - .MinimumLevel.Information() - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) - .Enrich.FromLogContext() - .Enrich.WithComponentName(provider) - .Enrich.WithVersion(provider) - .WriteTo.Console(); - - if (!string.IsNullOrWhiteSpace(connectionString)) - { - configuration.WriteTo.AzureApplicationInsightsWithConnectionString(provider, connectionString); - } - - return configuration; - } -#endif - } -} diff --git a/src/Arcus.Templates.AzureFunctions.Http/local.settings.json b/src/Arcus.Templates.AzureFunctions.Http/local.settings.json index 60202ed9..fa1548e9 100644 --- a/src/Arcus.Templates.AzureFunctions.Http/local.settings.json +++ b/src/Arcus.Templates.AzureFunctions.Http/local.settings.json @@ -1,11 +1,7 @@ { - "IsEncrypted": false, + "IsEncrypted": false, "Values": { - //#if(Isolated) "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", - //#else - "FUNCTIONS_WORKER_RUNTIME": "dotnet", - //#endif //#if (Serilog_AppInsights) "APPLICATIONINSIGHTS_CONNECTION_STRING": "InstrumentationKey=yourKey", //#endif diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/AzureFunctionsHttpProjectOptions.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/AzureFunctionsHttpProjectOptions.cs index a6816c2d..16fae31d 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/AzureFunctionsHttpProjectOptions.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/AzureFunctionsHttpProjectOptions.cs @@ -1,6 +1,4 @@ -using System; - -namespace Arcus.Templates.Tests.Integration.AzureFunctions.Http +namespace Arcus.Templates.Tests.Integration.AzureFunctions.Http { /// /// Represents the additional consumer options for the . @@ -14,17 +12,6 @@ public AzureFunctionsHttpProjectOptions() { } - /// - /// Adds the project option to configure the Azure Functions worker type of the Azure Functions HTTP trigger project. - /// - /// The type of functions worker to use when setting up the Azure Functions HTTP trigger project. - /// Thrown when the is outside the bounds of the enumeration. - public AzureFunctionsHttpProjectOptions WithFunctionsWorker(FunctionsWorker workerType) - { - SetFunctionsWorker(workerType); - return this; - } - /// /// Adds the project option to include the health checks Azure Function from the Azure Functions HTTP trigger project. /// diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Fix/OrderBatchTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Fix/OrderBatchTests.cs deleted file mode 100644 index 66466199..00000000 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Fix/OrderBatchTests.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Arcus.Templates.AzureFunctions.Http; -using Arcus.Templates.AzureFunctions.Http.Model; -using Arcus.Templates.Tests.Integration.Fixture; -using Bogus; -using Newtonsoft.Json; -using Xunit; -using Xunit.Abstractions; - -namespace Arcus.Templates.Tests.Integration.AzureFunctions.Http.Fix -{ - [Collection(TestCollections.Integration)] - [Trait("Category", TestTraits.Integration)] - public class OrderBatchTests - { - private readonly ITestOutputHelper _outputWriter; - - private static readonly Faker BogusGenerator = new Faker(); - - /// - /// Initializes a new instance of the class. - /// - public OrderBatchTests(ITestOutputHelper outputWriter) - { - _outputWriter = outputWriter; - } - - [Fact] - public async Task OrderFunction_ReceivedBatchedOrders_ReturnsSuccess() - { - // Arrange - var config = TestConfig.Create(); - var options = new AzureFunctionsHttpProjectOptions() - .WithFunctionsWorker(FunctionsWorker.InProcess); - - using (var project = AzureFunctionsHttpProject.CreateNew(config, options, _outputWriter)) - { - project.UpdateFileInProject($"{nameof(OrderFunction)}.cs", contents => - { - return contents.Replace("GetJsonBodyAsync", "GetJsonBodyAsync"); - }); - await project.StartAsync(); - - IEnumerable orders = BogusGenerator.Make(3, CreateRandomOrder); - string json = JsonConvert.SerializeObject(orders.ToArray()); - - // Act - using (HttpResponseMessage response = await project.Order.PostAsync(json)) - { - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - } - } - - private static Order CreateRandomOrder() - { - var order = new Order - { - Id = Guid.NewGuid().ToString(), - ArticleNumber = BogusGenerator.Random.String(1, 100), - Scheduled = BogusGenerator.Date.RecentOffset() - }; - - return order; - } - } -} diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Health/HealthChecksTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Health/HealthChecksTests.cs index 0f64300a..f79e5c4b 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Health/HealthChecksTests.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Health/HealthChecksTests.cs @@ -28,15 +28,12 @@ public HealthChecksTests(ITestOutputHelper outputWriter) _config = TestConfig.Create(); } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task HttpAzureFunctionsProject_WithIncludeHealthChecks_ContainsHealthChecks(FunctionsWorker workerType) + [Fact] + public async Task HttpAzureFunctionsProject_WithIncludeHealthChecks_ContainsHealthChecks() { // Arrange var options = new AzureFunctionsHttpProjectOptions() - .WithFunctionsWorker(workerType) .WithIncludeHealthChecks(); using (var project = await AzureFunctionsHttpProject.StartNewAsync(_config, options, _outputWriter)) @@ -56,15 +53,12 @@ public async Task HttpAzureFunctionsProject_WithIncludeHealthChecks_ContainsHeal } } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task HttpAzureFunctionsProject_RemovesExceptionDetails_WhenRequestingHealth(FunctionsWorker workerType) + [Fact] + public async Task HttpAzureFunctionsProject_RemovesExceptionDetails_WhenRequestingHealth() { // Arrange var options = new AzureFunctionsHttpProjectOptions() - .WithFunctionsWorker(workerType) .WithIncludeHealthChecks(); using (var project = AzureFunctionsHttpProject.CreateNew(_config, options, _outputWriter)) @@ -97,15 +91,12 @@ public async Task HttpAzureFunctionsProject_RemovesExceptionDetails_WhenRequesti } } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task HttpAzureFunctionsProject_WithIncludeHealthChecks_ChecksAcceptRequestHeader(FunctionsWorker workerType) + [Fact] + public async Task HttpAzureFunctionsProject_WithIncludeHealthChecks_ChecksAcceptRequestHeader() { // Arrange var options = new AzureFunctionsHttpProjectOptions() - .WithFunctionsWorker(workerType) .WithIncludeHealthChecks(); using (var project = await AzureFunctionsHttpProject.StartNewAsync(_config, options, _outputWriter)) @@ -123,14 +114,11 @@ public async Task HttpAzureFunctionsProject_WithIncludeHealthChecks_ChecksAccept } } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task HttpAzureFunctionsProject_WithoutOptions_DoesNotContainHealthChecks(FunctionsWorker workerType) + [Fact] + public async Task HttpAzureFunctionsProject_WithoutOptions_DoesNotContainHealthChecks() { // Arrange - var options = new AzureFunctionsHttpProjectOptions().WithFunctionsWorker(workerType); - using (var project = await AzureFunctionsHttpProject.StartNewAsync(_config, options, _outputWriter)) + using (var project = await AzureFunctionsHttpProject.StartNewAsync(_config, _outputWriter)) { // Act using (HttpResponseMessage response = await project.Health.GetAsync()) diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Logging/SerilogLoggingTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Logging/SerilogLoggingTests.cs index f9bce855..9ee8ef38 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Logging/SerilogLoggingTests.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Logging/SerilogLoggingTests.cs @@ -25,10 +25,8 @@ public SerilogLoggingTests(ITestOutputHelper outputWriter) _outputWriter = outputWriter; } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task HttpTriggerProject_WithoutSerilog_StillProcessHttpRequest(FunctionsWorker workerType) + [Fact] + public async Task HttpTriggerProject_WithoutSerilog_StillProcessHttpRequest() { // Arrange var order = new Order @@ -39,7 +37,6 @@ public async Task HttpTriggerProject_WithoutSerilog_StillProcessHttpRequest(Func }; var options = new AzureFunctionsHttpProjectOptions() - .WithFunctionsWorker(workerType) .WithExcludeSerilog(); // Act @@ -55,10 +52,8 @@ public async Task HttpTriggerProject_WithoutSerilog_StillProcessHttpRequest(Func } } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task HttpTriggerProject_WithSerilog_StillProcessHttpRequest(FunctionsWorker workerType) + [Fact] + public async Task HttpTriggerProject_WithSerilog_StillProcessHttpRequest() { // Arrange var order = new Order @@ -68,10 +63,8 @@ public async Task HttpTriggerProject_WithSerilog_StillProcessHttpRequest(Functio Scheduled = BogusGenerator.Date.RecentOffset() }; - var options = new AzureFunctionsHttpProjectOptions().WithFunctionsWorker(workerType); - // Act - using (var project = await AzureFunctionsHttpProject.StartNewAsync(options, _outputWriter)) + using (var project = await AzureFunctionsHttpProject.StartNewAsync(_outputWriter)) { using (HttpResponseMessage response = await project.Order.PostAsync(order)) { diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Swagger/SwaggerOpenApiTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Swagger/SwaggerOpenApiTests.cs index 137138b2..a7361a78 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Swagger/SwaggerOpenApiTests.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Swagger/SwaggerOpenApiTests.cs @@ -33,10 +33,8 @@ public SwaggerOpenApiTests(ITestOutputHelper outputWriter) _outputWriter = outputWriter; } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task PostOrder_WithoutOpenApiDocs_StillWorks(FunctionsWorker workerType) + [Fact] + public async Task PostOrder_WithoutOpenApiDocs_StillWorks() { // Arrange var order = new Order @@ -48,7 +46,6 @@ public async Task PostOrder_WithoutOpenApiDocs_StillWorks(FunctionsWorker worker var options = new AzureFunctionsHttpProjectOptions() - .WithFunctionsWorker(workerType) .WithExcludeOpenApiDocs(); using (var project = await AzureFunctionsHttpProject.StartNewAsync(options, _outputWriter)) @@ -66,15 +63,12 @@ public async Task PostOrder_WithoutOpenApiDocs_StillWorks(FunctionsWorker worker } } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task GetHealth_WithoutOpenApiDocs_StillWorks(FunctionsWorker workerType) + [Fact] + public async Task GetHealth_WithoutOpenApiDocs_StillWorks() { // Arrange var options = new AzureFunctionsHttpProjectOptions() - .WithFunctionsWorker(workerType) .WithIncludeHealthChecks() .WithExcludeOpenApiDocs(); @@ -94,15 +88,12 @@ public async Task GetHealth_WithoutOpenApiDocs_StillWorks(FunctionsWorker worker } } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task Create_WithoutOpenApiDocs_RemovesOpenApiFiles(FunctionsWorker workerType) + [Fact] + public async Task Create_WithoutOpenApiDocs_RemovesOpenApiFiles() { // Arrange var options = new AzureFunctionsHttpProjectOptions() - .WithFunctionsWorker(workerType) .WithExcludeOpenApiDocs(); using (var project = await AzureFunctionsHttpProject.StartNewAsync(options, _outputWriter)) @@ -113,14 +104,11 @@ public async Task Create_WithoutOpenApiDocs_RemovesOpenApiFiles(FunctionsWorker } } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task Create_WithOpenApiDocs_RemovesOpenApiFiles(FunctionsWorker workerType) + [Fact] + public async Task Create_WithOpenApiDocs_RemovesOpenApiFiles() { // Arrange - var options = new AzureFunctionsHttpProjectOptions().WithFunctionsWorker(workerType); - using (var project = await AzureFunctionsHttpProject.StartNewAsync(options, _outputWriter)) + using (var project = await AzureFunctionsHttpProject.StartNewAsync(_outputWriter)) { // Assert Assert.True(project.ContainsFile("HttpCorrelationOpenApiResponseHeaders.cs"), "should contain OpenApi response headers file"); @@ -129,19 +117,15 @@ public async Task Create_WithOpenApiDocs_RemovesOpenApiFiles(FunctionsWorker wor } [Theory] - [InlineData(FunctionsWorker.InProcess, BuildConfiguration.Debug, HttpStatusCode.OK)] - [InlineData(FunctionsWorker.InProcess, BuildConfiguration.Release, HttpStatusCode.NotFound)] - [InlineData(FunctionsWorker.Isolated, BuildConfiguration.Debug, HttpStatusCode.OK)] - [InlineData(FunctionsWorker.Isolated, BuildConfiguration.Release, HttpStatusCode.OK)] + [InlineData(BuildConfiguration.Debug, HttpStatusCode.OK)] + [InlineData(BuildConfiguration.Release, HttpStatusCode.OK)] public async Task GetSwaggerUI_WithBuildConfiguration_Returns( - FunctionsWorker workerType, BuildConfiguration buildConfiguration, HttpStatusCode expectedStatusCode) { // Arrange var testConfiguration = TestConfig.Create(buildConfiguration); - var options = new AzureFunctionsHttpProjectOptions().WithFunctionsWorker(workerType); - using (var project = await AzureFunctionsHttpProject.StartNewAsync(testConfiguration, options, _outputWriter)) + using (var project = await AzureFunctionsHttpProject.StartNewAsync(testConfiguration, _outputWriter)) { // Act using (HttpResponseMessage response = await project.Swagger.GetSwaggerUIAsync()) @@ -153,15 +137,12 @@ public async Task GetSwaggerUI_WithBuildConfiguration_Returns( } } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task GetSwaggerUI_WithExcludeOpenApiProjectOption_ReturnsNotFound(FunctionsWorker workerType) + [Fact] + public async Task GetSwaggerUI_WithExcludeOpenApiProjectOption_ReturnsNotFound() { // Arrange var options = new AzureFunctionsHttpProjectOptions() - .WithFunctionsWorker(workerType) .WithExcludeOpenApiDocs(); using (var project = await AzureFunctionsHttpProject.StartNewAsync(options, _outputWriter)) @@ -174,15 +155,12 @@ public async Task GetSwaggerUI_WithExcludeOpenApiProjectOption_ReturnsNotFound(F } } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task GetSwaggerDocs_WithExcludeOpenApiProjectOption_ReturnsNotFound(FunctionsWorker workerType) + [Fact] + public async Task GetSwaggerDocs_WithExcludeOpenApiProjectOption_ReturnsNotFound() { // Arrange var options = new AzureFunctionsHttpProjectOptions() - .WithFunctionsWorker(workerType) .WithExcludeOpenApiDocs(); using (var project = await AzureFunctionsHttpProject.StartNewAsync(options, _outputWriter)) @@ -197,14 +175,11 @@ public async Task GetSwaggerDocs_WithExcludeOpenApiProjectOption_ReturnsNotFound } } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task GetSwaggerDocs_WithOpenApiConfigurationWithoutHealth_ReturnsOpenApiDocumentOfApplication(FunctionsWorker workerType) + [Fact] + public async Task GetSwaggerDocs_WithOpenApiConfigurationWithoutHealth_ReturnsOpenApiDocumentOfApplication() { // Arrange - var options = new AzureFunctionsHttpProjectOptions().WithFunctionsWorker(workerType); - using (var project = await AzureFunctionsHttpProject.StartNewAsync(options, _outputWriter)) + using (var project = await AzureFunctionsHttpProject.StartNewAsync(_outputWriter)) // Act using (HttpResponseMessage response = await project.Swagger.GetSwaggerDocsAsync()) { @@ -217,14 +192,11 @@ public async Task GetSwaggerDocs_WithOpenApiConfigurationWithoutHealth_ReturnsOp } } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task GetSwaggerDocs_WithOpenApiConfigurationWithHealth_ReturnsOpenApiDocumentOfApplication(FunctionsWorker workerType) + [Fact] + public async Task GetSwaggerDocs_WithOpenApiConfigurationWithHealth_ReturnsOpenApiDocumentOfApplication() { // Arrange var options = new AzureFunctionsHttpProjectOptions() - .WithFunctionsWorker(workerType) .WithIncludeHealthChecks(); using (var project = await AzureFunctionsHttpProject.StartNewAsync(options, _outputWriter)) From 79b401ca3c3150a7e7330d5ec50a0393a06d7011 Mon Sep 17 00:00:00 2001 From: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com> Date: Thu, 2 May 2024 06:36:36 +0200 Subject: [PATCH 04/10] feat: remove functions worker project option in az func eventhubs --- .../.template.config/template.json | 59 +------------- ....Templates.AzureFunctions.EventHubs.csproj | 14 ++-- .../Program.cs | 2 - .../SensorReadingFunction.cs | 54 +------------ .../Startup.cs | 81 ------------------- .../local.settings.json | 4 - .../AzureFunctionsEventHubsProjectOptions.cs | 10 --- .../EventHubs/Logging/SerilogLoggingTests.cs | 7 +- .../MessageHandling/MessageHandlingTests.cs | 18 +---- 9 files changed, 11 insertions(+), 238 deletions(-) delete mode 100644 src/Arcus.Templates.AzureFunctions.EventHubs/Startup.cs diff --git a/src/Arcus.Templates.AzureFunctions.EventHubs/.template.config/template.json b/src/Arcus.Templates.AzureFunctions.EventHubs/.template.config/template.json index 5c3234a6..1602d09a 100644 --- a/src/Arcus.Templates.AzureFunctions.EventHubs/.template.config/template.json +++ b/src/Arcus.Templates.AzureFunctions.EventHubs/.template.config/template.json @@ -26,20 +26,6 @@ "**/*.filelist", "**/*.user", "**/*.lock.json" - ], - "modifiers": [ - { - "condition": "Isolated", - "exclude": [ - "Startup.cs" - ] - }, - { - "condition": "InProcess", - "exclude": [ - "Program.cs" - ] - } ] } ], @@ -75,30 +61,6 @@ }, "replaces": "//#error" }, - "functions-worker": { - "type": "parameter", - "datatype": "choice", - "choices": [ - { - "choice": "inProcess", - "description": "Uses Azure Functions in-process worker template" - }, - { - "choice": "isolated", - "description": "Uses Azure Functions isolated worker template" - } - ], - "defaultValue": "isolated", - "description": "Chooses the kind of Azure Functions worker template" - }, - "InProcess": { - "type": "computed", - "value": "(functions-worker == \"inProcess\")" - }, - "Isolated": { - "type": "computed", - "value": "(functions-worker == \"isolated\")" - }, "exclude-serilog": { "type": "parameter", "datatype": "bool", @@ -109,24 +71,5 @@ "type": "computed", "value": "!(exclude-serilog)" } - }, - "postActions": [ - { - "condition": "InProcess", - "description": "Adding Reference to Microsoft.NET.Sdk.Functions NuGet package", - "actionId": "B17581D1-C5C9-4489-8F0A-004BE667B814", - "continueOnError": false, - "manualInstructions": [ - { - "text": "Manually add the reference to Microsoft.NET.Sdk.Functions to your project file" - } - ], - "args": { - "referenceType": "package", - "reference": "Microsoft.NET.Sdk.Functions", - "version": "4.1.3", - "projectFileExtensions": ".csproj" - } - } - ] + } } diff --git a/src/Arcus.Templates.AzureFunctions.EventHubs/Arcus.Templates.AzureFunctions.EventHubs.csproj b/src/Arcus.Templates.AzureFunctions.EventHubs/Arcus.Templates.AzureFunctions.EventHubs.csproj index f31245b3..f7e71244 100644 --- a/src/Arcus.Templates.AzureFunctions.EventHubs/Arcus.Templates.AzureFunctions.EventHubs.csproj +++ b/src/Arcus.Templates.AzureFunctions.EventHubs/Arcus.Templates.AzureFunctions.EventHubs.csproj @@ -1,7 +1,7 @@  net6.0 - Exe + Exe v4 Linux @@ -34,9 +34,7 @@ - $(DefineConstants);Serilog_AppInsights;InProcess - true - false + $(DefineConstants);Serilog_AppInsights true /home/site/wwwroot @@ -59,11 +57,9 @@ - - - - - + + + diff --git a/src/Arcus.Templates.AzureFunctions.EventHubs/Program.cs b/src/Arcus.Templates.AzureFunctions.EventHubs/Program.cs index d65bd3fb..e8c7a70c 100644 --- a/src/Arcus.Templates.AzureFunctions.EventHubs/Program.cs +++ b/src/Arcus.Templates.AzureFunctions.EventHubs/Program.cs @@ -55,13 +55,11 @@ private static IHostBuilder CreateHostBuilder(string[] args) services.AddAssemblyAppVersion(); }) #endif -#if Isolated .ConfigureFunctionsWorkerDefaults((context, builder) => { builder.Services.AddEventHubsMessageRouting() .WithEventHubsMessageHandler(); }) -#endif .ConfigureSecretStore((config, stores) => { //[#if DEBUG] diff --git a/src/Arcus.Templates.AzureFunctions.EventHubs/SensorReadingFunction.cs b/src/Arcus.Templates.AzureFunctions.EventHubs/SensorReadingFunction.cs index a00e1cc7..ad05934f 100644 --- a/src/Arcus.Templates.AzureFunctions.EventHubs/SensorReadingFunction.cs +++ b/src/Arcus.Templates.AzureFunctions.EventHubs/SensorReadingFunction.cs @@ -8,65 +8,14 @@ using Arcus.Messaging.Abstractions.EventHubs.MessageHandling; using Azure.Messaging.EventHubs; using GuardNet; -#if InProcess -using Arcus.Messaging.AzureFunctions.EventHubs; -using Microsoft.Azure.WebJobs; -using Arcus.Observability.Correlation; -#endif -#if Isolated using Microsoft.Azure.Functions.Worker; -#endif using Microsoft.Extensions.Logging; - + namespace Arcus.Templates.AzureFunctions.EventHubs { public class SensorReadingFunction { private readonly IAzureEventHubsMessageRouter _messageRouter; -#if InProcess - private readonly AzureFunctionsInProcessMessageCorrelation _messageCorrelation; - - /// - /// Initializes a new instance of the class. - /// - /// The message router instance to route the Azure EventHubs events through the sensor-reading processing.The message correlation instance to W3C correlate the Azure EventHubs events. - /// Thrown when the or the is null. - public SensorReadingFunction( - IAzureEventHubsMessageRouter messageRouter, - AzureFunctionsInProcessMessageCorrelation messageCorrelation) - { - Guard.NotNull(messageRouter, nameof(messageRouter), "Requires a message router instance to route incoming Azure EventHubs events through the sensor-reading processing"); - Guard.NotNull(messageCorrelation, nameof(messageCorrelation), "Requires a message correlation instance to W3C correlate incoming Azure EventHubs events"); - - _messageRouter = messageRouter; - _messageCorrelation = messageCorrelation; - } - - /// - /// Processes Azure EventHubs . - /// - /// The incoming events on the Azure EventHubs instance. - /// The logger instance to write informational messages during the message processing. - /// The token to cancel the message processing. - [FunctionName("sensor-reading")] - public async Task Run( - [EventHubTrigger("sensors", Connection = "EventHubsConnectionString")] EventData[] events, - ILogger log, - CancellationToken cancellationToken) - { - log.LogInformation("Azure EventHubs function triggered with {Length} events", events.Length); - foreach (EventData message in events) - { - AzureEventHubsMessageContext messageContext = message.GetMessageContext("sensor-reading.servicebus.windows.net", "sensors"); - using (MessageCorrelationResult result = _messageCorrelation.CorrelateMessage(message)) - { - await _messageRouter.RouteMessageAsync(message, messageContext, result.CorrelationInfo, cancellationToken); - } - } - } -#endif -#if Isolated /// /// Initializes a new instance of the class. @@ -118,6 +67,5 @@ private static EventData CreateEventData(string message, IDictionary - { -//[#if DEBUG] - stores.AddConfiguration(config); -//[#endif] - - //#error Please provide a valid secret provider, for example Azure Key Vault: https://security.arcus-azure.net/features/secret-store/provider/key-vault - stores.AddAzureKeyVaultWithManagedIdentity("https://your-keyvault.vault.azure.net/", CacheConfiguration.Default); - }); - - builder.AddEventHubsMessageRouting() - .WithEventHubsMessageHandler(); -#if Serilog_AppInsights - - builder.Services.AddAppName("EventHubs Trigger"); - builder.Services.AddAssemblyAppVersion(); - builder.Services.AddLogging(logging => - { - logging.RemoveMicrosoftApplicationInsightsLoggerProvider() - .AddSerilog(provider => CreateLoggerConfiguration(provider).CreateLogger()); - }); -#endif - } -#if Serilog_AppInsights - - private static LoggerConfiguration CreateLoggerConfiguration(IServiceProvider provider) - { - IConfiguration appConfig = provider.GetRequiredService(); - var logConfig = new LoggerConfiguration() - .MinimumLevel.Information() - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) - .Enrich.FromLogContext() - .Enrich.WithComponentName(provider) - .Enrich.WithVersion(provider) - .WriteTo.Console(); - - var connectionString = appConfig.GetValue("APPLICATIONINSIGHTS_CONNECTION_STRING"); - if (!string.IsNullOrWhiteSpace(connectionString)) - { - logConfig.WriteTo.AzureApplicationInsightsWithConnectionString(provider, connectionString); - } - - return logConfig; - } -#endif - } -} diff --git a/src/Arcus.Templates.AzureFunctions.EventHubs/local.settings.json b/src/Arcus.Templates.AzureFunctions.EventHubs/local.settings.json index 7880f7f0..ee03af9f 100644 --- a/src/Arcus.Templates.AzureFunctions.EventHubs/local.settings.json +++ b/src/Arcus.Templates.AzureFunctions.EventHubs/local.settings.json @@ -1,11 +1,7 @@ { "IsEncrypted": false, "Values": { - //#if(Isolated) "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", - //#else - "FUNCTIONS_WORKER_RUNTIME": "dotnet", - //#endif "AzureWebJobsStorage": "UseDevelopmentStorage=true" } } diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/AzureFunctionsEventHubsProjectOptions.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/AzureFunctionsEventHubsProjectOptions.cs index da5ba165..0e4651fc 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/AzureFunctionsEventHubsProjectOptions.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/AzureFunctionsEventHubsProjectOptions.cs @@ -12,16 +12,6 @@ public AzureFunctionsEventHubsProjectOptions() { } - /// - /// Sets the Azure Functions worker type to the project options when running the project template. - /// - /// The Azure Functions worker type the project should target. - public AzureFunctionsEventHubsProjectOptions WithFunctionWorker(FunctionsWorker workerType) - { - SetFunctionsWorker(workerType); - return this; - } - /// /// Adds the project option to exclude the Serilog logging infrastructure from the Azure Functions project. /// diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/Logging/SerilogLoggingTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/Logging/SerilogLoggingTests.cs index 16add2bd..4a62f6c7 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/Logging/SerilogLoggingTests.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/Logging/SerilogLoggingTests.cs @@ -19,15 +19,12 @@ public SerilogLoggingTests(ITestOutputHelper outputWriter) _outputWriter = outputWriter; } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task EventHubsProject_WithoutSerilog_CorrectlyProcessesMessage(FunctionsWorker workerType) + [Fact] + public async Task EventHubsProject_WithoutSerilog_CorrectlyProcessesMessage() { // Arrange var config = TestConfig.Create(); var options = new AzureFunctionsEventHubsProjectOptions() - .WithFunctionWorker(workerType) .ExcludeSerilog(); // Act diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/MessageHandling/MessageHandlingTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/MessageHandling/MessageHandlingTests.cs index 3e205a84..d8da5388 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/MessageHandling/MessageHandlingTests.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/MessageHandling/MessageHandlingTests.cs @@ -1,5 +1,4 @@ using System.Threading.Tasks; -using Arcus.Templates.Tests.Integration.Fixture; using Xunit; using Xunit.Abstractions; @@ -20,23 +19,10 @@ public MessageHandlingTests(ITestOutputHelper outputWriter) } [Fact] - public async Task EventHubsProject_AsIsolated_CorrectlyProcessesMessage() - { - await TestEventHubsProjectWithWorkerTypeCorrectlyProcessesMessage(FunctionsWorker.Isolated); - } - - [Fact] - public async Task EventHubsProject_AsInProcess_CorrectlyProcessesMessage() - { - await TestEventHubsProjectWithWorkerTypeCorrectlyProcessesMessage(FunctionsWorker.InProcess); - } - - private async Task TestEventHubsProjectWithWorkerTypeCorrectlyProcessesMessage(FunctionsWorker workerType) + public async Task EventHubsProject_WithDefault_CorrectlyProcessesMessage() { // Arrange - var config = TestConfig.Create(); - var options = new AzureFunctionsEventHubsProjectOptions().WithFunctionWorker(workerType); - await using (var project = await AzureFunctionsEventHubsProject.StartNewAsync(config, options, _outputWriter)) + await using (var project = await AzureFunctionsEventHubsProject.StartNewAsync(_outputWriter)) { // Act / Assert await project.Messaging.SimulateMessageProcessingAsync(); From 13858756ba9eff0cc270b3e2cd038c696df03217 Mon Sep 17 00:00:00 2001 From: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com> Date: Thu, 2 May 2024 06:41:53 +0200 Subject: [PATCH 05/10] feat: remove databricks az in-process project --- .../Arcus.Templates.Tests.Integration.csproj | 1 - .../Admin/AdminEndpointService.cs | 2 - .../AzureFunctions/AzureFunctionsProject.cs | 33 +--- .../AzureFunctionsProjectOptions.cs | 31 +-- .../ApplicationInsightsConfig.cs | 2 +- .../AzureFunctionsDatabricksProject.cs | 177 ------------------ .../AzureFunctionsDatabricksProjectOptions.cs | 25 --- .../AzureFunctionDatabricksConfig.cs | 54 ------ .../Configuration/LaunchSettingsTests.cs | 39 ---- .../Health/DatabricksHealthDockerTests.cs | 36 ---- .../JobMetrics/Logging/SerilogLoggingTests.cs | 39 ---- .../DatabricksMetricReportingTests.cs | 137 -------------- .../AzureFunctionsEventHubsProject.cs | 2 +- .../Fixture/ApplicationInsightsTests.cs | 2 +- .../Fixture/TestConfig.cs | 15 -- .../appsettings.json | 6 - src/Arcus.Templates.sln | 8 +- 17 files changed, 7 insertions(+), 602 deletions(-) rename src/Arcus.Templates.Tests.Integration/AzureFunctions/{Databricks/JobMetrics => }/Configuration/ApplicationInsightsConfig.cs (96%) delete mode 100644 src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/AzureFunctionsDatabricksProject.cs delete mode 100644 src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/AzureFunctionsDatabricksProjectOptions.cs delete mode 100644 src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Configuration/AzureFunctionDatabricksConfig.cs delete mode 100644 src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Configuration/LaunchSettingsTests.cs delete mode 100644 src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Health/DatabricksHealthDockerTests.cs delete mode 100644 src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Logging/SerilogLoggingTests.cs delete mode 100644 src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/MetricReporting/DatabricksMetricReportingTests.cs diff --git a/src/Arcus.Templates.Tests.Integration/Arcus.Templates.Tests.Integration.csproj b/src/Arcus.Templates.Tests.Integration/Arcus.Templates.Tests.Integration.csproj index 8b8456cc..2e8c8efc 100644 --- a/src/Arcus.Templates.Tests.Integration/Arcus.Templates.Tests.Integration.csproj +++ b/src/Arcus.Templates.Tests.Integration/Arcus.Templates.Tests.Integration.csproj @@ -41,7 +41,6 @@ - diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Admin/AdminEndpointService.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Admin/AdminEndpointService.cs index d3f1760a..fb250556 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Admin/AdminEndpointService.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Admin/AdminEndpointService.cs @@ -2,8 +2,6 @@ using System.Net.Http; using System.Text; using System.Threading.Tasks; -using Arcus.Templates.Tests.Integration.AzureFunctions.Configuration; -using Arcus.Templates.Tests.Integration.AzureFunctions.Databricks.JobMetrics.Configuration; using Arcus.Templates.Tests.Integration.WebApi.Fixture; using Flurl; using Xunit.Abstractions; diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/AzureFunctionsProject.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/AzureFunctionsProject.cs index f555c5fa..e0096855 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/AzureFunctionsProject.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/AzureFunctionsProject.cs @@ -4,7 +4,6 @@ using System.Net.Http; using System.Threading.Tasks; using Arcus.Templates.Tests.Integration.AzureFunctions.Configuration; -using Arcus.Templates.Tests.Integration.AzureFunctions.Databricks.JobMetrics.Configuration; using Arcus.Templates.Tests.Integration.Fixture; using Flurl; using GuardNet; @@ -43,18 +42,12 @@ protected AzureFunctionsProject( Guard.NotNull(outputWriter, nameof(outputWriter), "Requires an logger instance to write diagnostic trace messages during the lifetime of the project."); Configuration = configuration; - FunctionsWorker = options.FunctionsWorker; - RuntimeFileName = DetermineStartupCodeFileName(); + RuntimeFileName = "Program.cs"; RootEndpoint = configuration.GenerateRandomLocalhostUrl().ResetToRoot().ToUri(); AzureFunctionsConfig = configuration.GetAzureFunctionsConfig(); ApplicationInsightsConfig = configuration.GetApplicationInsightsConfig(); } - /// - /// Gets the Azure Functions worker type the project should target. - /// - public FunctionsWorker FunctionsWorker { get; } - /// /// Gets the file name of the Azure Functions that contains the startup code ('Startup.cs' for in-process functions, 'Program.cs' for isolated functions). /// @@ -86,34 +79,12 @@ protected AzureFunctionsProject( protected void AddLocalSettings() { string storageAccountConnectionString = AzureFunctionsConfig.StorageAccountConnectionString; - string workerRuntime = DetermineWorkerRuntime(); + string workerRuntime = "dotnet-isolated"; AddFileInProject("local.settings.json", $"{{ \"IsEncrypted\": false, \"Values\": {{ \"AzureWebJobsStorage\": \"{storageAccountConnectionString}\", \"FUNCTIONS_WORKER_RUNTIME\": \"{workerRuntime}\", \"APPLICATIONINSIGHTS_CONNECTION_STRING\": \"\" }}, \"Host\": {{ \"LocalHttpPort\": {RootEndpoint.Port} }} }}"); } - private string DetermineWorkerRuntime() - { - switch (FunctionsWorker) - { - case FunctionsWorker.InProcess: return "dotnet"; - case FunctionsWorker.Isolated: return "dotnet-isolated"; - default: - throw new ArgumentOutOfRangeException(nameof(FunctionsWorker), FunctionsWorker, "Unknown Azure Functions worker type"); - } - } - - private string DetermineStartupCodeFileName() - { - switch (FunctionsWorker) - { - case FunctionsWorker.InProcess: return "Startup.cs"; - case FunctionsWorker.Isolated: return "Program.cs"; - default: - throw new ArgumentOutOfRangeException(nameof(FunctionsWorker), FunctionsWorker, "Unknown Azure Functions worker type"); - } - } - /// /// Customized project process preparation that results in an instance. /// diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/AzureFunctionsProjectOptions.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/AzureFunctionsProjectOptions.cs index af26aa60..9b814056 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/AzureFunctionsProjectOptions.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/AzureFunctionsProjectOptions.cs @@ -1,5 +1,4 @@ -using System; -using Arcus.Templates.Tests.Integration.Fixture; +using Arcus.Templates.Tests.Integration.Fixture; namespace Arcus.Templates.Tests.Integration.AzureFunctions { @@ -8,33 +7,5 @@ namespace Arcus.Templates.Tests.Integration.AzureFunctions /// public class AzureFunctionsProjectOptions : ProjectOptions { - /// - /// Gets the Azure Functions worker type the project should target. - /// - public FunctionsWorker FunctionsWorker { get; protected set; } = FunctionsWorker.Isolated; - - /// - /// Sets the Azure Functions worker type of the project template. - /// - /// The functions worker type. - /// Thrown when the is outside the bounds of the enumeration. - protected void SetFunctionsWorker(FunctionsWorker workerType) - { - string workerTyperArgument = DetermineFunctionsWorkerArgument(workerType); - AddOption($"--functions-worker {workerTyperArgument}"); - - FunctionsWorker = workerType; - } - - private static string DetermineFunctionsWorkerArgument(FunctionsWorker workerType) - { - switch (workerType) - { - case FunctionsWorker.InProcess: return "inProcess"; - case FunctionsWorker.Isolated: return "isolated"; - default: - throw new ArgumentOutOfRangeException(nameof(workerType), workerType, "Unknown functions worker type"); - } - } } } diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Configuration/ApplicationInsightsConfig.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Configuration/ApplicationInsightsConfig.cs similarity index 96% rename from src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Configuration/ApplicationInsightsConfig.cs rename to src/Arcus.Templates.Tests.Integration/AzureFunctions/Configuration/ApplicationInsightsConfig.cs index 81f9d9a4..f1439edb 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Configuration/ApplicationInsightsConfig.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Configuration/ApplicationInsightsConfig.cs @@ -1,6 +1,6 @@ using GuardNet; -namespace Arcus.Templates.Tests.Integration.AzureFunctions.Databricks.JobMetrics.Configuration +namespace Arcus.Templates.Tests.Integration.AzureFunctions.Configuration { /// /// Represents an application configuration section related to information regarding Azure Application Insights. diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/AzureFunctionsDatabricksProject.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/AzureFunctionsDatabricksProject.cs deleted file mode 100644 index 31276a47..00000000 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/AzureFunctionsDatabricksProject.cs +++ /dev/null @@ -1,177 +0,0 @@ -using System; -using System.Diagnostics; -using System.Threading.Tasks; -using Arcus.Templates.Tests.Integration.AzureFunctions.Admin; -using Arcus.Templates.Tests.Integration.AzureFunctions.Databricks.JobMetrics.Configuration; -using Arcus.Templates.Tests.Integration.Fixture; -using GuardNet; -using Xunit.Abstractions; - -namespace Arcus.Templates.Tests.Integration.AzureFunctions.Databricks.JobMetrics -{ - /// - /// Project template to create new Azure Functions Databricks Job Metrics projects. - /// - [DebuggerDisplay("Project = {ProjectDirectory.FullName}, Databricks URL = {DatabricksUrlVariable}")] - public class AzureFunctionsDatabricksProject : AzureFunctionsProject - { - private const string ApplicationInsightsMetricNameVariable = "Arcus__ApplicationInsights__MetricName", - DatabricksUrlVariable = "Arcus__Databricks__Url"; - - /// - /// Gets the name of the Azure Function in the project. - /// - public const string FunctionName = "databricks-job-metrics"; - - private AzureFunctionsDatabricksProject( - TestConfig configuration, - AzureFunctionsDatabricksProjectOptions options, - ITestOutputHelper outputWriter) - : base(configuration.GetAzureFunctionsDatabricksJobMetricsProjectDirectory(), - configuration, - options, - outputWriter) - { - AzureFunctionDatabricksConfig = configuration.GetDatabricksConfig(); - Admin = new AdminEndpointService(RootEndpoint.Port, FunctionName, outputWriter); - } - - /// - /// Gets the Databricks connectivity information from the current application configuration, used by this project. - /// - public AzureFunctionDatabricksConfig AzureFunctionDatabricksConfig { get; } - - /// - /// Gets the service to run administrative actions on the Azure Functions project. - /// - public AdminEndpointService Admin { get; } - - /// - /// Starts a newly created project from the Azure Functions Databricks Job Metrics project template. - /// - /// The configuration to control the hosting of the to-be-created project. - /// The output logger to add telemetry information during the creation and startup process. - /// - /// A Azure Functions Databricks Job Metrics project with a full set of endpoint services to interact with the Azure Function. - /// - /// Thrown when the or is null. - public static async Task StartNewAsync(TestConfig configuration, ITestOutputHelper outputWriter) - { - Guard.NotNull(configuration, nameof(configuration), "Requires a test configuration instance to retrieve integration test configuration values to interact with Azure Databricks"); - Guard.NotNull(outputWriter, nameof(outputWriter), "Requires a logging instance to write diagnostic information during the creation and startup process"); - - AzureFunctionsDatabricksProject project = await StartNewAsync(configuration, new AzureFunctionsDatabricksProjectOptions(), outputWriter); - return project; - } - - /// - /// Starts a newly created project from the Azure Functions Databricks Job Metrics project template. - /// - /// The configuration to control the hosting of the to-be-created project. - /// The additional user project options to change the project contents and functionality. - /// The output logger to add telemetry information during the creation and startup process. - /// - /// A Azure Functions Databricks Job Metrics project with a full set of endpoint services to interact with the Azure Function. - /// - /// - /// Thrown when the , , or is null. - /// - public static async Task StartNewAsync(TestConfig configuration, AzureFunctionsDatabricksProjectOptions options, ITestOutputHelper outputWriter) - { - Guard.NotNull(configuration, nameof(configuration), "Requires a test configuration instance to retrieve integration test configuration values to interact with Azure Databricks"); - Guard.NotNull(options, nameof(options), "Requires a project options to change the project contents and functionality"); - Guard.NotNull(outputWriter, nameof(outputWriter), "Requires a logging instance to write diagnostic information during the creation and startup process"); - - AzureFunctionsDatabricksProject project = CreateNew(configuration, options, outputWriter); - await project.StartAsync(); - - return project; - } - - /// - /// Creates a project from the Azure Functions Databricks Job Metrics project template. - /// - /// The configuration to control the hosting of the to-be-created project. - /// The additional user project options to change the project contents and functionality. - /// The output logger to add telemetry information during the creation process. - /// - /// A Azure Functions Databricks Job Metrics project with a full set of endpoint services to interact with the Azure Function. - /// - /// - /// Thrown when the , , or is null. - /// - public static AzureFunctionsDatabricksProject CreateNew(TestConfig configuration, AzureFunctionsDatabricksProjectOptions options, ITestOutputHelper outputWriter) - { - Guard.NotNull(configuration, nameof(configuration), "Requires a test configuration instance to retrieve integration test configuration values to interact with Azure Databricks"); - Guard.NotNull(options, nameof(options), "Requires a project options to change the project contents and functionality"); - Guard.NotNull(outputWriter, nameof(outputWriter), "Requires a logging instance to write diagnostic information during the creation process"); - - var project = new AzureFunctionsDatabricksProject(configuration, options, outputWriter); - project.CreateNewProject(options); - project.AddDatabricksSecurityToken(project.AzureFunctionDatabricksConfig.SecurityToken); - project.AddLocalSettings(); - - return project; - } - - private async Task StartAsync() - { - try - { - Run(Configuration.BuildConfiguration, TargetFramework.Net6_0); - await WaitUntilTriggerIsAvailableAsync(Admin.Endpoint); - } - catch - { - Dispose(); - throw; - } - } - - private void AddDatabricksSecurityToken(string securityToken) - { - AddTypeAsFile(); - - UpdateFileInProject(RuntimeFileName, contents => - RemovesUserErrorsFromContents(contents) - .Replace("AddAzureKeyVaultWithManagedIdentity(\"https://your-keyvault.vault.azure.net/\", CacheConfiguration.Default)", - $"AddProvider(new {nameof(SingleValueSecretProvider)}(\"{securityToken}\"))")); - } - - /// - /// Customized project process preparation that results in an instance. - /// - /// The configuration to which the project should built. - /// The code framework to which this project targets to. - /// The CLI parameters which should be sent to the starting project. - /// - /// An run-ready instance that will be used to start the project. - /// - protected override ProcessStartInfo PrepareProjectRun( - BuildConfiguration buildConfiguration, - TargetFramework targetFramework, - CommandArgument[] commandArguments) - { - ProcessStartInfo startInfo = base.PrepareProjectRun(buildConfiguration, targetFramework, commandArguments); - Environment.SetEnvironmentVariable(ApplicationInsightsMetricNameVariable, ApplicationInsightsConfig.MetricName); - Environment.SetEnvironmentVariable(DatabricksUrlVariable, AzureFunctionDatabricksConfig.BaseUrl); - - ApplicationInsightsConfig appInsightsConfig = Configuration.GetApplicationInsightsConfig(); - Environment.SetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING", $"InstrumentationKey={appInsightsConfig.InstrumentationKey}"); - - return startInfo; - } - - /// - /// Performs additional application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - /// The flag indicating whether or not the additional tasks should be disposed. - protected override void Disposing(bool disposing) - { - base.Disposing(disposing); - Environment.SetEnvironmentVariable(ApplicationInsightsMetricNameVariable, null); - Environment.SetEnvironmentVariable(DatabricksUrlVariable, null); - Environment.SetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING", null); - } - } -} diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/AzureFunctionsDatabricksProjectOptions.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/AzureFunctionsDatabricksProjectOptions.cs deleted file mode 100644 index ddde6acc..00000000 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/AzureFunctionsDatabricksProjectOptions.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Arcus.Templates.Tests.Integration.AzureFunctions.Databricks.JobMetrics -{ - /// - /// Represents the additional user project options to change the project contents and functionality. - /// - public class AzureFunctionsDatabricksProjectOptions : AzureFunctionsProjectOptions - { - /// - /// Initializes a new instance of the class. - /// - public AzureFunctionsDatabricksProjectOptions() - { - FunctionsWorker = FunctionsWorker.InProcess; - } - - /// - /// Adds a project option that excludes all the Serilog logging functionality from the resulting project. - /// - public AzureFunctionsDatabricksProjectOptions WithExcludeSerilog() - { - AddOption("--exclude-serilog"); - return this; - } - } -} diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Configuration/AzureFunctionDatabricksConfig.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Configuration/AzureFunctionDatabricksConfig.cs deleted file mode 100644 index 037eb706..00000000 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Configuration/AzureFunctionDatabricksConfig.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using GuardNet; - -namespace Arcus.Templates.Tests.Integration.AzureFunctions.Databricks.JobMetrics.Configuration -{ - /// - /// Represents the Azure Databricks configuration used during the integration test suite. - /// - public class AzureFunctionDatabricksConfig - { - /// - /// Initializes a new instance of the class. - /// - /// The HTTP port where the Azure Functions project will be running. - /// The Databricks base URL to locate to the Azure Databricks resource. - /// The Databricks security token to authenticate with the Azure Databricks resource. - /// The Databricks job to use while interacting with the Databricks resource. - /// Thrown when the is less then zero. - /// Thrown when the or is blank. - /// Thrown when the is less then zero. - public AzureFunctionDatabricksConfig(int httpPort, string baseUrl, string securityToken, int jobId) - { - Guard.NotLessThan(httpPort, 0, nameof(httpPort), "Requires a HTTP port that's greater than zero to locate the endpoint where the Azure Functions project is running"); - Guard.NotNullOrWhitespace(baseUrl, nameof(baseUrl), "Requires a non-blank Databricks base URL for the integration test configuration"); - Guard.NotNullOrWhitespace(securityToken, nameof(securityToken), "Requires a non-blank Databricks security token for the integration test configuration"); - Guard.NotLessThan(jobId, 0, nameof(jobId), "Requires a Databricks job ID that's greater than zero"); - - HttpPort = httpPort; - BaseUrl = baseUrl; - SecurityToken = securityToken; - JobId = jobId; - } - - /// - /// Gets the HTTP port where the Azure Function project will be running. - /// - public int HttpPort { get; } - - /// - /// Gets the Databricks base URL to locate the Azure Databricks resource. - /// - public string BaseUrl { get; } - - /// - /// Gets the Databricks security token to authenticate with the Azure Databricks resource. - /// - public string SecurityToken { get; } - - /// - /// Gets the ID of the Databricks job that's being used to interact with the Azure Databricks resource. - /// - public int JobId { get; } - } -} diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Configuration/LaunchSettingsTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Configuration/LaunchSettingsTests.cs deleted file mode 100644 index 93db4974..00000000 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Configuration/LaunchSettingsTests.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.IO; -using Arcus.Templates.Tests.Integration.Fixture; -using Xunit; -using Xunit.Abstractions; - -namespace Arcus.Templates.Tests.Integration.AzureFunctions.Databricks.JobMetrics.Configuration -{ - [Trait("Category", TestTraits.Integration)] - public class LaunchSettingsTests - { - private readonly ITestOutputHelper _outputWriter; - - /// - /// Initializes a new instance of the class. - /// - public LaunchSettingsTests(ITestOutputHelper outputWriter) - { - _outputWriter = outputWriter; - } - - [Fact] - public void DatabricksJobMetricsTrigger_WithDefault_ConfiguresLaunchSettings() - { - // Arrange - var config = TestConfig.Create(); - var options = new AzureFunctionsDatabricksProjectOptions(); - - // Act - using (var project = AzureFunctionsDatabricksProject.CreateNew(config, options, _outputWriter)) - { - // Assert - string relativePath = Path.Combine("Properties", "launchSettings.json"); - string json = project.GetFileContentsInProject(relativePath); - Assert.Contains(TemplateProject.ProjectName, json); - Assert.Contains("Docker", json); - } - } - } -} diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Health/DatabricksHealthDockerTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Health/DatabricksHealthDockerTests.cs deleted file mode 100644 index c8e310cd..00000000 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Health/DatabricksHealthDockerTests.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Threading.Tasks; -using Arcus.Templates.Tests.Integration.AzureFunctions.Admin; -using Arcus.Templates.Tests.Integration.AzureFunctions.Databricks.JobMetrics.Configuration; -using Arcus.Templates.Tests.Integration.Fixture; -using Xunit; -using Xunit.Abstractions; - -namespace Arcus.Templates.Tests.Integration.AzureFunctions.Databricks.JobMetrics.Health -{ - [Collection(TestCollections.Docker)] - [Trait("Category", TestTraits.Docker)] - public class DatabricksHealthDockerTests - { - private readonly ITestOutputHelper _outputWriter; - - /// - /// Initializes a new instance of the class. - /// - public DatabricksHealthDockerTests(ITestOutputHelper outputWriter) - { - _outputWriter = outputWriter; - } - - [Fact] - public async Task AzureFunctionsDatabricksProject_WithoutOptions_ShouldAnswerToAdministratorEndpoint() - { - // Arrange - var configuration = TestConfig.Create(); - AzureFunctionDatabricksConfig databricksConfig = configuration.GetDatabricksConfig(); - var service = new AdminEndpointService(databricksConfig.HttpPort, AzureFunctionsDatabricksProject.FunctionName, _outputWriter); - - // Act / Assert - await service.TriggerFunctionAsync(); - } - } -} diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Logging/SerilogLoggingTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Logging/SerilogLoggingTests.cs deleted file mode 100644 index 28545769..00000000 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/Logging/SerilogLoggingTests.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Threading.Tasks; -using Arcus.Templates.Tests.Integration.Fixture; -using Xunit; -using Xunit.Abstractions; - -namespace Arcus.Templates.Tests.Integration.AzureFunctions.Databricks.JobMetrics.Logging -{ - [Collection(TestCollections.Integration)] - [Trait("Category", TestTraits.Integration)] - public class SerilogLoggingTests - { - private readonly ITestOutputHelper _outputWriter; - - /// - /// Initializes a new instance of the class. - /// - public SerilogLoggingTests(ITestOutputHelper outputWriter) - { - _outputWriter = outputWriter; - } - - [Fact] - public async Task DatabricksProject_WithoutSerilog_StillRuns() - { - // Arrange - var config = TestConfig.Create(); - var options = new AzureFunctionsDatabricksProjectOptions().WithExcludeSerilog(); - - // Act - using (var project = await AzureFunctionsDatabricksProject.StartNewAsync(config, options, _outputWriter)) - { - // Assert - await project.Admin.TriggerFunctionAsync(); - Assert.DoesNotContain("Serilog", project.GetFileContentsOfProjectFile()); - Assert.DoesNotContain("Serilog", project.GetFileContentsInProject("Startup.cs")); - } - } - } -} diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/MetricReporting/DatabricksMetricReportingTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/MetricReporting/DatabricksMetricReportingTests.cs deleted file mode 100644 index d4e15417..00000000 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Databricks/JobMetrics/MetricReporting/DatabricksMetricReportingTests.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Arcus.Templates.Tests.Integration.Fixture; -using Microsoft.Azure.ApplicationInsights.Query; -using Microsoft.Azure.ApplicationInsights.Query.Models; -using Microsoft.Azure.Databricks.Client; -using Microsoft.Azure.Databricks.Client.Models; -using Polly; -using Polly.Retry; -using Xunit; -using Xunit.Abstractions; -using Policy = Polly.Policy; - -namespace Arcus.Templates.Tests.Integration.AzureFunctions.Databricks.JobMetrics.MetricReporting -{ - [Collection(TestCollections.Integration)] - [Trait("Category", TestTraits.Integration)] - public class DatabricksMetricReportingTests : ApplicationInsightsTests - { - private readonly TestConfig _config; - - /// - /// Initializes a new instance of the class. - /// - public DatabricksMetricReportingTests(ITestOutputHelper outputWriter) : base(outputWriter) - { - _config = TestConfig.Create(); - } - - [Fact(Skip = "Fails now because the Databricks cluster is removed on Azure")] - public async Task MinimumAzureFunctionsDatabricksProject_WithEmbeddedTimer_ReportsAsMetricPeriodically() - { - var parameters = RunParameters.CreateNotebookParams(new Dictionary()); - - using (var project = await AzureFunctionsDatabricksProject.StartNewAsync(_config, Logger)) - using (var client = DatabricksClient.CreateClient(project.AzureFunctionDatabricksConfig.BaseUrl, project.AzureFunctionDatabricksConfig.SecurityToken)) - { - JobSettings settings = CreateEmptyJobSettings(); - long jobId = await client.Jobs.Create(settings); - - try - { - // Act - await client.Jobs.RunNow(jobId, parameters); - await WaitUntilDatabricksJobRunIsCompleted(client, jobId); - } - finally - { - await client.Jobs.Delete(jobId); - } - } - - // Assert - await RetryAssertUntilTelemetryShouldBeAvailableAsync(async client => - { - MetricsPostBodySchema bodySchema = CreateMetricPostBodySchemaForDatabricksTracking(); - IList results = - await client.Metrics.GetMultipleAsync(ApplicationInsightsConfig.ApplicationId, new List {bodySchema}); - - Assert.NotEmpty(results); - Assert.All(results, result => Assert.NotNull(result.Body.Value)); - }, - timeout: TimeSpan.FromMinutes(2)); - } - - private static JobSettings CreateEmptyJobSettings() - { - var settings = new JobSettings - { - Name = "(temp) Arcus Templates - Integration Testing", - JobClusters = new[] - { - new JobCluster - { - NewCluster = new ClusterAttributes - { - RuntimeVersion = "8.3.x-scala2.12", - AzureAttributes = new AzureAttributes - { - Availability = AzureAvailability.ON_DEMAND_AZURE, - FirstOnDemand = 1, - SpotBidMaxPrice = -1 - }, - NodeTypeId = "Standard_DS3_v2", - SparkEnvironmentVariables = new Dictionary - { - ["PYSPARK_PYTHON"] = "/databricks/python3/bin/python3" - }, - EnableElasticDisk = true, - NumberOfWorkers = 8 - } - } - }, - MaxConcurrentRuns = 10, - Tasks = new List - { - new JobTaskSettings - { - NotebookTask = new NotebookTask - { - NotebookPath = "/Arcus - Automation" - } - } - } - }; - - return settings; - } - - private MetricsPostBodySchema CreateMetricPostBodySchemaForDatabricksTracking() - { - const string past10MinFilter = "PT0.1H"; - var bodySchema = new MetricsPostBodySchema( - id: Guid.NewGuid().ToString(), - parameters: new MetricsPostBodySchemaParameters( - $"customMetrics/{ApplicationInsightsConfig.MetricName}", - timespan: past10MinFilter)); - - return bodySchema; - } - - private static async Task WaitUntilDatabricksJobRunIsCompleted(DatabricksClient client, long jobId) - { - AsyncRetryPolicy retryPolicy = - Policy.HandleResult(list => list.Runs is null || list.Runs.Any(r => !r.IsCompleted)) - .WaitAndRetryForeverAsync(index => TimeSpan.FromSeconds(10)); - - await Policy.TimeoutAsync(TimeSpan.FromMinutes(10)) - .WrapAsync(retryPolicy) - .ExecuteAsync(async () => await client.Jobs.RunsList(jobId)); - - await Task.Delay(TimeSpan.FromMinutes(2)); - } - } -} diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/AzureFunctionsEventHubsProject.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/AzureFunctionsEventHubsProject.cs index f0ecd419..f6e29a9b 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/AzureFunctionsEventHubsProject.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/AzureFunctionsEventHubsProject.cs @@ -1,6 +1,6 @@ using System; using System.Threading.Tasks; -using Arcus.Templates.Tests.Integration.AzureFunctions.Databricks.JobMetrics.Configuration; +using Arcus.Templates.Tests.Integration.AzureFunctions.Configuration; using Arcus.Templates.Tests.Integration.Fixture; using Arcus.Templates.Tests.Integration.Worker.Configuration; using Arcus.Templates.Tests.Integration.Worker.EventHubs.Fixture; diff --git a/src/Arcus.Templates.Tests.Integration/Fixture/ApplicationInsightsTests.cs b/src/Arcus.Templates.Tests.Integration/Fixture/ApplicationInsightsTests.cs index 065fc66d..f572dd5b 100644 --- a/src/Arcus.Templates.Tests.Integration/Fixture/ApplicationInsightsTests.cs +++ b/src/Arcus.Templates.Tests.Integration/Fixture/ApplicationInsightsTests.cs @@ -1,7 +1,7 @@ using System; using System.Linq; using System.Threading.Tasks; -using Arcus.Templates.Tests.Integration.AzureFunctions.Databricks.JobMetrics.Configuration; +using Arcus.Templates.Tests.Integration.AzureFunctions.Configuration; using GuardNet; using Microsoft.Azure.ApplicationInsights.Query; using Polly; diff --git a/src/Arcus.Templates.Tests.Integration/Fixture/TestConfig.cs b/src/Arcus.Templates.Tests.Integration/Fixture/TestConfig.cs index b6b571b7..729ee130 100644 --- a/src/Arcus.Templates.Tests.Integration/Fixture/TestConfig.cs +++ b/src/Arcus.Templates.Tests.Integration/Fixture/TestConfig.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using Arcus.Templates.Tests.Integration.AzureFunctions.Configuration; -using Arcus.Templates.Tests.Integration.AzureFunctions.Databricks.JobMetrics.Configuration; using Arcus.Templates.Tests.Integration.AzureFunctions.Http.Configuration; using Arcus.Templates.Tests.Integration.Worker.Configuration; using Microsoft.Extensions.Configuration; @@ -298,20 +297,6 @@ public AzureFunctionsConfig GetAzureFunctionsConfig() return new AzureFunctionsConfig(storageAccountConnectionString); } - /// - /// Gets the Azure Databricks application configuration to interact with the Databricks Azure Function. - /// - /// Thrown when one of the Azure Databricks configuration values are not found. - public AzureFunctionDatabricksConfig GetDatabricksConfig() - { - var httpPort = _configuration.GetRequiredValue("Arcus:AzureFunctions:Databricks:HttpPort"); - var baseUrl = _configuration.GetRequiredValue("Arcus:AzureFunctions:Databricks:BaseUrl"); - var securityToken = _configuration.GetRequiredValue("Arcus:AzureFunctions:Databricks:Token"); - var jobId = _configuration.GetRequiredValue("Arcus:AzureFunctions:Databricks:JobId"); - - return new AzureFunctionDatabricksConfig(httpPort, baseUrl, securityToken, jobId); - } - /// /// Gets the application configuration to interact with the HTTP Azure Function. /// diff --git a/src/Arcus.Templates.Tests.Integration/appsettings.json b/src/Arcus.Templates.Tests.Integration/appsettings.json index 50334a55..e95a53e5 100644 --- a/src/Arcus.Templates.Tests.Integration/appsettings.json +++ b/src/Arcus.Templates.Tests.Integration/appsettings.json @@ -38,12 +38,6 @@ }, "AzureFunctions": { "AzureWebJobsStorage": "#{Arcus.AzureFunctions.AzureWebJobsStorage}#", - "Databricks": { - "HttpPort": "#{Arcus.AzureFunctions.Databricks.HttpPort}#", - "BaseUrl": "#{Arcus.Databricks.Url}#", - "Token": "#{Arcus.Databricks.Token}#", - "JobId": "#{Arcus.Databricks.JobId}#" - }, "Http": { "Isolated": { "HttpPort": "#{Arcus.AzureFunctions.Http.Isolated.HttpPort}#" diff --git a/src/Arcus.Templates.sln b/src/Arcus.Templates.sln index 28e3bc0b..7e35d1fa 100644 --- a/src/Arcus.Templates.sln +++ b/src/Arcus.Templates.sln @@ -15,8 +15,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Arcus.Templates.ServiceBus. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Arcus.Templates.ServiceBus.Topic", "Arcus.Templates.ServiceBus.Topic\Arcus.Templates.ServiceBus.Topic.csproj", "{F4200B87-E88B-4DF3-8385-CAF357956D29}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Arcus.Templates.AzureFunctions.Databricks.JobMetrics", "Arcus.Templates.AzureFunctions.Databricks.JobMetrics\Arcus.Templates.AzureFunctions.Databricks.JobMetrics.csproj", "{2A73C4DA-FCE4-41D3-B688-1D44A4E94958}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Arcus.Templates.AzureFunctions.Http", "Arcus.Templates.AzureFunctions.Http\Arcus.Templates.AzureFunctions.Http.csproj", "{4DEFCD46-678C-4732-8595-A50E406C0A42}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Arcus.Templates.AzureFunctions.ServiceBus.Queue", "Arcus.Templates.AzureFunctions.ServiceBus.Queue\Arcus.Templates.AzureFunctions.ServiceBus.Queue.csproj", "{651CD421-8E6E-44B8-AF3B-E96DD6266B11}" @@ -25,7 +23,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Arcus.Templates.AzureFuncti EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Arcus.Templates.EventHubs", "Arcus.Templates.EventHubs\Arcus.Templates.EventHubs.csproj", "{1E5D0205-06E0-4CD8-9C22-37F306BB23AC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Arcus.Templates.AzureFunctions.EventHubs", "Arcus.Templates.AzureFunctions.EventHubs\Arcus.Templates.AzureFunctions.EventHubs.csproj", "{58CAF85E-5FFE-4422-B1E7-9D438DD94A57}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Arcus.Templates.AzureFunctions.EventHubs", "Arcus.Templates.AzureFunctions.EventHubs\Arcus.Templates.AzureFunctions.EventHubs.csproj", "{58CAF85E-5FFE-4422-B1E7-9D438DD94A57}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -53,10 +51,6 @@ Global {F4200B87-E88B-4DF3-8385-CAF357956D29}.Debug|Any CPU.Build.0 = Debug|Any CPU {F4200B87-E88B-4DF3-8385-CAF357956D29}.Release|Any CPU.ActiveCfg = Release|Any CPU {F4200B87-E88B-4DF3-8385-CAF357956D29}.Release|Any CPU.Build.0 = Release|Any CPU - {2A73C4DA-FCE4-41D3-B688-1D44A4E94958}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2A73C4DA-FCE4-41D3-B688-1D44A4E94958}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2A73C4DA-FCE4-41D3-B688-1D44A4E94958}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2A73C4DA-FCE4-41D3-B688-1D44A4E94958}.Release|Any CPU.Build.0 = Release|Any CPU {4DEFCD46-678C-4732-8595-A50E406C0A42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4DEFCD46-678C-4732-8595-A50E406C0A42}.Debug|Any CPU.Build.0 = Debug|Any CPU {4DEFCD46-678C-4732-8595-A50E406C0A42}.Release|Any CPU.ActiveCfg = Release|Any CPU From ce4bdd6c526d5f272eca358bf5be5264f8a8aaf0 Mon Sep 17 00:00:00 2001 From: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com> Date: Thu, 2 May 2024 06:43:44 +0200 Subject: [PATCH 06/10] docs: remove functions worker project option in docs --- ...unctions-databricks-jobmetrics-template.md | 32 ------------------- .../azurefunctions-eventhubs-template.md | 4 --- .../features/azurefunctions-http-template.md | 4 --- ...zurefunctions-servicebus-queue-template.md | 4 --- ...zurefunctions-servicebus-topic-template.md | 4 --- 5 files changed, 48 deletions(-) delete mode 100644 docs/preview/features/azurefunctions-databricks-jobmetrics-template.md diff --git a/docs/preview/features/azurefunctions-databricks-jobmetrics-template.md b/docs/preview/features/azurefunctions-databricks-jobmetrics-template.md deleted file mode 100644 index ef12690b..00000000 --- a/docs/preview/features/azurefunctions-databricks-jobmetrics-template.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: "Databricks Job Metrics template (Azure Functions)" -layout: default ---- - -# Databricks Job Metrics template (Azure Functions) - -## Create your first Arcus Azure Functions Databricks project - -First, install the template from NuGet: - -```shell -> dotnet new --install Arcus.Templates.AzureFunctions.Databricks.JobMetrics -``` - -When installed, the template can be created with shortname: `arcus-az-databricks-jobmetrics`: - -```shell -> dotnet new arcus-az-databricks-jobmetrics --name Arcus.Demo.AzureFunctions.Databricks.JobMetrics -``` - -## Features - -Creates a starter worker project with by default configured: - -* Azure Function timer that for each cycle the finished Databricks job runs reports as metrics ([official docs](https://background-jobs.arcus-azure.net/features/databricks/gain-insights)) -* Dockerfile - -### Configuration - -And additional features available with options: -* `-es|--exclude-serilog`: Exclude the [Serilog](https://serilog.net/) logging infrastructure in the Azure Functions project which includes default enrichers ([version](https://observability.arcus-azure.net/features/telemetry-enrichment#version-enricher) and [application](https://observability.arcus-azure.net/features/telemetry-enrichment#application-enricher)), and sinking to Application Insights. \ No newline at end of file diff --git a/docs/preview/features/azurefunctions-eventhubs-template.md b/docs/preview/features/azurefunctions-eventhubs-template.md index 28d172f7..957821cf 100644 --- a/docs/preview/features/azurefunctions-eventhubs-template.md +++ b/docs/preview/features/azurefunctions-eventhubs-template.md @@ -30,8 +30,4 @@ Creates a starter worker project with by default configured: ### Configuration And additional features available with options: -* `--functions-worker`: Configures the type of Azure Functions worker type the project should target. - * `isolated` (default): Uses the isolated Azure Functions worker type which runs on a different process as the Azure Function - * `inProcess`: Uses the in-process Azure Functions worker type which runs on the same process as run Azure Function - For more information on the difference between the two, see [Microsoft's documentation](https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide). * `-es|--exclude-serilog`: Exclude the [Serilog](https://serilog.net/) logging infrastructure in the worker project which includes default enrichers ([version](https://observability.arcus-azure.net/features/telemetry-enrichment#version-enricher) and [application](https://observability.arcus-azure.net/features/telemetry-enrichment#application-enricher)), and sinking to Application Insights. diff --git a/docs/preview/features/azurefunctions-http-template.md b/docs/preview/features/azurefunctions-http-template.md index cece4545..2c6a2040 100644 --- a/docs/preview/features/azurefunctions-http-template.md +++ b/docs/preview/features/azurefunctions-http-template.md @@ -37,10 +37,6 @@ Creates a starter worker project with by default configured: And additional features available with options: -* `--functions-worker`: Configures the type of Azure Functions worker type the project should target. - * `isolated` (default): Uses the isolated Azure Functions worker type which runs on a different process as the Azure Function - * `inProcess`: Uses the in-process Azure Functions worker type which runs on the same process as run Azure Function - For more information on the difference between the two, see [Microsoft's documentation](https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide). * `--include-healthchecks` (default `false`): include a default Health Azure Function and health check services from the project * `--exclude-openapi` (default `false`): exclude the [Azure Functions OpenAPI docs generation and UI](https://github.com/Azure/azure-functions-openapi-extension) from the project. * `--exclude-serilog` (default `false`): exclude the [Serilog](https://serilog.net/) logging infrastructure in the Azure Functions project which includes default enrichers ([version](https://observability.arcus-azure.net/features/telemetry-enrichment#version-enricher) and [application](https://observability.arcus-azure.net/features/telemetry-enrichment#application-enricher)), and sinking to Application Insights. diff --git a/docs/preview/features/azurefunctions-servicebus-queue-template.md b/docs/preview/features/azurefunctions-servicebus-queue-template.md index a34086e6..d96eb7d8 100644 --- a/docs/preview/features/azurefunctions-servicebus-queue-template.md +++ b/docs/preview/features/azurefunctions-servicebus-queue-template.md @@ -30,8 +30,4 @@ Creates a starter worker project with by default configured: ### Configuration And additional features available with options: -* `--functions-worker`: Configures the type of Azure Functions worker type the project should target. - * `isolated` (default): Uses the isolated Azure Functions worker type which runs on a different process as the Azure Function - * `inProcess`: Uses the in-process Azure Functions worker type which runs on the same process as run Azure Function - For more information on the difference between the two, see [Microsoft's documentation](https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide). * `--exclude-serilog`: Exclude the [Serilog](https://serilog.net/) logging infrastructure in the Azure Functions project which includes default enrichers ([version](https://observability.arcus-azure.net/features/telemetry-enrichment#version-enricher) and [application](https://observability.arcus-azure.net/features/telemetry-enrichment#application-enricher)), and sinking to Application Insights. \ No newline at end of file diff --git a/docs/preview/features/azurefunctions-servicebus-topic-template.md b/docs/preview/features/azurefunctions-servicebus-topic-template.md index cee931d2..1ec814cf 100644 --- a/docs/preview/features/azurefunctions-servicebus-topic-template.md +++ b/docs/preview/features/azurefunctions-servicebus-topic-template.md @@ -30,8 +30,4 @@ Creates a starter worker project with by default configured: ### Configuration And additional features available with options: -* `--functions-worker`: Configures the type of Azure Functions worker type the project should target. - * `isolated` (default): Uses the isolated Azure Functions worker type which runs on a different process as the Azure Function - * `inProcess`: Uses the in-process Azure Functions worker type which runs on the same process as run Azure Function - For more information on the difference between the two, see [Microsoft's documentation](https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide). * `--exclude-serilog`: Exclude the [Serilog](https://serilog.net/) logging infrastructure in the Azure Functions project which includes default enrichers ([version](https://observability.arcus-azure.net/features/telemetry-enrichment#version-enricher) and [application](https://observability.arcus-azure.net/features/telemetry-enrichment#application-enricher)), and sinking to Application Insights. \ No newline at end of file From fdc614361221aa88a31e2c240bb5e805fb21b4c2 Mon Sep 17 00:00:00 2001 From: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com> Date: Thu, 2 May 2024 06:53:41 +0200 Subject: [PATCH 07/10] pr-chore: remove in-process docker integration tests --- build/templates/docker-integration-tests.yml | 90 -------------------- 1 file changed, 90 deletions(-) diff --git a/build/templates/docker-integration-tests.yml b/build/templates/docker-integration-tests.yml index af15b0d6..529b8f84 100644 --- a/build/templates/docker-integration-tests.yml +++ b/build/templates/docker-integration-tests.yml @@ -86,36 +86,10 @@ stages: ARCUS_STORAGEACCOUNT_CONNECTIONSTRING=$(Arcus.EventHubs.BlobStorage.StorageAccountConnectionString) ARCUS_SERVICEBUS_CONNECTIONSTRING=$(Arcus.Worker.ServiceBus.Queue.ConnectionString) APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=$(Arcus.ApplicationInsights.InstrumentationKey) - - template: 'run-new-project-from-template.yml' - parameters: - projectName: 'Arcus.Demo.AzureFunctions.Databricks.JobMetrics' - projectAlias: 'arcus-az-databricks-jobmetrics' - ports: '$(Arcus.AzureFunctions.Databricks.HttpPort):80' - script: | - Get-Content './Arcus.Demo.AzureFunctions.Databricks.JobMetrics/Startup.cs' -Raw | - % { $_ -replace '#error', '#warning' -replace '#if DEBUG', '#if RELEASE' } | - Set-Content './Arcus.Demo.AzureFunctions.Databricks.JobMetrics/Startup.cs' - envVars: | - Arcus__Databricks__Url=$(Arcus.Databricks.Url) - Arcus__ApplicationInsights__MetricName=$(Arcus.ApplicationInsights.MetricName) - APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=$(Arcus.ApplicationInsights.InstrumentationKey) - - template: 'run-new-project-from-template.yml' - parameters: - projectName: 'Arcus.Demo.AzureFunctions.InProcess.Http' - projectAlias: 'arcus-az-func-http' - projectOptions: '--functions-worker inProcess' - ports: '$(Arcus.AzureFunctions.Http.InProcess.HttpPort):80' - script: | - Get-Content './Arcus.Demo.AzureFunctions.InProcess.Http/Startup.cs' -Raw | - % { $_ -replace '#error', '#warning' -replace '#if DEBUG', '#if RELEASE' } | - Set-Content './Arcus.Demo.AzureFunctions.InProcess.Http/Startup.cs' - envVars: | - APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=$(Arcus.ApplicationInsights.InstrumentationKey) - template: 'run-new-project-from-template.yml' parameters: projectName: 'Arcus.Demo.AzureFunctions.Isolated.Http' projectAlias: 'arcus-az-func-http' - projectOptions: '--functions-worker isolated' ports: '$(Arcus.AzureFunctions.Http.Isolated.HttpPort):80' script: | Get-Content './Arcus.Demo.AzureFunctions.Isolated.Http/Program.cs' -Raw | @@ -123,24 +97,10 @@ stages: Set-Content './Arcus.Demo.AzureFunctions.Isolated.Http/Program.cs' envVars: | APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=$(Arcus.ApplicationInsights.InstrumentationKey) - - template: 'run-new-project-from-template.yml' - parameters: - projectName: 'Arcus.Demo.AzureFunctions.ServiceBus.Queue.InProcess' - projectAlias: 'arcus-az-func-servicebus-queue' - projectOptions: '--functions-worker inProcess' - ports: '$(Arcus.AzureFunctions.ServiceBus.Queue.InProcess.Port):$(Arcus.AzureFunctions.ServiceBus.Queue.InProcess.Port)' - script: | - Get-Content './Arcus.Demo.AzureFunctions.ServiceBus.Queue.InProcess/Startup.cs' -Raw | - % { $_ -replace '#error', '#warning' -replace '#if DEBUG', '#if RELEASE' } | - Set-Content './Arcus.Demo.AzureFunctions.ServiceBus.Queue.InProcess/Startup.cs' - envVars: | - ServiceBusConnectionString=$(Arcus.Worker.ServiceBus.Queue.ConnectionString) - APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=$(Arcus.ApplicationInsights.InstrumentationKey) - template: 'run-new-project-from-template.yml' parameters: projectName: 'Arcus.Demo.AzureFunctions.ServiceBus.Queue.Isolated' projectAlias: 'arcus-az-func-servicebus-queue' - projectOptions: '--functions-worker isolated' ports: '$(Arcus.AzureFunctions.ServiceBus.Queue.Isolated.Port):$(Arcus.AzureFunctions.ServiceBus.Queue.Isolated.Port)' script: | Get-Content './Arcus.Demo.AzureFunctions.ServiceBus.Queue.Isolated/Program.cs' -Raw | @@ -149,24 +109,10 @@ stages: envVars: | ServiceBusConnectionString=$(Arcus.Worker.ServiceBus.Queue.ConnectionString) APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=$(Arcus.ApplicationInsights.InstrumentationKey) - - template: 'run-new-project-from-template.yml' - parameters: - projectName: 'Arcus.Demo.AzureFunctions.ServiceBus.Topic.InProcess' - projectAlias: 'arcus-az-func-servicebus-topic' - projectOptions: '--functions-worker inProcess' - ports: '$(Arcus.AzureFunctions.ServiceBus.Topic.InProcess.Port):$(Arcus.AzureFunctions.ServiceBus.Topic.InProcess.Port)' - script: | - Get-Content './Arcus.Demo.AzureFunctions.ServiceBus.Topic.InProcess/Startup.cs' -Raw | - % { $_ -replace '#error', '#warning' -replace '#if DEBUG', '#if RELEASE' } | - Set-Content './Arcus.Demo.AzureFunctions.ServiceBus.Topic.InProcess/Startup.cs' - envVars: | - ServiceBusConnectionString=$(Arcus.Worker.ServiceBus.Topic.ConnectionString) - APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=$(Arcus.ApplicationInsights.InstrumentationKey) - template: 'run-new-project-from-template.yml' parameters: projectName: 'Arcus.Demo.AzureFunctions.ServiceBus.Topic.Isolated' projectAlias: 'arcus-az-func-servicebus-topic' - projectOptions: '--functions-worker isolated' ports: '$(Arcus.AzureFunctions.ServiceBus.Topic.Isolated.Port):$(Arcus.AzureFunctions.ServiceBus.Topic.Isolated.Port)' script: | Get-Content './Arcus.Demo.AzureFunctions.ServiceBus.Topic.Isolated/Program.cs' -Raw | @@ -175,28 +121,10 @@ stages: envVars: | ServiceBusConnectionString=$(Arcus.Worker.ServiceBus.Topic.ConnectionString) APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=$(Arcus.ApplicationInsights.InstrumentationKey) - - template: 'run-new-project-from-template.yml' - parameters: - projectName: 'Arcus.Demo.AzureFunctions.EventHubs.InProcess' - projectAlias: 'arcus-az-func-eventhubs' - projectOptions: '--functions-worker inProcess' - ports: '$(Arcus.AzureFunctions.EventHubs.InProcess.Port):$(Arcus.AzureFunctions.EventHubs.InProcess.Port)' - script: | - Get-Content './Arcus.Demo.AzureFunctions.EventHubs.InProcess/Startup.cs' -Raw | - % { $_ -replace '#error', '#warning' -replace '#if DEBUG', '#if RELEASE' } | - Set-Content './Arcus.Demo.AzureFunctions.EventHubs.InProcess/Startup.cs' - Get-Content './Arcus.Demo.AzureFunctions.EventHubs.InProcess/SensorReadingFunction.cs' -Raw | - % { $_ -replace 'sensors', '$(Arcus.EventHubs.Docker.EventHubsName)' } | - Set-Content './Arcus.Demo.AzureFunctions.EventHubs.InProcess/SensorReadingFunction.cs' - envVars: | - EventHubsConnectionString=$(Arcus.EventHubs.ConnectionString) - AzureWebJobsStorage=$(Arcus.EventHubs.BlobStorage.StorageAccountConnectionString) - APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=$(Arcus.ApplicationInsights.InstrumentationKey) - template: 'run-new-project-from-template.yml' parameters: projectName: 'Arcus.Demo.AzureFunctions.EventHubs.Isolated' projectAlias: 'arcus-az-func-eventhubs' - projectOptions: '--functions-worker isolated' ports: '$(Arcus.AzureFunctions.EventHubs.Isolated.Port):$(Arcus.AzureFunctions.EventHubs.Isolated.Port)' script: | Get-Content './Arcus.Demo.AzureFunctions.EventHubs.Isolated/Program.cs' -Raw | @@ -238,36 +166,18 @@ stages: targetType: 'inline' script: 'docker logs Arcus.Demo.EventHubs' condition: failed() - - task: PowerShell@2 - displayName: 'Get Docker container logs for Arcus.Demo.AzureFunctions.EventHubs.InProcess' - inputs: - targetType: 'inline' - script: 'docker logs Arcus.Demo.AzureFunctions.EventHubs.InProcess' - condition: failed() - task: PowerShell@2 displayName: 'Get Docker container logs for Arcus.Demo.AzureFunctions.EventHubs.Isolated' inputs: targetType: 'inline' script: 'docker logs Arcus.Demo.AzureFunctions.EventHubs.Isolated' condition: failed() - - task: PowerShell@2 - displayName: 'Get Docker container logs for Arcus.Demo.AzureFunctions.ServiceBus.Topic.InProcess' - inputs: - targetType: 'inline' - script: 'docker logs Arcus.Demo.AzureFunctions.ServiceBus.Topic.InProcess' - condition: failed() - task: PowerShell@2 displayName: 'Get Docker container logs for Arcus.Demo.AzureFunctions.ServiceBus.Topic.Isolated' inputs: targetType: 'inline' script: 'docker logs Arcus.Demo.AzureFunctions.ServiceBus.Topic.Isolated' condition: failed() - - task: PowerShell@2 - displayName: 'Get Docker container logs for Arcus.Demo.AzureFunctions.InProcess.Http' - inputs: - targetType: 'inline' - script: 'docker logs Arcus.Demo.AzureFunctions.InProcess.Http' - condition: failed() - task: PowerShell@2 displayName: 'Get Docker container logs for Arcus.Demo.AzureFunctions.Isolated.Http' inputs: From 13581b73a2c13265bb46dbda1986594e854705f8 Mon Sep 17 00:00:00 2001 From: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com> Date: Thu, 2 May 2024 08:14:17 +0200 Subject: [PATCH 08/10] pr-fix: correct w/ last references to in-process + new func tool support --- .../Arcus.Templates.AzureFunctions.EventHubs.csproj | 6 +++--- .../EventHubs/Logging/SerilogLoggingTests.cs | 1 - .../Http/Configuration/AzureFunctionHttpConfig.cs | 13 +++---------- .../Http/Health/HttpHealthDockerTests.cs | 8 +++----- 4 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/Arcus.Templates.AzureFunctions.EventHubs/Arcus.Templates.AzureFunctions.EventHubs.csproj b/src/Arcus.Templates.AzureFunctions.EventHubs/Arcus.Templates.AzureFunctions.EventHubs.csproj index f7e71244..3f2a4619 100644 --- a/src/Arcus.Templates.AzureFunctions.EventHubs/Arcus.Templates.AzureFunctions.EventHubs.csproj +++ b/src/Arcus.Templates.AzureFunctions.EventHubs/Arcus.Templates.AzureFunctions.EventHubs.csproj @@ -57,9 +57,9 @@ - - - + + + diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/Logging/SerilogLoggingTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/Logging/SerilogLoggingTests.cs index 4a62f6c7..6eb143f8 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/Logging/SerilogLoggingTests.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/EventHubs/Logging/SerilogLoggingTests.cs @@ -30,7 +30,6 @@ public async Task EventHubsProject_WithoutSerilog_CorrectlyProcessesMessage() // Act await using (var project = await AzureFunctionsEventHubsProject.StartNewAsync(config, options, _outputWriter)) { - project.TearDownOptions = TearDownOptions.KeepProjectDirectory; // Assert await project.Messaging.SimulateMessageProcessingAsync(); Assert.DoesNotContain("Serilog", project.GetFileContentsOfProjectFile()); diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Configuration/AzureFunctionHttpConfig.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Configuration/AzureFunctionHttpConfig.cs index 2dfcb462..53549626 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Configuration/AzureFunctionHttpConfig.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Configuration/AzureFunctionHttpConfig.cs @@ -11,7 +11,7 @@ public class AzureFunctionHttpConfig private readonly int _isolatedHttpPort, _inProcessHttpPort; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The HTTP port where the isolated Azure Functions project will be running. /// The HTTP port where the in-process Azure Functions project will be running. @@ -28,16 +28,9 @@ public AzureFunctionHttpConfig(int isolatedHttpPort, int inProcessHttpPort) /// /// Gets the HTTP port associated with the running Azure Functions Docker project. /// - /// The functions worker type of the running Azure Functions Docker project. - public int GetHttpPort(FunctionsWorker workerType) + public int GetHttpPort() { - switch (workerType) - { - case FunctionsWorker.InProcess: return _inProcessHttpPort; - case FunctionsWorker.Isolated: return _isolatedHttpPort; - default: - throw new ArgumentOutOfRangeException(nameof(workerType), workerType, "Unknown Azure Functions worker type"); - } + return _isolatedHttpPort; } } } diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Health/HttpHealthDockerTests.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Health/HttpHealthDockerTests.cs index 7a365826..5cfd2d57 100644 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Health/HttpHealthDockerTests.cs +++ b/src/Arcus.Templates.Tests.Integration/AzureFunctions/Http/Health/HttpHealthDockerTests.cs @@ -21,15 +21,13 @@ public HttpHealthDockerTests(ITestOutputHelper outputWriter) _outputWriter = outputWriter; } - [Theory] - [InlineData(FunctionsWorker.InProcess)] - [InlineData(FunctionsWorker.Isolated)] - public async Task AzureFunctionsHttpProject_WithoutOptions_ShouldAnswerToAdministratorEndpoint(FunctionsWorker workerType) + [Fact] + public async Task AzureFunctionsHttpProject_WithoutOptions_ShouldAnswerToAdministratorEndpoint() { // Arrange var configuration = TestConfig.Create(); AzureFunctionHttpConfig httpConfig = configuration.GetAzureFunctionHttpConfig(); - int httpPort = httpConfig.GetHttpPort(workerType); + int httpPort = httpConfig.GetHttpPort(); var service = new AdminEndpointService(httpPort, AzureFunctionsHttpProject.OrderFunctionName, _outputWriter); // Act / Assert From 75cdcc2c0fb51405aa9557fc6dfa73af74ef7df8 Mon Sep 17 00:00:00 2001 From: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com> Date: Thu, 2 May 2024 09:20:59 +0200 Subject: [PATCH 09/10] pr-fix: use older func version for now --- build/ci-build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/ci-build.yml b/build/ci-build.yml index b4219434..62cc182e 100644 --- a/build/ci-build.yml +++ b/build/ci-build.yml @@ -89,6 +89,8 @@ stages: steps: - task: FuncToolsInstaller@0 displayName: 'Install Azure Functions Core tools' + inputs: + version: '4.0.5390' - template: test/run-integration-tests.yml@templates parameters: dotnetSdkVersion: '$(DotNet.Sdk.Version)' From 762788e8dced5bcebfbb0655190e4e5def64169d Mon Sep 17 00:00:00 2001 From: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com> Date: Thu, 2 May 2024 09:21:20 +0200 Subject: [PATCH 10/10] pr-remove: unused FunctionsWorker enum --- .../AzureFunctions/FunctionsWorker.cs | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 src/Arcus.Templates.Tests.Integration/AzureFunctions/FunctionsWorker.cs diff --git a/src/Arcus.Templates.Tests.Integration/AzureFunctions/FunctionsWorker.cs b/src/Arcus.Templates.Tests.Integration/AzureFunctions/FunctionsWorker.cs deleted file mode 100644 index 69669e4f..00000000 --- a/src/Arcus.Templates.Tests.Integration/AzureFunctions/FunctionsWorker.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Arcus.Templates.Tests.Integration.AzureFunctions -{ - public enum FunctionsWorker - { - InProcess, - Isolated - } -}