tools/code/publisher/Backend.cs (202 lines of code) (raw):
using Azure.Core.Pipeline;
using common;
using LanguageExt;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace publisher;
public delegate ValueTask PutBackends(CancellationToken cancellationToken);
public delegate ValueTask DeleteBackends(CancellationToken cancellationToken);
public delegate Option<BackendName> TryParseBackendName(FileInfo file);
public delegate bool IsBackendNameInSourceControl(BackendName name);
public delegate ValueTask PutBackend(BackendName name, CancellationToken cancellationToken);
public delegate ValueTask<Option<BackendDto>> FindBackendDto(BackendName name, CancellationToken cancellationToken);
public delegate ValueTask PutBackendInApim(BackendName name, BackendDto dto, CancellationToken cancellationToken);
public delegate ValueTask DeleteBackend(BackendName name, CancellationToken cancellationToken);
public delegate ValueTask DeleteBackendFromApim(BackendName name, CancellationToken cancellationToken);
internal static class BackendModule
{
public static void ConfigurePutBackends(IHostApplicationBuilder builder)
{
CommonModule.ConfigureGetPublisherFiles(builder);
ConfigureTryParseBackendName(builder);
ConfigureIsBackendNameInSourceControl(builder);
ConfigurePutBackend(builder);
builder.Services.TryAddSingleton(GetPutBackends);
}
private static PutBackends GetPutBackends(IServiceProvider provider)
{
var getPublisherFiles = provider.GetRequiredService<GetPublisherFiles>();
var tryParseName = provider.GetRequiredService<TryParseBackendName>();
var isNameInSourceControl = provider.GetRequiredService<IsBackendNameInSourceControl>();
var put = provider.GetRequiredService<PutBackend>();
var activitySource = provider.GetRequiredService<ActivitySource>();
var logger = provider.GetRequiredService<ILogger>();
return async cancellationToken =>
{
using var _ = activitySource.StartActivity(nameof(PutBackends));
logger.LogInformation("Putting backends...");
await getPublisherFiles()
.Choose(tryParseName.Invoke)
.Where(isNameInSourceControl.Invoke)
.Distinct()
.IterParallel(put.Invoke, cancellationToken);
};
}
private static void ConfigureTryParseBackendName(IHostApplicationBuilder builder)
{
AzureModule.ConfigureManagementServiceDirectory(builder);
builder.Services.TryAddSingleton(GetTryParseBackendName);
}
private static TryParseBackendName GetTryParseBackendName(IServiceProvider provider)
{
var serviceDirectory = provider.GetRequiredService<ManagementServiceDirectory>();
return file => from informationFile in BackendInformationFile.TryParse(file, serviceDirectory)
select informationFile.Parent.Name;
}
private static void ConfigureIsBackendNameInSourceControl(IHostApplicationBuilder builder)
{
CommonModule.ConfigureGetArtifactFiles(builder);
AzureModule.ConfigureManagementServiceDirectory(builder);
builder.Services.TryAddSingleton(GetIsBackendNameInSourceControl);
}
private static IsBackendNameInSourceControl GetIsBackendNameInSourceControl(IServiceProvider provider)
{
var getArtifactFiles = provider.GetRequiredService<GetArtifactFiles>();
var serviceDirectory = provider.GetRequiredService<ManagementServiceDirectory>();
return doesInformationFileExist;
bool doesInformationFileExist(BackendName name)
{
var artifactFiles = getArtifactFiles();
var informationFile = BackendInformationFile.From(name, serviceDirectory);
return artifactFiles.Contains(informationFile.ToFileInfo());
}
}
private static void ConfigurePutBackend(IHostApplicationBuilder builder)
{
ConfigureFindBackendDto(builder);
ConfigurePutBackendInApim(builder);
builder.Services.TryAddSingleton(GetPutBackend);
}
private static PutBackend GetPutBackend(IServiceProvider provider)
{
var findDto = provider.GetRequiredService<FindBackendDto>();
var putInApim = provider.GetRequiredService<PutBackendInApim>();
var activitySource = provider.GetRequiredService<ActivitySource>();
return async (name, cancellationToken) =>
{
using var _ = activitySource.StartActivity(nameof(PutBackend))
?.AddTag("backend.name", name);
var dtoOption = await findDto(name, cancellationToken);
await dtoOption.IterTask(async dto => await putInApim(name, dto, cancellationToken));
};
}
private static void ConfigureFindBackendDto(IHostApplicationBuilder builder)
{
AzureModule.ConfigureManagementServiceDirectory(builder);
CommonModule.ConfigureTryGetFileContents(builder);
OverrideDtoModule.ConfigureOverrideDtoFactory(builder);
builder.Services.TryAddSingleton(GetFindBackendDto);
}
private static FindBackendDto GetFindBackendDto(IServiceProvider provider)
{
var serviceDirectory = provider.GetRequiredService<ManagementServiceDirectory>();
var tryGetFileContents = provider.GetRequiredService<TryGetFileContents>();
var overrideFactory = provider.GetRequiredService<OverrideDtoFactory>();
var overrideDto = overrideFactory.Create<BackendName, BackendDto>();
return async (name, cancellationToken) =>
{
var informationFile = BackendInformationFile.From(name, serviceDirectory);
var contentsOption = await tryGetFileContents(informationFile.ToFileInfo(), cancellationToken);
return from contents in contentsOption
let dto = contents.ToObjectFromJson<BackendDto>()
select overrideDto(name, dto);
};
}
private static void ConfigurePutBackendInApim(IHostApplicationBuilder builder)
{
AzureModule.ConfigureManagementServiceUri(builder);
AzureModule.ConfigureHttpPipeline(builder);
builder.Services.TryAddSingleton(GetPutBackendInApim);
}
private static PutBackendInApim GetPutBackendInApim(IServiceProvider provider)
{
var serviceUri = provider.GetRequiredService<ManagementServiceUri>();
var pipeline = provider.GetRequiredService<HttpPipeline>();
var logger = provider.GetRequiredService<ILogger>();
return async (name, dto, cancellationToken) =>
{
logger.LogInformation("Putting backend {BackendName}...", name);
var resourceUri = BackendUri.From(name, serviceUri);
await resourceUri.PutDto(dto, pipeline, cancellationToken);
};
}
public static void ConfigureDeleteBackends(IHostApplicationBuilder builder)
{
CommonModule.ConfigureGetPublisherFiles(builder);
ConfigureTryParseBackendName(builder);
ConfigureIsBackendNameInSourceControl(builder);
ConfigureDeleteBackend(builder);
builder.Services.TryAddSingleton(GetDeleteBackends);
}
private static DeleteBackends GetDeleteBackends(IServiceProvider provider)
{
var getPublisherFiles = provider.GetRequiredService<GetPublisherFiles>();
var tryParseName = provider.GetRequiredService<TryParseBackendName>();
var isNameInSourceControl = provider.GetRequiredService<IsBackendNameInSourceControl>();
var delete = provider.GetRequiredService<DeleteBackend>();
var activitySource = provider.GetRequiredService<ActivitySource>();
var logger = provider.GetRequiredService<ILogger>();
return async cancellationToken =>
{
using var _ = activitySource.StartActivity(nameof(DeleteBackends));
logger.LogInformation("Deleting backends...");
await getPublisherFiles()
.Choose(tryParseName.Invoke)
.Where(name => isNameInSourceControl(name) is false)
.Distinct()
.IterParallel(delete.Invoke, cancellationToken);
};
}
private static void ConfigureDeleteBackend(IHostApplicationBuilder builder)
{
ConfigureDeleteBackendFromApim(builder);
builder.Services.TryAddSingleton(GetDeleteBackend);
}
private static DeleteBackend GetDeleteBackend(IServiceProvider provider)
{
var deleteFromApim = provider.GetRequiredService<DeleteBackendFromApim>();
var activitySource = provider.GetRequiredService<ActivitySource>();
return async (name, cancellationToken) =>
{
using var _ = activitySource.StartActivity(nameof(DeleteBackend))
?.AddTag("backend.name", name);
await deleteFromApim(name, cancellationToken);
};
}
private static void ConfigureDeleteBackendFromApim(IHostApplicationBuilder builder)
{
AzureModule.ConfigureManagementServiceUri(builder);
AzureModule.ConfigureHttpPipeline(builder);
builder.Services.TryAddSingleton(GetDeleteBackendFromApim);
}
private static DeleteBackendFromApim GetDeleteBackendFromApim(IServiceProvider provider)
{
var serviceUri = provider.GetRequiredService<ManagementServiceUri>();
var pipeline = provider.GetRequiredService<HttpPipeline>();
var logger = provider.GetRequiredService<ILogger>();
return async (name, cancellationToken) =>
{
logger.LogInformation("Deleting backend {BackendName}...", name);
var resourceUri = BackendUri.From(name, serviceUri);
await resourceUri.Delete(pipeline, cancellationToken);
};
}
}