public void BuildCluster_IncompleteLabels_UsesDefaultValues() { // Arrange var labels = new Dictionary <string, string>() { { "YARP.Backend.BackendId", "MyCoolClusterId" }, }; // Act var cluster = LabelsParser.BuildCluster(_testServiceName, labels); // Assert var expectedCluster = new Cluster { Id = "MyCoolClusterId", SessionAffinity = new SessionAffinityOptions(), HttpRequest = new ProxyHttpRequestOptions(), HealthCheck = new HealthCheckOptions { Active = new ActiveHealthCheckOptions(), Passive = new PassiveHealthCheckOptions() }, Metadata = new Dictionary <string, string>(), }; cluster.Should().BeEquivalentTo(expectedCluster); }
public void BuildRoutes_SingleRoute_Works() { // Arrange var labels = new Dictionary <string, string>() { { "YARP.Backend.BackendId", "MyCoolClusterId" }, { "YARP.Routes.MyRoute.Hosts", "example.com" }, { "YARP.Routes.MyRoute.Order", "2" }, { "YARP.Routes.MyRoute.Metadata.Foo", "Bar" }, }; // Act var routes = LabelsParser.BuildRoutes(_testServiceName, labels); // Assert var expectedRoutes = new List <ProxyRoute> { new ProxyRoute { RouteId = "MyCoolClusterId:MyRoute", Match = { Hosts = new[] { "example.com" }, }, Order = 2, ClusterId = "MyCoolClusterId", Metadata = new Dictionary <string, string> { { "Foo", "Bar" }, }, }, }; routes.Should().BeEquivalentTo(expectedRoutes); }
public async void ExecuteAsync_ReplicaHealthReportDisabled_ReplicasHealthIsNotReported() { // Setup _scenarioOptions = new ServiceFabricDiscoveryOptions { ReportReplicasHealth = false }; const string TestClusterId = "MyService123"; var labels = SFTestHelpers.DummyLabels(TestClusterId); ApplicationWrapper application; Mock_AppsResponse( application = CreateApp_1Service_SingletonPartition_1Replica("MyApp", "MYService", out var service, out var replica)); Mock_ServiceLabels(application, service, labels); // Act var(routes, clusters) = await RunScenarioAsync(); // Assert var expectedClusters = new[] { ClusterWithDestinations( LabelsParser.BuildCluster(_testServiceName, labels), SFTestHelpers.BuildDestinationFromReplica(replica)), }; var expectedRoutes = LabelsParser.BuildRoutes(_testServiceName, labels); clusters.Should().BeEquivalentTo(expectedClusters); routes.Should().BeEquivalentTo(expectedRoutes); AssertServiceHealthReported(service, HealthState.Ok); _healthReports.Should().HaveCount(1); }
public async void ExecuteAsync_StatefulService_SkipReplicaWork(string selectionMode, ReplicaRole?replicaRole) { // Setup _scenarioOptions = new ServiceFabricDiscoveryOptions { ReportReplicasHealth = true }; const string TestClusterId = "MyService123"; var labels = SFTestHelpers.DummyLabels(TestClusterId); labels["YARP.Backend.ServiceFabric.StatefulReplicaSelectionMode"] = selectionMode; ApplicationWrapper application; Mock_AppsResponse(application = CreateApp_1Service_SingletonPartition_1Replica("MyApp", "MYService", out var service, out var replica, serviceKind: ServiceKind.Stateful)); Mock_ServiceLabels(application, service, labels); replica.ServiceKind = ServiceKind.Stateful; replica.Role = replicaRole; // Act var(routes, clusters) = await RunScenarioAsync(); // Assert var expectedClusters = new[] { LabelsParser.BuildCluster(_testServiceName, labels), }; clusters.Should().BeEquivalentTo(expectedClusters); _healthReports.Should().HaveCount(1); }
public async void ExecuteAsync_InvalidListenerNameForStatelessService_NoEndpointsAndBadHealthReported() { // Setup _scenarioOptions = new ServiceFabricDiscoveryOptions { ReportReplicasHealth = true }; const string TestClusterId = "MyService123"; var labels = SFTestHelpers.DummyLabels(TestClusterId); labels["YARP.Backend.ServiceFabric.ListenerName"] = "UnexistingListener"; ApplicationWrapper application; Mock_AppsResponse( application = CreateApp_1Service_SingletonPartition_1Replica("MyApp", "MyService", out var service, out var replica, serviceKind: ServiceKind.Stateless)); Mock_ServiceLabels(application, service, labels); // Act var(routes, clusters) = await RunScenarioAsync(); // Assert var expectedClusters = new[] { LabelsParser.BuildCluster(_testServiceName, labels), }; var expectedRoutes = LabelsParser.BuildRoutes(_testServiceName, labels); clusters.Should().BeEquivalentTo(expectedClusters); routes.Should().BeEquivalentTo(expectedRoutes); AssertServiceHealthReported(service, HealthState.Ok); AssertStatelessServiceInstanceHealthReported(replica, HealthState.Warning, (description) => description.StartsWith("Could not build service endpoint") && description.Contains("UnexistingListener")); _healthReports.Should().HaveCount(2); }
public async void ExecuteAsync_SingleServiceWithGatewayEnabledAndActiveHealthCheck() { // Setup _scenarioOptions = new ServiceFabricDiscoveryOptions(); const string TestClusterId = "MyService123"; var labels = SFTestHelpers.DummyLabels(TestClusterId, activeHealthChecks: true); ApplicationWrapper application; Mock_AppsResponse( application = CreateApp_1StatelessService_2Partition_2ReplicasEach("MyApp", "MYService", out var service, out var replicas)); Mock_ServiceLabels(application, service, labels); // Act var(routes, clusters) = await RunScenarioAsync(); // Assert var expectedClusters = new[] { ClusterWithDestinations( LabelsParser.BuildCluster(_testServiceName, labels), SFTestHelpers.BuildDestinationFromReplica(replicas[0]), SFTestHelpers.BuildDestinationFromReplica(replicas[1]), SFTestHelpers.BuildDestinationFromReplica(replicas[2]), SFTestHelpers.BuildDestinationFromReplica(replicas[3])), }; var expectedRoutes = LabelsParser.BuildRoutes(_testServiceName, labels); routes.Should().BeEquivalentTo(expectedRoutes); clusters.Should().BeEquivalentTo(expectedClusters); AssertServiceHealthReported(service, HealthState.Ok); _healthReports.Should().HaveCount(1); }
public async void ExecuteAsync_ValidListenerNameForStatelessService_Work() { _scenarioOptions = new ServiceFabricDiscoveryOptions { ReportReplicasHealth = true }; const string TestClusterId = "MyService123"; var labels = SFTestHelpers.DummyLabels(TestClusterId); labels["YARP.Backend.ServiceFabric.ListenerName"] = "ExampleTeamEndpoint"; labels["YARP.Backend.HealthCheck.Active.ServiceFabric.ListenerName"] = "ExampleTeamHealthEndpoint"; ApplicationWrapper application; Mock_AppsResponse( application = CreateApp_1Service_SingletonPartition_1Replica("MyApp", "MyService", out var service, out var replica, serviceKind: ServiceKind.Stateless)); replica.ReplicaAddress = MockReplicaAdressWithListenerName("MyApp", "MyService", new string[] { "ExampleTeamEndpoint", "ExampleTeamHealthEndpoint" }); Mock_ServiceLabels(application, service, labels); var(routes, clusters) = await RunScenarioAsync(); var expectedClusters = new[] { ClusterWithDestinations(_testServiceName, labels, SFTestHelpers.BuildDestinationFromReplica(replica, "ExampleTeamHealthEndpoint")), }; var expectedRoutes = LabelsParser.BuildRoutes(_testServiceName, labels); clusters.Should().BeEquivalentTo(expectedClusters); routes.Should().BeEquivalentTo(expectedRoutes); AssertServiceHealthReported(service, HealthState.Ok); AssertStatelessServiceInstanceHealthReported(replica, HealthState.Ok, (description) => description.StartsWith("Successfully built")); _healthReports.Should().HaveCount(2); }
public void BuildRoutes_MissingBackendId_UsesServiceName(int scenario) { var labels = new Dictionary <string, string>() { { "YARP.Routes.MyRoute.Hosts", "example.com" }, { "YARP.Routes.MyRoute.Order", "2" }, }; if (scenario == 1) { labels.Add("YARP.Backend.BackendId", string.Empty); } var routes = LabelsParser.BuildRoutes(_testServiceName, labels); var expectedRoutes = new List <ProxyRoute> { new ProxyRoute { RouteId = $"{Uri.EscapeDataString(_testServiceName.ToString())}:MyRoute", Match = new RouteMatch { Hosts = new[] { "example.com" }, }, Order = 2, ClusterId = _testServiceName.ToString(), Metadata = new Dictionary <string, string>(), }, }; routes.Should().BeEquivalentTo(expectedRoutes); }
public void BuildRoutes_MissingHost_Works() { var labels = new Dictionary <string, string>() { { "YARP.Routes.MyRoute.Path", "/{**catchall}" }, }; var routes = LabelsParser.BuildRoutes(_testServiceName, labels); var expectedRoutes = new List <ProxyRoute> { new ProxyRoute { RouteId = $"{Uri.EscapeDataString(_testServiceName.ToString())}:MyRoute", Match = new RouteMatch { Path = "/{**catchall}", }, ClusterId = _testServiceName.ToString(), Metadata = new Dictionary <string, string>(), }, }; routes.Should().BeEquivalentTo(expectedRoutes); }
public async void ExecuteAsync_OneServiceWithGatewayEnabledAndOneNotEnabled_OnlyTheOneEnabledFound() { _scenarioOptions = new ServiceFabricDiscoveryOptions { ReportReplicasHealth = true }; const string TestClusterIdApp1Sv1 = "MyService123"; const string TestClusterIdApp2Sv2 = "MyService234"; var gatewayEnabledLabels = SFTestHelpers.DummyLabels(TestClusterIdApp1Sv1); var gatewayNotEnabledLabels = SFTestHelpers.DummyLabels(TestClusterIdApp2Sv2, false); ApplicationWrapper application1, application2; Mock_AppsResponse( application1 = CreateApp_1Service_SingletonPartition_1Replica("MyApp", "MyService1", out var service1, out var replica1), application2 = CreateApp_1Service_SingletonPartition_1Replica("MyApp2", "MyService2", out var service2, out var replica2)); Mock_ServiceLabels(application1, service1, gatewayEnabledLabels); Mock_ServiceLabels(application2, service2, gatewayNotEnabledLabels); var(routes, clusters) = await RunScenarioAsync(); var expectedClusters = new[] { ClusterWithDestinations(_testServiceName, gatewayEnabledLabels, SFTestHelpers.BuildDestinationFromReplica(replica1)), }; var expectedRoutes = LabelsParser.BuildRoutes(_testServiceName, gatewayEnabledLabels); clusters.Should().BeEquivalentTo(expectedClusters); routes.Should().BeEquivalentTo(expectedRoutes); AssertServiceHealthReported(service1, HealthState.Ok); AssertStatelessServiceInstanceHealthReported(replica1, HealthState.Ok); _healthReports.Should().HaveCount(2); }
public async void ExecuteAsync_NotHttpsSchemeForStatelessService_NoEndpointsAndBadHealthReported() { _scenarioOptions = new ServiceFabricDiscoveryOptions { ReportReplicasHealth = true }; const string TestClusterId = "MyService123"; const string ServiceName = "fabric:/MyApp/MyService"; var labels = SFTestHelpers.DummyLabels(TestClusterId); labels["YARP.Backend.ServiceFabric.ListenerName"] = "ExampleTeamEndpoint"; ApplicationWrapper application; Mock_AppsResponse( application = CreateApp_1Service_SingletonPartition_1Replica("MyApp", "MyService", out var service, out var replica, serviceKind: ServiceKind.Stateless)); var nonHttpAddress = $"http://127.0.0.1/{ServiceName}/0"; replica.ReplicaAddress = $"{{'Endpoints': {{'ExampleTeamEndpoint': '{nonHttpAddress}' }} }}".Replace("'", "\""); Mock_ServiceLabels(application, service, labels); var(routes, clusters) = await RunScenarioAsync(); var expectedClusters = new[] { LabelsParser.BuildCluster(_testServiceName, labels, new Dictionary <string, Destination>()), }; var expectedRoutes = LabelsParser.BuildRoutes(_testServiceName, labels); clusters.Should().BeEquivalentTo(expectedClusters); routes.Should().BeEquivalentTo(expectedRoutes); AssertServiceHealthReported(service, HealthState.Ok); AssertStatelessServiceInstanceHealthReported(replica, HealthState.Warning, (description) => description.StartsWith("Could not build service endpoint") && description.Contains("ExampleTeamEndpoint")); _healthReports.Should().HaveCount(2); }
public void BuildRoutes_SingleRouteWithSemanticallyInvalidRule_WorksAndDoesNotThrow() { var labels = new Dictionary <string, string>() { { "YARP.Backend.BackendId", "MyCoolClusterId" }, { "YARP.Routes.MyRoute.Hosts", "'this invalid thing" }, }; var routes = LabelsParser.BuildRoutes(_testServiceName, labels); var expectedRoutes = new List <ProxyRoute> { new ProxyRoute { RouteId = "MyCoolClusterId:MyRoute", Match = new ProxyMatch { Hosts = new[] { "'this invalid thing" }, }, ClusterId = "MyCoolClusterId", Metadata = new Dictionary <string, string>(), }, }; routes.Should().BeEquivalentTo(expectedRoutes); }
public void BuildRoutes_IncompleteRoute_UsesDefaults() { var labels = new Dictionary <string, string>() { { "YARP.Backend.BackendId", "MyCoolClusterId" }, { "YARP.Routes.MyRoute.Hosts", "example.com" }, }; var routes = LabelsParser.BuildRoutes(_testServiceName, labels); var expectedRoutes = new List <ProxyRoute> { new ProxyRoute { RouteId = "MyCoolClusterId:MyRoute", Match = new ProxyMatch { Hosts = new[] { "example.com" }, }, ClusterId = "MyCoolClusterId", Metadata = new Dictionary <string, string>(), }, }; routes.Should().BeEquivalentTo(expectedRoutes); }
public void BuildRoutes_InvalidLabelKeys_IgnoresAndDoesNotThrow(string invalidKey, string value) { var labels = new Dictionary <string, string>() { { "YARP.Backend.BackendId", "MyCoolClusterId" }, { "YARP.Routes.MyRoute.Hosts", "example.com" }, { "YARP.Routes.MyRoute.Order", "2" }, { "YARP.Routes.MyRoute.Metadata.Foo", "Bar" }, }; labels[invalidKey] = value; var routes = LabelsParser.BuildRoutes(_testServiceName, labels); var expectedRoutes = new List <ProxyRoute> { new ProxyRoute { RouteId = "MyCoolClusterId:MyRoute", Match = new RouteMatch { Hosts = new[] { "example.com" }, }, Order = 2, ClusterId = "MyCoolClusterId", Metadata = new Dictionary <string, string> { { "Foo", "Bar" }, }, }, }; routes.Should().BeEquivalentTo(expectedRoutes); }
public void BuildRoutes_ValidRouteName_Works(string routeName) { var labels = new Dictionary <string, string>() { { "YARP.Backend.BackendId", "MyCoolClusterId" }, { $"YARP.Routes.{routeName}.Hosts", "example.com" }, { $"YARP.Routes.{routeName}.Order", "2" }, }; var routes = LabelsParser.BuildRoutes(_testServiceName, labels); var expectedRoutes = new List <ProxyRoute> { new ProxyRoute { RouteId = $"MyCoolClusterId:{routeName}", Match = new RouteMatch { Hosts = new[] { "example.com" }, }, Order = 2, ClusterId = "MyCoolClusterId", Metadata = new Dictionary <string, string>(), }, }; routes.Should().BeEquivalentTo(expectedRoutes); }
public void BuildRoutes_MultipleRoutes_Works() { var labels = new Dictionary <string, string>() { { "YARP.Backend.BackendId", "MyCoolClusterId" }, { "YARP.Routes.MyRoute.Hosts", "example.com" }, { "YARP.Routes.MyRoute.Path", "v2/{**rest}" }, { "YARP.Routes.MyRoute.Order", "1" }, { "YARP.Routes.MyRoute.Metadata.Foo", "Bar" }, { "YARP.Routes.CoolRoute.Hosts", "example.net" }, { "YARP.Routes.CoolRoute.Order", "2" }, { "YARP.Routes.EvenCoolerRoute.Hosts", "example.org" }, { "YARP.Routes.EvenCoolerRoute.Order", "3" }, }; var routes = LabelsParser.BuildRoutes(_testServiceName, labels); var expectedRoutes = new List <RouteConfig> { new RouteConfig { RouteId = "MyCoolClusterId:MyRoute", Match = new RouteMatch { Hosts = new[] { "example.com" }, Path = "v2/{**rest}", }, Order = 1, ClusterId = "MyCoolClusterId", Metadata = new Dictionary <string, string> { { "Foo", "Bar" } }, }, new RouteConfig { RouteId = "MyCoolClusterId:CoolRoute", Match = new RouteMatch { Hosts = new[] { "example.net" }, }, Order = 2, ClusterId = "MyCoolClusterId", Metadata = new Dictionary <string, string>(), }, new RouteConfig { RouteId = "MyCoolClusterId:EvenCoolerRoute", Match = new RouteMatch { Hosts = new[] { "example.org" }, }, Order = 3, ClusterId = "MyCoolClusterId", Metadata = new Dictionary <string, string>(), }, }; routes.Should().BeEquivalentTo(expectedRoutes); }
public async void ExecuteAsync_MultipleServicesWithGatewayEnabled_MultipleClustersFound() { // Setup _scenarioOptions = new ServiceFabricDiscoveryOptions { ReportReplicasHealth = true }; const string TestClusterIdApp1Sv1 = "MyService123"; const string TestClusterIdApp1Sv2 = "MyService234"; const string TestClusterIdApp2Sv3 = "MyService345"; var labels1 = SFTestHelpers.DummyLabels(TestClusterIdApp1Sv1); var labels2 = SFTestHelpers.DummyLabels(TestClusterIdApp1Sv2); var labels3 = SFTestHelpers.DummyLabels(TestClusterIdApp2Sv3); ApplicationWrapper application1, application2; Mock_AppsResponse( application1 = CreateApp_1Service_SingletonPartition_1Replica("MyApp", "MYService", out var service1, out var replica1), application2 = CreateApp_2StatelessService_SingletonPartition_1Replica("MyApp2", "MyService2", "MyService3", out var service2, out var service3, out var replica2, out var replica3)); Mock_ServiceLabels(application1, service1, labels1); Mock_ServiceLabels(application2, service2, labels2); Mock_ServiceLabels(application2, service3, labels3); // Act var(routes, clusters) = await RunScenarioAsync(); // Assert var expectedClusters = new[] { ClusterWithDestinations( LabelsParser.BuildCluster(_testServiceName, labels1), SFTestHelpers.BuildDestinationFromReplica(replica1)), ClusterWithDestinations( LabelsParser.BuildCluster(_testServiceName, labels2), SFTestHelpers.BuildDestinationFromReplica(replica2)), ClusterWithDestinations( LabelsParser.BuildCluster(_testServiceName, labels3), SFTestHelpers.BuildDestinationFromReplica(replica3)), }; var expectedRoutes = new List <ProxyRoute>(); expectedRoutes.AddRange(LabelsParser.BuildRoutes(_testServiceName, labels1)); expectedRoutes.AddRange(LabelsParser.BuildRoutes(_testServiceName, labels2)); expectedRoutes.AddRange(LabelsParser.BuildRoutes(_testServiceName, labels3)); clusters.Should().BeEquivalentTo(expectedClusters); routes.Should().BeEquivalentTo(expectedRoutes); AssertServiceHealthReported(service1, HealthState.Ok); AssertServiceHealthReported(service2, HealthState.Ok); AssertServiceHealthReported(service3, HealthState.Ok); AssertStatelessServiceInstanceHealthReported(replica1, HealthState.Ok); AssertStatelessServiceInstanceHealthReported(replica2, HealthState.Ok); AssertStatelessServiceInstanceHealthReported(replica3, HealthState.Ok); _healthReports.Should().HaveCount(6); }
public void BuildCluster_NullTimespan(string value) { var labels = new Dictionary <string, string>() { { "YARP.Backend.HealthCheck.Active.Interval", value }, }; var cluster = LabelsParser.BuildCluster(_testServiceName, labels, null); cluster.HealthCheck.Active.Interval.Should().BeNull(); }
public void BuildCluster_HealthCheckOptions_Enabled_Invalid(string label) { var labels = new Dictionary <string, string>() { { "YARP.Backend.BackendId", "MyCoolClusterId" }, { "YARP.Backend.HealthCheck.Active.Enabled", label }, }; Action action = () => LabelsParser.BuildCluster(_testServiceName, labels, null); action.Should().Throw <ConfigException>(); }
public void BuildCluster_HealthCheckOptions_Enabled_Valid(string label, bool?expected) { var labels = new Dictionary <string, string>() { { "YARP.Backend.BackendId", "MyCoolClusterId" }, { "YARP.Backend.HealthCheck.Active.Enabled", label }, }; var cluster = LabelsParser.BuildCluster(_testServiceName, labels, null); cluster.HealthCheck.Active.Enabled.Should().Be(expected); }
private static Cluster ClusterWithDestinations(Uri serviceName, Dictionary <string, string> labels, params KeyValuePair <string, Destination>[] destinations) { var newDestinations = new Dictionary <string, Destination>(StringComparer.OrdinalIgnoreCase); foreach (var destination in destinations) { newDestinations.Add(destination.Key, destination.Value); } return(LabelsParser.BuildCluster(serviceName, labels, newDestinations)); }
public void BuildCluster_InvalidValues_Throws(string key, string invalidValue) { var labels = new Dictionary <string, string>() { { "YARP.Backend.BackendId", "MyCoolClusterId" }, { key, invalidValue }, }; Func <ClusterConfig> func = () => LabelsParser.BuildCluster(_testServiceName, labels, null); func.Should().Throw <ConfigException>().WithMessage($"Could not convert label {key}='{invalidValue}' *"); }
public async void ExecuteAsync_SomeUnhealthyReplicas_OnlyHealthyReplicasAreUsed() { // Setup _scenarioOptions = new ServiceFabricDiscoveryOptions { ReportReplicasHealth = true }; const string TestClusterId = "MyService123"; var labels = SFTestHelpers.DummyLabels(TestClusterId); ApplicationWrapper application; Mock_AppsResponse( application = CreateApp_1StatelessService_2Partition_2ReplicasEach( "MyApp", "MYService", out var service, out var replicas)); Mock_ServiceLabels(application, service, labels); replicas[0].ReplicaStatus = ServiceReplicaStatus.Ready; // Should be used despite Warning health state replicas[0].HealthState = HealthState.Warning; replicas[1].ReplicaStatus = ServiceReplicaStatus.Ready; // Should be used replicas[1].HealthState = HealthState.Ok; replicas[2].ReplicaStatus = ServiceReplicaStatus.Ready; // Should be used despite Error health state replicas[2].HealthState = HealthState.Error; replicas[3].ReplicaStatus = ServiceReplicaStatus.Down; // Should be skipped because of status replicas[3].HealthState = HealthState.Ok; // Act var(routes, clusters) = await RunScenarioAsync(); // Assert var expectedClusters = new[] { ClusterWithDestinations( LabelsParser.BuildCluster(_testServiceName, labels), SFTestHelpers.BuildDestinationFromReplica(replicas[0]), SFTestHelpers.BuildDestinationFromReplica(replicas[1]), SFTestHelpers.BuildDestinationFromReplica(replicas[2])), }; var expectedRoutes = LabelsParser.BuildRoutes(_testServiceName, labels); clusters.Should().BeEquivalentTo(expectedClusters); routes.Should().BeEquivalentTo(expectedRoutes); AssertServiceHealthReported(service, HealthState.Ok); AssertStatelessServiceInstanceHealthReported(replicas[0], HealthState.Ok); AssertStatelessServiceInstanceHealthReported(replicas[1], HealthState.Ok); AssertStatelessServiceInstanceHealthReported(replicas[2], HealthState.Ok); _healthReports.Should().HaveCount(4); // 1 service + 3 replicas = 4 health reports }
public void BuildRoutes_InvalidOrder_Throws() { var labels = new Dictionary <string, string>() { { "YARP.Backend.BackendId", "MyCoolClusterId" }, { "YARP.Routes.MyRoute.Hosts", "example.com" }, { "YARP.Routes.MyRoute.Order", "this is no number" }, }; Func <List <RouteConfig> > func = () => LabelsParser.BuildRoutes(_testServiceName, labels); func.Should() .Throw <ConfigException>() .WithMessage("Could not convert label YARP.Routes.MyRoute.Order='this is no number' *"); }
public void BuildCluster_MissingBackendId_UsesServiceName() { var labels = new Dictionary <string, string>() { { "YARP.Backend.Quota.Burst", "2.3" }, { "YARP.Backend.Partitioning.Count", "5" }, { "YARP.Backend.Partitioning.KeyExtractor", "Header('x-ms-organization-id')" }, { "YARP.Backend.Partitioning.Algorithm", "SHA256" }, { "YARP.Backend.HealthCheck.Active.Interval", "00:00:5" }, }; var cluster = LabelsParser.BuildCluster(_testServiceName, labels, null); cluster.ClusterId.Should().Be(_testServiceName.ToString()); }
public void BuildCluster_CompleteLabels_Works() { // Arrange var labels = new Dictionary <string, string>() { { "YARP.Enable", "true" }, { "YARP.Backend.BackendId", "MyCoolClusterId" }, { "YARP.Backend.CircuitBreaker.MaxConcurrentRequests", "42" }, { "YARP.Backend.CircuitBreaker.MaxConcurrentRetries", "5" }, { "YARP.Backend.Quota.Average", "1.2" }, { "YARP.Backend.Quota.Burst", "2.3" }, { "YARP.Backend.Partitioning.Count", "5" }, { "YARP.Backend.Partitioning.KeyExtractor", "Header('x-ms-organization-id')" }, { "YARP.Backend.Partitioning.Algorithm", "SHA256" }, { "YARP.Backend.Healthcheck.Active.Enabled", "true" }, { "YARP.Backend.Healthcheck.Active.Interval", "5" }, { "YARP.Backend.Healthcheck.Active.Timeout", "5" }, { "YARP.Backend.Healthcheck.Active.Path", "/api/health" }, { "YARP.Backend.Metadata.Foo", "Bar" }, }; // Act var cluster = LabelsParser.BuildCluster(_testServiceName, labels); // Assert var expectedCluster = new Cluster { Id = "MyCoolClusterId", LoadBalancing = new LoadBalancingOptions(), HealthCheck = new HealthCheckOptions { Active = new ActiveHealthCheckOptions { Enabled = true, Interval = TimeSpan.FromSeconds(5), Timeout = TimeSpan.FromSeconds(5), Path = "/api/health", }, }, Metadata = new Dictionary <string, string> { { "Foo", "Bar" }, }, }; cluster.Should().BeEquivalentTo(expectedCluster); }
public void BuildRoutes_InvalidTransformIndex_Throws(string invalidKey, string value) { var labels = new Dictionary <string, string>() { { "YARP.Backend.BackendId", "MyCoolClusterId" }, { "YARP.Routes.MyRoute.Hosts", "example.com" }, { "YARP.Routes.MyRoute.Priority", "2" }, { "YARP.Routes.MyRoute.Metadata.Foo", "Bar" }, }; labels[invalidKey] = value; Func <List <RouteConfig> > func = () => LabelsParser.BuildRoutes(_testServiceName, labels); func.Should() .Throw <ConfigException>() .WithMessage($"Invalid transform index '*', should be transform index wrapped in square brackets."); }
public void BuildRoutes_InvalidRouteName_Throws(string invalidKey, string value) { var labels = new Dictionary <string, string>() { { "YARP.Backend.BackendId", "MyCoolClusterId" }, { "YARP.Routes.MyRoute.Hosts", "example.com" }, { "YARP.Routes.MyRoute.Priority", "2" }, { "YARP.Routes.MyRoute.Metadata.Foo", "Bar" }, }; labels[invalidKey] = value; Func <List <RouteConfig> > func = () => LabelsParser.BuildRoutes(_testServiceName, labels); func.Should() .Throw <ConfigException>() .WithMessage($"Invalid route name '*', should only contain alphanumerical characters, underscores or hyphens."); }
public void BuildRoutes_MatchHeadersWithCSVs_Works(string invalidKey, string value, string[] expected) { // Arrange var labels = new Dictionary <string, string>() { { "YARP.Backend.BackendId", "MyCoolClusterId" }, { "YARP.Routes.MyRoute0.Hosts", "example0.com" }, { "YARP.Routes.MyRoute0.Metadata.Foo", "bar" }, { "YARP.Routes.MyRoute0.MatchHeaders.[0].Name", "x-test-header" }, { "YARP.Routes.MyRoute0.MatchHeaders.[0].Mode", "ExactHeader" }, }; labels[invalidKey] = value; // Act var routes = LabelsParser.BuildRoutes(_testServiceName, labels); // Assert var expectedRoutes = new List <ProxyRoute> { new ProxyRoute { RouteId = $"MyCoolClusterId:MyRoute0", Match = { Hosts = new[] { "example0.com" }, Headers = new List <RouteHeader>() { new RouteHeader() { Name = "x-test-header", Mode = HeaderMatchMode.ExactHeader, Values = expected }, } }, Metadata = new Dictionary <string, string>() { { "Foo", "bar" } }, ClusterId = "MyCoolClusterId", } }; routes.Should().BeEquivalentTo(expectedRoutes); }
public void BuildRoutes_InvalidHeaderMatchProperty_Throws(string invalidKey, string value) { // Arrange var labels = new Dictionary <string, string>() { { "YARP.Backend.BackendId", "MyCoolClusterId" }, { "YARP.Routes.MyRoute.Hosts", "example.com" }, { "YARP.Routes.MyRoute.Priority", "2" }, { "YARP.Routes.MyRoute.Metadata.Foo", "Bar" }, }; labels[invalidKey] = value; // Act Func <List <RouteConfig> > func = () => LabelsParser.BuildRoutes(_testServiceName, labels); // Assert func.Should() .Throw <ConfigException>() .WithMessage($"Invalid header matching property '*', only valid values are Name, Values, IsCaseSensitive and Mode."); }