Engineering
Dotnet Aspire - Erste Konfiguration für ein Bestandsprojekt
Ausgangslage
Das erste Produkt, in dem wir Aspire testen möchten, ist ein Produkt, das wir seit einiger Zeit immer wieder weiterentwickeln. Die Codebasis entstand mit .NET 5. Damit können wir auch testen, ob sich Aspire einfach in ältere Codebasen einbetten lässt.
Das Projekt basiert auf einer ASP.NET Core Webapplikation (Razor Pages), die auch ein paar wenige Typescript basierte Webkomponenten hat. Daten werden in einer Postgres-Datenbank gespeichert. E-Mails werden über ein SMTP-Service übermittelt und ein Open Telemetry Agent filtert unwichtige Telemetry aus, bevor sie an unseren zentrales Telemetry Store weitergeleitet werden.
Bisher haben wir zur Verwaltung ein kleines Tool namens batect verwendet, das Abhängigkeiten in Form von Containern aus einer Container-Registry aktualisiert, in ein gemeinsames Netzwerk eingehängt und abhängig von Tasks gestartet hat. Es hatte gute Dienste geleistet, aber leider wurde die Entwicklung eingestellt.
Dotnet Aspire Projekt
Ein Aspire Projekt ist ein Dotnet-Projekt, welches einen DistributedApplicationBuilder
verwendet, um die Konfiguration
zu erstellen.
Als ersten Schritt kann dazu einfach eine C#-Console Application als Projekt in die Solution eingefügt werden. In einer
neuen Solution legt das Template von Microsoft das Projekt als <SolutionName>.AppHost
an. Diese Konvention habe ich
daher übernommen.
Das neue Projekt muss das Package Aspire.Hosting.AppHost
und deine Webapplikationen referenzieren.
<ItemGroup>
<PackageReference Include="Aspire.Hosting.AppHost" Version="8.0.2"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Web\Web.csproj"/>
</ItemGroup>
Die Referenz auf das Webprojekt erzeugt über einen Source Generator in Aspire eine Klasse, die dem Namen des referenzierten Projektes entspricht.
Die erste Konfiguration kann dann für ein referenziertes Projekt Web
so aussehen:
using Microsoft.Extensions.Configuration;
using Projects;
var builder = DistributedApplication.CreateBuilder(args);
builder.AddProject<Web>("Web");
builder.Build().Run();
Füge noch eine launchsettings.json
in das Projekt hinzu.
Wenn das AppHost
-Projekt gestartet wird, bekommst du Folgendes:
- Aspire-Dashboard, welches alle deine gestarteten Services anzeigt
- Für Web-Projekte, die in ihrem
launchsettings.json
richtig konfiguriert sind, ein Link zur laufenden Webapplikation - Logs der gestarteten Ressourcen
- Traces (wenn Open Telemetry in eurem Projekt konfiguriert ist)
Fehlen noch unsere beiden Abhängigkeiten, die Postgres Datenbank und Mailhog, unser Test SMTP Server.
using Microsoft.Extensions.Configuration;
using Projects;
var builder = DistributedApplication.CreateBuilder(args);
var smtp = builder.AddContainer("smtp", "mailhog/mailhog", "latest")
.WithEndpoint(name: "smtp-endpoint", port: 1025, targetPort: 1025) // Port unter dem der SMTP Server zu erreichen ist
.WithHttpEndpoint(8025, 8025); // Port für das Mailhog Web Interface
var databaseInstance = builder.AddPostgres("database")
.WithOtlpExporter()
.WithEnvironment("POSTGRES_DB", "Web"); // Erzeugt die Datenbank mit dem Namen Web beim Startup des Containers
var database = databaseInstance.AddDatabase("DB", "Web"); // Fügt die Datenbank mit dem Namen Web in die Aspire Konfiguration ein
builder.AddProject<Web>("Web")
.WithReference(database)
.WithReference(smtp.GetEndpoint("smtp-endpoint"));
builder.Build().Run();
Im Beispiel ist zu sehen, dass Endpunkte als Referenz an das Webprojekt übergeben werden. Das ist Teil der Service-Discovery von Aspire, die wir uns im nächsten Teil ansehen werden.