Files
OPC/ControlPlane.Worker/Program.cs
T
2026-04-26 16:12:00 -04:00

77 lines
2.7 KiB
C#

using ControlPlane.Core.Config;
using ControlPlane.Core.Interfaces;
using ControlPlane.Core.Services;
using ControlPlane.Worker;
using ControlPlane.Worker.Services;
using ControlPlane.Worker.Steps;
using Keycloak.AuthServices.Sdk;
using MassTransit;
using Npgsql;
var builder = Host.CreateApplicationBuilder(args);
builder.AddServiceDefaults();
// Centralized infrastructure options — domain, network, internal URLs, cert paths
builder.Services.Configure<ClarityInfraOptions>(
builder.Configuration.GetSection(ClarityInfraOptions.Section));
// Keycloak Admin SDK client
builder.Services.AddKeycloakAdminHttpClient(o =>
{
o.AuthServerUrl = builder.Configuration["Keycloak:AuthServerUrl"] ?? "http://localhost:8080";
o.Realm = builder.Configuration["Keycloak:Realm"] ?? "master";
o.Resource = builder.Configuration["Keycloak:Resource"] ?? "admin-cli";
});
// Custom admin client - handles realm creation, roles, role assignment (not in SDK)
builder.Services.AddSingleton<KeycloakAdminClient>();
// Named HttpClient for Gitea commit status API (self-signed cert)
builder.Services.AddHttpClient("gitea").ConfigurePrimaryHttpMessageHandler(() =>
new HttpClientHandler { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator });
// opcdb for build/release history tracking
var opcConnStr = builder.Configuration.GetConnectionString("opcdb");
builder.Services.AddSingleton(NpgsqlDataSource.Create(
!string.IsNullOrWhiteSpace(opcConnStr) ? opcConnStr : "Host=127.0.0.1;Port=5433;Database=opcdb;Username=postgres;Password=controlplane-dev"));
builder.Services.AddSingleton<BuildHistoryService>();
// Docker container manager for per-tenant Clarity.Server instances
builder.Services.AddSingleton<ClarityContainerService>();
// Tenant registry - persists provisioned tenant XML files to ClientAssets folder
builder.Services.AddSingleton<TenantRegistryService>();
// Saga steps in execution order — container launches LAST once all context is populated
builder.Services.AddSingleton<ISagaStep, KeycloakStep>();
builder.Services.AddSingleton<ISagaStep, VaultStep>();
builder.Services.AddSingleton<ISagaStep, MigrationStep>();
builder.Services.AddSingleton<ISagaStep, LaunchStep>();
builder.Services.AddSingleton<ISagaStep, HandoffStep>();
builder.Services.AddMassTransit(x =>
{
x.SetKebabCaseEndpointNameFormatter();
x.AddConsumer<ProvisioningConsumer>();
x.AddConsumer<BuildConsumer>();
x.UsingRabbitMq((ctx, cfg) =>
{
cfg.Host(builder.Configuration.GetConnectionString("rabbitmq"));
cfg.ConfigureEndpoints(ctx);
});
});
try
{
var host = builder.Build();
host.Run();
}
catch (Exception ex)
{
Console.Error.WriteLine($"FATAL WORKER CRASH: {ex}");
throw;
}