Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cluster to ConfigureRouteAsync #1231

Merged
merged 4 commits into from
Sep 7, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public ValueTask<ClusterConfig> ConfigureClusterAsync(ClusterConfig origCluster,
return new ValueTask<ClusterConfig>(origCluster with { Destinations = newDests });
}

public ValueTask<RouteConfig> ConfigureRouteAsync(RouteConfig route, CancellationToken cancel)
public ValueTask<RouteConfig> ConfigureRouteAsync(RouteConfig route, ClusterConfig cluster, CancellationToken cancel)
{
// Example: do not let config based routes take priority over code based routes.
// Lower numbers are higher priority. Code routes default to 0.
Expand Down
3 changes: 2 additions & 1 deletion src/ReverseProxy/Configuration/IProxyConfigFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public interface IProxyConfigFilter
/// Allows modification of a route configuration.
/// </summary>
/// <param name="route">The <see cref="RouteConfig"/> instance to configure.</param>
ValueTask<RouteConfig> ConfigureRouteAsync(RouteConfig route, CancellationToken cancel);
/// <param name="cluster">The <see cref="ClusterConfig"/> instance related to <see cref="RouteConfig"/>.</param>
ValueTask<RouteConfig> ConfigureRouteAsync(RouteConfig route, ClusterConfig? cluster, CancellationToken cancel);
}
}
22 changes: 18 additions & 4 deletions src/ReverseProxy/Management/ProxyConfigManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ private async Task ReloadConfigAsync()
// Throws for validation failures
private async Task<bool> ApplyConfigAsync(IProxyConfig config)
{
var (configuredRoutes, routeErrors) = await VerifyRoutesAsync(config.Routes, cancellation: default);
var (configuredClusters, clusterErrors) = await VerifyClustersAsync(config.Clusters, cancellation: default);
var (configuredRoutes, routeErrors) = await VerifyRoutesAsync(config.Routes, configuredClusters, cancellation: default);

if (routeErrors.Count > 0 || clusterErrors.Count > 0)
{
Expand All @@ -223,7 +223,7 @@ private async Task<bool> ApplyConfigAsync(IProxyConfig config)
return routesChanged;
}

private async Task<(IList<RouteConfig>, IList<Exception>)> VerifyRoutesAsync(IReadOnlyList<RouteConfig> routes, CancellationToken cancellation)
private async Task<(IList<RouteConfig>, IList<Exception>)> VerifyRoutesAsync(IReadOnlyList<RouteConfig> routes, IList<ClusterConfig> clusters, CancellationToken cancellation)
{
if (routes == null)
{
Expand All @@ -234,6 +234,16 @@ private async Task<bool> ApplyConfigAsync(IProxyConfig config)
var configuredRoutes = new List<RouteConfig>(routes.Count);
var errors = new List<Exception>();

Dictionary<string, ClusterConfig>? clusterDictionary = null;
if (_filters.Length != 0)
{
clusterDictionary = new Dictionary<string, ClusterConfig>();
foreach (var cluster in clusters)
{
clusterDictionary.Add(cluster.ClusterId, cluster);
}
}
Tratcher marked this conversation as resolved.
Show resolved Hide resolved

foreach (var r in routes)
{
if (seenRouteIds.Contains(r.RouteId))
Expand All @@ -246,9 +256,13 @@ private async Task<bool> ApplyConfigAsync(IProxyConfig config)

try
{
foreach (var filter in _filters)
if (_filters.Length != 0)
{
route = await filter.ConfigureRouteAsync(route, cancellation);
clusterDictionary!.TryGetValue(route.ClusterId!, out var cluster);
foreach (var filter in _filters)
{
route = await filter.ConfigureRouteAsync(route, cluster, cancellation);
}
}
}
catch (Exception ex)
Expand Down
53 changes: 40 additions & 13 deletions test/ReverseProxy.Tests/Management/ProxyConfigManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ public ValueTask<ClusterConfig> ConfigureClusterAsync(ClusterConfig cluster, Can
return new ValueTask<ClusterConfig>(cluster);
}

public ValueTask<RouteConfig> ConfigureRouteAsync(RouteConfig route, CancellationToken cancel)
public ValueTask<RouteConfig> ConfigureRouteAsync(RouteConfig route, ClusterConfig cluster, CancellationToken cancel)
{
return new ValueTask<RouteConfig>(route with
{
Expand All @@ -387,45 +387,72 @@ public ValueTask<ClusterConfig> ConfigureClusterAsync(ClusterConfig cluster, Can
});
}

public ValueTask<RouteConfig> ConfigureRouteAsync(RouteConfig route, CancellationToken cancel)
public ValueTask<RouteConfig> ConfigureRouteAsync(RouteConfig route, ClusterConfig cluster, CancellationToken cancel)
{
return new ValueTask<RouteConfig>(route with { Order = 12 });
string order;
if (cluster != null)
{
order = cluster.Metadata["Order"];
}
else
{
order = "12";
}

return new ValueTask<RouteConfig>(route with { Order = int.Parse(order) });
}
}

[Fact]
public async Task LoadAsync_ConfigFilterConfiguresCluster_Works()
{
var route = new RouteConfig
var route1 = new RouteConfig
{
RouteId = "route1",
ClusterId = "cluster1",
Match = new RouteMatch { Path = "/" }
};
var route2 = new RouteConfig
{
RouteId = "route2",
ClusterId = "cluster2",
Match = new RouteMatch { Path = "/" }
};
var cluster = new ClusterConfig()
{
ClusterId = "cluster1",
Destinations = new Dictionary<string, DestinationConfig>(StringComparer.OrdinalIgnoreCase)
{
{ "d1", new DestinationConfig() { Address = "http://localhost" } }
},
Metadata = new Dictionary<string, string>
{
["Order"] = "47"
}
};
var services = CreateServices(new List<RouteConfig>() { route }, new List<ClusterConfig>() { cluster }, proxyBuilder =>
var services = CreateServices(new List<RouteConfig>() { route1, route2 }, new List<ClusterConfig>() { cluster }, proxyBuilder =>
{
proxyBuilder.AddConfigFilter<ClusterAndRouteFilter>();
});
var manager = services.GetRequiredService<ProxyConfigManager>();
var dataSource = await manager.InitialLoadAsync();

Assert.NotNull(dataSource);
var endpoint = Assert.Single(dataSource.Endpoints);
var routeConfig = endpoint.Metadata.GetMetadata<RouteModel>();
var clusterState = routeConfig.Cluster;
Assert.NotNull(clusterState);
Assert.True(clusterState.Model.Config.HealthCheck.Active.Enabled);
Assert.Equal(TimeSpan.FromSeconds(12), clusterState.Model.Config.HealthCheck.Active.Interval);
var destination = Assert.Single(clusterState.DestinationsState.AllDestinations);
Assert.Equal(2, dataSource.Endpoints.Count);

var endpoint1 = dataSource.Endpoints[0];
var routeConfig1 = endpoint1.Metadata.GetMetadata<RouteModel>();
Assert.Equal(47, routeConfig1.Config.Order);
Tratcher marked this conversation as resolved.
Show resolved Hide resolved
var clusterState1 = routeConfig1.Cluster;
Assert.NotNull(clusterState1);
Assert.True(clusterState1.Model.Config.HealthCheck.Active.Enabled);
Assert.Equal(TimeSpan.FromSeconds(12), clusterState1.Model.Config.HealthCheck.Active.Interval);
var destination = Assert.Single(clusterState1.DestinationsState.AllDestinations);
Assert.Equal("http://localhost", destination.Model.Config.Address);

var endpoint2 = dataSource.Endpoints[1];
var routeConfig2 = endpoint2.Metadata.GetMetadata<RouteModel>();
Assert.Equal(12, routeConfig2.Config.Order);
}

private class ClusterAndRouteThrows : IProxyConfigFilter
Expand All @@ -435,7 +462,7 @@ public ValueTask<ClusterConfig> ConfigureClusterAsync(ClusterConfig cluster, Can
throw new NotFiniteNumberException("Test exception");
}

public ValueTask<RouteConfig> ConfigureRouteAsync(RouteConfig route, CancellationToken cancel)
public ValueTask<RouteConfig> ConfigureRouteAsync(RouteConfig route, ClusterConfig cluster, CancellationToken cancel)
{
throw new NotFiniteNumberException("Test exception");
}
Expand Down
2 changes: 1 addition & 1 deletion testassets/ReverseProxy.Config/CustomConfigFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public ValueTask<ClusterConfig> ConfigureClusterAsync(ClusterConfig cluster, Can
return new ValueTask<ClusterConfig>(cluster);
}

public ValueTask<RouteConfig> ConfigureRouteAsync(RouteConfig route, CancellationToken cancel)
public ValueTask<RouteConfig> ConfigureRouteAsync(RouteConfig route, ClusterConfig cluster, CancellationToken cancel)
{
// Do not let config based routes take priority over code based routes.
// Lower numbers are higher priority. Code routes default to 0.
Expand Down