tools/code/publisher/ProductApi.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 PutProductApis(CancellationToken cancellationToken);
public delegate Option<(ApiName Name, ProductName ProductName)> TryParseProductApiName(FileInfo file);
public delegate bool IsProductApiNameInSourceControl(ApiName name, ProductName productName);
public delegate ValueTask PutProductApi(ApiName name, ProductName productName, CancellationToken cancellationToken);
public delegate ValueTask<Option<ProductApiDto>> FindProductApiDto(ApiName name, ProductName productName, CancellationToken cancellationToken);
public delegate ValueTask PutProductApiInApim(ApiName name, ProductApiDto dto, ProductName productName, CancellationToken cancellationToken);
public delegate ValueTask DeleteProductApis(CancellationToken cancellationToken);
public delegate ValueTask DeleteProductApi(ApiName name, ProductName productName, CancellationToken cancellationToken);
public delegate ValueTask DeleteProductApiFromApim(ApiName name, ProductName productName, CancellationToken cancellationToken);
internal static class ProductApiModule
{
public static void ConfigurePutProductApis(IHostApplicationBuilder builder)
{
CommonModule.ConfigureGetPublisherFiles(builder);
ConfigureTryProductParseApiName(builder);
ConfigureIsProductApiNameInSourceControl(builder);
ConfigurePutProductApi(builder);
builder.Services.TryAddSingleton(GetPutProductApis);
}
private static PutProductApis GetPutProductApis(IServiceProvider provider)
{
var getPublisherFiles = provider.GetRequiredService<GetPublisherFiles>();
var tryParseName = provider.GetRequiredService<TryParseProductApiName>();
var isNameInSourceControl = provider.GetRequiredService<IsProductApiNameInSourceControl>();
var put = provider.GetRequiredService<PutProductApi>();
var activitySource = provider.GetRequiredService<ActivitySource>();
var logger = provider.GetRequiredService<ILogger>();
return async cancellationToken =>
{
using var _ = activitySource.StartActivity(nameof(PutProductApis));
logger.LogInformation("Putting product apis...");
await getPublisherFiles()
.Choose(tryParseName.Invoke)
.Where(api => isNameInSourceControl(api.Name, api.ProductName))
.Distinct()
.IterParallel(put.Invoke, cancellationToken);
};
}
private static void ConfigureTryProductParseApiName(IHostApplicationBuilder builder)
{
AzureModule.ConfigureManagementServiceDirectory(builder);
builder.Services.TryAddSingleton(GetTryParseProductApiName);
}
private static TryParseProductApiName GetTryParseProductApiName(IServiceProvider provider)
{
var serviceDirectory = provider.GetRequiredService<ManagementServiceDirectory>();
return file => from informationFile in ProductApiInformationFile.TryParse(file, serviceDirectory)
select (informationFile.Parent.Name, informationFile.Parent.Parent.Parent.Name);
}
private static void ConfigureIsProductApiNameInSourceControl(IHostApplicationBuilder builder)
{
CommonModule.ConfigureGetArtifactFiles(builder);
AzureModule.ConfigureManagementServiceDirectory(builder);
builder.Services.TryAddSingleton(GetIsApiNameInSourceControl);
}
private static IsProductApiNameInSourceControl GetIsApiNameInSourceControl(IServiceProvider provider)
{
var getArtifactFiles = provider.GetRequiredService<GetArtifactFiles>();
var serviceDirectory = provider.GetRequiredService<ManagementServiceDirectory>();
return doesInformationFileExist;
bool doesInformationFileExist(ApiName name, ProductName productName)
{
var artifactFiles = getArtifactFiles();
var apiFile = ProductApiInformationFile.From(name, productName, serviceDirectory);
return artifactFiles.Contains(apiFile.ToFileInfo());
}
}
private static void ConfigurePutProductApi(IHostApplicationBuilder builder)
{
ConfigureFindProductApiDto(builder);
ConfigurePutProductApiInApim(builder);
builder.Services.TryAddSingleton(GetPutProductApi);
}
private static PutProductApi GetPutProductApi(IServiceProvider provider)
{
var findDto = provider.GetRequiredService<FindProductApiDto>();
var putInApim = provider.GetRequiredService<PutProductApiInApim>();
var activitySource = provider.GetRequiredService<ActivitySource>();
return async (name, productName, cancellationToken) =>
{
using var _ = activitySource.StartActivity(nameof(PutProductApi))
?.AddTag("product_api.name", name)
?.AddTag("product.name", productName);
var dtoOption = await findDto(name, productName, cancellationToken);
await dtoOption.IterTask(async dto => await putInApim(name, dto, productName, cancellationToken));
};
}
private static void ConfigureFindProductApiDto(IHostApplicationBuilder builder)
{
AzureModule.ConfigureManagementServiceDirectory(builder);
CommonModule.ConfigureTryGetFileContents(builder);
builder.Services.TryAddSingleton(GetFindProductApiDto);
}
private static FindProductApiDto GetFindProductApiDto(IServiceProvider provider)
{
var serviceDirectory = provider.GetRequiredService<ManagementServiceDirectory>();
var tryGetFileContents = provider.GetRequiredService<TryGetFileContents>();
return async (name, productName, cancellationToken) =>
{
var informationFile = ProductApiInformationFile.From(name, productName, serviceDirectory);
var contentsOption = await tryGetFileContents(informationFile.ToFileInfo(), cancellationToken);
return from contents in contentsOption
select contents.ToObjectFromJson<ProductApiDto>();
};
}
private static void ConfigurePutProductApiInApim(IHostApplicationBuilder builder)
{
AzureModule.ConfigureManagementServiceUri(builder);
AzureModule.ConfigureHttpPipeline(builder);
builder.Services.TryAddSingleton(GetPutProductApiInApim);
}
private static PutProductApiInApim GetPutProductApiInApim(IServiceProvider provider)
{
var serviceUri = provider.GetRequiredService<ManagementServiceUri>();
var pipeline = provider.GetRequiredService<HttpPipeline>();
var logger = provider.GetRequiredService<ILogger>();
return async (name, dto, productName, cancellationToken) =>
{
logger.LogInformation("Adding API {ApiName} to product {ProductName}...", name, productName);
await ProductApiUri.From(name, productName, serviceUri)
.PutDto(dto, pipeline, cancellationToken);
};
}
public static void ConfigureDeleteProductApis(IHostApplicationBuilder builder)
{
CommonModule.ConfigureGetPublisherFiles(builder);
ConfigureTryProductParseApiName(builder);
ConfigureIsProductApiNameInSourceControl(builder);
ConfigureDeleteProductApi(builder);
builder.Services.TryAddSingleton(GetDeleteProductApis);
}
private static DeleteProductApis GetDeleteProductApis(IServiceProvider provider)
{
var getPublisherFiles = provider.GetRequiredService<GetPublisherFiles>();
var tryParseName = provider.GetRequiredService<TryParseProductApiName>();
var isNameInSourceControl = provider.GetRequiredService<IsProductApiNameInSourceControl>();
var delete = provider.GetRequiredService<DeleteProductApi>();
var activitySource = provider.GetRequiredService<ActivitySource>();
var logger = provider.GetRequiredService<ILogger>();
return async cancellationToken =>
{
using var _ = activitySource.StartActivity(nameof(DeleteProductApis));
logger.LogInformation("Deleting product apis...");
await getPublisherFiles()
.Choose(tryParseName.Invoke)
.Where(api => isNameInSourceControl(api.Name, api.ProductName) is false)
.Distinct()
.IterParallel(delete.Invoke, cancellationToken);
};
}
private static void ConfigureDeleteProductApi(IHostApplicationBuilder builder)
{
ConfigureDeleteProductApiFromApim(builder);
builder.Services.TryAddSingleton(GetDeleteProductApi);
}
private static DeleteProductApi GetDeleteProductApi(IServiceProvider provider)
{
var deleteFromApim = provider.GetRequiredService<DeleteProductApiFromApim>();
var activitySource = provider.GetRequiredService<ActivitySource>();
return async (name, productName, cancellationToken) =>
{
using var _ = activitySource.StartActivity(nameof(DeleteProductApi))
?.AddTag("product_api.name", name)
?.AddTag("product.name", productName);
await deleteFromApim(name, productName, cancellationToken);
};
}
private static void ConfigureDeleteProductApiFromApim(IHostApplicationBuilder builder)
{
AzureModule.ConfigureManagementServiceUri(builder);
AzureModule.ConfigureHttpPipeline(builder);
builder.Services.TryAddSingleton(GetDeleteProductApiFromApim);
}
private static DeleteProductApiFromApim GetDeleteProductApiFromApim(IServiceProvider provider)
{
var serviceUri = provider.GetRequiredService<ManagementServiceUri>();
var pipeline = provider.GetRequiredService<HttpPipeline>();
var logger = provider.GetRequiredService<ILogger>();
return async (name, productName, cancellationToken) =>
{
logger.LogInformation("Removing API {ApiName} from product {ProductName}...", name, productName);
await ProductApiUri.From(name, productName, serviceUri)
.Delete(pipeline, cancellationToken);
};
}
}