diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java index 0b069f42..721dad40 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package org.springframework.cloud.kubernetes.client.discovery; -import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -29,12 +28,8 @@ import io.kubernetes.client.openapi.models.V1EndpointSubset; import io.kubernetes.client.openapi.models.V1Endpoints; import io.kubernetes.client.openapi.models.V1ObjectMeta; import io.kubernetes.client.openapi.models.V1Service; -import io.kubernetes.client.openapi.models.V1ServiceSpec; -import io.kubernetes.client.openapi.models.V1ServiceStatus; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.kubernetes.commons.discovery.DefaultKubernetesServiceInstance; @@ -42,404 +37,313 @@ import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscover import static org.assertj.core.api.Assertions.assertThat; -@RunWith(MockitoJUnitRunner.class) -public class KubernetesInformerDiscoveryClientTests { +class KubernetesInformerDiscoveryClientTests { - @Mock - private SharedInformerFactory sharedInformerFactory; + private static final V1Service SERVICE_1 = service("test-svc-1", "namespace1", Map.of()); - private static final V1Service testService1 = new V1Service() - .metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1")) - .spec(new V1ServiceSpec().loadBalancerIP("1.1.1.1")).status(new V1ServiceStatus()); + private static final V1Service SERVICE_2 = service("test-svc-1", "namespace2", Map.of()); - private static final V1Service testServiceSecuredAnnotation1 = new V1Service() - .metadata( - new V1ObjectMeta().name("test-svc-1").namespace("namespace1").putAnnotationsItem("secured", "true")) - .spec(new V1ServiceSpec().loadBalancerIP("1.1.1.1")).status(new V1ServiceStatus()); + private static final V1Service SERVICE_3 = service("test-svc-3", "namespace1", + Map.of("spring", "true", "k8s", "true")); - private static final V1Service testServiceSecuredLabel1 = new V1Service() - .metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1").putLabelsItem("secured", "true")) - .spec(new V1ServiceSpec().loadBalancerIP("1.1.1.1")).status(new V1ServiceStatus()); + private static final V1Service SERVICE_4 = service("test-svc-1", "namespace1", Map.of("secured", "true")); - private static final V1Service testService2 = new V1Service() - .metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace2")) - .spec(new V1ServiceSpec().loadBalancerIP("1.1.1.1")).status(new V1ServiceStatus()); + private static final V1Service SERVICE_5 = service("test-svc-1", "namespace1", Map.of("primary-port-name", "oops")); - private static final V1Service testService3 = new V1Service() - .metadata(new V1ObjectMeta().name("test-svc-3").namespace("namespace1").putLabelsItem("spring", "true") - .putLabelsItem("k8s", "true")) - .spec(new V1ServiceSpec().loadBalancerIP("1.1.1.1")).status(new V1ServiceStatus()); + private static final V1Service SERVICE_6 = service("test-svc-1", "namespace1", + Map.of("primary-port-name", "https")); - private static final V1Endpoints testEndpoints1 = new V1Endpoints() - .metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1")) - .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().port(8080)) - .addAddressesItem(new V1EndpointAddress().ip("2.2.2.2"))); + private static final SharedInformerFactory SHARED_INFORMER_FACTORY = Mockito.mock(SharedInformerFactory.class); - private static final V1Endpoints testEndpoints2 = new V1Endpoints() - .metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace2")) - .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().port(8080)) - .addAddressesItem(new V1EndpointAddress().ip("2.2.2.2"))); + private static final V1Endpoints ENDPOINTS_1 = endpointsReadyAddress("test-svc-1", "namespace1"); - private static final V1Endpoints testEndpointWithoutReadyAddresses = new V1Endpoints() - .metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1")) - .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().port(8080)) - .addNotReadyAddressesItem(new V1EndpointAddress().ip("2.2.2.2"))); + private static final V1Endpoints ENDPOINTS_2 = endpointsReadyAddress("test-svc-1", "namespace2"); - private static final V1Endpoints testEndpointWithoutPorts = new V1Endpoints() - .metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1")) - .addSubsetsItem(new V1EndpointSubset().addAddressesItem(new V1EndpointAddress().ip("1.1.1.1"))); + private static final V1Endpoints ENDPOINTS_3 = endpointsReadyAddress("test-svc-3", "namespace1"); - private static final V1Endpoints testEndpointWithUnsetPortName = new V1Endpoints() - .metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1")) - .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().port(80)) - .addAddressesItem(new V1EndpointAddress().ip("1.1.1.1"))); + private static final V1Endpoints ENDPOINTS_NOT_READY_ADDRESS = endpointsNotReadyAddress(); - private static final V1Endpoints testEndpointWithMultiplePorts = new V1Endpoints() - .metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1")) - .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().name("http").port(80)) - .addPortsItem(new CoreV1EndpointPort().name("https").port(443)) - .addAddressesItem(new V1EndpointAddress().ip("1.1.1.1"))); + private static final V1Endpoints ENDPOINTS_NO_PORTS = endpointsNoPorts(); - private static final V1Endpoints testEndpointWithMultiplePortsWithoutHttps = new V1Endpoints() - .metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1")) - .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().name("http").port(80)) - .addPortsItem(new CoreV1EndpointPort().name("tcp").port(443)) - .addAddressesItem(new V1EndpointAddress().ip("1.1.1.1"))); + private static final V1Endpoints ENDPOINTS_NO_UNSET_PORT_NAME = endpointsNoUnsetPortName(); - private static final V1Endpoints testEndpointWithMultiplePortsWithoutSupportedPortNames = new V1Endpoints() - .metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1")) - .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().name("tcp1").port(80)) - .addPortsItem(new CoreV1EndpointPort().name("tcp2").port(443)) - .addAddressesItem(new V1EndpointAddress().ip("1.1.1.1"))); + private static final V1Endpoints ENDPOINTS_WITH = endpointsWithMultiplePorts(); - private static final V1Endpoints testEndpoints3 = new V1Endpoints() - .metadata(new V1ObjectMeta().name("test-svc-3").namespace("namespace1")) - .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().port(8080)) - .addAddressesItem(new V1EndpointAddress().ip("2.2.2.2"))); + private static final V1Endpoints ENDPOINTS_WITH_MULTIPLE_PORTS_NO_HTTPS = endpointsWithMultiplePortsNoHttps(); + + private static final V1Endpoints ENDPOINTS_MULTIPLE_PORTS_WITHOUT_SUPPORTED_PORT_NAMES = endpointsMultiplePortsWithoutSupportedPortNames(); + + private static final KubernetesDiscoveryProperties ALL_NAMESPACES = properties(true, Map.of()); + + private static final KubernetesDiscoveryProperties NOT_ALL_NAMESPACES = properties(false, Map.of()); @Test - public void testServiceWithUnsetPortNames() { - Lister serviceLister = setupServiceLister(testService1); - Lister endpointsLister = setupEndpointsLister(testEndpointWithUnsetPortName); - - KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, true, - Set.of(), true, 60, false, null, Set.of(), Map.of(), null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true); + void testServiceWithUnsetPortNames() { + Lister serviceLister = setupServiceLister(SERVICE_1); + Lister endpointsLister = setupEndpointsLister(ENDPOINTS_NO_UNSET_PORT_NAME); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("", - sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, ALL_NAMESPACES); - Map ports = new HashMap<>(); - ports.put("", "80"); assertThat(discoveryClient.getInstances("test-svc-1").toArray()) - .containsOnly(new DefaultKubernetesServiceInstance("", "test-svc-1", "1.1.1.1", 80, ports, false, - "namespace1", null)); + .containsOnly(new DefaultKubernetesServiceInstance("", "test-svc-1", "1.1.1.1", 80, + Map.of("", "80"), false, "namespace1", null)); } @Test - public void testDiscoveryGetServicesAllNamespaceShouldWork() { - Lister serviceLister = setupServiceLister(testService1, testService2); + void testDiscoveryGetServicesAllNamespaceShouldWork() { + Lister serviceLister = setupServiceLister(SERVICE_1, SERVICE_2); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("", - sharedInformerFactory, serviceLister, null, null, null, KubernetesDiscoveryProperties.DEFAULT); + SHARED_INFORMER_FACTORY, serviceLister, null, null, null, KubernetesDiscoveryProperties.DEFAULT); - assertThat(discoveryClient.getServices().toArray()).containsOnly(testService1.getMetadata().getName(), - testService2.getMetadata().getName()); + assertThat(discoveryClient.getServices().toArray()).containsOnly(SERVICE_1.getMetadata().getName(), + SERVICE_2.getMetadata().getName()); } @Test - public void testDiscoveryWithServiceLabels() { - Lister serviceLister = setupServiceLister(testService1, testService2, testService3); + void testDiscoveryWithServiceLabels() { + Lister serviceLister = setupServiceLister(SERVICE_1, SERVICE_2, SERVICE_3); - Map labels = new HashMap<>(); - labels.put("k8s", "true"); - labels.put("spring", "true"); - - KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, true, - Set.of(), true, 60, false, null, Set.of(), labels, null, null, 0, true); + Map labels = Map.of("k8s", "true", "spring", "true"); + KubernetesDiscoveryProperties kubernetesDiscoveryProperties = properties(true, labels); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("", - sharedInformerFactory, serviceLister, null, null, null, kubernetesDiscoveryProperties); + SHARED_INFORMER_FACTORY, serviceLister, null, null, null, kubernetesDiscoveryProperties); - assertThat(discoveryClient.getServices().toArray()).containsOnly(testService3.getMetadata().getName()); + assertThat(discoveryClient.getServices().toArray()).containsOnly(SERVICE_3.getMetadata().getName()); } @Test - public void testDiscoveryInstancesWithServiceLabels() { - Lister serviceLister = setupServiceLister(testService1, testService2, testService3); - Lister endpointsLister = setupEndpointsLister(testEndpoints1, testEndpoints3); + void testDiscoveryInstancesWithServiceLabels() { + Lister serviceLister = setupServiceLister(SERVICE_1, SERVICE_2, SERVICE_3); + Lister endpointsLister = setupEndpointsLister(ENDPOINTS_1, ENDPOINTS_3); - Map labels = new HashMap<>(); - labels.put("k8s", "true"); - labels.put("spring", "true"); - - KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, true, - Set.of(), true, 60, false, null, Set.of(), labels, null, null, 0, true); + Map labels = Map.of("k8s", "true", "spring", "true"); + KubernetesDiscoveryProperties kubernetesDiscoveryProperties = properties(true, labels); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("", - sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); assertThat(discoveryClient.getInstances("test-svc-1").toArray()).isEmpty(); assertThat(discoveryClient.getInstances("test-svc-3").toArray()) - .containsOnly(new DefaultKubernetesServiceInstance("", "test-svc-3", "2.2.2.2", 8080, new HashMap<>(), - false, "namespace1", null)); + .containsOnly(new DefaultKubernetesServiceInstance("", "test-svc-3", "2.2.2.2", 8080, + Map.of("spring", "true", "", "8080", "k8s", "true"), false, "namespace1", null)); } @Test - public void testDiscoveryInstancesWithSecuredServiceByAnnotations() { - Lister serviceLister = setupServiceLister(testServiceSecuredAnnotation1); - Lister endpointsLister = setupEndpointsLister(testEndpoints1); - KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, true, - Set.of(), true, 60, false, null, Set.of(), new HashMap<>(), null, null, 0, false); + void testDiscoveryInstancesWithSecuredServiceByAnnotations() { + Lister serviceLister = setupServiceLister(SERVICE_4); + Lister endpointsLister = setupEndpointsLister(ENDPOINTS_1); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1", - sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); - assertThat(discoveryClient.getServices().toArray()) - .containsOnly(testServiceSecuredAnnotation1.getMetadata().getName()); - ServiceInstance serviceInstance = discoveryClient - .getInstances(testServiceSecuredAnnotation1.getMetadata().getName()).get(0); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, ALL_NAMESPACES); + assertThat(discoveryClient.getServices().toArray()).containsOnly(SERVICE_4.getMetadata().getName()); + ServiceInstance serviceInstance = discoveryClient.getInstances(SERVICE_4.getMetadata().getName()).get(0); assertThat(serviceInstance.isSecure()).isTrue(); } @Test - public void testDiscoveryInstancesWithSecuredServiceByLabels() { - Lister serviceLister = setupServiceLister(testServiceSecuredLabel1); - Lister endpointsLister = setupEndpointsLister(testEndpoints1); - KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, true, - Set.of(), true, 60, false, null, Set.of(), new HashMap<>(), null, null, 0, false); + void testDiscoveryInstancesWithSecuredServiceByLabels() { + Lister serviceLister = setupServiceLister(SERVICE_4); + Lister endpointsLister = setupEndpointsLister(ENDPOINTS_1); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1", - sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, ALL_NAMESPACES); - assertThat(discoveryClient.getServices().toArray()) - .containsOnly(testServiceSecuredLabel1.getMetadata().getName()); - ServiceInstance serviceInstance = discoveryClient.getInstances(testServiceSecuredLabel1.getMetadata().getName()) - .get(0); + assertThat(discoveryClient.getServices().toArray()).containsOnly(SERVICE_4.getMetadata().getName()); + ServiceInstance serviceInstance = discoveryClient.getInstances(SERVICE_4.getMetadata().getName()).get(0); assertThat(serviceInstance.isSecure()).isTrue(); } @Test - public void testDiscoveryGetServicesOneNamespaceShouldWork() { - Lister serviceLister = setupServiceLister(testService1, testService2); + void testDiscoveryGetServicesOneNamespaceShouldWork() { + Lister serviceLister = setupServiceLister(SERVICE_1, SERVICE_2); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1", - sharedInformerFactory, serviceLister, null, null, null, KubernetesDiscoveryProperties.DEFAULT); + SHARED_INFORMER_FACTORY, serviceLister, null, null, null, KubernetesDiscoveryProperties.DEFAULT); - assertThat(discoveryClient.getServices().toArray()).containsOnly(testService1.getMetadata().getName()); + assertThat(discoveryClient.getServices().toArray()).containsOnly(SERVICE_1.getMetadata().getName()); } @Test - public void testDiscoveryGetInstanceAllNamespaceShouldWork() { - Lister serviceLister = setupServiceLister(testService1, testService2); - Lister endpointsLister = setupEndpointsLister(testEndpoints1); - - KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, true, - Set.of(), true, 60, false, null, Set.of(), Map.of(), null, null, 0, true); + void testDiscoveryGetInstanceAllNamespaceShouldWork() { + Lister serviceLister = setupServiceLister(SERVICE_1, SERVICE_2); + Lister endpointsLister = setupEndpointsLister(ENDPOINTS_1); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("", - sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance("", - "test-svc-1", "2.2.2.2", 8080, new HashMap<>(), false, "namespace1", null)); + "test-svc-1", "2.2.2.2", 8080, Map.of("", "8080"), false, "namespace1", null)); } @Test - public void testDiscoveryGetInstanceOneNamespaceShouldWork() { - Lister serviceLister = setupServiceLister(testService1, testService2); - Lister endpointsLister = setupEndpointsLister(testEndpoints1); - - KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false, - Set.of(), true, 60, false, null, Set.of(), Map.of(), null, null, 0, true); + void testDiscoveryGetInstanceOneNamespaceShouldWork() { + Lister serviceLister = setupServiceLister(SERVICE_1, SERVICE_2); + Lister endpointsLister = setupEndpointsLister(ENDPOINTS_1); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1", - sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance("", - "test-svc-1", "2.2.2.2", 8080, new HashMap<>(), false, "namespace1", null)); + "test-svc-1", "2.2.2.2", 8080, Map.of("", "8080"), false, "namespace1", null)); } @Test - public void testDiscoveryGetInstanceWithoutReadyAddressesShouldWork() { - Lister serviceLister = setupServiceLister(testService1); - Lister endpointsLister = setupEndpointsLister(testEndpointWithoutReadyAddresses); + void testDiscoveryGetInstanceWithoutReadyAddressesShouldWork() { + Lister serviceLister = setupServiceLister(SERVICE_1); + Lister endpointsLister = setupEndpointsLister(ENDPOINTS_NOT_READY_ADDRESS); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1", - sharedInformerFactory, serviceLister, endpointsLister, null, null, + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, KubernetesDiscoveryProperties.DEFAULT); assertThat(discoveryClient.getInstances("test-svc-1")).isEmpty(); } @Test - public void testDiscoveryGetInstanceWithNotReadyAddressesIncludedShouldWork() { - Lister serviceLister = setupServiceLister(testService1); - Lister endpointsLister = setupEndpointsLister(testEndpointWithoutReadyAddresses); + void testDiscoveryGetInstanceWithNotReadyAddressesIncludedShouldWork() { + Lister serviceLister = setupServiceLister(SERVICE_1); + Lister endpointsLister = setupEndpointsLister(ENDPOINTS_NOT_READY_ADDRESS); KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, true, null, Set.of(), Map.of(), null, null, 0, true); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1", - sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance("", - "test-svc-1", "2.2.2.2", 8080, new HashMap<>(), false, "namespace1", null)); + "test-svc-1", "2.2.2.2", 8080, Map.of(), false, "namespace1", null)); } @Test - public void instanceWithoutEndpointsShouldBeSkipped() { - Lister serviceLister = setupServiceLister(testService1); + void instanceWithoutEndpointsShouldBeSkipped() { + Lister serviceLister = setupServiceLister(SERVICE_1); Lister endpointsLister = setupEndpointsLister(); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1", - sharedInformerFactory, serviceLister, endpointsLister, null, null, + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, KubernetesDiscoveryProperties.DEFAULT); assertThat(discoveryClient.getInstances("test-svc-1")).isEmpty(); } @Test - public void instanceWithoutPortsShouldBeSkipped() { - Lister serviceLister = setupServiceLister(testService1); - Lister endpointsLister = setupEndpointsLister(testEndpointWithoutPorts); + void instanceWithoutPortsShouldBeSkipped() { + Lister serviceLister = setupServiceLister(SERVICE_1); + Lister endpointsLister = setupEndpointsLister(ENDPOINTS_NO_PORTS); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1", - sharedInformerFactory, serviceLister, endpointsLister, null, null, + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, KubernetesDiscoveryProperties.DEFAULT); assertThat(discoveryClient.getInstances("test-svc-1")).isEmpty(); } @Test - public void instanceWithMultiplePortsAndPrimaryPortNameConfiguredWithLabelShouldWork() { - V1ObjectMeta oldMetadata = testService1.getMetadata(); - Lister serviceLister = setupServiceLister(testService1.metadata(new V1ObjectMeta().name("test-svc-1") - .namespace("namespace1").putLabelsItem("primary-port-name", "https"))); - Lister endpointsLister = setupEndpointsLister(testEndpointWithMultiplePorts); - - KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false, - Set.of(), true, 60, false, null, Set.of(), Map.of(), null, null, 0, true); + void instanceWithMultiplePortsAndPrimaryPortNameConfiguredWithLabelShouldWork() { + Lister serviceLister = setupServiceLister(SERVICE_6); + Lister endpointsLister = setupEndpointsLister(ENDPOINTS_WITH); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1", - sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); - assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance("", - "test-svc-1", "1.1.1.1", 443, new HashMap<>(), false, "namespace1", null)); - testService1.metadata(oldMetadata); + assertThat(discoveryClient.getInstances("test-svc-1")) + .containsOnly(new DefaultKubernetesServiceInstance("", "test-svc-1", "1.1.1.1", 443, + Map.of("http", "80", "primary-port-name", "https", "https", "443"), false, "namespace1", null)); } @Test - public void instanceWithMultiplePortsAndMisconfiguredPrimaryPortNameInLabelShouldReturnFirstPortAndLogWarning() { - V1ObjectMeta oldMetadata = testService1.getMetadata(); - Lister serviceLister = setupServiceLister(testService1.metadata(new V1ObjectMeta().name("test-svc-1") - .namespace("namespace1").putLabelsItem("primary-port-name", "oops"))); + void instanceWithMultiplePortsAndMisconfiguredPrimaryPortNameInLabelShouldReturnFirstPortAndLogWarning() { + Lister serviceLister = setupServiceLister(SERVICE_5); Lister endpointsLister = setupEndpointsLister( - testEndpointWithMultiplePortsWithoutSupportedPortNames); - - KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false, - Set.of(), true, 60, false, null, Set.of(), Map.of(), null, null, 0, true); + ENDPOINTS_MULTIPLE_PORTS_WITHOUT_SUPPORTED_PORT_NAMES); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1", - sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); - assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance("", - "test-svc-1", "1.1.1.1", 80, new HashMap<>(), false, "namespace1", null)); - testService1.metadata(oldMetadata); + assertThat(discoveryClient.getInstances("test-svc-1")) + .containsOnly(new DefaultKubernetesServiceInstance("", "test-svc-1", "1.1.1.1", 80, + Map.of("tcp1", "80", "primary-port-name", "oops", "tcp2", "443"), false, "namespace1", null)); } @Test - public void instanceWithMultiplePortsAndGenericPrimaryPortNameConfiguredShouldWork() { - Lister serviceLister = setupServiceLister(testService1); - Lister endpointsLister = setupEndpointsLister(testEndpointWithMultiplePorts); - - KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false, - Set.of(), true, 60, false, null, Set.of(), Map.of(), "https", null, 0, true); + void instanceWithMultiplePortsAndGenericPrimaryPortNameConfiguredShouldWork() { + Lister serviceLister = setupServiceLister(SERVICE_1); + Lister endpointsLister = setupEndpointsLister(ENDPOINTS_WITH); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1", - sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance("", - "test-svc-1", "1.1.1.1", 443, new HashMap<>(), false, "namespace1", null)); + "test-svc-1", "1.1.1.1", 443, Map.of("http", "80", "https", "443"), false, "namespace1", null)); } @Test - public void instanceWithMultiplePortsAndMisconfiguredGenericPrimaryPortNameShouldReturnFirstPortAndLogWarning() { - Lister serviceLister = setupServiceLister(testService1); + void instanceWithMultiplePortsAndMisconfiguredGenericPrimaryPortNameShouldReturnFirstPortAndLogWarning() { + Lister serviceLister = setupServiceLister(SERVICE_1); Lister endpointsLister = setupEndpointsLister( - testEndpointWithMultiplePortsWithoutSupportedPortNames); - - KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false, - Set.of(), true, 60, false, null, Set.of(), Map.of(), "oops", null, 0, true); + ENDPOINTS_MULTIPLE_PORTS_WITHOUT_SUPPORTED_PORT_NAMES); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1", - sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance("", - "test-svc-1", "1.1.1.1", 80, new HashMap<>(), false, "namespace1", null)); + "test-svc-1", "1.1.1.1", 80, Map.of("tcp1", "80", "tcp2", "443"), false, "namespace1", null)); } @Test - public void instanceWithMultiplePortsAndWithoutPrimaryPortNameSpecifiedShouldFallBackToHttpsPort() { - Lister serviceLister = setupServiceLister(testService1); - Lister endpointsLister = setupEndpointsLister(testEndpointWithMultiplePorts); - - KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false, - Set.of(), true, 60, false, null, Set.of(), Map.of(), null, null, 0, true); + void instanceWithMultiplePortsAndWithoutPrimaryPortNameSpecifiedShouldFallBackToHttpsPort() { + Lister serviceLister = setupServiceLister(SERVICE_1); + Lister endpointsLister = setupEndpointsLister(ENDPOINTS_WITH); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1", - sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance("", - "test-svc-1", "1.1.1.1", 443, new HashMap<>(), false, "namespace1", null)); + "test-svc-1", "1.1.1.1", 443, Map.of("http", "80", "https", "443"), false, "namespace1", null)); } @Test - public void instanceWithMultiplePortsAndWithoutPrimaryPortNameSpecifiedOrHttpsPortShouldFallBackToHttpPort() { - Lister serviceLister = setupServiceLister(testService1); - Lister endpointsLister = setupEndpointsLister(testEndpointWithMultiplePortsWithoutHttps); - - KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false, - Set.of(), true, 60, false, null, Set.of(), Map.of(), null, null, 0, true); + void instanceWithMultiplePortsAndWithoutPrimaryPortNameSpecifiedOrHttpsPortShouldFallBackToHttpPort() { + Lister serviceLister = setupServiceLister(SERVICE_1); + Lister endpointsLister = setupEndpointsLister(ENDPOINTS_WITH_MULTIPLE_PORTS_NO_HTTPS); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1", - sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance("", - "test-svc-1", "1.1.1.1", 80, new HashMap<>(), false, "namespace1", null)); + "test-svc-1", "1.1.1.1", 80, Map.of("http", "80", "tcp", "443"), false, "namespace1", null)); } @Test - public void instanceWithMultiplePortsAndWithoutAnyConfigurationShouldPickTheFirstPort() { - Lister serviceLister = setupServiceLister(testService1); + void instanceWithMultiplePortsAndWithoutAnyConfigurationShouldPickTheFirstPort() { + Lister serviceLister = setupServiceLister(SERVICE_1); Lister endpointsLister = setupEndpointsLister( - testEndpointWithMultiplePortsWithoutSupportedPortNames); - - KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false, - Set.of(), true, 60, false, null, Set.of(), Map.of(), null, null, 0, true); + ENDPOINTS_MULTIPLE_PORTS_WITHOUT_SUPPORTED_PORT_NAMES); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1", - sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance("", - "test-svc-1", "1.1.1.1", 80, new HashMap<>(), false, "namespace1", null)); + "test-svc-1", "1.1.1.1", 80, Map.of("tcp1", "80", "tcp2", "443"), false, "namespace1", null)); } @Test - public void getInstancesShouldReturnInstancesWithTheSameServiceIdFromNamespaces() { - Lister serviceLister = setupServiceLister(testService1, testService2); - Lister endpointsLister = setupEndpointsLister(testEndpoints1, testEndpoints2); - - KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, true, - Set.of(), true, 60, false, null, Set.of(), Map.of(), null, null, 0, false); + void getInstancesShouldReturnInstancesWithTheSameServiceIdFromNamespaces() { + Lister serviceLister = setupServiceLister(SERVICE_1, SERVICE_2); + Lister endpointsLister = setupEndpointsLister(ENDPOINTS_1, ENDPOINTS_2); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(null, - sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly( - new DefaultKubernetesServiceInstance("", "test-svc-1", "2.2.2.2", 8080, new HashMap<>(), false, - "namespace1", null), - new DefaultKubernetesServiceInstance("", "test-svc-1", "2.2.2.2", 8080, new HashMap<>(), false, - "namespace2", null)); + new DefaultKubernetesServiceInstance("", "test-svc-1", "2.2.2.2", 8080, Map.of("", "8080"), + false, "namespace1", null), + new DefaultKubernetesServiceInstance("", "test-svc-1", "2.2.2.2", 8080, Map.of("", "8080"), + false, "namespace2", null)); } private Lister setupServiceLister(V1Service... services) { @@ -460,4 +364,57 @@ public class KubernetesInformerDiscoveryClientTests { return endpointsLister; } + private static V1Service service(String name, String namespace, Map labels) { + return new V1Service().metadata(new V1ObjectMeta().name(name).namespace(namespace).labels(labels)); + } + + private static V1Endpoints endpointsReadyAddress(String name, String namespace) { + return new V1Endpoints().metadata(new V1ObjectMeta().name(name).namespace(namespace)) + .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().port(8080)) + .addAddressesItem(new V1EndpointAddress().ip("2.2.2.2"))); + } + + private static V1Endpoints endpointsNotReadyAddress() { + return new V1Endpoints().metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1")) + .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().port(8080)) + .addNotReadyAddressesItem(new V1EndpointAddress().ip("2.2.2.2"))); + } + + private static V1Endpoints endpointsNoPorts() { + return new V1Endpoints().metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1")) + .addSubsetsItem(new V1EndpointSubset().addAddressesItem(new V1EndpointAddress().ip("1.1.1.1"))); + } + + private static V1Endpoints endpointsNoUnsetPortName() { + return new V1Endpoints().metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1")) + .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().port(80)) + .addAddressesItem(new V1EndpointAddress().ip("1.1.1.1"))); + } + + private static V1Endpoints endpointsWithMultiplePorts() { + return new V1Endpoints().metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1")) + .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().name("http").port(80)) + .addPortsItem(new CoreV1EndpointPort().name("https").port(443)) + .addAddressesItem(new V1EndpointAddress().ip("1.1.1.1"))); + } + + private static V1Endpoints endpointsWithMultiplePortsNoHttps() { + return new V1Endpoints().metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1")) + .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().name("http").port(80)) + .addPortsItem(new CoreV1EndpointPort().name("tcp").port(443)) + .addAddressesItem(new V1EndpointAddress().ip("1.1.1.1"))); + } + + private static V1Endpoints endpointsMultiplePortsWithoutSupportedPortNames() { + return new V1Endpoints().metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1")) + .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().name("tcp1").port(80)) + .addPortsItem(new CoreV1EndpointPort().name("tcp2").port(443)) + .addAddressesItem(new V1EndpointAddress().ip("1.1.1.1"))); + } + + private static KubernetesDiscoveryProperties properties(boolean allNamespaces, Map labels) { + return new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), true, 60, false, null, Set.of(), + labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true); + } + }