diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
index 7791fce..fc8f0cd 100644
--- a/.github/workflows/dotnet.yml
+++ b/.github/workflows/dotnet.yml
@@ -26,5 +26,5 @@ jobs:
- name: Pack NuGet
run: dotnet pack -c Release --version-suffix preview.1.`date +%y%m%d%H%M` -o ./
- name: Push NuGet
- run: dotnet nuget push '*.nupkg' -s https://api.nuget.org/v3/index.json -k ${{ secrets.NUGET_API_KEY }} -n true --skip-duplicate
+ run: dotnet nuget push '*.nupkg' -s https://www.myget.org/F/netcorepal/api/v3/index.json -k ${{ secrets.MYGET_API_KEY }} -n true --skip-duplicate
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..821637a
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,29 @@
+name: .NET
+
+on:
+ push:
+ tags:
+ - 'v*'
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v2
+ with:
+ dotnet-version: 6.0.104
+ - name: Restore dependencies
+ run: dotnet restore
+ - name: Build
+ run: dotnet build --no-restore
+ - name: Test
+ run: dotnet test --no-build --verbosity normal
+ - name: Pack NuGet
+ run: dotnet pack -c Release --version-suffix preview.1.`date +%y%m%d%H%M` -o ./
+ - name: Push NuGet
+ run: dotnet nuget push '*.nupkg' -s https://api.nuget.org/v3/index.json -k ${{ secrets.NUGET_API_KEY }} -n true --skip-duplicate
+
diff --git a/Directory.Build.targets b/Directory.Build.targets
new file mode 100644
index 0000000..a9c2664
--- /dev/null
+++ b/Directory.Build.targets
@@ -0,0 +1,39 @@
+
+
+ 6.0.0
+ 6.0.0
+
+
+ 7.0.0
+ 7.0.0
+
+
+ 8.0.0
+ 8.0.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
diff --git a/NuGet.config b/NuGet.config
index 7ef1014..ad39e34 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -1,6 +1,9 @@
+
+
+
diff --git a/README.md b/README.md
index ccb694b..350ca31 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,35 @@
# netcorepal-extensions-yarp
-NetCorePal Extensions for YAEP
\ No newline at end of file
+[![Release Build](https://img.shields.io/github/actions/workflow/status/netcorepal/netcorepal-extensions-yarp/release.yml?label=release%20build)](https://github.com/netcorepal/netcorepal-extensions-yarp/actions/workflows/release.yml)
+[![Preview Build](https://img.shields.io/github/actions/workflow/status/netcorepal/netcorepal-extensions-yarp/dotnet.yml?label=preview%20build)](https://github.com/netcorepal/netcorepal-extensions-yarp/actions/workflows/dotnet.yml)
+[![NuGet](https://img.shields.io/nuget/v/NetCorePal.Yarp.ReverseProxy.Dashboard.svg)](https://www.nuget.org/packages/NetCorePal.Yarp.ReverseProxy.Dashboard)
+[![MyGet Preview](https://img.shields.io/myget/netcorepal/vpre/NetCorePal.Yarp.ReverseProxy.Dashboard?label=preview)](https://www.myget.org/feed/netcorepal/package/nuget/NetCorePal.Yarp.ReverseProxy.Dashboard)
+[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/netcorepal/netcorepal-extensions-yarp/blob/main/LICENSE)
+
+The Extensions for [YAEP](https://github.com/microsoft/reverse-proxy)
+
+## Package List
+
+|Package|Release|Preview|
+|---|---|---|
+|NetCorePal.Yarp.ReverseProxy.Dashboard|[![NuGet](https://img.shields.io/nuget/v/NetCorePal.Yarp.ReverseProxy.Dashboard.svg)](https://www.nuget.org/packages/NetCorePal.Yarp.ReverseProxy.Dashboard)|[![MyGet Preview](https://img.shields.io/myget/netcorepal/vpre/NetCorePal.Yarp.ReverseProxy.Dashboard?label=preview)](https://www.myget.org/feed/netcorepal/package/nuget/NetCorePal.Yarp.ReverseProxy.Dashboard)|
+|NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates|[![NuGet](https://img.shields.io/nuget/v/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.svg)](https://www.nuget.org/packages/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates)|[![MyGet Preview](https://img.shields.io/myget/netcorepal/vpre/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates?label=preview)](https://www.myget.org/feed/netcorepal/package/nuget/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates)|
+
+## Preview Build
+
+Preview NuGet Feed:
+
+```text
+https://www.myget.org/F/netcorepal/api/v3/index.json
+```
+
+NuGet.config:
+
+```xml
+
+
+
+
+
+
+```
diff --git a/eng/versions.props b/eng/versions.props
index b02cfd4..ee7f7a8 100644
--- a/eng/versions.props
+++ b/eng/versions.props
@@ -1,6 +1,6 @@
- 0.1.0
+ 0.2.0
diff --git a/netcorepal-extensions-yarp.sln b/netcorepal-extensions-yarp.sln
index aaf556d..19a522d 100644
--- a/netcorepal-extensions-yarp.sln
+++ b/netcorepal-extensions-yarp.sln
@@ -13,9 +13,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "解决方案项", "解决
eng\versions.props = eng\versions.props
EndProjectSection
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetCorePal.Extensions.Yarp.ServiceDiscovery", "src\NetCorePal.Extensions.Yarp.ServiceDiscovery\NetCorePal.Extensions.Yarp.ServiceDiscovery.csproj", "{B9913396-5C97-4296-97A4-9F0D7716A1E6}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetCorePal.Yarp.ServiceDiscovery", "src\NetCorePal.Yarp.ServiceDiscovery\NetCorePal.Yarp.ServiceDiscovery.csproj", "{B9913396-5C97-4296-97A4-9F0D7716A1E6}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetCorePal.Extensions.YarpProxyStateUI", "src\NetCorePal.Extensions.YarpProxyStateUI\NetCorePal.Extensions.YarpProxyStateUI.csproj", "{10DFF0FD-CF81-4C18-AFA5-2EEACEAC0845}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetCorePal.Yarp.ReverseProxy.Dashboard", "src\NetCorePal.Yarp.ReverseProxy.Dashboard\NetCorePal.Yarp.ReverseProxy.Dashboard.csproj", "{10DFF0FD-CF81-4C18-AFA5-2EEACEAC0845}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates", "src\NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates\NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.csproj", "{EF55F855-1B26-47A0-A0F4-61C0B482BADF}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{BEE4A397-41B9-4EFC-A37C-C74F1A97ACBE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests", "test\NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests\NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests.csproj", "{85BA9DE7-5526-4937-8C40-4EC3D2DD4455}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IngressControllerTestWebHost", "test\IngressControllerTestWebHost\IngressControllerTestWebHost.csproj", "{4AB4F9D3-6C63-44E3-8484-2CC0DD460E33}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -31,6 +39,18 @@ Global
{10DFF0FD-CF81-4C18-AFA5-2EEACEAC0845}.Debug|Any CPU.Build.0 = Debug|Any CPU
{10DFF0FD-CF81-4C18-AFA5-2EEACEAC0845}.Release|Any CPU.ActiveCfg = Release|Any CPU
{10DFF0FD-CF81-4C18-AFA5-2EEACEAC0845}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EF55F855-1B26-47A0-A0F4-61C0B482BADF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EF55F855-1B26-47A0-A0F4-61C0B482BADF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EF55F855-1B26-47A0-A0F4-61C0B482BADF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EF55F855-1B26-47A0-A0F4-61C0B482BADF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {85BA9DE7-5526-4937-8C40-4EC3D2DD4455}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {85BA9DE7-5526-4937-8C40-4EC3D2DD4455}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {85BA9DE7-5526-4937-8C40-4EC3D2DD4455}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {85BA9DE7-5526-4937-8C40-4EC3D2DD4455}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4AB4F9D3-6C63-44E3-8484-2CC0DD460E33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4AB4F9D3-6C63-44E3-8484-2CC0DD460E33}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4AB4F9D3-6C63-44E3-8484-2CC0DD460E33}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4AB4F9D3-6C63-44E3-8484-2CC0DD460E33}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -38,6 +58,9 @@ Global
GlobalSection(NestedProjects) = preSolution
{B9913396-5C97-4296-97A4-9F0D7716A1E6} = {07187FF1-BBBA-4EC6-A16B-A88BFB309065}
{10DFF0FD-CF81-4C18-AFA5-2EEACEAC0845} = {07187FF1-BBBA-4EC6-A16B-A88BFB309065}
+ {EF55F855-1B26-47A0-A0F4-61C0B482BADF} = {07187FF1-BBBA-4EC6-A16B-A88BFB309065}
+ {85BA9DE7-5526-4937-8C40-4EC3D2DD4455} = {BEE4A397-41B9-4EFC-A37C-C74F1A97ACBE}
+ {4AB4F9D3-6C63-44E3-8484-2CC0DD460E33} = {BEE4A397-41B9-4EFC-A37C-C74F1A97ACBE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {82B031CC-A5AC-4C7B-BC85-EFBC09207DBB}
diff --git a/src/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates/IngressServerCertificateManager.cs b/src/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates/IngressServerCertificateManager.cs
new file mode 100644
index 0000000..3eaa01e
--- /dev/null
+++ b/src/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates/IngressServerCertificateManager.cs
@@ -0,0 +1,148 @@
+using System.Collections.Concurrent;
+using System.Security.Cryptography.X509Certificates;
+using k8s;
+using k8s.Models;
+using Microsoft.AspNetCore.Connections;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Yarp.Kubernetes.Controller;
+using Yarp.Kubernetes.Controller.Caching;
+using Yarp.Kubernetes.Controller.Certificates;
+using Yarp.Kubernetes.Controller.Client;
+
+namespace NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates;
+
+public class IngressServerCertificateManager : IHostedService
+{
+ private readonly IngressServerCertificateSelector _certificateSelector;
+
+ private readonly object _lock = new object();
+
+ private readonly ICache _cache;
+
+ private readonly ILogger _logger;
+
+ private readonly ConcurrentDictionary _secrets = new();
+
+ private readonly ICertificateHelper _certificateHelper;
+
+ public IngressServerCertificateManager(
+ IngressServerCertificateSelector certificateSelector,
+ ICache cache,
+ ICertificateHelper certificateHelper,
+ IResourceInformer secretInformer,
+ IResourceInformer ingressInformer,
+ ILogger logger)
+ {
+ _certificateSelector = certificateSelector;
+ _cache = cache;
+ _certificateHelper = certificateHelper;
+ secretInformer.Register(Update);
+ ingressInformer.Register(Update);
+ _logger = logger;
+ }
+
+ private void Update(WatchEventType eventType, V1Ingress ingress)
+ {
+ try
+ {
+ ResetCertificates();
+ }
+ catch (Exception e)
+ {
+ _logger.LogError(e, "Update ingress certificate error when update ingress");
+ }
+ }
+
+ private void Update(WatchEventType eventType, V1Secret resource)
+ {
+ try
+ {
+ NamespacedName n = new NamespacedName(resource.Namespace(), resource.Name());
+ switch (eventType)
+ {
+ case WatchEventType.Added:
+ case WatchEventType.Modified:
+ _secrets.TryAdd(n, _certificateHelper.ConvertCertificate(n, resource));
+ break;
+ case WatchEventType.Deleted:
+ _secrets.TryRemove(n, out _);
+ break;
+ }
+
+ ResetCertificates();
+ }
+ catch (Exception e)
+ {
+ _logger.LogError(e, "Update ingress certificate error when update secret");
+ }
+ }
+
+
+ private void ResetCertificates()
+ {
+ lock (_lock)
+ {
+ var certs = new Dictionary();
+ var wildcardCerts = new Dictionary();
+ foreach (var ingress in _cache.GetIngresses())
+ {
+ if (ingress.Spec?.Tls == null) continue;
+
+ foreach (var tls in ingress.Spec.Tls)
+ {
+ if (!string.IsNullOrEmpty(tls.SecretName))
+ {
+ var secretName = new NamespacedName(ingress.Metadata.Namespace(), tls.SecretName);
+ if (_secrets.TryGetValue(secretName, out var certificate))
+ {
+ foreach (var host in tls.Hosts)
+ {
+ if (IsWildcardDomain(host))
+ {
+ wildcardCerts[host] = certificate;
+ }
+ else
+ {
+ certs[host] = certificate;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Interlocked.Exchange(ref _certificateSelector._domainCertificates, certs);
+ Interlocked.Exchange(ref _certificateSelector._wildcardDomainCertificates, wildcardCerts);
+ }
+ }
+
+
+ bool IsWildcardDomain(string domainName)
+ {
+ return domainName.StartsWith("*", StringComparison.Ordinal);
+ }
+
+ bool TryToWildcardDomain(string domainName, out string wildcardDomainName)
+ {
+ wildcardDomainName = string.Empty;
+ var index = domainName.IndexOf(".", StringComparison.Ordinal);
+ if (index == -1)
+ {
+ return false;
+ }
+
+ wildcardDomainName = string.Concat("*", domainName.AsSpan(index));
+ return true;
+ }
+
+ public Task StartAsync(CancellationToken cancellationToken)
+ {
+ return Task.CompletedTask;
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/src/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates/IngressServerCertificateSelector.cs b/src/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates/IngressServerCertificateSelector.cs
new file mode 100644
index 0000000..f962e39
--- /dev/null
+++ b/src/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates/IngressServerCertificateSelector.cs
@@ -0,0 +1,55 @@
+using System.Security.Cryptography.X509Certificates;
+using Microsoft.AspNetCore.Connections;
+using Yarp.Kubernetes.Controller;
+using Yarp.Kubernetes.Controller.Certificates;
+
+namespace NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates;
+
+public class IngressServerCertificateSelector : IServerCertificateSelector
+{
+ private X509Certificate2? _defaultCertificate = null;
+
+ internal volatile Dictionary _domainCertificates = new();
+
+ internal volatile Dictionary _wildcardDomainCertificates = new();
+
+
+ public X509Certificate2? GetCertificate(ConnectionContext connectionContext, string domainName)
+ {
+ if (_domainCertificates.TryGetValue(domainName, out var certificate))
+ {
+ return certificate;
+ }
+
+ if (TryToWildcardDomain(domainName, out var wildcardDomainName)
+ && _wildcardDomainCertificates.TryGetValue(wildcardDomainName, out var certificate1))
+ {
+ return certificate1;
+ }
+
+ return _defaultCertificate;
+ }
+
+ public void AddCertificate(NamespacedName certificateName, X509Certificate2 certificate)
+ {
+ _defaultCertificate = certificate;
+ }
+
+ public void RemoveCertificate(NamespacedName certificateName)
+ {
+ _defaultCertificate = null;
+ }
+
+ bool TryToWildcardDomain(string domainName, out string wildcardDomainName)
+ {
+ wildcardDomainName = string.Empty;
+ var index = domainName.IndexOf(".", StringComparison.Ordinal);
+ if (index == -1)
+ {
+ return false;
+ }
+
+ wildcardDomainName = string.Concat("*", domainName.AsSpan(index));
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.csproj b/src/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.csproj
new file mode 100644
index 0000000..5abd457
--- /dev/null
+++ b/src/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net6.0;net7.0;net8.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/src/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates/ReverseProxyBuilderExtensions.cs b/src/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates/ReverseProxyBuilderExtensions.cs
new file mode 100644
index 0000000..9e0cca7
--- /dev/null
+++ b/src/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates/ReverseProxyBuilderExtensions.cs
@@ -0,0 +1,17 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using Yarp.Kubernetes.Controller.Certificates;
+
+namespace NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates;
+
+public static class ReverseProxyBuilderExtensions
+{
+ public static IReverseProxyBuilder UseIngressServerCertificateSelector(this IReverseProxyBuilder builder)
+ {
+ builder.Services.TryAddSingleton();
+ builder.Services.AddHostedService();
+ builder.Services.Replace(ServiceDescriptor
+ .Singleton(p => p.GetRequiredService()));
+ return builder;
+ }
+}
\ No newline at end of file
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/NetCorePal.Extensions.YarpProxyStateUI.csproj b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/NetCorePal.Yarp.ReverseProxy.Dashboard.csproj
similarity index 91%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/NetCorePal.Extensions.YarpProxyStateUI.csproj
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/NetCorePal.Yarp.ReverseProxy.Dashboard.csproj
index 3167c30..9d46a43 100644
--- a/src/NetCorePal.Extensions.YarpProxyStateUI/NetCorePal.Extensions.YarpProxyStateUI.csproj
+++ b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/NetCorePal.Yarp.ReverseProxy.Dashboard.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net6.0;net7.0;net8.0
enable
enable
true
@@ -12,7 +12,7 @@
-
+
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/Pages/_State.cshtml b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/Pages/_State.cshtml
similarity index 94%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/Pages/_State.cshtml
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/Pages/_State.cshtml
index 8567753..19dc0ac 100644
--- a/src/NetCorePal.Extensions.YarpProxyStateUI/Pages/_State.cshtml
+++ b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/Pages/_State.cshtml
@@ -1,6 +1,6 @@
@page
@using System.Text.Json
-@model NetCorePal.Extensions.YarpProxyStateUI.Pages.ProxyStateModel
+@model NetCorePal.Yarp.ReverseProxy.Dashboard.Pages.ProxyStateModel
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/Pages/_State.cshtml.cs b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/Pages/_State.cshtml.cs
similarity index 78%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/Pages/_State.cshtml.cs
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/Pages/_State.cshtml.cs
index 59a8a40..5b5a933 100644
--- a/src/NetCorePal.Extensions.YarpProxyStateUI/Pages/_State.cshtml.cs
+++ b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/Pages/_State.cshtml.cs
@@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Yarp.ReverseProxy;
-namespace NetCorePal.Extensions.YarpProxyStateUI.Pages;
+namespace NetCorePal.Yarp.ReverseProxy.Dashboard.Pages;
public class ProxyStateModel : PageModel
{
@@ -13,11 +13,5 @@ public ProxyStateModel(IProxyStateLookup proxyStateLookup)
{
this.ProxyStateLookup = proxyStateLookup;
}
-
-
- public void OnGet()
- {
-
- }
}
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/ServiceCollectionExtensions.cs b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/ServiceCollectionExtensions.cs
similarity index 51%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/ServiceCollectionExtensions.cs
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/ServiceCollectionExtensions.cs
index a04238b..51b308c 100644
--- a/src/NetCorePal.Extensions.YarpProxyStateUI/ServiceCollectionExtensions.cs
+++ b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/ServiceCollectionExtensions.cs
@@ -1,32 +1,27 @@
-using System;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Routing;
-using Microsoft.Extensions.DependencyInjection;
-using NetCorePal.Extensions.YarpProxyStateUI;
+using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.FileProviders;
-using Microsoft.AspNetCore.Builder;
namespace Microsoft.Extensions.DependencyInjection
{
public static class ServiceCollectionExtensions
{
- public static IServiceCollection AddYarpProxyStateUI(this IServiceCollection services)
+ public static IServiceCollection AddYarpDashboard(this IServiceCollection services)
{
services.AddRazorPages();
return services;
}
- public static IApplicationBuilder UseYarpProxyStateUIStaticFiles(this IApplicationBuilder builder)
+ public static IApplicationBuilder UseYarpDashboardStaticFiles(this IApplicationBuilder builder)
{
builder.UseStaticFiles(new StaticFileOptions
{
RequestPath = "/_static",
- FileProvider = new EmbeddedFileProvider(typeof(ServiceCollectionExtensions).Assembly, "NetCorePal.Extensions.YarpProxyStateUI.wwwroot")
+ FileProvider = new EmbeddedFileProvider(typeof(ServiceCollectionExtensions).Assembly, "NetCorePal.Yarp.ReverseProxy.Dashboard.wwwroot")
});
return builder;
}
- public static IApplicationBuilder UseYarpProxyStateUI(this IApplicationBuilder builder, int? port = null)
+ public static IApplicationBuilder UseYarpDashboard(this IApplicationBuilder builder, int? port = null)
{
if (port == null)
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap-theme.css b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap-theme.css
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap-theme.css
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap-theme.css
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap-theme.css.map b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap-theme.css.map
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap-theme.css.map
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap-theme.css.map
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap-theme.min.css b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap-theme.min.css
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap-theme.min.css
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap-theme.min.css
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap-theme.min.css.map b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap-theme.min.css.map
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap-theme.min.css.map
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap-theme.min.css.map
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap.css b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap.css
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap.css
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap.css
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap.css.map b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap.css.map
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap.css.map
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap.css.map
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap.min.css b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap.min.css
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap.min.css
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap.min.css
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap.min.css.map b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap.min.css.map
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/css/bootstrap.min.css.map
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/css/bootstrap.min.css.map
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/fonts/glyphicons-halflings-regular.eot b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/fonts/glyphicons-halflings-regular.eot
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/fonts/glyphicons-halflings-regular.eot
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/fonts/glyphicons-halflings-regular.eot
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/fonts/glyphicons-halflings-regular.svg b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/fonts/glyphicons-halflings-regular.svg
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/fonts/glyphicons-halflings-regular.svg
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/fonts/glyphicons-halflings-regular.svg
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/fonts/glyphicons-halflings-regular.ttf b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/fonts/glyphicons-halflings-regular.ttf
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/fonts/glyphicons-halflings-regular.ttf
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/fonts/glyphicons-halflings-regular.ttf
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/fonts/glyphicons-halflings-regular.woff b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/fonts/glyphicons-halflings-regular.woff
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/fonts/glyphicons-halflings-regular.woff
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/fonts/glyphicons-halflings-regular.woff
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/fonts/glyphicons-halflings-regular.woff2 b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/fonts/glyphicons-halflings-regular.woff2
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/fonts/glyphicons-halflings-regular.woff2
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/fonts/glyphicons-halflings-regular.woff2
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/js/bootstrap.js b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/js/bootstrap.js
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/js/bootstrap.js
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/js/bootstrap.js
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/js/bootstrap.min.js b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/js/bootstrap.min.js
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/js/bootstrap.min.js
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/js/bootstrap.min.js
diff --git a/src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/js/npm.js b/src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/js/npm.js
similarity index 100%
rename from src/NetCorePal.Extensions.YarpProxyStateUI/wwwroot/js/npm.js
rename to src/NetCorePal.Yarp.ReverseProxy.Dashboard/wwwroot/js/npm.js
diff --git a/src/NetCorePal.Extensions.Yarp.ServiceDiscovery/NetCorePal.Extensions.Yarp.ServiceDiscovery.csproj b/src/NetCorePal.Yarp.ServiceDiscovery/NetCorePal.Yarp.ServiceDiscovery.csproj
similarity index 92%
rename from src/NetCorePal.Extensions.Yarp.ServiceDiscovery/NetCorePal.Extensions.Yarp.ServiceDiscovery.csproj
rename to src/NetCorePal.Yarp.ServiceDiscovery/NetCorePal.Yarp.ServiceDiscovery.csproj
index 00d80ad..7b051a3 100644
--- a/src/NetCorePal.Extensions.Yarp.ServiceDiscovery/NetCorePal.Extensions.Yarp.ServiceDiscovery.csproj
+++ b/src/NetCorePal.Yarp.ServiceDiscovery/NetCorePal.Yarp.ServiceDiscovery.csproj
@@ -4,6 +4,7 @@
net6.0
enable
enable
+ false
diff --git a/src/NetCorePal.Extensions.Yarp.ServiceDiscovery/ReverseProxyBuilderExtensions.cs b/src/NetCorePal.Yarp.ServiceDiscovery/ReverseProxyBuilderExtensions.cs
similarity index 93%
rename from src/NetCorePal.Extensions.Yarp.ServiceDiscovery/ReverseProxyBuilderExtensions.cs
rename to src/NetCorePal.Yarp.ServiceDiscovery/ReverseProxyBuilderExtensions.cs
index 33ef7d3..f7eea95 100644
--- a/src/NetCorePal.Extensions.Yarp.ServiceDiscovery/ReverseProxyBuilderExtensions.cs
+++ b/src/NetCorePal.Yarp.ServiceDiscovery/ReverseProxyBuilderExtensions.cs
@@ -1,5 +1,5 @@
using System;
-using NetCorePal.Extensions.Yarp.ServiceDiscovery;
+using NetCorePal.Yarp.ServiceDiscovery;
using Yarp.ReverseProxy.Configuration;
namespace Microsoft.Extensions.DependencyInjection
diff --git a/src/NetCorePal.Extensions.Yarp.ServiceDiscovery/ServiceDiscoveryProxyConfig.cs b/src/NetCorePal.Yarp.ServiceDiscovery/ServiceDiscoveryProxyConfig.cs
similarity index 91%
rename from src/NetCorePal.Extensions.Yarp.ServiceDiscovery/ServiceDiscoveryProxyConfig.cs
rename to src/NetCorePal.Yarp.ServiceDiscovery/ServiceDiscoveryProxyConfig.cs
index 2c70437..a8b7d39 100644
--- a/src/NetCorePal.Extensions.Yarp.ServiceDiscovery/ServiceDiscoveryProxyConfig.cs
+++ b/src/NetCorePal.Yarp.ServiceDiscovery/ServiceDiscoveryProxyConfig.cs
@@ -1,7 +1,7 @@
using System;
using Microsoft.Extensions.Primitives;
using Yarp.ReverseProxy.Configuration;
-namespace NetCorePal.Extensions.Yarp.ServiceDiscovery
+namespace NetCorePal.Yarp.ServiceDiscovery
{
internal class ServiceDiscoveryProxyConfig : IProxyConfig
{
diff --git a/src/NetCorePal.Extensions.Yarp.ServiceDiscovery/ServiceDiscoveryProxyConfigProvider.cs b/src/NetCorePal.Yarp.ServiceDiscovery/ServiceDiscoveryProxyConfigProvider.cs
similarity index 94%
rename from src/NetCorePal.Extensions.Yarp.ServiceDiscovery/ServiceDiscoveryProxyConfigProvider.cs
rename to src/NetCorePal.Yarp.ServiceDiscovery/ServiceDiscoveryProxyConfigProvider.cs
index 2719c59..2ba5066 100644
--- a/src/NetCorePal.Extensions.Yarp.ServiceDiscovery/ServiceDiscoveryProxyConfigProvider.cs
+++ b/src/NetCorePal.Yarp.ServiceDiscovery/ServiceDiscoveryProxyConfigProvider.cs
@@ -1,7 +1,7 @@
using NetCorePal.ServiceDiscovery;
using Yarp.ReverseProxy.Configuration;
-namespace NetCorePal.Extensions.Yarp.ServiceDiscovery
+namespace NetCorePal.Yarp.ServiceDiscovery
{
public class ServiceDiscoveryProxyConfigProvider : IProxyConfigProvider
{
diff --git a/test/Directory.Build.props b/test/Directory.Build.props
new file mode 100644
index 0000000..50ce2f4
--- /dev/null
+++ b/test/Directory.Build.props
@@ -0,0 +1,9 @@
+
+
+ false
+ preview
+
+
+
+
+
diff --git a/test/IngressControllerTestWebHost/IngressControllerTestWebHost.csproj b/test/IngressControllerTestWebHost/IngressControllerTestWebHost.csproj
new file mode 100644
index 0000000..b80b917
--- /dev/null
+++ b/test/IngressControllerTestWebHost/IngressControllerTestWebHost.csproj
@@ -0,0 +1,14 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
diff --git a/test/IngressControllerTestWebHost/Program.cs b/test/IngressControllerTestWebHost/Program.cs
new file mode 100644
index 0000000..af45c90
--- /dev/null
+++ b/test/IngressControllerTestWebHost/Program.cs
@@ -0,0 +1,26 @@
+using NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates;
+using Microsoft.Extensions.DependencyInjection;
+
+var builder = WebApplication.CreateBuilder(args);
+builder.Services.AddYarpDashboard();
+builder.Services.AddKubernetesReverseProxy(builder.Configuration)
+ .UseIngressServerCertificateSelector()
+ .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
+
+if (builder.Environment.IsDevelopment())
+{
+ builder.WebHost.UseKubernetesReverseProxyCertificateSelector();
+}
+
+builder.Services.AddCors(options =>
+{
+ options.AddPolicy("apiPolicy", p => p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
+});
+
+var app = builder.Build();
+app.UseYarpDashboardStaticFiles();
+app.UseRouting();
+app.UseYarpDashboard();
+app.MapGet("/", () => "Hello World!");
+app.MapReverseProxy();
+app.Run();
\ No newline at end of file
diff --git a/test/IngressControllerTestWebHost/Properties/launchSettings.json b/test/IngressControllerTestWebHost/Properties/launchSettings.json
new file mode 100644
index 0000000..a5ecee0
--- /dev/null
+++ b/test/IngressControllerTestWebHost/Properties/launchSettings.json
@@ -0,0 +1,38 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:65372",
+ "sslPort": 44310
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:5091",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:7031;http://localhost:5091",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/test/IngressControllerTestWebHost/appsettings.Development.json b/test/IngressControllerTestWebHost/appsettings.Development.json
new file mode 100644
index 0000000..d528010
--- /dev/null
+++ b/test/IngressControllerTestWebHost/appsettings.Development.json
@@ -0,0 +1,15 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "Yarp": {
+ "ControllerClass": "rivtower.com/rivdap",
+ "ServerCertificates": true,
+ "DefaultSslCertificate": "app-rivdap-saas/nft-fe-tls",
+ "ControllerServiceNamespace": "app-rivdap-saas",
+ "ControllerServiceName": "rivtower-ingress-controller"
+ }
+}
diff --git a/test/IngressControllerTestWebHost/appsettings.json b/test/IngressControllerTestWebHost/appsettings.json
new file mode 100644
index 0000000..10f68b8
--- /dev/null
+++ b/test/IngressControllerTestWebHost/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/test/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests/GlobalUsings.cs b/test/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests/GlobalUsings.cs
new file mode 100644
index 0000000..8c927eb
--- /dev/null
+++ b/test/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests/GlobalUsings.cs
@@ -0,0 +1 @@
+global using Xunit;
\ No newline at end of file
diff --git a/test/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests/IngressServerCertificateSelectorTests.cs b/test/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests/IngressServerCertificateSelectorTests.cs
new file mode 100644
index 0000000..2f4ad54
--- /dev/null
+++ b/test/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests/IngressServerCertificateSelectorTests.cs
@@ -0,0 +1,47 @@
+using k8s;
+using k8s.Models;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Moq;
+using NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates;
+using Yarp.Kubernetes.Controller.Caching;
+using Yarp.Kubernetes.Controller.Certificates;
+using Yarp.Kubernetes.Controller.Client;
+
+namespace NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests;
+
+public class IngressServerCertificateSelectorTests
+{
+ [Fact]
+ public void Test1()
+ {
+ var cacheMock = new Mock();
+ var certificateHelperLoggerMock = new Mock>();
+ ICertificateHelper certificateHelper = new CertificateHelper(certificateHelperLoggerMock.Object);
+
+ var secretInformer = new Mock>();
+
+ ResourceInformerCallback? secretCallback = null;
+ secretInformer.Setup(p => p.Register(It.IsAny>()))
+ .Callback((ResourceInformerCallback c) => secretCallback = c);
+
+ ResourceInformerCallback? ingressCallback = null;
+ var ingressInformer = new Mock>();
+ ingressInformer.Setup(p => p.Register(It.IsAny>()))
+ .Callback((ResourceInformerCallback c) => ingressCallback = c);
+
+ var loggerMock = new Mock>();
+ var manager = new IngressServerCertificateManager(
+ new IngressServerCertificateSelector(),
+ cacheMock.Object,
+ certificateHelper,
+ secretInformer.Object,
+ ingressInformer.Object,
+ loggerMock.Object);
+
+ Assert.NotNull(secretCallback);
+ Assert.NotNull(ingressCallback);
+
+ secretCallback(WatchEventType.Added, new V1Secret());
+ }
+}
\ No newline at end of file
diff --git a/test/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests.csproj b/test/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests.csproj
new file mode 100644
index 0000000..324e86b
--- /dev/null
+++ b/test/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.Tests.csproj
@@ -0,0 +1,30 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+