public static IServiceCollection AddHealthChecksUI(this IServiceCollection services, string databaseName = "healthchecksdb") { var configuration = services.BuildServiceProvider() .GetService <IConfiguration>(); services.AddOptions(); services.Configure <Settings>((settings) => { configuration.Bind(Keys.HEALTHCHECKSUI_SECTION_SETTING_KEY, settings); }); services.AddSingleton <IHostedService, HealthCheckCollectorHostedService>(); services.AddScoped <IHealthCheckFailureNotifier, WebHookFailureNotifier>(); services.AddScoped <IHealthCheckReportCollector, HealthCheckReportCollector>(); services.AddDbContext <HealthChecksDb>(db => { db.UseSqlite($"Data Source={databaseName}"); }); var kubernetesDiscoveryOptions = new KubernetesDiscoveryOptions(); configuration.Bind(Keys.HEALTHCHECKSUI_KUBERNETES_DISCOVERY_SETTING_KEY, kubernetesDiscoveryOptions); if (kubernetesDiscoveryOptions.Enabled) { services.AddSingleton(kubernetesDiscoveryOptions); services.AddHostedService <KubernetesDiscoveryHostedService>(); } var serviceProvider = services.BuildServiceProvider(); CreateDatabase(serviceProvider).Wait(); return(services); }
public void GetInstances_ShouldBeAbleToHandleEndpointsFromMultipleNamespaces() { // arrange var mockHttpMessageHandler = new MockHttpMessageHandler(); mockHttpMessageHandler.Expect(HttpMethod.Get, "/api/v1/endpoints?fieldSelector=metadata.name%3Dendpoint") .Respond( HttpStatusCode.OK, new StringContent("{\"apiVersion\":\"v1\",\"items\":[{\"apiVersion\":\"v1\",\"kind\":\"Endpoints\",\"metadata\":{\"name\":\"endpoint\",\"namespace\":\"test\"},\"subsets\":[{\"addresses\":[{\"ip\":\"ip1\", \"targetRef\": {\"uid\":\"uid1\"}}],\"ports\":[{\"name\":\"http\",\"port\":80,\"protocol\":\"TCP\"}]}]},{\"apiVersion\":\"v1\",\"kind\":\"Endpoints\",\"metadata\":{\"name\":\"endpoint\",\"namespace\":\"test2\"},\"subsets\":[{\"addresses\":[{\"ip\":\"ip2\",\"targetRef\": {\"uid\":\"uid2\"}}],\"ports\":[{\"name\":\"http\",\"port\":80,\"protocol\":\"TCP\"}]}]}],\"kind\":\"List\",\"metadata\":{\"resourceVersion\":\"\",\"selfLink\":\"\"}}")); mockHttpMessageHandler.When(HttpMethod.Get, "/api/v1/namespaces/test/services") .WithQueryString("fieldSelector=metadata.name%3Dendpoint") .Respond( HttpStatusCode.OK, new StringContent( "{\"apiVersion\":\"v1\",\"items\":[{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"labels\":{\"l\":\"v\"},\"name\":\"endpoint\",\"namespace\":\"test\",\"uid\":\"uids1\"}}],\"kind\":\"List\",\"metadata\":{\"resourceVersion\":\"\",\"selfLink\":\"\"}}")); mockHttpMessageHandler.When(HttpMethod.Get, "/api/v1/namespaces/test2/services") .WithQueryString("fieldSelector=metadata.name%3Dendpoint") .Respond( HttpStatusCode.OK, new StringContent( "{\"apiVersion\":\"v1\",\"items\":[{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"labels\":{\"l\":\"v\"},\"name\":\"endpoint\",\"namespace\":\"test2\",\"uid\":\"uids2\"}}],\"kind\":\"List\",\"metadata\":{\"resourceVersion\":\"\",\"selfLink\":\"\"}}")); using var client = new Kubernetes( config: new KubernetesClientConfiguration { Host = "http://localhost" }, httpClient: mockHttpMessageHandler.ToHttpClient()); var options = new KubernetesDiscoveryOptions() { AllNamespaces = true }; IDiscoveryClient discoveryClient = new KubernetesDiscoveryClient( new DefaultIsServicePortSecureResolver(options), client, options); // act var genericInstances = discoveryClient.GetInstances("endpoint"); var instances = genericInstances.Select(s => (KubernetesServiceInstance)s).ToList(); // assert Assert.NotNull(instances); Assert.Equal(actual: instances.Count, expected: 2); Assert.Equal( actual: instances.Count(s => s.Host.Equals("ip1") && !s.IsSecure), expected: 1); Assert.Equal( actual: instances.Count(s => s.Host.Equals("ip2") && !s.IsSecure), expected: 1); Assert.Equal( actual: instances.Count(s => s.InstanceId.Equals("uid1")), expected: 1); Assert.Equal( actual: instances.Count(s => s.InstanceId.Equals("uid2")), expected: 1); }
public void GetInstances_ThrowsOnNull() { var k8SDiscoveryOptions = new KubernetesDiscoveryOptions(); using var client = new Kubernetes(new KubernetesClientConfiguration { Host = "http://localhost" }); var testK8SDiscoveryClient = new KubernetesDiscoveryClient( new DefaultIsServicePortSecureResolver(k8SDiscoveryOptions), client, k8SDiscoveryOptions); Assert.Throws <ArgumentNullException>(() => testK8SDiscoveryClient.GetInstances(null)); }
public void EnabledPropertyWorksBothWays() { // arrange var mockHttpMessageHandler = new MockHttpMessageHandler(); mockHttpMessageHandler .When(HttpMethod.Get, "/api/v1/namespaces/test/services") .Respond( HttpStatusCode.OK, new StringContent( "{\"apiVersion\":\"v1\",\"items\":[{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":" + "{\"labels\":{\"label1\":\"value1\"},\"name\":\"endpoint1\",\"namespace\":\"test\",\"uid\":" + "\"uids1\"}},{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"labels\":{\"label2\":" + "\"value2\"},\"name\":\"endpoint2\",\"namespace\":\"test\",\"uid\":\"uids2\"}}]," + "\"kind\":\"List\",\"metadata\"" + ":{\"resourceVersion\":\"\",\"selfLink\":\"\"}}")); using var client = new k8s.Kubernetes( config: new KubernetesClientConfiguration { Host = "http://localhost" }, httpClient: mockHttpMessageHandler.ToHttpClient()); var k8sOptions = new KubernetesDiscoveryOptions() { Enabled = false, Namespace = "test" }; var options = new TestOptionsMonitor <KubernetesDiscoveryOptions>(k8sOptions); var discoveryClient = new KubernetesDiscoveryClient( new DefaultIsServicePortSecureResolver(options.CurrentValue), client, options); // act var services = discoveryClient.Services; // assert Assert.NotNull(services); Assert.Empty(services); // turn it on k8sOptions.Enabled = true; // act services = discoveryClient.Services; // assert Assert.NotNull(services); Assert.Equal(actual: services.Count, expected: 2); Assert.True(services.Contains("endpoint1")); Assert.True(services.Contains("endpoint2")); }
public void PortNumbers_ShouldBeSecuredIfDefaultOrAdded() { var properties = new KubernetesDiscoveryOptions(); properties.KnownSecurePorts.Add(12345); var sut = new DefaultIsServicePortSecureResolver(properties); Assert.False(sut.Resolve(new Input("dummy"))); Assert.False(sut.Resolve(new Input("dummy", 8080))); Assert.False(sut.Resolve(new Input("dummy", 1234))); Assert.True(sut.Resolve(new Input("dummy", 443))); Assert.True(sut.Resolve(new Input("dummy", 8443))); Assert.True(sut.Resolve(new Input("dummy", 12345))); }
public static IDiscoveryClient CreateClient(KubernetesDiscoveryOptions options, IKubernetes kubernetes) { if (options == null) { throw new ArgumentNullException(nameof(options)); } if (kubernetes == null) { throw new ArgumentNullException(nameof(kubernetes)); } var isServicePortSecureResolver = new DefaultIsServicePortSecureResolver(options); return(new KubernetesDiscoveryClient(isServicePortSecureResolver, kubernetes, options)); }
public void Constructor_Initializes_Correctly() { // arrange var mockHttpMessageHandler = new MockHttpMessageHandler(); using var client = new Kubernetes(new KubernetesClientConfiguration { Host = "http://localhost" }, mockHttpMessageHandler.ToHttpClient()); const string expectedDesc = "Steeltoe provided Kubernetes native service discovery client"; var k8SDiscoveryOptions = new KubernetesDiscoveryOptions(); // act var testK8SDiscoveryClient = new KubernetesDiscoveryClient( new DefaultIsServicePortSecureResolver(k8SDiscoveryOptions), client, k8SDiscoveryOptions); // assert Assert.Equal(expectedDesc, testK8SDiscoveryClient.Description); }
public void GetServices_ShouldReturnOnlyMatchingServicesWhenLabelsAreAppliedToTheClient() { // arrange var mockHttpMessageHandler = new MockHttpMessageHandler(); mockHttpMessageHandler.When(HttpMethod.Get, "/api/v1/namespaces/test/services") .WithQueryString("labelSelector=label%3Dvalue") .Respond( HttpStatusCode.OK, new StringContent( "{\"apiVersion\":\"v1\",\"items\":[{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":" + "{\"labels\":{\"label1\":\"value1\"},\"name\":\"endpoint1\",\"namespace\":\"test\",\"uid\":" + "\"uids1\"}},{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"labels\":{\"label2\":" + "\"value2\"},\"name\":\"endpoint2\",\"namespace\":\"test\",\"uid\":\"uids2\"}}]," + "\"kind\":\"List\",\"metadata\"" + ":{\"resourceVersion\":\"\",\"selfLink\":\"\"}}")); using var client = new Kubernetes( config: new KubernetesClientConfiguration { Host = "http://localhost" }, httpClient: mockHttpMessageHandler.ToHttpClient()); var options = new KubernetesDiscoveryOptions() { Namespace = "test" }; var discoveryClient = new KubernetesDiscoveryClient( new DefaultIsServicePortSecureResolver(options), client, options); // act var services = discoveryClient.GetServices(new Dictionary <string, string> { { "label", "value" } }); // assert Assert.NotNull(services); Assert.Equal(actual: services.Count, expected: 2); Assert.True(services.Contains("endpoint1")); Assert.True(services.Contains("endpoint2")); }
public static IServiceCollection AddBeatPulseUI(this IServiceCollection services) { var configuration = services.BuildServiceProvider() .GetService <IConfiguration>(); services.AddOptions(); services.Configure <BeatPulseSettings>((settings) => { configuration.Bind(BeatPulseUIKeys.BEATPULSEUI_SECTION_SETTING_KEY, settings); }); services.AddSingleton <IHostedService, LivenessHostedService>(); services.AddScoped <ILivenessFailureNotifier, WebHookFailureNotifier>(); services.AddScoped <ILivenessRunner, LivenessRunner>(); services.AddDbContext <LivenessDb>(db => { db.UseSqlite("Data Source=livenessdb"); }); var kubernetesDiscoveryOptions = new KubernetesDiscoveryOptions(); configuration.Bind(BeatPulseUIKeys.BEATPULSEUI_KUBERNETES_DISCOVERY_SETTING_KEY, kubernetesDiscoveryOptions); if (kubernetesDiscoveryOptions.Enabled) { services.AddSingleton(kubernetesDiscoveryOptions); services.AddHostedService <KubernetesDiscoveryHostedService>(); } var serviceProvider = services.BuildServiceProvider(); CreateDatabase(serviceProvider).Wait(); return(services); }