Skip to content

Commit

Permalink
feat: started implementing dashboard for cdns
Browse files Browse the repository at this point in the history
  • Loading branch information
bielu committed Jan 3, 2024
1 parent bde07f0 commit 71c7a50
Show file tree
Hide file tree
Showing 18 changed files with 216 additions and 69 deletions.
3 changes: 2 additions & 1 deletion src/bielu.Umbraco.Cdn.Abstraction/Models/Provider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ namespace bielu.Umbraco.Cdn.Models;

public class Provider
{
public bool Enabled { get; set; }
public string? Id { get; set; }
public string? Name { get; set; }
public IList<string>? SupportedHostnames { get; set; }
public int NodeId { get; set; }
public string Version { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using bielu.Umbraco.Cdn.Aws.Services;
using bielu.Umbraco.Cdn.Services;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.DependencyInjection;
Expand All @@ -19,7 +20,7 @@ public static IUmbracoBuilder AddAwsCloudFrontCdnProvider(
.AddClasses(c => c.AssignableTo(typeof(ICdnService)))
.AsImplementedInterfaces()
.WithTransientLifetime());

builder.Services.AddSingleton<IAmazonCloudFrontClientFactory, AmazonCloudFrontClientFactory>();

return builder;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<EmbedRazorGenerateSources>true</EmbedRazorGenerateSources>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AWSSDK.CloudFront" Version="3.7.301.18" />
<PackageReference Include="AWSSDK.CloudFront" Version="3.7.301.21" />
<PackageReference Include="bielu.SchemaGenerator.Core" Version="1.0.0-alpha.50" />
<PackageReference Include="Scrutor" Version="3.3.0"/>
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using bielu.Umbraco.Cdn.Azure.Configuration;
using bielu.Umbraco.Cdn.Azure.Services;
using bielu.Umbraco.Cdn.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.DependencyInjection;

namespace bielu.Umbraco.Cdn.Azure.Extensions
{
public static class BieluUmbracoCdnAzureFrontDoorExtensions
{
public static IUmbracoBuilder AddAzureFrontDoorCdnProvider(
this IUmbracoBuilder builder)
{
if (builder == null)
throw new ArgumentNullException(nameof(builder));
builder.Services.Scan(s =>
s.FromAssemblies(new List<Assembly>() { typeof(BieluUmbracoCdnAzureFrontDoorExtensions).Assembly })
.AddClasses(c => c.AssignableTo(typeof(ICdnService)))
.AsImplementedInterfaces()
.WithTransientLifetime());
builder.Services.AddSingleton(typeof(IFrontDoorClientFactory), typeof(FrontDoorClientFactory));
builder.Services.AddSingleton(typeof(IArmClientFactory), typeof(ArmClientFactory));
var positionOptions = new FrontDoorOptions();
builder.Config.GetSection(FrontDoorOptions.SectionName).Bind(positionOptions);
builder.Services.AddOptions<FrontDoorOptions>().BindConfiguration(FrontDoorOptions.SectionName);
return builder;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ public FrontDoorClientFactory(IArmClientFactory armClientFactory, IOptionsMonito

public FrontDoorResource GetFrontDoorClient()
{
if (_frontDoorOptions.CurrentValue.Disabled)
{
return null;
}
var armClient = _armClientFactory.GetFrontDoorClient();
string resourceGroupName =_frontDoorOptions.CurrentValue.ResourceGroupName;
SubscriptionResource subscription = armClient.GetSubscriptionResource(new ResourceIdentifier(_frontDoorOptions.CurrentValue.SubscriptionId));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<EmbedRazorGenerateSources>true</EmbedRazorGenerateSources>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.3.0"/>
<PackageReference Include="Azure.Identity" Version="1.10.4" />
<PackageReference Include="Azure.ResourceManager.FrontDoor" Version="1.2.0" />
<PackageReference Include="bielu.SchemaGenerator.Core" Version="1.0.0-alpha.50" />
<PackageReference Include="Scrutor" Version="3.3.0"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public async Task HandleAsync(ContentMovingNotification notification, Cancellati
}

//todo: optimize as now we dont valide which domains is valid for either of cdns
foreach (var cdnServices in _cdnServices)
foreach (var cdnServices in _cdnServices.Where(x=>x.IsEnabled()))
{
var result = Task.Run(async () => { return await cdnServices.PurgePages(pages); }).Result;
var errors = false;
Expand Down Expand Up @@ -109,7 +109,7 @@ public async Task HandleAsync(ContentDeletingNotification notification, Cancella
}

//todo: optimize as now we dont valide which domains is valid for either of cdns
foreach (var cdnServices in _cdnServices)
foreach (var cdnServices in _cdnServices.Where(x=>x.IsEnabled()))
{
try
{
Expand Down Expand Up @@ -220,7 +220,7 @@ public async Task HandleAsync(ContentPublishedNotification notification, Cancell
try
{
//todo: optimize as now we dont valide which domains is valid for either of cdns
foreach (var cdnServices in _cdnServices)
foreach (var cdnServices in _cdnServices.Where(x=>x.IsEnabled()))
{
var result = Task.Run(async () => { return await cdnServices.PurgePages(pages); }).Result;
EventMessage message;
Expand Down Expand Up @@ -330,7 +330,7 @@ public async Task HandleAsync(ContentSavedNotification notification, Cancellatio
}
}

foreach (var cdnServices in _cdnServices)
foreach (var cdnServices in _cdnServices.Where(x=>x.IsEnabled()))
{
var result = Task.Run(async () => { return await cdnServices.PurgePages(pages); }).Result;
EventMessage message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public DomainEventNotificationNotificationHandler(IUmbracoUrlDeliveryService umb
public async Task HandleAsync(DomainSavedNotification notification, CancellationToken cancellationToken)
{
//todo: optimize as now we dont valide which domains is valid for either of cdns
foreach (var cdnServices in _cdnServices)
foreach (var cdnServices in _cdnServices.Where(x=>x.IsEnabled()))
{
//todo: split on / as umbraco is dump to count / as part of domain
var result = Task.Run(async () =>
Expand All @@ -52,7 +52,7 @@ public async Task HandleAsync(DomainSavedNotification notification, Cancellation
public async Task HandleAsync(DomainDeletedNotification notification, CancellationToken cancellationToken)
{
//todo: optimize as now we dont valide which domains is valid for either of cdns
foreach (var cdnServices in _cdnServices)
foreach (var cdnServices in _cdnServices.Where(x=>x.IsEnabled()))
{
//todo: split on / as umbraco is dump to count / as part of domain
var result = Task.Run(async () =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public async Task HandleAsync(MediaSavedNotification notification, CancellationT

}
//todo: optimize as now we dont valide which domains is valid for either of cdns
foreach (var cdnServices in _cdnServices)
foreach (var cdnServices in _cdnServices.Where(x=>x.IsEnabled()))
{
var result = Task.Run(async () =>
{
Expand Down
52 changes: 32 additions & 20 deletions src/bielu.Umbraco.Cdn.Core/Services/CdnManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,48 @@ public class CdnManager : ICdnManager
{
private readonly IEnumerable<ICdnService> _services;
private readonly IUmbracoContextFactory _contextFactory;
private readonly IEnumerable<Provider> _providers;

public CdnManager(IEnumerable<ICdnService> services, IUmbracoContextFactory contextFactory)
private IEnumerable<Provider> _providers
{
_services = services;
_contextFactory = contextFactory;
using (var contextReference = _contextFactory.EnsureUmbracoContext())
get
{
var umbracoDomains = contextReference.UmbracoContext.Domains.GetAll(false);

_providers = umbracoDomains.SelectMany(domain =>
using (var contextReference = _contextFactory.EnsureUmbracoContext())
{
return services.Select(x => new Provider()
{
Name = x.GetType().Name,
Id = x.GetType().Name,
NodeId = domain.ContentId,
SupportedHostnames = Task.Run(async () =>
var umbracoDomains = contextReference.UmbracoContext.Domains.GetAll(false);


return _services.Select(x => new Provider()
{
var supportedHostNames = await x.GetSupportedHostnames();
return umbracoDomains.Where(domain => supportedHostNames.Contains(domain.Name))
.Select(domain => domain.Name).ToList();
}).Result
});
});
Name = x.GetType().Name,
Id = x.GetType().Name,
Version = x.GetType().Assembly.GetName().Version.ToString(),
Enabled = x.IsEnabled(),
SupportedHostnames = Task.Run(async () =>
{
if (!x.IsEnabled())
{
return null;
}
var supportedHostNames = await x.GetSupportedHostnames();
return umbracoDomains.Where(domain => supportedHostNames.Any(zone=>domain.Name.Contains(zone)))
.Select(domain => domain.Name).ToList();
}).Result
});
}
}
}

public CdnManager(IEnumerable<ICdnService> services, IUmbracoContextFactory contextFactory)
{
_services = services;
_contextFactory = contextFactory;

}


public async Task<IEnumerable<Provider>> GetProviders(int guid)
{

return _providers;
}

Expand Down
4 changes: 2 additions & 2 deletions src/bielu.Umbraco.TestProject/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ public void ConfigureServices(IServiceCollection services)
.AddComposers()
.AddCloudflareCdnProvider()
.AddAzureFrontDoorCdnProvider()
.AddAwsCloudFrontCdnProvider()
.AddAkamaiCdnProvider()
// .AddAwsCloudFrontCdnProvider()
//.AddAkamaiCdnProvider()
.Build();

services.AddTransient(typeof(IClouflareAuthentication), typeof(TokenApiClouflareAuthentication));
Expand Down
5 changes: 3 additions & 2 deletions src/bielu.Umbraco.TestProject/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
"umbracoDbDSN": "Data Source=|DataDirectory|/Umbraco.sqlite.db;Cache=Shared;Foreign Keys=True;Pooling=True",
"umbracoDbDSN_ProviderName": "Microsoft.Data.SQLite"
},
"bielu": {
"cdn": {
"Bielu": {
"Cdn": {
"DevMode": true,
"cloudflare": {
"enabled": true,
"token": "-- token - use secret.json --"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@
</ItemGroup>


<!-- <Target Name="NSwag" BeforeTargets="AfterBuild" Condition="'$(TF_BUILD)'!='True'">
<Target Name="NSwag" BeforeTargets="AfterBuild" Condition="'$(TF_BUILD)'!='True'">
<Exec ConsoleToMSBuild="true" ContinueOnError="true" Command="$(NSwagExe_Net60) run nswag.json /variables:Configuration=$(Configuration),TypescriptOutputPath=$(MSBuildThisFileDirectory)..\bielu.cdn.ui\src\services\umbraco\generated">
<Output TaskParameter="ExitCode" PropertyName="NSwagExitCode"/>
<Output TaskParameter="ConsoleOutput" PropertyName="NSwagOutput" />
</Exec>

<Message Text="$(NSwagOutput)" Condition="'$(NSwagExitCode)' == '0'" Importance="low"/>
<Error Text="$(NSwagOutput)" Condition="'$(NSwagExitCode)' != '0'"/>
</Target>-->
</Target>
<PropertyGroup>
<CopyRazorGenerateFilesToPublishDirectory>true</CopyRazorGenerateFilesToPublishDirectory>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/bielu.Umbraco.TestProject/nswag.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"msBuildProjectExtensionsPath": null,
"configuration": null,
"runtime": "",
"targetFramework": "net60",
"targetFramework": "net6.0",
"noBuild": true,
"verbose": true,
"workingDirectory": null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface IManagementClient {

getProviders(id?: number | undefined): Promise<Provider[] | null>;

refreshForNode(id: number, providerId?: string | null | undefined, domain?: string | null | undefined): Promise<Status | null>;
refreshForNode(id: number, providerId?: string | undefined, domain?: string | undefined): Promise<Status | null>;
}

export class ManagementClient implements IManagementClient {
Expand Down Expand Up @@ -117,15 +117,19 @@ export class ManagementClient implements IManagementClient {
return Promise.resolve<Provider[] | null>(null as any);
}

refreshForNode(id: number, providerId?: string | null | undefined, domain?: string | null | undefined): Promise<Status | null> {
refreshForNode(id: number, providerId?: string | undefined, domain?: string | undefined): Promise<Status | null> {
let url_ = this.baseUrl + "/cdn/api/management/RefreshForNode?";
if (id === undefined || id === null)
throw new Error("The parameter 'id' must be defined and cannot be null.");
else
url_ += "id=" + encodeURIComponent("" + id) + "&";
if (providerId !== undefined && providerId !== null)
if (providerId === null)
throw new Error("The parameter 'providerId' cannot be null.");
else if (providerId !== undefined)
url_ += "providerId=" + encodeURIComponent("" + providerId) + "&";
if (domain !== undefined && domain !== null)
if (domain === null)
throw new Error("The parameter 'domain' cannot be null.");
else if (domain !== undefined)
url_ += "domain=" + encodeURIComponent("" + domain) + "&";
url_ = url_.replace(/[?&]$/, "");

Expand Down Expand Up @@ -212,10 +216,11 @@ export interface IAuditRecord {
}

export class Provider implements IProvider {
enabled!: boolean;
id!: string | null;
name!: string | null;
supportedHostnames!: string[] | null;
nodeId!: number;
version!: string;

constructor(data?: IProvider) {
if (data) {
Expand All @@ -228,6 +233,7 @@ export class Provider implements IProvider {

init(_data?: any, _mappings?: any) {
if (_data) {
this.enabled = _data["enabled"] !== undefined ? _data["enabled"] : <any>null;
this.id = _data["id"] !== undefined ? _data["id"] : <any>null;
this.name = _data["name"] !== undefined ? _data["name"] : <any>null;
if (Array.isArray(_data["supportedHostnames"])) {
Expand All @@ -238,7 +244,7 @@ export class Provider implements IProvider {
else {
this.supportedHostnames = <any>null;
}
this.nodeId = _data["nodeId"] !== undefined ? _data["nodeId"] : <any>null;
this.version = _data["version"] !== undefined ? _data["version"] : <any>null;
}
}

Expand All @@ -249,30 +255,32 @@ export class Provider implements IProvider {

toJSON(data?: any) {
data = typeof data === 'object' ? data : {};
data["enabled"] = this.enabled !== undefined ? this.enabled : <any>null;
data["id"] = this.id !== undefined ? this.id : <any>null;
data["name"] = this.name !== undefined ? this.name : <any>null;
if (Array.isArray(this.supportedHostnames)) {
data["supportedHostnames"] = [];
for (let item of this.supportedHostnames)
data["supportedHostnames"].push(item);
}
data["nodeId"] = this.nodeId !== undefined ? this.nodeId : <any>null;
data["version"] = this.version !== undefined ? this.version : <any>null;
return data;
}
}

export interface IProvider {
enabled: boolean;
id: string | null;
name: string | null;
supportedHostnames: string[] | null;
nodeId: number;
version: string;
}

export class Status implements IStatus {
success!: boolean;
message!: string | null;
details!: string | null;
errors!: (Errors | null)[] | null;
errors!: Errors[] | null;
exception!: Exception | null;
messageType!: EventMessageType | null;

Expand Down Expand Up @@ -328,7 +336,7 @@ export interface IStatus {
success: boolean;
message: string | null;
details: string | null;
errors: (Errors | null)[] | null;
errors: Errors[] | null;
exception: Exception | null;
messageType: EventMessageType | null;
}
Expand Down
Loading

0 comments on commit 71c7a50

Please sign in to comment.