public void DynamicState_ReactsToDestinationStateChanges() { var cluster = new ClusterInfo("abc"); EnableHealthChecks(cluster); cluster.ProcessDestinationChanges(); var state1 = cluster.DynamicState; Assert.NotNull(state1); Assert.Empty(state1.AllDestinations); var destination = cluster.Destinations.GetOrAdd("d1", id => new DestinationInfo(id)); cluster.ProcessDestinationChanges(); Assert.NotSame(state1, cluster.DynamicState); var state2 = cluster.DynamicState; destination.Health.Active = DestinationHealth.Unhealthy; cluster.UpdateDynamicState(); Assert.NotSame(state2, cluster.DynamicState); var state3 = cluster.DynamicState; Assert.Contains(destination, state3.AllDestinations); Assert.Empty(state3.HealthyDestinations); destination.Health.Active = DestinationHealth.Healthy; cluster.UpdateDynamicState(); Assert.NotSame(state3, cluster.DynamicState); var state4 = cluster.DynamicState; Assert.Contains(destination, state4.AllDestinations); Assert.Contains(destination, state4.HealthyDestinations); }
public void DynamicState_ReactsToDestinationChanges() { var cluster = new ClusterInfo("abc"); cluster.ProcessDestinationChanges(); var state1 = cluster.DynamicState; Assert.NotNull(state1); Assert.Empty(state1.AllDestinations); var destination = cluster.Destinations.GetOrAdd("d1", id => new DestinationInfo(id)); cluster.ProcessDestinationChanges(); Assert.NotSame(state1, cluster.DynamicState); var state2 = cluster.DynamicState; Assert.Contains(destination, state2.AllDestinations); cluster.Destinations.TryRemove("d1", out var _); cluster.ProcessDestinationChanges(); Assert.NotSame(state2, cluster.DynamicState); var state3 = cluster.DynamicState; Assert.Empty(state3.AllDestinations); }
private static ClusterInfo CreateCluster(bool passive, bool active, params DestinationInfo[] destinations) { var cluster = new ClusterInfo("cluster0"); cluster.Config = new ClusterConfig( new Cluster { Id = cluster.ClusterId, HealthCheck = new HealthCheckOptions() { Passive = new PassiveHealthCheckOptions() { Policy = "policy0", Enabled = passive, }, Active = new ActiveHealthCheckOptions() { Enabled = active, Policy = "policy1", }, }, }, default); foreach (var destination in destinations) { cluster.Destinations.TryAdd(destination.DestinationId, destination); } cluster.ProcessDestinationChanges(); return(cluster); }
public void DynamicState_WithoutHealthChecks_AssumesAllHealthy() { var cluster = new ClusterInfo("abc"); var destination1 = cluster.Destinations.GetOrAdd("d1", id => new DestinationInfo(id) { Health = { Active = DestinationHealth.Healthy } }); var destination2 = cluster.Destinations.GetOrAdd("d2", id => new DestinationInfo(id) { Health = { Active = DestinationHealth.Unhealthy } }); var destination3 = cluster.Destinations.GetOrAdd("d3", id => new DestinationInfo(id)); // Unknown health state var destination4 = cluster.Destinations.GetOrAdd("d4", id => new DestinationInfo(id) { Health = { Passive = DestinationHealth.Healthy } }); cluster.ProcessDestinationChanges(); var sorted = cluster.DynamicState.AllDestinations.OrderBy(d => d.DestinationId).ToList(); Assert.Same(destination1, sorted[0]); Assert.Same(destination2, sorted[1]); Assert.Same(destination3, sorted[2]); Assert.Same(destination4, sorted[3]); sorted = cluster.DynamicState.HealthyDestinations.OrderBy(d => d.DestinationId).ToList(); Assert.Same(destination1, sorted[0]); Assert.Same(destination2, sorted[1]); Assert.Same(destination3, sorted[2]); Assert.Same(destination4, sorted[3]); }
private ClusterInfo GetClusterInfo(string id, string policy, bool enabled = true) { var clusterConfig = new ClusterConfig( new Cluster { Id = id, HealthCheck = new HealthCheckOptions { Passive = new PassiveHealthCheckOptions { Enabled = enabled, Policy = policy, } } }, null); var clusterInfo = new ClusterInfo(id); clusterInfo.Config = clusterConfig; clusterInfo.Destinations.GetOrAdd("destination0", id => new DestinationInfo(id)); clusterInfo.Destinations.GetOrAdd("destination1", id => new DestinationInfo(id)); clusterInfo.ProcessDestinationChanges(); return(clusterInfo); }
public async Task Invoke_NoHealthyEndpoints_CallsNext() { var httpClient = new HttpMessageInvoker(new Mock <HttpMessageHandler>().Object); var cluster1 = new ClusterInfo(clusterId: "cluster1"); cluster1.Config = new ClusterConfig( new Cluster() { HealthCheck = new HealthCheckOptions { Active = new ActiveHealthCheckOptions { Enabled = true, Timeout = Timeout.InfiniteTimeSpan, Interval = Timeout.InfiniteTimeSpan, Policy = "Any5xxResponse", } } }, httpClient); var destination1 = cluster1.Destinations.GetOrAdd( "destination1", id => new DestinationInfo(id) { Config = new DestinationConfig(new Destination { Address = "https://localhost:123/a/b/" }), Health = { Active = DestinationHealth.Unhealthy }, }); cluster1.ProcessDestinationChanges(); var aspNetCoreEndpoints = new List <Endpoint>(); var routeConfig = new RouteConfig( proxyRoute: new ProxyRoute(), cluster: cluster1, transformer: null); var aspNetCoreEndpoint = CreateAspNetCoreEndpoint(routeConfig); aspNetCoreEndpoints.Add(aspNetCoreEndpoint); var httpContext = new DefaultHttpContext(); httpContext.SetEndpoint(aspNetCoreEndpoint); var sut = Create <DestinationInitializerMiddleware>(); await sut.Invoke(httpContext); var feature = httpContext.Features.Get <IReverseProxyFeature>(); Assert.NotNull(feature); Assert.Single(feature.AllDestinations); Assert.Empty(feature.AvailableDestinations); Assert.Equal(StatusCodes.Status418ImATeapot, httpContext.Response.StatusCode); }
internal ClusterInfo GetCluster() { var cluster = new ClusterInfo("cluster-1"); var destinationManager = cluster.Destinations; destinationManager.GetOrAdd("dest-A", id => new DestinationInfo(id)); destinationManager.GetOrAdd(AffinitizedDestinationName, id => new DestinationInfo(id)); destinationManager.GetOrAdd("dest-C", id => new DestinationInfo(id)); cluster.Config = ClusterConfig; cluster.ProcessDestinationChanges(); return(cluster); }
public async Task Invoke_SetsFeatures() { var httpClient = new HttpMessageInvoker(new Mock <HttpMessageHandler>().Object); var cluster1 = new ClusterInfo(clusterId: "cluster1"); cluster1.Config = new ClusterConfig(new Cluster(), httpClient); var destination1 = cluster1.Destinations.GetOrAdd( "destination1", id => new DestinationInfo(id) { Config = new DestinationConfig(new Destination { Address = "https://localhost:123/a/b/" }) }); cluster1.ProcessDestinationChanges(); var aspNetCoreEndpoints = new List <Endpoint>(); var routeConfig = new RouteConfig( proxyRoute: new ProxyRoute(), cluster1, transformer: null); var aspNetCoreEndpoint = CreateAspNetCoreEndpoint(routeConfig); aspNetCoreEndpoints.Add(aspNetCoreEndpoint); var httpContext = new DefaultHttpContext(); httpContext.SetEndpoint(aspNetCoreEndpoint); var sut = Create <DestinationInitializerMiddleware>(); await sut.Invoke(httpContext); var proxyFeature = httpContext.GetRequiredProxyFeature(); Assert.NotNull(proxyFeature); Assert.NotNull(proxyFeature.AvailableDestinations); Assert.Equal(1, proxyFeature.AvailableDestinations.Count); Assert.Same(destination1, proxyFeature.AvailableDestinations[0]); Assert.Same(cluster1.Config, proxyFeature.ClusterSnapshot); Assert.Equal(StatusCodes.Status418ImATeapot, httpContext.Response.StatusCode); }
internal ClusterInfo GetCluster() { var cluster = new ClusterInfo("cluster-1"); cluster.Destinations.GetOrAdd("dest-A", id => new DestinationInfo(id)); cluster.Config = new ClusterConfig(new Cluster { SessionAffinity = new SessionAffinityOptions { Enabled = true, Mode = "Mode-B", FailurePolicy = "Policy-1", } }, new HttpMessageInvoker(new Mock <HttpMessageHandler>().Object)); cluster.ProcessDestinationChanges(); return(cluster); }
private ClusterInfo GetClusterInfo(string id, int destinationCount, int?failureThreshold = null) { var metadata = failureThreshold != null ? new Dictionary <string, string> { { ConsecutiveFailuresHealthPolicyOptions.ThresholdMetadataName, failureThreshold.ToString() } } : null; var clusterConfig = new ClusterConfig( new Cluster { Id = id, HealthCheck = new HealthCheckOptions() { Active = new ActiveHealthCheckOptions { Enabled = true, Policy = "policy", Path = "/api/health/", }, }, Metadata = metadata, }, null); var clusterInfo = new ClusterInfo(id); clusterInfo.Config = clusterConfig; for (var i = 0; i < destinationCount; i++) { var destinationConfig = new DestinationConfig(new Destination { Address = $"https://localhost:1000{i}/{id}/", Health = $"https://localhost:2000{i}/{id}/" }); var destinationId = $"destination{i}"; clusterInfo.Destinations.GetOrAdd(destinationId, id => new DestinationInfo(id) { Config = destinationConfig }); } clusterInfo.ProcessDestinationChanges(); return(clusterInfo); }
public void DynamicState_WithHealthChecks_HonorsHealthState() { var cluster = new ClusterInfo("abc"); EnableHealthChecks(cluster); var destination1 = cluster.Destinations.GetOrAdd("d1", id => new DestinationInfo(id) { Health = { Active = DestinationHealth.Healthy } }); var destination2 = cluster.Destinations.GetOrAdd("d2", id => new DestinationInfo(id) { Health = { Active = DestinationHealth.Unhealthy } }); var destination3 = cluster.Destinations.GetOrAdd("d3", id => new DestinationInfo(id)); // Unknown health state var destination4 = cluster.Destinations.GetOrAdd("d4", id => new DestinationInfo(id) { Health = { Passive = DestinationHealth.Healthy } }); var destination5 = cluster.Destinations.GetOrAdd("d5", id => new DestinationInfo(id) { Health = { Passive = DestinationHealth.Unhealthy } }); cluster.ProcessDestinationChanges(); Assert.Equal(5, cluster.DynamicState.AllDestinations.Count); var sorted = cluster.DynamicState.AllDestinations.OrderBy(d => d.DestinationId).ToList(); Assert.Same(destination1, sorted[0]); Assert.Same(destination2, sorted[1]); Assert.Same(destination3, sorted[2]); Assert.Same(destination4, sorted[3]); Assert.Same(destination5, sorted[4]); Assert.Equal(3, cluster.DynamicState.HealthyDestinations.Count); sorted = cluster.DynamicState.HealthyDestinations.OrderBy(d => d.DestinationId).ToList(); Assert.Same(destination1, sorted[0]); Assert.Same(destination3, sorted[1]); Assert.Same(destination4, sorted[2]); }
public void DynamicState_ManuallyUpdated() { var cluster = new ClusterInfo("abc"); var state1 = cluster.DynamicState; Assert.NotNull(state1); Assert.Empty(state1.AllDestinations); cluster.ProcessDestinationChanges(); var state2 = cluster.DynamicState; Assert.NotSame(state1, state2); Assert.NotNull(state2); Assert.Empty(state2.AllDestinations); cluster.Config = new ClusterConfig(new Cluster(), httpClient: new HttpMessageInvoker(new Mock <HttpMessageHandler>().Object)); Assert.Same(state2, cluster.DynamicState); cluster.UpdateDynamicState(); Assert.NotSame(state2, cluster.DynamicState); Assert.Empty(cluster.DynamicState.AllDestinations); }