tools/code/publisher/GatewayApi.cs (200 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 PutGatewayApis(CancellationToken cancellationToken); public delegate Option<(ApiName Name, GatewayName GatewayName)> TryParseGatewayApiName(FileInfo file); public delegate bool IsGatewayApiNameInSourceControl(ApiName name, GatewayName gatewayName); public delegate ValueTask PutGatewayApi(ApiName name, GatewayName gatewayName, CancellationToken cancellationToken); public delegate ValueTask<Option<GatewayApiDto>> FindGatewayApiDto(ApiName name, GatewayName gatewayName, CancellationToken cancellationToken); public delegate ValueTask PutGatewayApiInApim(ApiName name, GatewayApiDto dto, GatewayName gatewayName, CancellationToken cancellationToken); public delegate ValueTask DeleteGatewayApis(CancellationToken cancellationToken); public delegate ValueTask DeleteGatewayApi(ApiName name, GatewayName gatewayName, CancellationToken cancellationToken); public delegate ValueTask DeleteGatewayApiFromApim(ApiName name, GatewayName gatewayName, CancellationToken cancellationToken); internal static class GatewayApiModule { public static void ConfigurePutGatewayApis(IHostApplicationBuilder builder) { CommonModule.ConfigureGetPublisherFiles(builder); ConfigureTryGatewayParseApiName(builder); ConfigureIsGatewayApiNameInSourceControl(builder); ConfigurePutGatewayApi(builder); builder.Services.TryAddSingleton(GetPutGatewayApis); } private static PutGatewayApis GetPutGatewayApis(IServiceProvider provider) { var getPublisherFiles = provider.GetRequiredService<GetPublisherFiles>(); var tryParseName = provider.GetRequiredService<TryParseGatewayApiName>(); var isNameInSourceControl = provider.GetRequiredService<IsGatewayApiNameInSourceControl>(); var put = provider.GetRequiredService<PutGatewayApi>(); var activitySource = provider.GetRequiredService<ActivitySource>(); var logger = provider.GetRequiredService<ILogger>(); return async cancellationToken => { using var _ = activitySource.StartActivity(nameof(PutGatewayApis)); logger.LogInformation("Putting gateway apis..."); await getPublisherFiles() .Choose(tryParseName.Invoke) .Where(api => isNameInSourceControl(api.Name, api.GatewayName)) .Distinct() .IterParallel(put.Invoke, cancellationToken); }; } private static void ConfigureTryGatewayParseApiName(IHostApplicationBuilder builder) { AzureModule.ConfigureManagementServiceDirectory(builder); builder.Services.TryAddSingleton(GetTryParseGatewayApiName); } private static TryParseGatewayApiName GetTryParseGatewayApiName(IServiceProvider provider) { var serviceDirectory = provider.GetRequiredService<ManagementServiceDirectory>(); return file => from informationFile in GatewayApiInformationFile.TryParse(file, serviceDirectory) select (informationFile.Parent.Name, informationFile.Parent.Parent.Parent.Name); } private static void ConfigureIsGatewayApiNameInSourceControl(IHostApplicationBuilder builder) { CommonModule.ConfigureGetArtifactFiles(builder); AzureModule.ConfigureManagementServiceDirectory(builder); builder.Services.TryAddSingleton(GetIsApiNameInSourceControl); } private static IsGatewayApiNameInSourceControl GetIsApiNameInSourceControl(IServiceProvider provider) { var getArtifactFiles = provider.GetRequiredService<GetArtifactFiles>(); var serviceDirectory = provider.GetRequiredService<ManagementServiceDirectory>(); return doesInformationFileExist; bool doesInformationFileExist(ApiName name, GatewayName gatewayName) { var artifactFiles = getArtifactFiles(); var apiFile = GatewayApiInformationFile.From(name, gatewayName, serviceDirectory); return artifactFiles.Contains(apiFile.ToFileInfo()); } } private static void ConfigurePutGatewayApi(IHostApplicationBuilder builder) { ConfigureFindGatewayApiDto(builder); ConfigurePutGatewayApiInApim(builder); builder.Services.TryAddSingleton(GetPutGatewayApi); } private static PutGatewayApi GetPutGatewayApi(IServiceProvider provider) { var findDto = provider.GetRequiredService<FindGatewayApiDto>(); var putInApim = provider.GetRequiredService<PutGatewayApiInApim>(); var activitySource = provider.GetRequiredService<ActivitySource>(); return async (name, gatewayName, cancellationToken) => { using var _ = activitySource.StartActivity(nameof(PutGatewayApi)) ?.AddTag("gateway_api.name", name) ?.AddTag("gateway.name", gatewayName); var dtoOption = await findDto(name, gatewayName, cancellationToken); await dtoOption.IterTask(async dto => await putInApim(name, dto, gatewayName, cancellationToken)); }; } private static void ConfigureFindGatewayApiDto(IHostApplicationBuilder builder) { AzureModule.ConfigureManagementServiceDirectory(builder); CommonModule.ConfigureTryGetFileContents(builder); builder.Services.TryAddSingleton(GetFindGatewayApiDto); } private static FindGatewayApiDto GetFindGatewayApiDto(IServiceProvider provider) { var serviceDirectory = provider.GetRequiredService<ManagementServiceDirectory>(); var tryGetFileContents = provider.GetRequiredService<TryGetFileContents>(); return async (name, gatewayName, cancellationToken) => { var informationFile = GatewayApiInformationFile.From(name, gatewayName, serviceDirectory); var contentsOption = await tryGetFileContents(informationFile.ToFileInfo(), cancellationToken); return from contents in contentsOption select contents.ToObjectFromJson<GatewayApiDto>(); }; } private static void ConfigurePutGatewayApiInApim(IHostApplicationBuilder builder) { AzureModule.ConfigureManagementServiceUri(builder); AzureModule.ConfigureHttpPipeline(builder); builder.Services.TryAddSingleton(GetPutGatewayApiInApim); } private static PutGatewayApiInApim GetPutGatewayApiInApim(IServiceProvider provider) { var serviceUri = provider.GetRequiredService<ManagementServiceUri>(); var pipeline = provider.GetRequiredService<HttpPipeline>(); var logger = provider.GetRequiredService<ILogger>(); return async (name, dto, gatewayName, cancellationToken) => { logger.LogInformation("Adding API {ApiName} to gateway {GatewayName}...", name, gatewayName); await GatewayApiUri.From(name, gatewayName, serviceUri) .PutDto(dto, pipeline, cancellationToken); }; } public static void ConfigureDeleteGatewayApis(IHostApplicationBuilder builder) { CommonModule.ConfigureGetPublisherFiles(builder); ConfigureTryGatewayParseApiName(builder); ConfigureIsGatewayApiNameInSourceControl(builder); ConfigureDeleteGatewayApi(builder); builder.Services.TryAddSingleton(GetDeleteGatewayApis); } private static DeleteGatewayApis GetDeleteGatewayApis(IServiceProvider provider) { var getPublisherFiles = provider.GetRequiredService<GetPublisherFiles>(); var tryParseName = provider.GetRequiredService<TryParseGatewayApiName>(); var isNameInSourceControl = provider.GetRequiredService<IsGatewayApiNameInSourceControl>(); var delete = provider.GetRequiredService<DeleteGatewayApi>(); var activitySource = provider.GetRequiredService<ActivitySource>(); var logger = provider.GetRequiredService<ILogger>(); return async cancellationToken => { using var _ = activitySource.StartActivity(nameof(DeleteGatewayApis)); logger.LogInformation("Deleting gateway apis..."); await getPublisherFiles() .Choose(tryParseName.Invoke) .Where(api => isNameInSourceControl(api.Name, api.GatewayName) is false) .Distinct() .IterParallel(delete.Invoke, cancellationToken); }; } private static void ConfigureDeleteGatewayApi(IHostApplicationBuilder builder) { ConfigureDeleteGatewayApiFromApim(builder); builder.Services.TryAddSingleton(GetDeleteGatewayApi); } private static DeleteGatewayApi GetDeleteGatewayApi(IServiceProvider provider) { var deleteFromApim = provider.GetRequiredService<DeleteGatewayApiFromApim>(); var activitySource = provider.GetRequiredService<ActivitySource>(); return async (name, gatewayName, cancellationToken) => { using var _ = activitySource.StartActivity(nameof(DeleteGatewayApi)) ?.AddTag("gateway_api.name", name) ?.AddTag("gateway.name", gatewayName); await deleteFromApim(name, gatewayName, cancellationToken); }; } private static void ConfigureDeleteGatewayApiFromApim(IHostApplicationBuilder builder) { AzureModule.ConfigureManagementServiceUri(builder); AzureModule.ConfigureHttpPipeline(builder); builder.Services.TryAddSingleton(GetDeleteGatewayApiFromApim); } private static DeleteGatewayApiFromApim GetDeleteGatewayApiFromApim(IServiceProvider provider) { var serviceUri = provider.GetRequiredService<ManagementServiceUri>(); var pipeline = provider.GetRequiredService<HttpPipeline>(); var logger = provider.GetRequiredService<ILogger>(); return async (name, gatewayName, cancellationToken) => { logger.LogInformation("Removing API {ApiName} from gateway {GatewayName}...", name, gatewayName); await GatewayApiUri.From(name, gatewayName, serviceUri) .Delete(pipeline, cancellationToken); }; } }