From e38ab5fc97531d3e3421e774bf1d4c149b0506fc Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 30 Jan 2026 22:15:38 +0200 Subject: [PATCH 01/19] fix issue Signed-off-by: wind57 --- .../discovery/DiscoveryClientUtils.java | 23 ++++++ .../discovery/DiscoveryClientUtilsTests.java | 75 +++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/DiscoveryClientUtils.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/DiscoveryClientUtils.java index f7075e538..aaa573dfe 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/DiscoveryClientUtils.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/DiscoveryClientUtils.java @@ -154,6 +154,8 @@ public static ServiceInstance serviceInstance(@Nullable ServicePortSecureResolve Map> podMetadata = podMetadata(data.podName(), serviceInstanceMetadata, properties, podLabelsAndMetadata); + serviceInstanceMetadata = addPodMetadataToServiceInstanceMetadata(podMetadata, serviceInstanceMetadata); + return new DefaultKubernetesServiceInstance(data.instanceId(), serviceMetadata.name(), data.host(), portData.portNumber(), serviceInstanceMetadata, secured, serviceMetadata.namespace(), null, podMetadata); @@ -245,6 +247,27 @@ private static void logServiceSpecificWarning(String serviceName, String primary } } + /** + * there are cases when we need to add pod specific metadata to the service instance + * metadata. For example, currently, we need to add "zone" label from the pod to the + * serviceInstance. See: + * this + * issue + */ + private static Map addPodMetadataToServiceInstanceMetadata( + Map> podMetadata, Map serviceInstanceMetadata) { + + return Optional.ofNullable(podMetadata.get("labels")) + .flatMap(innerMap -> Optional.ofNullable(innerMap.get("zone"))) + .map(zone -> { + Map copyOfServiceInstanceMetadata = new HashMap<>(serviceInstanceMetadata); + copyOfServiceInstanceMetadata.put("zone", zone); + return copyOfServiceInstanceMetadata; + }) + .orElse(serviceInstanceMetadata); + + } + private static void logGenericWarning() { LOG.warn(() -> """ Make sure that either the primary-port-name label has been added to the service, diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/discovery/DiscoveryClientUtilsTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/discovery/DiscoveryClientUtilsTests.java index 033143df0..6da013c19 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/discovery/DiscoveryClientUtilsTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/discovery/DiscoveryClientUtilsTests.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.Set; import java.util.function.Function; +import java.util.function.Supplier; import java.util.stream.Collectors; import org.assertj.core.api.Assertions; @@ -954,6 +955,80 @@ void testPodMetadataBothLabelsAndAnnotations(CapturedOutput output) { .contains("adding podMetadata : {annotations={c=d}, labels={a=b}} from pod : my-pod"); } + @Test + void testServiceInstanceWithPodLabelsAndAnnotations() { + + boolean addPodLabels = true; + boolean addPodAnnotations = true; + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(true, null, true, + null, true, "port.", addPodLabels, addPodAnnotations); + + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, + false, "", Set.of(), Map.of(), "", metadata, 0, false, false, null); + + ServicePortNameAndNumber portData = new ServicePortNameAndNumber(-1, "http"); + ServiceMetadata forServiceInstance = new ServiceMetadata("my-service", "k8s", "ClusterIP", Map.of(), Map.of()); + + InstanceIdHostPodName instanceIdHostPodName = new InstanceIdHostPodName("123", "spring.io", "podName"); + Supplier instanceIdHostPodNameSupplier = () -> instanceIdHostPodName; + + Map podLabels = Map.of("labelA", "a"); + Map podAnnotations = Map.of("annotationB", "b"); + PodLabelsAndAnnotations podLabelsAndAnnotations = new PodLabelsAndAnnotations(podLabels, podAnnotations); + Function podLabelsAndAnnotationsFunction = x -> podLabelsAndAnnotations; + + Map serviceMetadata = Map.of("a", "b"); + + ServiceInstance serviceInstance = serviceInstance(null, forServiceInstance, instanceIdHostPodNameSupplier, + podLabelsAndAnnotationsFunction, portData, serviceMetadata, properties); + + Assertions.assertThat(serviceInstance).isInstanceOf(DefaultKubernetesServiceInstance.class); + DefaultKubernetesServiceInstance defaultInstance = (DefaultKubernetesServiceInstance) serviceInstance; + Map> podMetadata = defaultInstance.podMetadata(); + + Assertions.assertThat(podMetadata).hasSize(2); + Assertions.assertThat(podMetadata.get("labels")).isEqualTo(Map.of("labelA", "a")); + Assertions.assertThat(podMetadata.get("annotations")).isEqualTo(Map.of("annotationB", "b")); + } + + @Test + void testServiceInstanceWithPodLabelsAndAnnotationsWithZone() { + + boolean addPodLabels = true; + boolean addPodAnnotations = true; + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(true, null, true, + null, true, "port.", addPodLabels, addPodAnnotations); + + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, + false, "", Set.of(), Map.of(), "", metadata, 0, false, false, null); + + ServicePortNameAndNumber portData = new ServicePortNameAndNumber(-1, "http"); + ServiceMetadata forServiceInstance = new ServiceMetadata("my-service", "k8s", "ClusterIP", Map.of(), Map.of()); + + InstanceIdHostPodName instanceIdHostPodName = new InstanceIdHostPodName("123", "spring.io", "podName"); + Supplier instanceIdHostPodNameSupplier = () -> instanceIdHostPodName; + + Map podLabels = Map.of("labelA", "a", "zone", "zone-a"); + Map podAnnotations = Map.of("annotationB", "b"); + PodLabelsAndAnnotations podLabelsAndAnnotations = new PodLabelsAndAnnotations(podLabels, podAnnotations); + Function podLabelsAndAnnotationsFunction = x -> podLabelsAndAnnotations; + + Map serviceMetadata = Map.of("a", "b"); + + ServiceInstance serviceInstance = serviceInstance(null, forServiceInstance, instanceIdHostPodNameSupplier, + podLabelsAndAnnotationsFunction, portData, serviceMetadata, properties); + + Assertions.assertThat(serviceInstance).isInstanceOf(DefaultKubernetesServiceInstance.class); + DefaultKubernetesServiceInstance defaultInstance = (DefaultKubernetesServiceInstance) serviceInstance; + Map> podMetadata = defaultInstance.podMetadata(); + + Assertions.assertThat(podMetadata).hasSize(2); + Assertions.assertThat(podMetadata.get("labels")).isEqualTo(Map.of("labelA", "a", "zone", "zone-a")); + Assertions.assertThat(podMetadata.get("annotations")).isEqualTo(Map.of("annotationB", "b")); + + Assertions.assertThat(defaultInstance.getMetadata().get("zone")).isEqualTo("zone-a"); + } + private String filterOnK8sNamespaceAndType(Map result) { return result.entrySet() .stream() From 51864ff70b5c30c1d7516fb71da3eae49f31f9eb Mon Sep 17 00:00:00 2001 From: wind57 Date: Sun, 1 Feb 2026 11:59:57 +0200 Subject: [PATCH 02/19] started work Signed-off-by: wind57 --- ...veryClientServiceLabelsFilteringTests.java | 206 ++++++++++++++++++ ...bric8DiscoveryClientAutoConfiguration.java | 2 +- .../Fabric8InformerAutoConfiguration.java | 5 + 3 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java index 130c392c9..881bcca1c 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java @@ -16,15 +16,55 @@ package org.springframework.cloud.kubernetes.client.discovery; +<<<<<<< Updated upstream +======= +import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.junit5.WireMockExtension; +import io.kubernetes.client.informer.SharedIndexInformer; +import io.kubernetes.client.informer.SharedInformerFactory; +import io.kubernetes.client.informer.cache.Lister; +import io.kubernetes.client.openapi.ApiClient; +import io.kubernetes.client.openapi.JSON; +import io.kubernetes.client.openapi.apis.CoreV1Api; +import io.kubernetes.client.openapi.models.CoreV1EndpointPort; +import io.kubernetes.client.openapi.models.V1EndpointAddress; +import io.kubernetes.client.openapi.models.V1EndpointSubset; +import io.kubernetes.client.openapi.models.V1Endpoints; +import io.kubernetes.client.openapi.models.V1EndpointsList; +import io.kubernetes.client.openapi.models.V1ListMeta; +import io.kubernetes.client.openapi.models.V1ObjectMeta; +import io.kubernetes.client.openapi.models.V1Service; +import io.kubernetes.client.openapi.models.V1ServiceList; +import io.kubernetes.client.openapi.models.V1ServiceSpec; +import io.kubernetes.client.util.ClientBuilder; +import org.awaitility.Awaitility; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; + +>>>>>>> Stashed changes import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; +<<<<<<< Updated upstream import org.junit.jupiter.api.Test; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; +======= +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +>>>>>>> Stashed changes import static org.assertj.core.api.Assertions.assertThat; /** @@ -33,6 +73,52 @@ class KubernetesClientDiscoveryClientServiceLabelsFilteringTests extends KubernetesClientDiscoveryClientServiceLabelsFiltering { +<<<<<<< Updated upstream +======= + private static final String NAMESPACE_A = "namespaceA"; + + private static final String NAMESPACE_B = "namespaceB"; + + private static final String SERVICE_NAME = "serviceX"; + + private static final String ENDPOINTS_NAME = "endpointsX"; + + private static final Map SHAPE_CIRCLE = Map.of("shape", "circle"); + + private static final Map SHAPE_TRIANGLE = Map.of("shape", "triangle"); + + private static final KubernetesClientInformerAutoConfiguration CONFIGURATION = new KubernetesClientInformerAutoConfiguration(); + + private static ApiClient apiClient; + + private static CoreV1Api coreV1Api; + + @RegisterExtension + private static final WireMockExtension API_SERVER = WireMockExtension.newInstance() + .options(options().dynamicPort()) + .build(); + + @BeforeAll + static void beforeAll() { + WireMock.configureFor("localhost", API_SERVER.getPort()); + apiClient = new ClientBuilder().setBasePath("http://localhost:" + API_SERVER.getPort()).build(); + coreV1Api = new CoreV1Api(apiClient); + } + + @AfterAll + static void afterAll() { + API_SERVER.shutdownServer(); + } + + @AfterEach + void afterEach() { + API_SERVER.resetAll(); + } + + /** + * //TODO + */ +>>>>>>> Stashed changes @Test void namespaceARedLabels() { @@ -40,6 +126,7 @@ void namespaceARedLabels() { List namespaces = List.of("namespaceA"); Set namespacesAsSet = Set.of("namespaceA"); boolean discoveryInAllNamespaces = false; +<<<<<<< Updated upstream KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, @@ -386,6 +473,125 @@ void allNamespacesNoLabels() { assertThat(serviceInstancesXX.stream().map(x -> x.getMetadata().get("namespace")).toList()) .containsExactlyInAnyOrder("a", "b"); +======= + Set selectiveNamespaces = Set.of(NAMESPACE_A, NAMESPACE_B); + List selectiveNamespacesAsList = List.of(NAMESPACE_A, NAMESPACE_B); + + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, discoveryInAllNamespaces, + selectiveNamespaces, true, 60L, false, null, Set.of(), SHAPE_CIRCLE, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + + service(NAMESPACE_A, SHAPE_CIRCLE); + service(NAMESPACE_B, SHAPE_CIRCLE); + service(NAMESPACE_B, SHAPE_TRIANGLE); + + endpoints(NAMESPACE_A, SHAPE_CIRCLE); + endpoints(NAMESPACE_B, SHAPE_CIRCLE); + endpoints(NAMESPACE_B, SHAPE_TRIANGLE); + + List sharedInformerFactories = + CONFIGURATION.sharedInformerFactories(apiClient, selectiveNamespacesAsList); + + List> serviceSharedIndexInformers = CONFIGURATION.serviceSharedIndexInformers( + sharedInformerFactories, selectiveNamespacesAsList, coreV1Api , properties); + List> endpointsSharedIndexInformers = CONFIGURATION.endpointsSharedIndexInformers( + sharedInformerFactories, selectiveNamespacesAsList, coreV1Api , properties); + + List> serviceListers = CONFIGURATION.serviceListers(selectiveNamespacesAsList, + serviceSharedIndexInformers); + List> endpointsListers = CONFIGURATION.endpointsListers(selectiveNamespacesAsList, + endpointsSharedIndexInformers); + + startInformers(sharedInformerFactories, serviceSharedIndexInformers, endpointsSharedIndexInformers); + + KubernetesClientInformerDiscoveryClient discoveryClient = new KubernetesClientInformerDiscoveryClient( + sharedInformerFactories, serviceListers, endpointsListers, null, null, + properties, coreV1Api, x -> true); + + List serviceInstances = discoveryClient.getInstances(SERVICE_NAME); + assertThat(serviceInstances.size()).isEqualTo(1); + assertThat(serviceInstances.get(0).getMetadata().get("k8s_namespace")).isEqualTo("namespaceA"); + } + + private void service(String namespace, Map labels) { + V1Service service = new V1Service().metadata(new V1ObjectMeta().name(SERVICE_NAME).namespace(namespace).labels(labels)) + .spec(new V1ServiceSpec().type("ClusterIP")); + mockServicesCall(namespace, labelSelector(labels), service); + } + + private void endpoints(String namespace, Map labels) { + V1Endpoints endpoints = new V1Endpoints().metadata(new V1ObjectMeta().name(ENDPOINTS_NAME).namespace(namespace).labels(labels)) + .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().port(8080)) + .addAddressesItem(new V1EndpointAddress().ip("2.2.2.2"))); + mockEndpointsCall(namespace, labelSelector(labels), endpoints); + } + + private static void mockEndpointsCall(String namespace, String labelSelector, + V1Endpoints endpoints) { + + // watch=false, first call to populate watcher cache + // this is when we provide the Endpoints + KubernetesClientDiscoveryClientServiceLabelsFilteringTests.API_SERVER + .stubFor(get(urlPathEqualTo("/api/v1/namespaces/" + namespace + "/endpoints")) + .withQueryParam("watch", equalTo("false")) + .withQueryParam("labelSelector", equalTo(labelSelector)) + .willReturn(aResponse() + .withStatus(200) + .withBody(JSON.serialize(new V1EndpointsList().metadata(new V1ListMeta().resourceVersion("0")) + .addItemsItem(endpoints))))); + + // watch=true, call to re-sync + // nothing new is incoming when we re-sync + KubernetesClientDiscoveryClientServiceLabelsFilteringTests.API_SERVER + .stubFor(get(urlPathEqualTo("/api/v1/namespaces/" + namespace + "/endpoints")) + .withQueryParam("watch", equalTo("true")) + .withQueryParam("labelSelector", equalTo(labelSelector)) + .willReturn(aResponse().withStatus(200).withBody(""))); + } + + private static void mockServicesCall(String namespace, String labelSelector, + V1Service service) { + + // watch=false, first call to populate watcher cache + // this is when we provide the Service + KubernetesClientDiscoveryClientServiceLabelsFilteringTests.API_SERVER + .stubFor(get(urlPathEqualTo("/api/v1/namespaces/" + namespace + "/services")) + .withQueryParam("watch", equalTo("false")) + .withQueryParam("labelSelector", equalTo(labelSelector)) + .willReturn(aResponse() + .withStatus(200) + .withBody(JSON.serialize(new V1ServiceList().metadata(new V1ListMeta().resourceVersion("0")) + .addItemsItem(service))))); + + // watch=true, call to re-sync + // nothing new is incoming when we re-sync + KubernetesClientDiscoveryClientServiceLabelsFilteringTests.API_SERVER + .stubFor(get(urlPathEqualTo("/api/v1/namespaces/" + namespace + "/services")) + .withQueryParam("watch", equalTo("true")) + .withQueryParam("labelSelector", equalTo(labelSelector)) + .willReturn(aResponse().withStatus(200).withBody(""))); +>>>>>>> Stashed changes + } + + private String labelSelector(Map labels) { + return labels.entrySet().stream().map(entry -> entry.getKey() + "=" + entry.getValue()) + .collect(Collectors.joining("&")); + } + + private void startInformers(List sharedInformerFactories, + List> serviceSharedIndexInformers, + List> endpointsSharedIndexInformers) { + sharedInformerFactories.forEach(SharedInformerFactory::startAllRegisteredInformers); + + Awaitility.await().until(() -> serviceSharedIndexInformers.stream() + .map(SharedIndexInformer::hasSynced) + .reduce(Boolean::logicalAnd) + .orElse(false)); + + Awaitility.await().until(() -> endpointsSharedIndexInformers.stream() + .map(SharedIndexInformer::hasSynced) + .reduce(Boolean::logicalAnd) + .orElse(false)); } } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientAutoConfiguration.java index c38173760..5e64550cc 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientAutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientAutoConfiguration.java @@ -54,7 +54,7 @@ @ConditionalOnSpringCloudKubernetesBlockingDiscovery @AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class }) @AutoConfigureAfter({ Fabric8AutoConfiguration.class, KubernetesDiscoveryPropertiesAutoConfiguration.class, - Fabric8DiscoveryClientSpelAutoConfiguration.class, Fabric8DiscoveryClientSpelAutoConfiguration.class }) + Fabric8DiscoveryClientSpelAutoConfiguration.class }) public final class Fabric8DiscoveryClientAutoConfiguration { private static final LogAccessor LOG = new LogAccessor( diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java new file mode 100644 index 000000000..7f9c5801f --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java @@ -0,0 +1,5 @@ +package org.springframework.cloud.kubernetes.fabric8.discovery; + +public class Fabric8InformerAutoConfiguration { + +} From f02b7961e5efcacca46a8eb9cf494b8a737c4423 Mon Sep 17 00:00:00 2001 From: wind57 Date: Sun, 1 Feb 2026 12:32:18 +0200 Subject: [PATCH 03/19] wip Signed-off-by: wind57 --- .../Fabric8DiscoveryClientUtils.java | 54 +++--- .../Fabric8InformerAutoConfiguration.java | 180 +++++++++++++++++- 2 files changed, 206 insertions(+), 28 deletions(-) diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java index dcac8b50a..e76c716d3 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java @@ -91,33 +91,33 @@ else if (!properties.namespaces().isEmpty()) { return endpointSlices; } - static List endpoints(KubernetesDiscoveryProperties properties, KubernetesClient client, - KubernetesNamespaceProvider namespaceProvider, String target, @Nullable String serviceName, - Predicate filter) { - - List endpoints; - - if (!properties.namespaces().isEmpty()) { - LOG.debug(() -> "discovering endpoints in namespaces : " + properties.namespaces()); - List inner = new ArrayList<>(properties.namespaces().size()); - properties.namespaces() - .forEach(namespace -> inner.addAll(filteredEndpoints( - client.endpoints().inNamespace(namespace).withNewFilter(), properties, serviceName))); - endpoints = inner; - } - else if (properties.allNamespaces()) { - LOG.debug(() -> "discovering endpoints in all namespaces"); - endpoints = filteredEndpoints(client.endpoints().inAnyNamespace().withNewFilter(), properties, serviceName); - } - else { - String namespace = Fabric8Utils.getApplicationNamespace(client, null, target, namespaceProvider); - LOG.debug(() -> "discovering endpoints in namespace : " + namespace); - endpoints = filteredEndpoints(client.endpoints().inNamespace(namespace).withNewFilter(), properties, - serviceName); - } - - return withFilter(endpoints, properties, client, filter); - } +// static List endpoints(KubernetesDiscoveryProperties properties, KubernetesClient client, +// KubernetesNamespaceProvider namespaceProvider, String target, @Nullable String serviceName, +// Predicate filter) { +// +// List endpoints; +// +// if (!properties.namespaces().isEmpty()) { +// LOG.debug(() -> "discovering endpoints in namespaces : " + properties.namespaces()); +// List inner = new ArrayList<>(properties.namespaces().size()); +// properties.namespaces() +// .forEach(namespace -> inner.addAll(filteredEndpoints( +// client.endpoints().inNamespace(namespace).withNewFilter(), properties, serviceName))); +// endpoints = inner; +// } +// else if (properties.allNamespaces()) { +// LOG.debug(() -> "discovering endpoints in all namespaces"); +// endpoints = filteredEndpoints(client.endpoints().inAnyNamespace().withNewFilter(), properties, serviceName); +// } +// else { +// String namespace = Fabric8Utils.getApplicationNamespace(client, null, target, namespaceProvider); +// LOG.debug(() -> "discovering endpoints in namespace : " + namespace); +// endpoints = filteredEndpoints(client.endpoints().inNamespace(namespace).withNewFilter(), properties, +// serviceName); +// } +// +// return withFilter(endpoints, properties, client, filter); +// } // see https://github.com/spring-cloud/spring-cloud-kubernetes/issues/1182 on why this // is needed diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java index 7f9c5801f..198eb84ca 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java @@ -1,5 +1,183 @@ +/* + * Copyright 2012-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.cloud.kubernetes.fabric8.discovery; -public class Fabric8InformerAutoConfiguration { +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; + +import io.fabric8.kubernetes.api.model.Endpoints; +import io.fabric8.kubernetes.api.model.Service; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.informers.SharedInformerFactory; +import jakarta.annotation.Nullable; + +import org.apache.commons.logging.LogFactory; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.cloud.CloudPlatform; +import org.springframework.cloud.client.CommonsClientAutoConfiguration; +import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled; +import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration; +import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; +import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; +import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryPropertiesAutoConfiguration; +import org.springframework.cloud.kubernetes.commons.discovery.conditionals.ConditionalOnBlockingOrReactiveDiscoveryEnabled; +import org.springframework.cloud.kubernetes.commons.discovery.conditionals.ConditionalOnKubernetesDiscoveryEnabled; +import org.springframework.cloud.kubernetes.fabric8.Fabric8AutoConfiguration; +import org.springframework.cloud.kubernetes.fabric8.Fabric8Utils; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.core.log.LogAccessor; + +import static org.springframework.cloud.kubernetes.fabric8.Fabric8Utils.getApplicationNamespace; + +/** + * @author wind57 + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnDiscoveryEnabled +@ConditionalOnKubernetesDiscoveryEnabled +@ConditionalOnBlockingOrReactiveDiscoveryEnabled +@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) +@AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class }) +@AutoConfigureAfter({ Fabric8AutoConfiguration.class }) +final class Fabric8InformerAutoConfiguration { + + private static final LogAccessor LOG = new LogAccessor( + LogFactory.getLog(Fabric8InformerAutoConfiguration.class)); + + // we rely on the order of namespaces to enable listers, as such provide a bean of + // namespaces as a list, instead of the incoming Set. + @Bean + List fabric8InformerNamespaces(KubernetesDiscoveryProperties properties, + KubernetesClient kubernetesClient, Environment environment) { + + KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(environment); + + if (!properties.namespaces().isEmpty()) { + LOG.debug(() -> "discovering endpoints in namespaces : " + properties.namespaces()); + return properties.namespaces().stream().toList(); + } + + if (properties.allNamespaces()) { + LOG.debug(() -> "discovering endpoints in all namespaces"); + return List.of(""); + } + + String namespace = getApplicationNamespace(kubernetesClient, null, "fabric8 discovery", namespaceProvider); + LOG.debug(() -> "discovering endpoints in namespace : " + namespace); + return List.of(namespace); + } + + @Bean + @ConditionalOnMissingBean(value = SharedInformerFactory.class, parameterizedContainer = List.class) + List sharedInformerFactories(ApiClient apiClient, List selectiveNamespaces) { + + new SharedInformerFactory() + + int howManyNamespaces = selectiveNamespaces.size(); + List sharedInformerFactories = new ArrayList<>(howManyNamespaces); + for (int i = 0; i < howManyNamespaces; ++i) { + sharedInformerFactories.add(new SharedInformerFactory(apiClient)); + } + return sharedInformerFactories; + } + + @Bean + @ConditionalOnMissingBean(value = V1Service.class, + parameterizedContainer = { List.class, SharedIndexInformer.class }) + List> serviceSharedIndexInformers( + List sharedInformerFactories, List selectiveNamespaces, CoreV1Api api, + KubernetesDiscoveryProperties properties) { + + int howManyNamespaces = selectiveNamespaces.size(); + List> serviceSharedIndexedInformers = new ArrayList<>(howManyNamespaces); + for (int i = 0; i < howManyNamespaces; ++i) { + String namespace = selectiveNamespaces.get(i); + + CallGenerator callGenerator = servicesCallGenerator(api, properties.serviceLabels(), namespace); + + SharedIndexInformer sharedIndexInformer = sharedInformerFactories.get(i) + .sharedIndexInformerFor(callGenerator, V1Service.class, V1ServiceList.class); + serviceSharedIndexedInformers.add(sharedIndexInformer); + } + return serviceSharedIndexedInformers; + } + + @Bean + @ConditionalOnMissingBean(value = V1Service.class, parameterizedContainer = { List.class, Lister.class }) + List> serviceListers(List selectiveNamespaces, + List> serviceSharedIndexInformers) { + + int howManyNamespaces = selectiveNamespaces.size(); + List> serviceListers = new ArrayList<>(howManyNamespaces); + + for (int i = 0; i < howManyNamespaces; ++i) { + String namespace = selectiveNamespaces.get(i); + Lister lister = new Lister<>(serviceSharedIndexInformers.get(i).getIndexer(), namespace); + LOG.debug(() -> "registering lister (for services) in namespace : " + namespace); + serviceListers.add(lister); + } + + return serviceListers; + } + + @Bean + @ConditionalOnMissingBean(value = V1Endpoints.class, + parameterizedContainer = { List.class, SharedIndexInformer.class }) + List> endpointsSharedIndexInformers( + List sharedInformerFactories, List selectiveNamespaces, CoreV1Api api, + KubernetesDiscoveryProperties properties) { + + int howManyNamespaces = selectiveNamespaces.size(); + List> endpointsSharedIndexedInformers = new ArrayList<>(howManyNamespaces); + for (int i = 0; i < howManyNamespaces; ++i) { + String namespace = selectiveNamespaces.get(i); + + CallGenerator callGenerator = endpointsCallGenerator(api, properties.serviceLabels(), namespace); + + SharedIndexInformer sharedIndexInformer = sharedInformerFactories.get(i) + .sharedIndexInformerFor(callGenerator, V1Endpoints.class, V1EndpointsList.class); + endpointsSharedIndexedInformers.add(sharedIndexInformer); + } + return endpointsSharedIndexedInformers; + } + + @Bean + @ConditionalOnMissingBean(value = V1Endpoints.class, parameterizedContainer = { List.class, Lister.class }) + List> endpointsListers(List selectiveNamespaces, + List> endpointsSharedIndexInformers) { + + int howManyNamespaces = selectiveNamespaces.size(); + List> endpointsListers = new ArrayList<>(howManyNamespaces); + + for (int i = 0; i < howManyNamespaces; ++i) { + String namespace = selectiveNamespaces.get(i); + Lister lister = new Lister<>(endpointsSharedIndexInformers.get(i).getIndexer(), namespace); + LOG.debug(() -> "registering lister (for endpoints) in namespace : " + namespace); + endpointsListers.add(lister); + } + + return endpointsListers; + } + } From bb4ecc6ca61160af55ff9f373a2db9707877de60 Mon Sep 17 00:00:00 2001 From: wind57 Date: Sun, 1 Feb 2026 12:58:25 +0200 Subject: [PATCH 04/19] rename method Signed-off-by: wind57 --- .../Fabric8InformerAutoConfiguration.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java index 198eb84ca..20cd8e0ab 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java @@ -22,7 +22,9 @@ import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.Service; +import io.fabric8.kubernetes.api.model.ServiceList; import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.informers.SharedIndexInformer; import io.fabric8.kubernetes.client.informers.SharedInformerFactory; import jakarta.annotation.Nullable; @@ -67,7 +69,7 @@ final class Fabric8InformerAutoConfiguration { // we rely on the order of namespaces to enable listers, as such provide a bean of // namespaces as a list, instead of the incoming Set. @Bean - List fabric8InformerNamespaces(KubernetesDiscoveryProperties properties, + List selectiveNamespaces(KubernetesDiscoveryProperties properties, KubernetesClient kubernetesClient, Environment environment) { KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(environment); @@ -89,34 +91,33 @@ List fabric8InformerNamespaces(KubernetesDiscoveryProperties properties, @Bean @ConditionalOnMissingBean(value = SharedInformerFactory.class, parameterizedContainer = List.class) - List sharedInformerFactories(ApiClient apiClient, List selectiveNamespaces) { - - new SharedInformerFactory() + List sharedInformerFactories(KubernetesClient kubernetesClient, + List selectiveNamespaces) { int howManyNamespaces = selectiveNamespaces.size(); List sharedInformerFactories = new ArrayList<>(howManyNamespaces); for (int i = 0; i < howManyNamespaces; ++i) { - sharedInformerFactories.add(new SharedInformerFactory(apiClient)); + sharedInformerFactories.add(kubernetesClient.informers()); } return sharedInformerFactories; } @Bean - @ConditionalOnMissingBean(value = V1Service.class, + @ConditionalOnMissingBean(value = Service.class, parameterizedContainer = { List.class, SharedIndexInformer.class }) - List> serviceSharedIndexInformers( + List> serviceSharedIndexInformers( List sharedInformerFactories, List selectiveNamespaces, CoreV1Api api, KubernetesDiscoveryProperties properties) { int howManyNamespaces = selectiveNamespaces.size(); - List> serviceSharedIndexedInformers = new ArrayList<>(howManyNamespaces); + List> serviceSharedIndexedInformers = new ArrayList<>(howManyNamespaces); for (int i = 0; i < howManyNamespaces; ++i) { String namespace = selectiveNamespaces.get(i); CallGenerator callGenerator = servicesCallGenerator(api, properties.serviceLabels(), namespace); - SharedIndexInformer sharedIndexInformer = sharedInformerFactories.get(i) - .sharedIndexInformerFor(callGenerator, V1Service.class, V1ServiceList.class); + SharedIndexInformer sharedIndexInformer = sharedInformerFactories.get(i) + .sharedIndexInformerFor(Service.class, ServiceList.class); serviceSharedIndexedInformers.add(sharedIndexInformer); } return serviceSharedIndexedInformers; From ee91966460a94ecd4269d6fefc612a758315faa2 Mon Sep 17 00:00:00 2001 From: wind57 Date: Mon, 2 Feb 2026 23:40:00 +0200 Subject: [PATCH 05/19] started basic work Signed-off-by: wind57 --- ...abric8AbstractBlockingDiscoveryClient.java | 175 +++++++++------ .../Fabric8CacheableDiscoveryClient.java | 16 +- .../Fabric8ConfigServerBootstrapper.java | 23 +- .../discovery/Fabric8DiscoveryClient.java | 16 +- ...bric8DiscoveryClientAutoConfiguration.java | 29 +-- .../Fabric8DiscoveryClientUtils.java | 203 ++---------------- .../Fabric8EndpointSliceCatalogWatch.java | 51 ++++- .../Fabric8EndpointsCatalogWatch.java | 43 +++- .../Fabric8InformerAutoConfiguration.java | 115 +++++----- .../Fabric8InstanceIdHostPodNameSupplier.java | 5 +- ...abric8PodLabelsAndAnnotationsSupplier.java | 3 +- ...ctiveDiscoveryClientAutoConfiguration.java | 40 ++-- ...ctiveDiscoveryHealthAutoConfiguration.java | 19 +- ...ic8InstanceIdHostPodNameSupplierTests.java | 17 +- ...8PodLabelsAndAnnotationsSupplierTests.java | 6 +- 15 files changed, 382 insertions(+), 379 deletions(-) diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8AbstractBlockingDiscoveryClient.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8AbstractBlockingDiscoveryClient.java index 1bcb4c73b..39e958277 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8AbstractBlockingDiscoveryClient.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8AbstractBlockingDiscoveryClient.java @@ -21,17 +21,22 @@ import java.util.Map; import java.util.Objects; import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Collectors; import io.fabric8.kubernetes.api.model.EndpointAddress; import io.fabric8.kubernetes.api.model.EndpointSubset; import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.informers.SharedIndexInformer; +import io.fabric8.kubernetes.client.informers.cache.Lister; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import org.apache.commons.logging.LogFactory; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.cloud.kubernetes.commons.discovery.ServiceMetadata; import org.springframework.cloud.kubernetes.commons.discovery.ServicePortNameAndNumber; @@ -46,10 +51,9 @@ import static org.springframework.cloud.kubernetes.fabric8.Fabric8Utils.serviceMetadata; import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.addresses; import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.endpointSubsetsPortData; -import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.endpoints; -import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.services; -import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8InstanceIdHostPodNameSupplier.externalName; -import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8InstanceIdHostPodNameSupplier.nonExternalName; +import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.postConstruct; +import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8InstanceIdHostPodNameSupplier.fabric8InstanceIdHostPodNameSupplier; +import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8PodLabelsAndAnnotationsSupplier.fabric8PodLabelsAndAnnotationsSupplier; /** * @author wind57 @@ -59,70 +63,97 @@ abstract class Fabric8AbstractBlockingDiscoveryClient implements DiscoveryClient private static final LogAccessor LOG = new LogAccessor( LogFactory.getLog(Fabric8AbstractBlockingDiscoveryClient.class)); - private final KubernetesDiscoveryProperties properties; + private final List> serviceListers; - private final ServicePortSecureResolver servicePortSecureResolver; + private final List> endpointsListers; - private final KubernetesClient client; + private final List> serviceInformers; - private final KubernetesNamespaceProvider namespaceProvider; + private final List> endpointsInformers; + + private final Supplier informersReadyFunc; + + private final KubernetesDiscoveryProperties properties; private final Predicate predicate; - Fabric8AbstractBlockingDiscoveryClient(KubernetesClient client, - KubernetesDiscoveryProperties kubernetesDiscoveryProperties, - ServicePortSecureResolver servicePortSecureResolver, KubernetesNamespaceProvider namespaceProvider, + private final ServicePortSecureResolver servicePortSecureResolver; + + private final KubernetesClient kubernetesClient; + + Fabric8AbstractBlockingDiscoveryClient(KubernetesClient kubernetesClient, List> serviceListers, + List> endpointsListers, List> serviceInformers, + List> endpointsInformers, KubernetesDiscoveryProperties properties, Predicate predicate) { - this.client = client; - this.properties = kubernetesDiscoveryProperties; - this.servicePortSecureResolver = servicePortSecureResolver; - this.namespaceProvider = namespaceProvider; + this.serviceListers = serviceListers; + this.endpointsListers = endpointsListers; + this.serviceInformers = serviceInformers; + this.endpointsInformers = endpointsInformers; + this.properties = properties; this.predicate = predicate; + this.kubernetesClient = kubernetesClient; + + servicePortSecureResolver = new ServicePortSecureResolver(properties); + + this.informersReadyFunc = () -> { + boolean serviceInformersReady = serviceInformers.isEmpty() || serviceInformers.stream() + .map(SharedIndexInformer::hasSynced) + .reduce(Boolean::logicalAnd) + .orElse(false); + boolean endpointsInformersReady = endpointsInformers.isEmpty() || endpointsInformers.stream() + .map(SharedIndexInformer::hasSynced) + .reduce(Boolean::logicalAnd) + .orElse(false); + return serviceInformersReady && endpointsInformersReady; + }; } public abstract String description(); @Override public List getInstances(String serviceId) { - Objects.requireNonNull(serviceId); + Objects.requireNonNull(serviceId, "serviceId must be provided"); - List allEndpoints = endpoints(properties, client, namespaceProvider, "fabric8-discovery", serviceId, - predicate); + List allServices = serviceListers.stream() + .flatMap(x -> x.list().stream()) + .filter(service -> service.getMetadata() != null) + .filter(service -> serviceId.equals(service.getMetadata().getName())) + .toList(); - List instances = new ArrayList<>(); - for (Endpoints endpoints : allEndpoints) { - // endpoints are only those that matched the serviceId - instances.addAll(serviceInstances(endpoints, serviceId)); - } + List serviceInstances = allServices.stream() + .filter(predicate) + .flatMap(service -> serviceInstances(service).stream()) + .collect(Collectors.toCollection(ArrayList::new)); if (properties.includeExternalNameServices()) { LOG.debug(() -> "Searching for 'ExternalName' type of services with serviceId : " + serviceId); - List services = services(properties, client, namespaceProvider, - s -> s.getSpec().getType().equals(EXTERNAL_NAME), Map.of("metadata.name", serviceId), - "fabric8-discovery"); - for (Service service : services) { + List externalNameServices = allServices.stream() + .filter(s -> s.getSpec() != null) + .filter(s -> EXTERNAL_NAME.equals(s.getSpec().getType())) + .toList(); + for (Service service : externalNameServices) { ServiceMetadata serviceMetadata = serviceMetadata(service); Map serviceInstanceMetadata = serviceInstanceMetadata(Map.of(), serviceMetadata, properties); - Fabric8InstanceIdHostPodNameSupplier supplierOne = externalName(service); - - ServiceInstance externalNameServiceInstance = externalNameServiceInstance(serviceMetadata, supplierOne, - serviceInstanceMetadata); - - instances.add(externalNameServiceInstance); + Fabric8InstanceIdHostPodNameSupplier fabric8InstanceIdHostPodNameSupplier = fabric8InstanceIdHostPodNameSupplier( + service); + ServiceInstance externalNameServiceInstance = externalNameServiceInstance(serviceMetadata, + fabric8InstanceIdHostPodNameSupplier, serviceInstanceMetadata); + serviceInstances.add(externalNameServiceInstance); } } - return instances; + return serviceInstances; } @Override public List getServices() { - List services = services(properties, client, namespaceProvider, predicate, null, "fabric8 discovery") - .stream() - .map(service -> service.getMetadata().getName()) + List services = serviceListers.stream() + .flatMap(serviceLister -> serviceLister.list().stream()) + .filter(predicate) + .map(s -> s.getMetadata().getName()) .distinct() .toList(); LOG.debug(() -> "will return services : " + services); @@ -134,38 +165,62 @@ public int getOrder() { return properties.order(); } - private List serviceInstances(Endpoints endpoints, String serviceId) { + @PostConstruct + void afterPropertiesSet() { + postConstruct(properties, informersReadyFunc, serviceListers); + } - List subsets = endpoints.getSubsets(); - if (subsets.isEmpty()) { - LOG.debug(() -> "serviceId : " + serviceId + " does not have any subsets"); - return List.of(); - } + @PreDestroy + void preDestroy() { + serviceInformers.forEach(SharedIndexInformer::close); + endpointsInformers.forEach(SharedIndexInformer::close); + } + + private List serviceInstances(Service service) { + + String serviceId = service.getMetadata().getName(); + String serviceNamespace = service.getMetadata().getNamespace(); - String namespace = endpoints.getMetadata().getNamespace(); List instances = new ArrayList<>(); - Service service = client.services().inNamespace(namespace).withName(serviceId).get(); - ServiceMetadata serviceMetadata = serviceMetadata(service); - Map portsData = endpointSubsetsPortData(subsets); + List allEndpoints = endpointsListers.stream() + .map(endpointsLister -> endpointsLister.namespace(serviceNamespace).get(serviceId)) + .filter(Objects::nonNull) + .toList(); + + ServiceMetadata k8sServiceMetadata = serviceMetadata(service); + + for (Endpoints endpoints : allEndpoints) { + List subsets = endpoints.getSubsets(); + if (subsets == null || subsets.isEmpty()) { + LOG.debug(() -> "serviceId : " + serviceId + " does not have any subsets"); + } + else { + Map portsData = endpointSubsetsPortData(subsets); + Map serviceInstanceMetadata = serviceInstanceMetadata(portsData, k8sServiceMetadata, + properties); - Map serviceInstanceMetadata = serviceInstanceMetadata(portsData, serviceMetadata, properties); + for (EndpointSubset endpointSubset : subsets) { - for (EndpointSubset endpointSubset : subsets) { + Map endpointsPortData = endpointSubsetsPortData(List.of(endpointSubset)); + ServicePortNameAndNumber portData = endpointsPort(endpointsPortData, k8sServiceMetadata, + properties); - Map endpointsPortData = endpointSubsetsPortData(List.of(endpointSubset)); - ServicePortNameAndNumber portData = endpointsPort(endpointsPortData, serviceMetadata, properties); + List addresses = addresses(endpointSubset, properties); + for (EndpointAddress endpointAddress : addresses) { - List addresses = addresses(endpointSubset, properties); - for (EndpointAddress endpointAddress : addresses) { + Fabric8InstanceIdHostPodNameSupplier instanceIdHostPodNameSupplier = fabric8InstanceIdHostPodNameSupplier( + endpointAddress, service); + Fabric8PodLabelsAndAnnotationsSupplier podLabelsAndAnnotationsSupplier = fabric8PodLabelsAndAnnotationsSupplier( + kubernetesClient, service.getMetadata().getNamespace()); - Fabric8InstanceIdHostPodNameSupplier supplierOne = nonExternalName(endpointAddress, service); - Fabric8PodLabelsAndAnnotationsSupplier supplierTwo = Fabric8PodLabelsAndAnnotationsSupplier - .nonExternalName(client, namespace); + ServiceInstance serviceInstance = serviceInstance(servicePortSecureResolver, k8sServiceMetadata, + instanceIdHostPodNameSupplier, podLabelsAndAnnotationsSupplier, portData, + serviceInstanceMetadata, properties); + instances.add(serviceInstance); + } + } - ServiceInstance serviceInstance = serviceInstance(servicePortSecureResolver, serviceMetadata, - supplierOne, supplierTwo, portData, serviceInstanceMetadata, properties); - instances.add(serviceInstance); } } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8CacheableDiscoveryClient.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8CacheableDiscoveryClient.java index ccabcb7aa..dd4105fa4 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8CacheableDiscoveryClient.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8CacheableDiscoveryClient.java @@ -19,15 +19,16 @@ import java.util.List; import java.util.function.Predicate; +import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.informers.SharedIndexInformer; +import io.fabric8.kubernetes.client.informers.cache.Lister; import org.springframework.cache.annotation.Cacheable; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; -import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; /** * Cacheable Fabric8 Kubernetes implementation of {@link DiscoveryClient}. @@ -37,12 +38,13 @@ */ class Fabric8CacheableDiscoveryClient extends Fabric8AbstractBlockingDiscoveryClient { - Fabric8CacheableDiscoveryClient(KubernetesClient client, - KubernetesDiscoveryProperties kubernetesDiscoveryProperties, - ServicePortSecureResolver servicePortSecureResolver, KubernetesNamespaceProvider namespaceProvider, - Predicate predicate) { + Fabric8CacheableDiscoveryClient(KubernetesClient client, List> serviceListers, + List> endpointsListers, List> serviceInformers, + List> endpointsInformers, + KubernetesDiscoveryProperties kubernetesDiscoveryProperties, Predicate predicate) { - super(client, kubernetesDiscoveryProperties, servicePortSecureResolver, namespaceProvider, predicate); + super(client, serviceListers, endpointsListers, serviceInformers, endpointsInformers, + kubernetesDiscoveryProperties, predicate); } @Override diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java index c0f1f6299..ff0ba9b5a 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java @@ -17,9 +17,14 @@ package org.springframework.cloud.kubernetes.fabric8.discovery; import java.util.Collections; +import java.util.List; +import io.fabric8.kubernetes.api.model.Endpoints; +import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.informers.SharedIndexInformer; +import io.fabric8.kubernetes.client.informers.cache.Lister; import jakarta.annotation.Nonnull; import org.springframework.boot.bootstrap.BootstrapRegistry; @@ -73,10 +78,22 @@ public void initialize(@Nonnull BootstrapRegistry registry) { .kubernetesClientConfig(context.get(KubernetesClientProperties.class)); KubernetesClient kubernetesClient = fabric8AutoConfiguration.kubernetesClient(config); KubernetesDiscoveryProperties discoveryProperties = context.get(KubernetesDiscoveryProperties.class); + + + + Fabric8InformerAutoConfiguration fabric8InformerAutoConfiguration = new Fabric8InformerAutoConfiguration(); + + List> serviceListers, + List> endpointsListers, List> serviceInformers, + List> endpointsInformers + + client, serviceListers, endpointsListers, serviceInformers, endpointsInformers, + kubernetesDiscoveryProperties, predicat + + Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(kubernetesClient, - discoveryProperties, new ServicePortSecureResolver(discoveryProperties), - new KubernetesNamespaceProvider(propertyResolver - .get(KubernetesNamespaceProvider.NAMESPACE_PROPERTY, String.class, null)), + + discoveryProperties, new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(discoveryProperties)); return discoveryClient::getInstances; } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClient.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClient.java index 56c1ca369..a6e9bf94f 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClient.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClient.java @@ -16,15 +16,17 @@ package org.springframework.cloud.kubernetes.fabric8.discovery; +import java.util.List; import java.util.function.Predicate; +import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.informers.SharedIndexInformer; +import io.fabric8.kubernetes.client.informers.cache.Lister; import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; -import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; /** * Fabric8 Kubernetes implementation of {@link DiscoveryClient}. @@ -34,11 +36,13 @@ */ final class Fabric8DiscoveryClient extends Fabric8AbstractBlockingDiscoveryClient { - Fabric8DiscoveryClient(KubernetesClient client, KubernetesDiscoveryProperties kubernetesDiscoveryProperties, - ServicePortSecureResolver servicePortSecureResolver, KubernetesNamespaceProvider namespaceProvider, - Predicate predicate) { + Fabric8DiscoveryClient(KubernetesClient client, List> serviceListers, + List> endpointsListers, List> serviceInformers, + List> endpointsInformers, + KubernetesDiscoveryProperties kubernetesDiscoveryProperties, Predicate predicate) { - super(client, kubernetesDiscoveryProperties, servicePortSecureResolver, namespaceProvider, predicate); + super(client, serviceListers, endpointsListers, serviceInformers, endpointsInformers, + kubernetesDiscoveryProperties, predicate); } @Override diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientAutoConfiguration.java index 5e64550cc..9e2b7edef 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientAutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientAutoConfiguration.java @@ -16,10 +16,14 @@ package org.springframework.cloud.kubernetes.fabric8.discovery; +import java.util.List; import java.util.function.Predicate; +import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.informers.SharedIndexInformer; +import io.fabric8.kubernetes.client.informers.cache.Lister; import org.apache.commons.logging.LogFactory; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -27,12 +31,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.cloud.client.CommonsClientAutoConfiguration; import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.PodUtils; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryClientHealthIndicatorInitializer; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryPropertiesAutoConfiguration; -import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; import org.springframework.cloud.kubernetes.commons.discovery.conditionals.ConditionalOnDiscoveryCacheableBlockingDisabled; import org.springframework.cloud.kubernetes.commons.discovery.conditionals.ConditionalOnDiscoveryCacheableBlockingEnabled; import org.springframework.cloud.kubernetes.commons.discovery.conditionals.ConditionalOnSpringCloudKubernetesBlockingDiscovery; @@ -41,7 +43,6 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; import org.springframework.core.log.LogAccessor; /** @@ -63,22 +64,24 @@ public final class Fabric8DiscoveryClientAutoConfiguration { @Bean @ConditionalOnMissingBean @ConditionalOnDiscoveryCacheableBlockingDisabled - Fabric8DiscoveryClient fabric8DiscoveryClient(KubernetesClient client, KubernetesDiscoveryProperties properties, - Predicate predicate, Environment environment) { - ServicePortSecureResolver servicePortSecureResolver = new ServicePortSecureResolver(properties); - KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(environment); - return new Fabric8DiscoveryClient(client, properties, servicePortSecureResolver, namespaceProvider, predicate); + Fabric8DiscoveryClient fabric8DiscoveryClient(KubernetesClient client, List> serviceListers, + List> endpointsListers, List> serviceInformers, + List> endpointsInformers, KubernetesDiscoveryProperties properties, + Predicate predicate) { + return new Fabric8DiscoveryClient(client, serviceListers, endpointsListers, serviceInformers, + endpointsInformers, properties, predicate); } @Bean @ConditionalOnMissingBean @ConditionalOnDiscoveryCacheableBlockingEnabled Fabric8CacheableDiscoveryClient fabric8CacheableDiscoveryClient(KubernetesClient client, - KubernetesDiscoveryProperties properties, Predicate predicate, Environment environment) { - ServicePortSecureResolver servicePortSecureResolver = new ServicePortSecureResolver(properties); - KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(environment); - return new Fabric8CacheableDiscoveryClient(client, properties, servicePortSecureResolver, namespaceProvider, - predicate); + List> serviceListers, List> endpointsListers, + List> serviceInformers, + List> endpointsInformers, KubernetesDiscoveryProperties properties, + Predicate predicate) { + return new Fabric8CacheableDiscoveryClient(client, serviceListers, endpointsListers, serviceInformers, + endpointsInformers, properties, predicate); } @Bean diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java index e76c716d3..29771f28e 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java @@ -16,37 +16,27 @@ package org.springframework.cloud.kubernetes.fabric8.discovery; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Set; import java.util.function.Predicate; +import java.util.function.Supplier; import java.util.stream.Collectors; import io.fabric8.kubernetes.api.model.EndpointAddress; import io.fabric8.kubernetes.api.model.EndpointPort; import io.fabric8.kubernetes.api.model.EndpointSubset; -import io.fabric8.kubernetes.api.model.Endpoints; -import io.fabric8.kubernetes.api.model.EndpointsList; import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.api.model.ServiceList; -import io.fabric8.kubernetes.api.model.discovery.v1.EndpointSlice; -import io.fabric8.kubernetes.api.model.discovery.v1.EndpointSliceList; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.dsl.FilterNested; -import io.fabric8.kubernetes.client.dsl.FilterWatchListDeletable; -import io.fabric8.kubernetes.client.dsl.Resource; -import io.fabric8.kubernetes.client.dsl.ServiceResource; -import jakarta.annotation.Nullable; +import io.fabric8.kubernetes.client.informers.cache.Lister; import org.apache.commons.logging.LogFactory; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; -import org.springframework.cloud.kubernetes.fabric8.Fabric8Utils; import org.springframework.core.log.LogAccessor; import org.springframework.util.CollectionUtils; +import static org.springframework.cloud.kubernetes.commons.discovery.DiscoveryClientUtils.poll; import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryConstants.UNSET_PORT_NAME; import static org.springframework.util.StringUtils.hasText; @@ -63,120 +53,27 @@ private Fabric8DiscoveryClientUtils() { } - static List endpointSlices(KubernetesDiscoveryProperties properties, KubernetesClient client, - KubernetesNamespaceProvider namespaceProvider, String target) { + static void postConstruct(KubernetesDiscoveryProperties properties, Supplier informersReadyFunc, + List> serviceListers) { - List endpointSlices; - - if (properties.allNamespaces()) { - LOG.debug(() -> "discovering endpoint slices in all namespaces"); - endpointSlices = filteredEndpointSlices( - client.discovery().v1().endpointSlices().inAnyNamespace().withNewFilter(), properties); - } - else if (!properties.namespaces().isEmpty()) { - LOG.debug(() -> "discovering endpoint slices in namespaces : " + properties.namespaces()); - List inner = new ArrayList<>(properties.namespaces().size()); - properties.namespaces() - .forEach(namespace -> inner.addAll(filteredEndpointSlices( - client.discovery().v1().endpointSlices().inNamespace(namespace).withNewFilter(), properties))); - endpointSlices = inner; + if (!poll(Duration.ofSeconds(1), Duration.ofSeconds(properties.cacheLoadingTimeoutSeconds()), () -> { + LOG.info(() -> "Waiting for the cache of informers to be fully loaded.."); + return informersReadyFunc.get(); + })) { + if (properties.waitCacheReady()) { + throw new IllegalStateException( + "Timeout waiting for informers cache to be ready, is the kubernetes service up?"); + } + else { + LOG.warn(() -> "Timeout waiting for informers cache to be ready, " + + "ignoring the failure because waitForInformerCacheReady property is false"); + } } else { - String namespace = Fabric8Utils.getApplicationNamespace(client, null, target, namespaceProvider); - LOG.debug(() -> "discovering endpoint slices in namespace : " + namespace); - endpointSlices = filteredEndpointSlices( - client.discovery().v1().endpointSlices().inNamespace(namespace).withNewFilter(), properties); - } - - return endpointSlices; - } - -// static List endpoints(KubernetesDiscoveryProperties properties, KubernetesClient client, -// KubernetesNamespaceProvider namespaceProvider, String target, @Nullable String serviceName, -// Predicate filter) { -// -// List endpoints; -// -// if (!properties.namespaces().isEmpty()) { -// LOG.debug(() -> "discovering endpoints in namespaces : " + properties.namespaces()); -// List inner = new ArrayList<>(properties.namespaces().size()); -// properties.namespaces() -// .forEach(namespace -> inner.addAll(filteredEndpoints( -// client.endpoints().inNamespace(namespace).withNewFilter(), properties, serviceName))); -// endpoints = inner; -// } -// else if (properties.allNamespaces()) { -// LOG.debug(() -> "discovering endpoints in all namespaces"); -// endpoints = filteredEndpoints(client.endpoints().inAnyNamespace().withNewFilter(), properties, serviceName); -// } -// else { -// String namespace = Fabric8Utils.getApplicationNamespace(client, null, target, namespaceProvider); -// LOG.debug(() -> "discovering endpoints in namespace : " + namespace); -// endpoints = filteredEndpoints(client.endpoints().inNamespace(namespace).withNewFilter(), properties, -// serviceName); -// } -// -// return withFilter(endpoints, properties, client, filter); -// } - - // see https://github.com/spring-cloud/spring-cloud-kubernetes/issues/1182 on why this - // is needed - static List withFilter(List endpoints, KubernetesDiscoveryProperties properties, - KubernetesClient client, Predicate filter) { - - if (properties.filter() == null || properties.filter().isBlank() || filter == ALWAYS_TRUE) { - LOG.debug(() -> "filter not present"); - return endpoints; - } - - List result = new ArrayList<>(); - // group by namespace in order to make a single API call per namespace when - // retrieving services - Map> endpointsByNamespace = endpoints.stream() - .collect(Collectors.groupingBy(x -> x.getMetadata().getNamespace())); - - for (Map.Entry> entry : endpointsByNamespace.entrySet()) { - // get all services in the namespace that match the filter - Set filteredServiceNames = client.services() - .inNamespace(entry.getKey()) - .list() - .getItems() - .stream() - .filter(filter) - .map(service -> service.getMetadata().getName()) - .collect(Collectors.toSet()); - - // in the previous step we might have taken "too many" services, so in the - // next one take only those that have a matching endpoints, by name. - // This way we only get the endpoints that have a matching service with an - // applied filter, it's like we filtered endpoints by that filter. - result.addAll(entry.getValue() - .stream() - .filter(endpoint -> filteredServiceNames.contains(endpoint.getMetadata().getName())) - .toList()); - - } - - return result; - } - - /** - * serviceName can be null, in which case the filter for "metadata.name" will not be - * applied. - */ - static List filteredEndpoints( - FilterNested>> filterNested, - KubernetesDiscoveryProperties properties, @Nullable String serviceName) { - - FilterNested>> partial = filterNested - .withLabels(properties.serviceLabels()); - - if (serviceName != null) { - partial = partial.withField("metadata.name", serviceName); + LOG.info(() -> "Cache fully loaded (total " + serviceListers.stream().mapToLong(x -> x.list().size()).sum() + + " services), discovery client is now available"); } - return partial.endFilter().list().getItems(); - } static List addresses(EndpointSubset endpointSubset, KubernetesDiscoveryProperties properties) { @@ -195,36 +92,6 @@ static List addresses(EndpointSubset endpointSubset, Kubernetes return addresses; } - static List services(KubernetesDiscoveryProperties properties, KubernetesClient client, - KubernetesNamespaceProvider namespaceProvider, Predicate predicate, - Map fieldFilters, String target) { - - List services; - - if (properties.allNamespaces()) { - LOG.debug(() -> "discovering services in all namespaces"); - services = filteredServices(client.services().inAnyNamespace().withNewFilter(), properties, predicate, - fieldFilters); - } - else if (!properties.namespaces().isEmpty()) { - LOG.debug(() -> "discovering services in namespaces : " + properties.namespaces()); - List inner = new ArrayList<>(properties.namespaces().size()); - properties.namespaces() - .forEach(namespace -> inner - .addAll(filteredServices(client.services().inNamespace(namespace).withNewFilter(), properties, - predicate, fieldFilters))); - services = inner; - } - else { - String namespace = Fabric8Utils.getApplicationNamespace(client, null, target, namespaceProvider); - LOG.debug(() -> "discovering services in namespace : " + namespace); - services = filteredServices(client.services().inNamespace(namespace).withNewFilter(), properties, predicate, - fieldFilters); - } - - return services; - } - /** * a service is allowed to have a single port defined without a name. */ @@ -236,34 +103,4 @@ static Map endpointSubsetsPortData(List endpoin EndpointPort::getPort)); } - /** - * serviceName can be null, in which case, such a filter will not be applied. - */ - private static List filteredServices( - FilterNested>> filterNested, - KubernetesDiscoveryProperties properties, Predicate predicate, - @Nullable Map fieldFilters) { - - FilterNested>> partial = filterNested - .withLabels(properties.serviceLabels()); - - if (fieldFilters != null) { - partial = partial.withFields(fieldFilters); - } - - return partial.endFilter().list().getItems().stream().filter(predicate).toList(); - - } - - private static List filteredEndpointSlices( - FilterNested>> filterNested, - KubernetesDiscoveryProperties properties) { - - FilterNested>> partial = filterNested - .withLabels(properties.serviceLabels()); - - return partial.endFilter().list().getItems(); - - } - } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8EndpointSliceCatalogWatch.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8EndpointSliceCatalogWatch.java index 4099518af..ac9cc8802 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8EndpointSliceCatalogWatch.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8EndpointSliceCatalogWatch.java @@ -16,7 +16,9 @@ package org.springframework.cloud.kubernetes.fabric8.discovery; +import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.function.Function; import java.util.stream.Stream; @@ -24,10 +26,12 @@ import io.fabric8.kubernetes.api.model.ObjectReference; import io.fabric8.kubernetes.api.model.discovery.v1.Endpoint; import io.fabric8.kubernetes.api.model.discovery.v1.EndpointSlice; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.apache.commons.logging.LogFactory; import org.springframework.cloud.kubernetes.commons.discovery.EndpointNameAndNamespace; - -import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.endpointSlices; +import org.springframework.cloud.kubernetes.fabric8.Fabric8Utils; +import org.springframework.core.log.LogAccessor; /** * Implementation that is based on EndpointSlice V1. @@ -37,10 +41,34 @@ final class Fabric8EndpointSliceCatalogWatch implements Function> { + private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(Fabric8EndpointSliceCatalogWatch.class)); + @Override public List apply(Fabric8CatalogWatchContext context) { - List endpointSlices = endpointSlices(context.properties(), context.kubernetesClient(), - context.namespaceProvider(), "catalog-watcher"); + List endpointSlices; + + KubernetesClient kubernetesClient = context.kubernetesClient(); + + if (context.properties().allNamespaces()) { + LOG.debug(() -> "discovering endpoint slices in all namespaces"); + endpointSlices = endpointSlices(kubernetesClient, context.properties().serviceLabels()); + } + else if (!context.properties().namespaces().isEmpty()) { + LOG.debug(() -> "discovering endpoint slices in " + context.properties().namespaces()); + List inner = new ArrayList<>(context.properties().namespaces().size()); + context.properties() + .namespaces() + .forEach(namespace -> inner.addAll( + namespacedEndpointSlices(kubernetesClient, namespace, context.properties().serviceLabels()))); + endpointSlices = inner; + } + else { + String namespace = Fabric8Utils.getApplicationNamespace(kubernetesClient, null, "fabric8 discovery", + context.namespaceProvider()); + LOG.debug(() -> "discovering endpoint slices in namespace : " + namespace); + endpointSlices = namespacedEndpointSlices(kubernetesClient, namespace, + context.properties().serviceLabels()); + } return generateState(endpointSlices); } @@ -59,4 +87,19 @@ List generateState(List endpointSlices) return Fabric8CatalogWatchContext.state(references); } + private List endpointSlices(KubernetesClient client, Map labels) { + return client.discovery().v1().endpointSlices().inAnyNamespace().withLabels(labels).list().getItems(); + } + + private List namespacedEndpointSlices(KubernetesClient kubernetesClient, String namespace, + Map labels) { + return kubernetesClient.discovery() + .v1() + .endpointSlices() + .inNamespace(namespace) + .withLabels(labels) + .list() + .getItems(); + } + } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8EndpointsCatalogWatch.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8EndpointsCatalogWatch.java index 80dd55026..b8cdd0e2e 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8EndpointsCatalogWatch.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8EndpointsCatalogWatch.java @@ -16,7 +16,9 @@ package org.springframework.cloud.kubernetes.fabric8.discovery; +import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.function.Function; import java.util.stream.Stream; @@ -25,11 +27,12 @@ import io.fabric8.kubernetes.api.model.EndpointSubset; import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.ObjectReference; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.apache.commons.logging.LogFactory; import org.springframework.cloud.kubernetes.commons.discovery.EndpointNameAndNamespace; - -import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.ALWAYS_TRUE; -import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.endpoints; +import org.springframework.cloud.kubernetes.fabric8.Fabric8Utils; +import org.springframework.core.log.LogAccessor; /** * Implementation that is based on Endpoints. @@ -39,10 +42,31 @@ final class Fabric8EndpointsCatalogWatch implements Function> { + private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(Fabric8EndpointsCatalogWatch.class)); + @Override public List apply(Fabric8CatalogWatchContext context) { - List endpoints = endpoints(context.properties(), context.kubernetesClient(), - context.namespaceProvider(), "catalog-watcher", null, ALWAYS_TRUE); + List endpoints; + KubernetesClient kubernetesClient = context.kubernetesClient(); + if (context.properties().allNamespaces()) { + LOG.debug(() -> "discovering endpoints in all namespaces"); + endpoints = endpoints(kubernetesClient, context.properties().serviceLabels()); + } + else if (!context.properties().namespaces().isEmpty()) { + LOG.debug(() -> "discovering endpoints in " + context.properties().namespaces()); + List inner = new ArrayList<>(context.properties().namespaces().size()); + context.properties() + .namespaces() + .forEach(namespace -> inner + .addAll(namespacedEndpoints(kubernetesClient, namespace, context.properties().serviceLabels()))); + endpoints = inner; + } + else { + String namespace = Fabric8Utils.getApplicationNamespace(kubernetesClient, null, "fabric8 discovery", + context.namespaceProvider()); + LOG.debug(() -> "discovering endpoints in namespace : " + namespace); + endpoints = namespacedEndpoints(kubernetesClient, namespace, context.properties().serviceLabels()); + } return generateState(endpoints); } @@ -73,4 +97,13 @@ List generateState(List endpoints) { return Fabric8CatalogWatchContext.state(references); } + private List endpoints(KubernetesClient client, Map labels) { + return client.endpoints().inAnyNamespace().withLabels(labels).list().getItems(); + } + + private List namespacedEndpoints(KubernetesClient kubernetesClient, String namespace, + Map labels) { + return kubernetesClient.endpoints().inNamespace(namespace).withLabels(labels).list().getItems(); + } + } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java index 20cd8e0ab..fe869fd80 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java @@ -18,17 +18,14 @@ import java.util.ArrayList; import java.util.List; -import java.util.function.Predicate; import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.api.model.ServiceList; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.informers.SharedIndexInformer; -import io.fabric8.kubernetes.client.informers.SharedInformerFactory; -import jakarta.annotation.Nullable; - +import io.fabric8.kubernetes.client.informers.cache.Lister; import org.apache.commons.logging.LogFactory; + import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform; @@ -39,11 +36,9 @@ import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration; import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; -import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryPropertiesAutoConfiguration; import org.springframework.cloud.kubernetes.commons.discovery.conditionals.ConditionalOnBlockingOrReactiveDiscoveryEnabled; import org.springframework.cloud.kubernetes.commons.discovery.conditionals.ConditionalOnKubernetesDiscoveryEnabled; import org.springframework.cloud.kubernetes.fabric8.Fabric8AutoConfiguration; -import org.springframework.cloud.kubernetes.fabric8.Fabric8Utils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; @@ -63,14 +58,13 @@ @AutoConfigureAfter({ Fabric8AutoConfiguration.class }) final class Fabric8InformerAutoConfiguration { - private static final LogAccessor LOG = new LogAccessor( - LogFactory.getLog(Fabric8InformerAutoConfiguration.class)); + private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(Fabric8InformerAutoConfiguration.class)); // we rely on the order of namespaces to enable listers, as such provide a bean of // namespaces as a list, instead of the incoming Set. @Bean - List selectiveNamespaces(KubernetesDiscoveryProperties properties, - KubernetesClient kubernetesClient, Environment environment) { + List selectiveNamespaces(KubernetesDiscoveryProperties properties, KubernetesClient kubernetesClient, + Environment environment) { KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(environment); @@ -90,50 +84,45 @@ List selectiveNamespaces(KubernetesDiscoveryProperties properties, } @Bean - @ConditionalOnMissingBean(value = SharedInformerFactory.class, parameterizedContainer = List.class) - List sharedInformerFactories(KubernetesClient kubernetesClient, - List selectiveNamespaces) { - - int howManyNamespaces = selectiveNamespaces.size(); - List sharedInformerFactories = new ArrayList<>(howManyNamespaces); - for (int i = 0; i < howManyNamespaces; ++i) { - sharedInformerFactories.add(kubernetesClient.informers()); - } - return sharedInformerFactories; - } - - @Bean - @ConditionalOnMissingBean(value = Service.class, - parameterizedContainer = { List.class, SharedIndexInformer.class }) - List> serviceSharedIndexInformers( - List sharedInformerFactories, List selectiveNamespaces, CoreV1Api api, - KubernetesDiscoveryProperties properties) { + @ConditionalOnMissingBean(value = Service.class, parameterizedContainer = { List.class, SharedIndexInformer.class }) + List> serviceSharedIndexInformers(List selectiveNamespaces, + KubernetesClient kubernetesClient, KubernetesDiscoveryProperties properties) { int howManyNamespaces = selectiveNamespaces.size(); List> serviceSharedIndexedInformers = new ArrayList<>(howManyNamespaces); - for (int i = 0; i < howManyNamespaces; ++i) { - String namespace = selectiveNamespaces.get(i); + for (String namespace : selectiveNamespaces) { + SharedIndexInformer sharedIndexInformer = null; + + // we treat this as all namespaces + if ("".equals(namespace)) { + sharedIndexInformer = kubernetesClient.services() + .inAnyNamespace() + .withLabels(properties.serviceLabels()) + .inform(); + } + else { + sharedIndexInformer = kubernetesClient.services() + .inNamespace(namespace) + .withLabels(properties.serviceLabels()) + .inform(); + } - CallGenerator callGenerator = servicesCallGenerator(api, properties.serviceLabels(), namespace); - - SharedIndexInformer sharedIndexInformer = sharedInformerFactories.get(i) - .sharedIndexInformerFor(Service.class, ServiceList.class); serviceSharedIndexedInformers.add(sharedIndexInformer); } return serviceSharedIndexedInformers; } @Bean - @ConditionalOnMissingBean(value = V1Service.class, parameterizedContainer = { List.class, Lister.class }) - List> serviceListers(List selectiveNamespaces, - List> serviceSharedIndexInformers) { + @ConditionalOnMissingBean(value = Service.class, parameterizedContainer = { List.class, Lister.class }) + List> serviceListers(List selectiveNamespaces, + List> serviceSharedIndexInformers) { int howManyNamespaces = selectiveNamespaces.size(); - List> serviceListers = new ArrayList<>(howManyNamespaces); + List> serviceListers = new ArrayList<>(howManyNamespaces); for (int i = 0; i < howManyNamespaces; ++i) { String namespace = selectiveNamespaces.get(i); - Lister lister = new Lister<>(serviceSharedIndexInformers.get(i).getIndexer(), namespace); + Lister lister = new Lister<>(serviceSharedIndexInformers.get(i).getIndexer(), namespace); LOG.debug(() -> "registering lister (for services) in namespace : " + namespace); serviceListers.add(lister); } @@ -142,37 +131,48 @@ List> serviceListers(List selectiveNamespaces, } @Bean - @ConditionalOnMissingBean(value = V1Endpoints.class, - parameterizedContainer = { List.class, SharedIndexInformer.class }) - List> endpointsSharedIndexInformers( - List sharedInformerFactories, List selectiveNamespaces, CoreV1Api api, - KubernetesDiscoveryProperties properties) { + @ConditionalOnMissingBean(value = Endpoints.class, + parameterizedContainer = { List.class, SharedIndexInformer.class }) + List> endpointsSharedIndexInformers(List selectiveNamespaces, + KubernetesClient kubernetesClient, KubernetesDiscoveryProperties properties) { int howManyNamespaces = selectiveNamespaces.size(); - List> endpointsSharedIndexedInformers = new ArrayList<>(howManyNamespaces); - for (int i = 0; i < howManyNamespaces; ++i) { - String namespace = selectiveNamespaces.get(i); - - CallGenerator callGenerator = endpointsCallGenerator(api, properties.serviceLabels(), namespace); + List> endpointsSharedIndexedInformers = new ArrayList<>(howManyNamespaces); + for (String namespace : selectiveNamespaces) { + + SharedIndexInformer sharedIndexInformer; + + // we treat this as all namespaces + if ("".equals(namespace)) { + sharedIndexInformer = kubernetesClient.endpoints() + .inAnyNamespace() + .withLabels(properties.serviceLabels()) + .inform(); + } + else { + sharedIndexInformer = kubernetesClient.endpoints() + .inNamespace(namespace) + .withLabels(properties.serviceLabels()) + .inform(); + } - SharedIndexInformer sharedIndexInformer = sharedInformerFactories.get(i) - .sharedIndexInformerFor(callGenerator, V1Endpoints.class, V1EndpointsList.class); endpointsSharedIndexedInformers.add(sharedIndexInformer); + } return endpointsSharedIndexedInformers; } @Bean - @ConditionalOnMissingBean(value = V1Endpoints.class, parameterizedContainer = { List.class, Lister.class }) - List> endpointsListers(List selectiveNamespaces, - List> endpointsSharedIndexInformers) { + @ConditionalOnMissingBean(value = Endpoints.class, parameterizedContainer = { List.class, Lister.class }) + List> endpointsListers(List selectiveNamespaces, + List> endpointsSharedIndexInformers) { int howManyNamespaces = selectiveNamespaces.size(); - List> endpointsListers = new ArrayList<>(howManyNamespaces); + List> endpointsListers = new ArrayList<>(howManyNamespaces); for (int i = 0; i < howManyNamespaces; ++i) { String namespace = selectiveNamespaces.get(i); - Lister lister = new Lister<>(endpointsSharedIndexInformers.get(i).getIndexer(), namespace); + Lister lister = new Lister<>(endpointsSharedIndexInformers.get(i).getIndexer(), namespace); LOG.debug(() -> "registering lister (for endpoints) in namespace : " + namespace); endpointsListers.add(lister); } @@ -180,5 +180,4 @@ List> endpointsListers(List selectiveNamespaces, return endpointsListers; } - } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InstanceIdHostPodNameSupplier.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InstanceIdHostPodNameSupplier.java index 88e9da74d..453796e47 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InstanceIdHostPodNameSupplier.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InstanceIdHostPodNameSupplier.java @@ -49,14 +49,15 @@ public InstanceIdHostPodName get() { /** * to be used when .spec.type of the Service is != 'ExternalName'. */ - static Fabric8InstanceIdHostPodNameSupplier nonExternalName(EndpointAddress endpointAddress, Service service) { + static Fabric8InstanceIdHostPodNameSupplier fabric8InstanceIdHostPodNameSupplier(EndpointAddress endpointAddress, + Service service) { return new Fabric8InstanceIdHostPodNameSupplier(endpointAddress, service); } /** * to be used when .spec.type of the Service is == 'ExternalName'. */ - static Fabric8InstanceIdHostPodNameSupplier externalName(Service service) { + static Fabric8InstanceIdHostPodNameSupplier fabric8InstanceIdHostPodNameSupplier(Service service) { return new Fabric8InstanceIdHostPodNameSupplier(null, service); } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8PodLabelsAndAnnotationsSupplier.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8PodLabelsAndAnnotationsSupplier.java index 9579b1983..939617cc5 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8PodLabelsAndAnnotationsSupplier.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8PodLabelsAndAnnotationsSupplier.java @@ -44,7 +44,8 @@ private Fabric8PodLabelsAndAnnotationsSupplier(KubernetesClient client, String n /** * to be used when .spec.type of the Service is != 'ExternalName'. */ - static Fabric8PodLabelsAndAnnotationsSupplier nonExternalName(KubernetesClient client, String namespace) { + static Fabric8PodLabelsAndAnnotationsSupplier fabric8PodLabelsAndAnnotationsSupplier(KubernetesClient client, + String namespace) { return new Fabric8PodLabelsAndAnnotationsSupplier(client, namespace); } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientAutoConfiguration.java index ae36b5f0d..19a2e00ec 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientAutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientAutoConfiguration.java @@ -16,10 +16,14 @@ package org.springframework.cloud.kubernetes.fabric8.discovery; +import java.util.List; import java.util.function.Predicate; +import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.informers.SharedIndexInformer; +import io.fabric8.kubernetes.client.informers.cache.Lister; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; @@ -27,16 +31,13 @@ import org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration; import org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration; import org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryClientAutoConfiguration; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryPropertiesAutoConfiguration; -import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; import org.springframework.cloud.kubernetes.commons.discovery.conditionals.ConditionalOnDiscoveryCacheableReactiveDisabled; import org.springframework.cloud.kubernetes.commons.discovery.conditionals.ConditionalOnDiscoveryCacheableReactiveEnabled; import org.springframework.cloud.kubernetes.commons.discovery.conditionals.ConditionalOnSpringCloudKubernetesReactiveDiscovery; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; /** * Auto configuration for reactive discovery client. @@ -56,11 +57,12 @@ public final class Fabric8ReactiveDiscoveryClientAutoConfiguration { @ConditionalOnMissingBean @ConditionalOnDiscoveryCacheableReactiveDisabled Fabric8ReactiveDiscoveryClient fabric8ReactiveDiscoveryClient(KubernetesClient client, - KubernetesDiscoveryProperties properties, Predicate predicate, Environment environment) { - ServicePortSecureResolver servicePortSecureResolver = new ServicePortSecureResolver(properties); - KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(environment); - Fabric8DiscoveryClient fabric8DiscoveryClient = new Fabric8DiscoveryClient(client, properties, - servicePortSecureResolver, namespaceProvider, predicate); + List> serviceListers, List> endpointsListers, + List> serviceInformers, + List> endpointsInformers, KubernetesDiscoveryProperties properties, + Predicate predicate) { + Fabric8DiscoveryClient fabric8DiscoveryClient = new Fabric8DiscoveryClient(client, serviceListers, + endpointsListers, serviceInformers, endpointsInformers, properties, predicate); return new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); } @@ -68,21 +70,21 @@ Fabric8ReactiveDiscoveryClient fabric8ReactiveDiscoveryClient(KubernetesClient c @ConditionalOnMissingBean @ConditionalOnDiscoveryCacheableReactiveEnabled Fabric8CacheableReactiveDiscoveryClient fabric8CacheableReactiveDiscoveryClient(KubernetesClient client, - KubernetesDiscoveryProperties properties, Predicate predicate, Environment environment) { - ServicePortSecureResolver servicePortSecureResolver = new ServicePortSecureResolver(properties); - KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(environment); - Fabric8DiscoveryClient blockingClient = new Fabric8DiscoveryClient(client, properties, - servicePortSecureResolver, namespaceProvider, predicate); + List> serviceListers, List> endpointsListers, + List> serviceInformers, + List> endpointsInformers, KubernetesDiscoveryProperties properties, + Predicate predicate) { + Fabric8DiscoveryClient blockingClient = new Fabric8DiscoveryClient(client, serviceListers, endpointsListers, + serviceInformers, endpointsInformers, properties, predicate); return new Fabric8CacheableReactiveDiscoveryClient(blockingClient); } // Above two beans are created when cacheable is enabled. In this case, we can't make // Fabric8DiscoveryClient a @Bean, since blocking discovery might be disabled and we - // do - // not want to allow wiring of it. Nevertheless, we still need an instance of - // Fabric8DiscoveryClient - // in order to create the ReactiveDiscoveryClientHealthIndicator and - // Fabric8CacheableReactiveDiscoveryClient - // As such, we create two of such instances in each bean. + // do not want to allow wiring of it. Nevertheless, we still need an instance of + // Fabric8DiscoveryClient in order to create the + // ReactiveDiscoveryClientHealthIndicator and + // Fabric8CacheableReactiveDiscoveryClient. As such, we create two of such instances + // in each bean. } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryHealthAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryHealthAutoConfiguration.java index 4d24181ab..c587b8320 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryHealthAutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryHealthAutoConfiguration.java @@ -16,10 +16,14 @@ package org.springframework.cloud.kubernetes.fabric8.discovery; +import java.util.List; import java.util.function.Predicate; +import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.informers.SharedIndexInformer; +import io.fabric8.kubernetes.client.informers.cache.Lister; import org.apache.commons.logging.LogFactory; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -33,18 +37,15 @@ import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicatorProperties; import org.springframework.cloud.client.discovery.health.reactive.ReactiveDiscoveryClientHealthIndicator; import org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryClientAutoConfiguration; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.PodUtils; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryClientHealthIndicatorInitializer; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryPropertiesAutoConfiguration; -import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; import org.springframework.cloud.kubernetes.commons.discovery.conditionals.ConditionalOnSpringCloudKubernetesReactiveDiscovery; import org.springframework.cloud.kubernetes.commons.discovery.conditionals.ConditionalOnSpringCloudKubernetesReactiveDiscoveryHealthInitializer; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; import org.springframework.core.log.LogAccessor; /** @@ -78,14 +79,14 @@ ReactiveDiscoveryClientHealthIndicator nonCacheableReactiveDiscoveryClientHealth @ConditionalOnMissingBean(Fabric8ReactiveDiscoveryClient.class) @ConditionalOnSpringCloudKubernetesReactiveDiscoveryHealthInitializer ReactiveDiscoveryClientHealthIndicator cacheableReactiveDiscoveryClientHealthIndicator(KubernetesClient client, + List> serviceListers, List> endpointsListers, + List> serviceInformers, + List> endpointsInformers, KubernetesDiscoveryProperties kubernetesDiscoveryProperties, Predicate predicate, - DiscoveryClientHealthIndicatorProperties properties, Environment environment) { + DiscoveryClientHealthIndicatorProperties properties) { - KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(environment); - ServicePortSecureResolver servicePortSecureResolver = new ServicePortSecureResolver( - kubernetesDiscoveryProperties); - Fabric8DiscoveryClient fabric8DiscoveryClient = new Fabric8DiscoveryClient(client, - kubernetesDiscoveryProperties, servicePortSecureResolver, namespaceProvider, predicate); + Fabric8DiscoveryClient fabric8DiscoveryClient = new Fabric8DiscoveryClient(client, serviceListers, + endpointsListers, serviceInformers, endpointsInformers, kubernetesDiscoveryProperties, predicate); Fabric8ReactiveDiscoveryClient reactiveClient = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InstanceIdHostPodNameSupplierTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InstanceIdHostPodNameSupplierTests.java index b10fe3d80..df8488c7d 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InstanceIdHostPodNameSupplierTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InstanceIdHostPodNameSupplierTests.java @@ -40,7 +40,8 @@ void instanceIdNoEndpointAddress() { .withMetadata(new ObjectMetaBuilder().withUid("123").build()) .build(); - Fabric8InstanceIdHostPodNameSupplier supplier = Fabric8InstanceIdHostPodNameSupplier.externalName(service); + Fabric8InstanceIdHostPodNameSupplier supplier = Fabric8InstanceIdHostPodNameSupplier + .fabric8InstanceIdHostPodNameSupplier(service); InstanceIdHostPodName result = supplier.get(); Assertions.assertThat(result).isNotNull(); @@ -57,7 +58,7 @@ void instanceIdWithEndpointAddress() { .build(); Fabric8InstanceIdHostPodNameSupplier supplier = Fabric8InstanceIdHostPodNameSupplier - .nonExternalName(endpointAddress, service); + .fabric8InstanceIdHostPodNameSupplier(endpointAddress, service); InstanceIdHostPodName result = supplier.get(); Assertions.assertThat(result).isNotNull(); @@ -71,7 +72,8 @@ void hostNoEndpointAddress() { .withMetadata(new ObjectMeta()) .build(); - Fabric8InstanceIdHostPodNameSupplier supplier = Fabric8InstanceIdHostPodNameSupplier.externalName(service); + Fabric8InstanceIdHostPodNameSupplier supplier = Fabric8InstanceIdHostPodNameSupplier + .fabric8InstanceIdHostPodNameSupplier(service); InstanceIdHostPodName result = supplier.get(); Assertions.assertThat(result).isNotNull(); @@ -87,7 +89,7 @@ void hostWithEndpointAddress() { .build(); Fabric8InstanceIdHostPodNameSupplier supplier = Fabric8InstanceIdHostPodNameSupplier - .nonExternalName(endpointAddress, service); + .fabric8InstanceIdHostPodNameSupplier(endpointAddress, service); InstanceIdHostPodName result = supplier.get(); Assertions.assertThat(result).isNotNull(); @@ -99,7 +101,8 @@ void testPodNameIsNull() { Service service = new ServiceBuilder().withMetadata(new ObjectMetaBuilder().withUid("123").build()) .withSpec(new ServiceSpecBuilder().withExternalName("external-name").build()) .build(); - Fabric8InstanceIdHostPodNameSupplier supplier = Fabric8InstanceIdHostPodNameSupplier.externalName(service); + Fabric8InstanceIdHostPodNameSupplier supplier = Fabric8InstanceIdHostPodNameSupplier + .fabric8InstanceIdHostPodNameSupplier(service); InstanceIdHostPodName result = supplier.get(); Assertions.assertThat(result).isNotNull(); @@ -117,7 +120,7 @@ void podNameKindNotPod() { .build(); Fabric8InstanceIdHostPodNameSupplier supplier = Fabric8InstanceIdHostPodNameSupplier - .nonExternalName(endpointAddress, service); + .fabric8InstanceIdHostPodNameSupplier(endpointAddress, service); InstanceIdHostPodName result = supplier.get(); Assertions.assertThat(result).isNotNull(); @@ -135,7 +138,7 @@ void podNameKindIsPod() { .build(); Fabric8InstanceIdHostPodNameSupplier supplier = Fabric8InstanceIdHostPodNameSupplier - .nonExternalName(endpointAddress, service); + .fabric8InstanceIdHostPodNameSupplier(endpointAddress, service); InstanceIdHostPodName result = supplier.get(); Assertions.assertThat(result).isNotNull(); diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8PodLabelsAndAnnotationsSupplierTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8PodLabelsAndAnnotationsSupplierTests.java index 2420bc112..dd08f103e 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8PodLabelsAndAnnotationsSupplierTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8PodLabelsAndAnnotationsSupplierTests.java @@ -52,7 +52,8 @@ void noObjetMeta() { .resource(new PodBuilder().withMetadata(new ObjectMetaBuilder().withName(POD_NAME).build()).build()) .create(); - PodLabelsAndAnnotations result = Fabric8PodLabelsAndAnnotationsSupplier.nonExternalName(client, NAMESPACE) + PodLabelsAndAnnotations result = Fabric8PodLabelsAndAnnotationsSupplier + .fabric8PodLabelsAndAnnotationsSupplier(client, NAMESPACE) .apply(POD_NAME); Assertions.assertThat(result).isNotNull(); Assertions.assertThat(result.labels()).isEmpty(); @@ -71,7 +72,8 @@ void labelsAndAnnotationsPresent() { .build()) .create(); - PodLabelsAndAnnotations result = Fabric8PodLabelsAndAnnotationsSupplier.nonExternalName(client, NAMESPACE) + PodLabelsAndAnnotations result = Fabric8PodLabelsAndAnnotationsSupplier + .fabric8PodLabelsAndAnnotationsSupplier(client, NAMESPACE) .apply(POD_NAME); Assertions.assertThat(result).isNotNull(); Assertions.assertThat(result.labels()).containsExactlyInAnyOrderEntriesOf(Map.of("a", "b")); From b2089f56b93c648b0048be79b5780cfcad3d4055 Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 3 Feb 2026 14:49:45 +0200 Subject: [PATCH 06/19] wip Signed-off-by: wind57 --- .../Fabric8ConfigServerBootstrapper.java | 2 + .../Fabric8DiscoveryClientUtils.java | 47 +++++++++++++++++++ .../Fabric8InformerAutoConfiguration.java | 42 +++-------------- 3 files changed, 55 insertions(+), 36 deletions(-) diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java index ff0ba9b5a..ac2ca19fd 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java @@ -82,6 +82,8 @@ public void initialize(@Nonnull BootstrapRegistry registry) { Fabric8InformerAutoConfiguration fabric8InformerAutoConfiguration = new Fabric8InformerAutoConfiguration(); + List selectiveNamespaces = fabric8InformerAutoConfiguration.selectiveNamespaces( + discoveryProperties, kubernetesClient, registry.ge) List> serviceListers, List> endpointsListers, List> serviceInformers, diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java index 29771f28e..15520544b 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java @@ -28,7 +28,10 @@ import io.fabric8.kubernetes.api.model.EndpointAddress; import io.fabric8.kubernetes.api.model.EndpointPort; import io.fabric8.kubernetes.api.model.EndpointSubset; +import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.Service; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.informers.SharedIndexInformer; import io.fabric8.kubernetes.client.informers.cache.Lister; import org.apache.commons.logging.LogFactory; @@ -103,4 +106,48 @@ static Map endpointSubsetsPortData(List endpoin EndpointPort::getPort)); } + static SharedIndexInformer serviceSharedIndexInformer(String namespace, + KubernetesClient kubernetesClient, Map serviceLabels) { + + SharedIndexInformer sharedIndexInformer; + + // we treat this as all namespaces + if ("".equals(namespace)) { + sharedIndexInformer = kubernetesClient.services() + .inAnyNamespace() + .withLabels(serviceLabels) + .inform(); + } + else { + sharedIndexInformer = kubernetesClient.services() + .inNamespace(namespace) + .withLabels(serviceLabels) + .inform(); + } + + return sharedIndexInformer; + } + + static SharedIndexInformer endpointsSharedIndexInformer(String namespace, + KubernetesClient kubernetesClient, Map serviceLabels) { + + SharedIndexInformer sharedIndexInformer; + + // we treat this as all namespaces + if ("".equals(namespace)) { + sharedIndexInformer = kubernetesClient.endpoints() + .inAnyNamespace() + .withLabels(serviceLabels) + .inform(); + } + else { + sharedIndexInformer = kubernetesClient.endpoints() + .inNamespace(namespace) + .withLabels(serviceLabels) + .inform(); + } + + return sharedIndexInformer; + } + } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java index fe869fd80..07384b8ec 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java @@ -45,6 +45,8 @@ import org.springframework.core.log.LogAccessor; import static org.springframework.cloud.kubernetes.fabric8.Fabric8Utils.getApplicationNamespace; +import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.endpointsSharedIndexInformer; +import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.serviceSharedIndexInformer; /** * @author wind57 @@ -91,23 +93,8 @@ List> serviceSharedIndexInformers(List sele int howManyNamespaces = selectiveNamespaces.size(); List> serviceSharedIndexedInformers = new ArrayList<>(howManyNamespaces); for (String namespace : selectiveNamespaces) { - SharedIndexInformer sharedIndexInformer = null; - - // we treat this as all namespaces - if ("".equals(namespace)) { - sharedIndexInformer = kubernetesClient.services() - .inAnyNamespace() - .withLabels(properties.serviceLabels()) - .inform(); - } - else { - sharedIndexInformer = kubernetesClient.services() - .inNamespace(namespace) - .withLabels(properties.serviceLabels()) - .inform(); - } - - serviceSharedIndexedInformers.add(sharedIndexInformer); + serviceSharedIndexedInformers.add(serviceSharedIndexInformer( + namespace, kubernetesClient, properties.serviceLabels())); } return serviceSharedIndexedInformers; } @@ -139,25 +126,8 @@ List> endpointsSharedIndexInformers(List int howManyNamespaces = selectiveNamespaces.size(); List> endpointsSharedIndexedInformers = new ArrayList<>(howManyNamespaces); for (String namespace : selectiveNamespaces) { - - SharedIndexInformer sharedIndexInformer; - - // we treat this as all namespaces - if ("".equals(namespace)) { - sharedIndexInformer = kubernetesClient.endpoints() - .inAnyNamespace() - .withLabels(properties.serviceLabels()) - .inform(); - } - else { - sharedIndexInformer = kubernetesClient.endpoints() - .inNamespace(namespace) - .withLabels(properties.serviceLabels()) - .inform(); - } - - endpointsSharedIndexedInformers.add(sharedIndexInformer); - + endpointsSharedIndexedInformers.add(endpointsSharedIndexInformer( + namespace, kubernetesClient, properties.serviceLabels())); } return endpointsSharedIndexedInformers; } From 8b928c0b6ee010c551ac89747e3b1cdcea8586a5 Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 3 Feb 2026 16:44:27 +0200 Subject: [PATCH 07/19] wip Signed-off-by: wind57 --- .../discovery/Fabric8ConfigServerBootstrapper.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java index ac2ca19fd..665fffb93 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java @@ -36,6 +36,9 @@ import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; import org.springframework.cloud.kubernetes.fabric8.Fabric8AutoConfiguration; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.Environment; +import org.springframework.core.env.StandardEnvironment; /** * @author Ryan Baxter @@ -79,6 +82,11 @@ public void initialize(@Nonnull BootstrapRegistry registry) { KubernetesClient kubernetesClient = fabric8AutoConfiguration.kubernetesClient(config); KubernetesDiscoveryProperties discoveryProperties = context.get(KubernetesDiscoveryProperties.class); + Environment environment = new StandardEnvironment(); + + + propertyResolver + .get(KubernetesNamespaceProvider.NAMESPACE_PROPERTY, String.class, null) Fabric8InformerAutoConfiguration fabric8InformerAutoConfiguration = new Fabric8InformerAutoConfiguration(); From afe758f5cc8f0a703c3e2334d986ac17738b2433 Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 3 Feb 2026 17:19:46 +0200 Subject: [PATCH 08/19] wip Signed-off-by: wind57 --- .../Fabric8ConfigServerBootstrapper.java | 30 +++++++++---------- .../Fabric8InformerAutoConfiguration.java | 5 +--- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java index 665fffb93..c59f7b174 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java @@ -85,26 +85,24 @@ public void initialize(@Nonnull BootstrapRegistry registry) { Environment environment = new StandardEnvironment(); - propertyResolver - .get(KubernetesNamespaceProvider.NAMESPACE_PROPERTY, String.class, null) + KubernetesNamespaceProvider kubernetesNamespaceProvider = new KubernetesNamespaceProvider(propertyResolver + .get(KubernetesNamespaceProvider.NAMESPACE_PROPERTY, String.class, null)); Fabric8InformerAutoConfiguration fabric8InformerAutoConfiguration = new Fabric8InformerAutoConfiguration(); List selectiveNamespaces = fabric8InformerAutoConfiguration.selectiveNamespaces( - discoveryProperties, kubernetesClient, registry.ge) - - List> serviceListers, - List> endpointsListers, List> serviceInformers, - List> endpointsInformers - - client, serviceListers, endpointsListers, serviceInformers, endpointsInformers, - kubernetesDiscoveryProperties, predicat - - - Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(kubernetesClient, - - discoveryProperties, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(discoveryProperties)); + discoveryProperties, kubernetesClient, kubernetesNamespaceProvider); + List> serviceInformers = fabric8InformerAutoConfiguration.serviceSharedIndexInformers( + selectiveNamespaces, kubernetesClient, discoveryProperties); + List> endpointsInformers = fabric8InformerAutoConfiguration.endpointsSharedIndexInformers( + selectiveNamespaces, kubernetesClient, discoveryProperties); + List> serviceListers = fabric8InformerAutoConfiguration.serviceListers(selectiveNamespaces, serviceInformers); + List> endpointsListers = fabric8InformerAutoConfiguration.endpointsListers(selectiveNamespaces, endpointsInformers); + + + Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient( + kubernetesClient, serviceListers, endpointsListers, serviceInformers, endpointsInformers, + discoveryProperties, x -> true); return discoveryClient::getInstances; } }); diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java index 07384b8ec..e05c083a7 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java @@ -41,7 +41,6 @@ import org.springframework.cloud.kubernetes.fabric8.Fabric8AutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; import org.springframework.core.log.LogAccessor; import static org.springframework.cloud.kubernetes.fabric8.Fabric8Utils.getApplicationNamespace; @@ -66,9 +65,7 @@ final class Fabric8InformerAutoConfiguration { // namespaces as a list, instead of the incoming Set. @Bean List selectiveNamespaces(KubernetesDiscoveryProperties properties, KubernetesClient kubernetesClient, - Environment environment) { - - KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(environment); + KubernetesNamespaceProvider namespaceProvider) { if (!properties.namespaces().isEmpty()) { LOG.debug(() -> "discovering endpoints in namespaces : " + properties.namespaces()); From 41d3ae945663774f20cc46ab07376e89e66c9653 Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 4 Feb 2026 19:43:32 +0200 Subject: [PATCH 09/19] wip Signed-off-by: wind57 --- .../Fabric8ConfigServerBootstrapper.java | 35 +- .../Fabric8DiscoveryClientUtils.java | 23 +- .../Fabric8InformerAutoConfiguration.java | 8 +- .../discovery/Fabric8DiscoveryClientBase.java | 124 +++ ...ric8DiscoveryClientFilterMetadataTest.java | 224 ++---- .../Fabric8DiscoveryClientFilterTest.java | 135 ++-- .../Fabric8DiscoveryClientOneTests.java | 87 +-- ...veryClientServiceWithoutPortNameTests.java | 10 +- .../Fabric8DiscoveryClientTwoTests.java | 327 ++++---- ...abric8DiscoveryClientUtilsFilterTests.java | 210 ++--- .../Fabric8DiscoveryClientUtilsTests.java | 717 +++++++++--------- .../Fabric8DiscoveryFilterTests.java | 295 +++---- .../Fabric8ReactiveDiscoveryClientTests.java | 441 ----------- 13 files changed, 1081 insertions(+), 1555 deletions(-) create mode 100644 spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientBase.java delete mode 100644 spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientTests.java diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java index c59f7b174..e14c49673 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java @@ -34,9 +34,7 @@ import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.config.KubernetesConfigServerBootstrapper; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; -import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; import org.springframework.cloud.kubernetes.fabric8.Fabric8AutoConfiguration; -import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.Environment; import org.springframework.core.env.StandardEnvironment; @@ -84,25 +82,24 @@ public void initialize(@Nonnull BootstrapRegistry registry) { Environment environment = new StandardEnvironment(); - - KubernetesNamespaceProvider kubernetesNamespaceProvider = new KubernetesNamespaceProvider(propertyResolver - .get(KubernetesNamespaceProvider.NAMESPACE_PROPERTY, String.class, null)); - + KubernetesNamespaceProvider kubernetesNamespaceProvider = new KubernetesNamespaceProvider( + propertyResolver.get(KubernetesNamespaceProvider.NAMESPACE_PROPERTY, String.class, null)); Fabric8InformerAutoConfiguration fabric8InformerAutoConfiguration = new Fabric8InformerAutoConfiguration(); - List selectiveNamespaces = fabric8InformerAutoConfiguration.selectiveNamespaces( - discoveryProperties, kubernetesClient, kubernetesNamespaceProvider); - List> serviceInformers = fabric8InformerAutoConfiguration.serviceSharedIndexInformers( - selectiveNamespaces, kubernetesClient, discoveryProperties); - List> endpointsInformers = fabric8InformerAutoConfiguration.endpointsSharedIndexInformers( - selectiveNamespaces, kubernetesClient, discoveryProperties); - List> serviceListers = fabric8InformerAutoConfiguration.serviceListers(selectiveNamespaces, serviceInformers); - List> endpointsListers = fabric8InformerAutoConfiguration.endpointsListers(selectiveNamespaces, endpointsInformers); - - - Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient( - kubernetesClient, serviceListers, endpointsListers, serviceInformers, endpointsInformers, - discoveryProperties, x -> true); + List selectiveNamespaces = fabric8InformerAutoConfiguration + .selectiveNamespaces(discoveryProperties, kubernetesClient, kubernetesNamespaceProvider); + List> serviceInformers = fabric8InformerAutoConfiguration + .serviceSharedIndexInformers(selectiveNamespaces, kubernetesClient, discoveryProperties); + List> endpointsInformers = fabric8InformerAutoConfiguration + .endpointsSharedIndexInformers(selectiveNamespaces, kubernetesClient, discoveryProperties); + List> serviceListers = fabric8InformerAutoConfiguration + .serviceListers(selectiveNamespaces, serviceInformers); + List> endpointsListers = fabric8InformerAutoConfiguration + .endpointsListers(selectiveNamespaces, endpointsInformers); + + Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(kubernetesClient, serviceListers, + endpointsListers, serviceInformers, endpointsInformers, discoveryProperties, + new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(discoveryProperties)); return discoveryClient::getInstances; } }); diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java index 15520544b..12514d1ed 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtils.java @@ -106,41 +106,34 @@ static Map endpointSubsetsPortData(List endpoin EndpointPort::getPort)); } - static SharedIndexInformer serviceSharedIndexInformer(String namespace, - KubernetesClient kubernetesClient, Map serviceLabels) { + static SharedIndexInformer serviceSharedIndexInformer(String namespace, KubernetesClient kubernetesClient, + Map serviceLabels) { SharedIndexInformer sharedIndexInformer; // we treat this as all namespaces if ("".equals(namespace)) { - sharedIndexInformer = kubernetesClient.services() - .inAnyNamespace() - .withLabels(serviceLabels) - .inform(); + sharedIndexInformer = kubernetesClient.services().inAnyNamespace().withLabels(serviceLabels).inform(); } else { - sharedIndexInformer = kubernetesClient.services() - .inNamespace(namespace) - .withLabels(serviceLabels) - .inform(); + sharedIndexInformer = kubernetesClient.services().inNamespace(namespace).withLabels(serviceLabels).inform(); } return sharedIndexInformer; } static SharedIndexInformer endpointsSharedIndexInformer(String namespace, - KubernetesClient kubernetesClient, Map serviceLabels) { + KubernetesClient kubernetesClient, Map serviceLabels) { SharedIndexInformer sharedIndexInformer; // we treat this as all namespaces if ("".equals(namespace)) { - sharedIndexInformer = kubernetesClient.endpoints() - .inAnyNamespace() - .withLabels(serviceLabels) - .inform(); + LOG.debug(() -> "discovering endpoints in all namespaces"); + sharedIndexInformer = kubernetesClient.endpoints().inAnyNamespace().withLabels(serviceLabels).inform(); } else { + LOG.debug(() -> "discovering endpoints in namespace : " + namespace); sharedIndexInformer = kubernetesClient.endpoints() .inNamespace(namespace) .withLabels(serviceLabels) diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java index e05c083a7..9b5d3d35a 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8InformerAutoConfiguration.java @@ -90,8 +90,8 @@ List> serviceSharedIndexInformers(List sele int howManyNamespaces = selectiveNamespaces.size(); List> serviceSharedIndexedInformers = new ArrayList<>(howManyNamespaces); for (String namespace : selectiveNamespaces) { - serviceSharedIndexedInformers.add(serviceSharedIndexInformer( - namespace, kubernetesClient, properties.serviceLabels())); + serviceSharedIndexedInformers + .add(serviceSharedIndexInformer(namespace, kubernetesClient, properties.serviceLabels())); } return serviceSharedIndexedInformers; } @@ -123,8 +123,8 @@ List> endpointsSharedIndexInformers(List int howManyNamespaces = selectiveNamespaces.size(); List> endpointsSharedIndexedInformers = new ArrayList<>(howManyNamespaces); for (String namespace : selectiveNamespaces) { - endpointsSharedIndexedInformers.add(endpointsSharedIndexInformer( - namespace, kubernetesClient, properties.serviceLabels())); + endpointsSharedIndexedInformers + .add(endpointsSharedIndexInformer(namespace, kubernetesClient, properties.serviceLabels())); } return endpointsSharedIndexedInformers; } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientBase.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientBase.java new file mode 100644 index 000000000..bf40056b0 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientBase.java @@ -0,0 +1,124 @@ +/* + * Copyright 2013-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.kubernetes.fabric8.discovery; + +import java.util.List; +import java.util.Map; + +import io.fabric8.kubernetes.api.model.EndpointPort; +import io.fabric8.kubernetes.api.model.EndpointPortBuilder; +import io.fabric8.kubernetes.api.model.Endpoints; +import io.fabric8.kubernetes.api.model.EndpointsBuilder; +import io.fabric8.kubernetes.api.model.ObjectMeta; +import io.fabric8.kubernetes.api.model.Service; +import io.fabric8.kubernetes.api.model.ServiceBuilder; +import io.fabric8.kubernetes.api.model.ServicePort; +import io.fabric8.kubernetes.api.model.ServicePortBuilder; +import io.fabric8.kubernetes.api.model.ServiceSpecBuilder; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.informers.SharedIndexInformer; +import io.fabric8.kubernetes.client.informers.cache.Lister; + +import org.assertj.core.util.Strings; +import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; + +import static java.util.stream.Collectors.toList; + +/** + * @author wind57 + */ +abstract class Fabric8DiscoveryClientBase { + + private final Fabric8InformerAutoConfiguration configuration = new Fabric8InformerAutoConfiguration(); + + Fabric8DiscoveryClient fabric8DiscoveryClient(KubernetesDiscoveryProperties properties, + List selectiveNamespaces, KubernetesClient kubernetesClient) { + List> serviceInformers = configuration.serviceSharedIndexInformers( + selectiveNamespaces, kubernetesClient, properties); + List> endpointsInformers = configuration.endpointsSharedIndexInformers( + selectiveNamespaces, kubernetesClient, properties); + List> serviceListers = configuration.serviceListers(selectiveNamespaces, serviceInformers); + List> endpointsListers = configuration.endpointsListers(selectiveNamespaces, endpointsInformers); + + return new Fabric8DiscoveryClient(kubernetesClient, serviceListers, + endpointsListers, serviceInformers, endpointsInformers, properties, + new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties)); + } + + void setupServiceWithLabelsAndAnnotationsAndPorts(KubernetesClient kubernetesClient, String serviceId, String namespace, + Map labels, Map annotations, Map ports) { + + Service service = service(serviceId, namespace, labels, annotations, ports); + kubernetesClient.services().inNamespace(namespace).resource(service).create(); + + Endpoints endpoints = endpoints(namespace, serviceId, labels, ports); + kubernetesClient.endpoints().inNamespace(namespace).resource(endpoints).create(); + + } + + static Service service(String namespace, String serviceId, Map labels, + Map annotations, Map ports) { + return new ServiceBuilder() + .withSpec(new ServiceSpecBuilder().withType("ClusterIP").withPorts(getServicePorts(ports)).build()) + .withNewMetadata() + .withNamespace(namespace) + .withName(serviceId) + .withLabels(labels) + .withAnnotations(annotations) + .endMetadata() + .build(); + } + + static Endpoints endpoints(String namespace, String serviceId, Map labels, Map ports) { + + ObjectMeta objectMeta = new ObjectMeta(); + objectMeta.setNamespace(namespace); + objectMeta.setName(serviceId); + objectMeta.setLabels(labels); + + return new EndpointsBuilder().withMetadata(objectMeta) + .addNewSubset() + .addAllToPorts(getEndpointPorts(ports)) + .addNewAddress() + .endAddress() + .endSubset() + .build(); + } + + private static List getServicePorts(Map ports) { + return ports.entrySet().stream().map(e -> { + ServicePortBuilder servicePortBuilder = new ServicePortBuilder(); + servicePortBuilder.withPort(e.getKey()); + if (!Strings.isNullOrEmpty(e.getValue())) { + servicePortBuilder.withName(e.getValue()); + } + return servicePortBuilder.build(); + }).collect(toList()); + } + + private static List getEndpointPorts(Map ports) { + return ports.entrySet().stream().map(e -> { + EndpointPortBuilder endpointPortBuilder = new EndpointPortBuilder(); + endpointPortBuilder.withPort(e.getKey()); + if (!Strings.isNullOrEmpty(e.getValue())) { + endpointPortBuilder.withName(e.getValue()); + } + return endpointPortBuilder.build(); + }).collect(toList()); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterMetadataTest.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterMetadataTest.java index b365034f6..7fa636ba3 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterMetadataTest.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterMetadataTest.java @@ -16,74 +16,34 @@ package org.springframework.cloud.kubernetes.fabric8.discovery; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; -import io.fabric8.kubernetes.api.model.EndpointPort; -import io.fabric8.kubernetes.api.model.EndpointPortBuilder; -import io.fabric8.kubernetes.api.model.Endpoints; -import io.fabric8.kubernetes.api.model.EndpointsBuilder; -import io.fabric8.kubernetes.api.model.EndpointsList; -import io.fabric8.kubernetes.api.model.ObjectMeta; -import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.api.model.ServiceBuilder; -import io.fabric8.kubernetes.api.model.ServiceList; -import io.fabric8.kubernetes.api.model.ServiceListBuilder; -import io.fabric8.kubernetes.api.model.ServicePort; -import io.fabric8.kubernetes.api.model.ServicePortBuilder; -import io.fabric8.kubernetes.api.model.ServiceSpecBuilder; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.dsl.FilterNested; -import io.fabric8.kubernetes.client.dsl.FilterWatchListDeletable; -import io.fabric8.kubernetes.client.dsl.MixedOperation; -import io.fabric8.kubernetes.client.dsl.Resource; -import io.fabric8.kubernetes.client.dsl.ServiceResource; -import org.assertj.core.util.Strings; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; -import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; -import org.springframework.core.env.Environment; -import org.springframework.mock.env.MockEnvironment; -import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; -import static org.mockito.ArgumentMatchers.anyMap; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties.Metadata; -@SuppressWarnings("unchecked") -class Fabric8DiscoveryClientFilterMetadataTest { +@EnableKubernetesMockClient(crud = true, https = false) +class Fabric8DiscoveryClientFilterMetadataTest extends Fabric8DiscoveryClientBase { - private static final KubernetesClient CLIENT = Mockito.mock(KubernetesClient.class); + private static final String NAMESPACE = "test"; - private static final ServicePortSecureResolver SERVICE_PORT_SECURE_RESOLVER = new ServicePortSecureResolver( - KubernetesDiscoveryProperties.DEFAULT); + private static KubernetesClient mockClient; - private static final KubernetesNamespaceProvider NAMESPACE_PROVIDER = new KubernetesNamespaceProvider( - mockEnvironment()); - - private final MixedOperation> serviceOperation = Mockito - .mock(MixedOperation.class); - - private final MixedOperation> endpointsOperation = Mockito - .mock(MixedOperation.class); - - private final ServiceResource serviceResource = Mockito.mock(ServiceResource.class); - - private final FilterWatchListDeletable> filter = Mockito - .mock(FilterWatchListDeletable.class); - - private final FilterNested>> filterNested = Mockito - .mock(FilterNested.class); + @AfterEach + void afterEach() { + mockClient.services().inAnyNamespace().delete(); + mockClient.endpoints().inAnyNamespace().delete(); + } @Test void testAllExtraMetadataDisabled() { @@ -91,39 +51,35 @@ void testAllExtraMetadataDisabled() { Metadata metadata = new Metadata(false, null, false, null, false, null); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, - false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); + false, null, Set.of(), Map.of("label1", "one"), null, metadata, 0, true, false, null); - Fabric8DiscoveryClient fabric8DiscoveryClient = new Fabric8DiscoveryClient(CLIENT, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties)); + setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one"), + Map.of("annotation1", "ann-one"), Map.of(80, "http", 5555, "")); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "lab"), Map.of("l1", "lab"), - Map.of(80, "http", 5555, "")); + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); List instances = fabric8DiscoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); - assertThat(instances.get(0).getMetadata()).isEqualTo(Map.of("k8s_namespace", "ns", "type", "ClusterIP")); + assertThat(instances.get(0).getMetadata()).isEqualTo(Map.of("k8s_namespace", NAMESPACE, "type", "ClusterIP")); } @Test void testLabelsEnabled() { String serviceId = "s"; - Metadata metadata = new Metadata(true, null, false, null, false, null); + Metadata metadata = new Metadata(true, null, true, null, false, null); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); - Fabric8DiscoveryClient fabric8DiscoveryClient = new Fabric8DiscoveryClient(CLIENT, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties)); + setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one"), + Map.of("annotation1", "ann-one"), Map.of(80, "http", 5555, "")); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "v1", "l2", "v2"), - Map.of("l1", "lab"), Map.of(80, "http", 5555, "")); + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); List instances = fabric8DiscoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); - assertThat(instances.get(0).getMetadata()).containsOnly(entry("l1", "v1"), entry("l2", "v2"), - entry("k8s_namespace", "ns"), entry("type", "ClusterIP")); + assertThat(instances.get(0).getMetadata()).containsOnly(entry("label1", "one"), entry("annotation1", "ann-one"), + entry("k8s_namespace", "test"), entry("type", "ClusterIP")); } @Test @@ -134,17 +90,15 @@ void testLabelsEnabledWithPrefix() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); - Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(CLIENT, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties)); + setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one", "label2", "two"), + Map.of("annotation1", "ann-one"), Map.of(80, "http", 5555, "")); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "v1", "l2", "v2"), - Map.of("l1", "lab"), Map.of(80, "http", 5555, "")); + Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); - assertThat(instances.get(0).getMetadata()).containsOnly(entry("l_l1", "v1"), entry("l_l2", "v2"), - entry("k8s_namespace", "ns"), entry("type", "ClusterIP")); + assertThat(instances.get(0).getMetadata()).containsOnly(entry("l_label1", "one"), entry("l_label2", "two"), + entry("k8s_namespace", NAMESPACE), entry("type", "ClusterIP")); } @Test @@ -155,17 +109,15 @@ void testAnnotationsEnabled() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); - Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(CLIENT, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties)); + setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one"), + Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "v1"), - Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); assertThat(instances.get(0).getMetadata()).containsOnly(entry("a1", "v1"), entry("a2", "v2"), - entry("k8s_namespace", "ns"), entry("type", "ClusterIP")); + entry("k8s_namespace", NAMESPACE), entry("type", "ClusterIP")); } @Test @@ -176,17 +128,15 @@ void testAnnotationsEnabledWithPrefix() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); - Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(CLIENT, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties)); + setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one"), + Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "v1"), - Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); assertThat(instances.get(0).getMetadata()).containsOnly(entry("a_a1", "v1"), entry("a_a2", "v2"), - entry("k8s_namespace", "ns"), entry("type", "ClusterIP")); + entry("k8s_namespace", NAMESPACE), entry("type", "ClusterIP")); } @Test @@ -197,12 +147,10 @@ void testPortsEnabled() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); - Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(CLIENT, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties)); + setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one"), + Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "test", Map.of("l1", "v1"), - Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); @@ -218,16 +166,14 @@ void testPortsEnabledWithPrefix() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); - Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(CLIENT, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties)); + setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one"), + Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "v1"), - Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); - assertThat(instances.get(0).getMetadata()).containsOnly(entry("p_http", "80"), entry("k8s_namespace", "ns"), + assertThat(instances.get(0).getMetadata()).containsOnly(entry("p_http", "80"), entry("k8s_namespace", NAMESPACE), entry("p_", "5555"), entry("type", "ClusterIP")); } @@ -239,94 +185,16 @@ void testLabelsAndAnnotationsAndPortsEnabledWithPrefix() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); - Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(CLIENT, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties)); + setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one"), + Map.of("a1", "an1", "a2", "an2"), Map.of(80, "http", 5555, "")); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "la1"), - Map.of("a1", "an1", "a2", "an2"), Map.of(80, "http", 5555, "")); + Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); assertThat(instances.get(0).getMetadata()).containsOnly(entry("a_a1", "an1"), entry("a_a2", "an2"), - entry("l_l1", "la1"), entry("p_http", "80"), entry("k8s_namespace", "ns"), entry("type", "ClusterIP"), + entry("l_label1", "one"), entry("p_http", "80"), entry("k8s_namespace", NAMESPACE), entry("type", "ClusterIP"), entry("p_", "5555")); } - private void setupServiceWithLabelsAndAnnotationsAndPorts(String serviceId, String namespace, - Map labels, Map annotations, Map ports) { - Service service = new ServiceBuilder() - .withSpec(new ServiceSpecBuilder().withType("ClusterIP").withPorts(getServicePorts(ports)).build()) - .withNewMetadata() - .withNamespace(namespace) - .withLabels(labels) - .withAnnotations(annotations) - .endMetadata() - .build(); - when(serviceOperation.withName(serviceId)).thenReturn(serviceResource); - when(serviceResource.get()).thenReturn(service); - when(CLIENT.services()).thenReturn(serviceOperation); - when(CLIENT.services().inNamespace(anyString())).thenReturn(serviceOperation); - when(serviceOperation.list()).thenReturn( - new ServiceListBuilder() - .withItems(new ServiceBuilder().withNewMetadata() - .withName(serviceId) - .withNamespace(namespace) - .endMetadata() - .build()) - .build()); - - ObjectMeta objectMeta = new ObjectMeta(); - objectMeta.setNamespace(namespace); - objectMeta.setName(serviceId); - - Endpoints endpoints = new EndpointsBuilder().withMetadata(objectMeta) - .addNewSubset() - .addAllToPorts(getEndpointPorts(ports)) - .addNewAddress() - .endAddress() - .endSubset() - .build(); - - when(CLIENT.endpoints()).thenReturn(endpointsOperation); - when(endpointsOperation.inNamespace(Mockito.anyString())).thenReturn(endpointsOperation); - when(endpointsOperation.withNewFilter()).thenReturn(filterNested); - - EndpointsList endpointsList = new EndpointsList(null, Collections.singletonList(endpoints), null, null); - when(filter.list()).thenReturn(endpointsList); - when(filterNested.withLabels(anyMap())).thenReturn(filterNested); - - when(filterNested.withField(eq("metadata.name"), eq(serviceId))).thenReturn(filterNested); - when(filterNested.endFilter()).thenReturn(filter); - - } - - private List getServicePorts(Map ports) { - return ports.entrySet().stream().map(e -> { - ServicePortBuilder servicePortBuilder = new ServicePortBuilder(); - servicePortBuilder.withPort(e.getKey()); - if (!Strings.isNullOrEmpty(e.getValue())) { - servicePortBuilder.withName(e.getValue()); - } - return servicePortBuilder.build(); - }).collect(toList()); - } - - private List getEndpointPorts(Map ports) { - return ports.entrySet().stream().map(e -> { - EndpointPortBuilder endpointPortBuilder = new EndpointPortBuilder(); - endpointPortBuilder.withPort(e.getKey()); - if (!Strings.isNullOrEmpty(e.getValue())) { - endpointPortBuilder.withName(e.getValue()); - } - return endpointPortBuilder.build(); - }).collect(toList()); - } - - private static Environment mockEnvironment() { - MockEnvironment environment = new MockEnvironment(); - environment.setProperty("spring.cloud.kubernetes.client.namespace", "test"); - return environment; - } - } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterTest.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterTest.java index d6ce3c84b..c58660585 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterTest.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterTest.java @@ -17,89 +17,76 @@ package org.springframework.cloud.kubernetes.fabric8.discovery; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; +import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.ObjectMeta; import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.api.model.ServiceList; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.dsl.FilterNested; -import io.fabric8.kubernetes.client.dsl.FilterWatchListDeletable; -import io.fabric8.kubernetes.client.dsl.MixedOperation; -import io.fabric8.kubernetes.client.dsl.ServiceResource; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; -import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; -import org.springframework.core.env.Environment; -import org.springframework.mock.env.MockEnvironment; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; -class Fabric8DiscoveryClientFilterTest { +@EnableKubernetesMockClient(crud = true, https = false) +class Fabric8DiscoveryClientFilterTest extends Fabric8DiscoveryClientBase { - private static final ServicePortSecureResolver SERVICE_PORT_SECURE_RESOLVER = new ServicePortSecureResolver( - KubernetesDiscoveryProperties.DEFAULT); + private KubernetesClient mockClient; - private static final KubernetesNamespaceProvider NAMESPACE_PROVIDER = new KubernetesNamespaceProvider( - mockEnvironment()); + private static final String NAMESPACE = "test"; - private final KubernetesClient kubernetesClient = Mockito.mock(KubernetesClient.class); - - @SuppressWarnings("unchecked") - private final MixedOperation> serviceOperation = Mockito - .mock(MixedOperation.class); - - @SuppressWarnings("unchecked") - private final FilterNested>> filterNested = Mockito - .mock(FilterNested.class); - - @SuppressWarnings("unchecked") - private final FilterWatchListDeletable> filter = Mockito - .mock(FilterWatchListDeletable.class); + @AfterEach + void afterEach() { + mockClient.services().inAnyNamespace().delete(); + mockClient.endpoints().inAnyNamespace().delete(); + } @Test void testFilteredServices() { - List springBootServiceNames = Arrays.asList("serviceA", "serviceB"); + List springBootServiceNames = List.of("serviceA", "serviceB"); List services = createSpringBootServiceByName(springBootServiceNames); // Add non spring boot service Service service = new Service(); ObjectMeta objectMeta = new ObjectMeta(); objectMeta.setName("ServiceNonSpringBoot"); + objectMeta.setNamespace(NAMESPACE); service.setMetadata(objectMeta); services.add(service); + mockClient.services().inNamespace(NAMESPACE).resource(service).create(); + Endpoints endpoints = endpoints(NAMESPACE, "ServiceNonSpringBoot", Map.of(), Map.of()); + mockClient.endpoints().inNamespace(NAMESPACE).resource(endpoints).create(); - ServiceList serviceList = new ServiceList(); - serviceList.setItems(services); - when(kubernetesClient.services()).thenReturn(serviceOperation); - when(serviceOperation.inNamespace(Mockito.anyString())).thenReturn(serviceOperation); - when(serviceOperation.withNewFilter()).thenReturn(filterNested); - when(filterNested.withLabels(Mockito.anyMap())).thenReturn(filterNested); - when(filterNested.endFilter()).thenReturn(filter); - when(filter.list()).thenReturn(serviceList); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, "metadata.additionalProperties['spring-boot']", Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true, false, null); - Fabric8DiscoveryClient client = new Fabric8DiscoveryClient(kubernetesClient, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties)); - List filteredServices = client.getServices(); - assertThat(filteredServices).isEqualTo(springBootServiceNames); + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); + + List filteredServices = fabric8DiscoveryClient.getServices(); + assertThat(filteredServices).containsExactlyInAnyOrder("serviceA", "serviceB"); + + // without filter + properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, + false, null, Set.of(), Map.of(), null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true, false, null); + + fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); + + filteredServices = fabric8DiscoveryClient.getServices(); + assertThat(filteredServices).containsExactlyInAnyOrder("serviceA", "serviceB", "ServiceNonSpringBoot"); } @Test void testFilteredServicesByPrefix() { - List springBootServiceNames = Arrays.asList("serviceA", "serviceB", "serviceC"); + List springBootServiceNames = List.of("serviceA", "serviceB", "serviceC"); List services = createSpringBootServiceByName(springBootServiceNames); // Add non spring boot service @@ -108,52 +95,37 @@ void testFilteredServicesByPrefix() { objectMeta.setName("anotherService"); service.setMetadata(objectMeta); services.add(service); - - ServiceList serviceList = new ServiceList(); - serviceList.setItems(services); - when(kubernetesClient.services()).thenReturn(serviceOperation); - when(serviceOperation.inNamespace(Mockito.anyString())).thenReturn(serviceOperation); - when(serviceOperation.withNewFilter()).thenReturn(filterNested); - when(filterNested.withLabels(Mockito.anyMap())).thenReturn(filterNested); - when(filterNested.endFilter()).thenReturn(filter); - when(filter.list()).thenReturn(serviceList); + mockClient.services().inNamespace(NAMESPACE).resource(service).create(); + Endpoints endpoints = endpoints(NAMESPACE, "anotherService", Map.of(), Map.of()); + mockClient.endpoints().inNamespace(NAMESPACE).resource(endpoints).create(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, "metadata.name.startsWith('service')", Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true, false, null); - Fabric8DiscoveryClient client = new Fabric8DiscoveryClient(kubernetesClient, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties)); - + Fabric8DiscoveryClient client = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); List filteredServices = client.getServices(); - assertThat(filteredServices).isEqualTo(springBootServiceNames); + assertThat(filteredServices).containsExactlyInAnyOrder("serviceA", "serviceB", "serviceC"); + + properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, + false, "metadata.name.startsWith('another')", Set.of(), Map.of(), null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true, false, null); + client = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); + filteredServices = client.getServices(); + assertThat(filteredServices).containsExactlyInAnyOrder("anotherService"); } @Test void testNoExpression() { - List springBootServiceNames = Arrays.asList("serviceA", "serviceB", "serviceC"); - List services = createSpringBootServiceByName(springBootServiceNames); - - ServiceList serviceList = new ServiceList(); - serviceList.setItems(services); - when(kubernetesClient.services()).thenReturn(serviceOperation); - when(serviceOperation.inNamespace(Mockito.anyString())).thenReturn(serviceOperation); - when(serviceOperation.withNewFilter()).thenReturn(filterNested); - when(filterNested.withLabels(Mockito.anyMap())).thenReturn(filterNested); - when(filterNested.endFilter()).thenReturn(filter); - when(filter.list()).thenReturn(serviceList); + List springBootServiceNames = List.of("serviceA", "serviceB", "serviceC"); + createSpringBootServiceByName(springBootServiceNames); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, "", Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true, false, null); - Fabric8DiscoveryClient client = new Fabric8DiscoveryClient(kubernetesClient, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties)); - + Fabric8DiscoveryClient client = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); List filteredServices = client.getServices(); - - assertThat(filteredServices).isEqualTo(springBootServiceNames); + assertThat(filteredServices).containsExactlyInAnyOrder("serviceA", "serviceB", "serviceC"); } @@ -166,14 +138,13 @@ private List createSpringBootServiceByName(List serviceNames) { objectMeta.setAdditionalProperty("spring-boot", "true"); service.setMetadata(objectMeta); serviceCollection.add(service); + + mockClient.services().inNamespace(NAMESPACE).resource(service).create(); + Endpoints endpoints = endpoints(NAMESPACE, serviceName, Map.of(), Map.of()); + mockClient.endpoints().inNamespace(NAMESPACE).resource(endpoints).create(); } - return serviceCollection; - } - private static Environment mockEnvironment() { - MockEnvironment environment = new MockEnvironment(); - environment.setProperty("spring.cloud.kubernetes.client.namespace", "test"); - return environment; + return serviceCollection; } } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientOneTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientOneTests.java index ee62b9781..aeb584f53 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientOneTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientOneTests.java @@ -36,24 +36,14 @@ import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesServiceInstance; -import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; -import org.springframework.core.env.Environment; -import org.springframework.mock.env.MockEnvironment; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties.Metadata; @EnableKubernetesMockClient(crud = true, https = false) -class Fabric8DiscoveryClientOneTests { - - private static final ServicePortSecureResolver SERVICE_PORT_SECURE_RESOLVER = new ServicePortSecureResolver( - KubernetesDiscoveryProperties.DEFAULT); - - private static final KubernetesNamespaceProvider NAMESPACE_PROVIDER = new KubernetesNamespaceProvider( - mockEnvironment()); +class Fabric8DiscoveryClientOneTests extends Fabric8DiscoveryClientBase { private KubernetesClient mockClient; @@ -105,8 +95,8 @@ void getInstancesShouldBeAbleToHandleEndpointsSingleAddress() { mockClient.services().inNamespace("test").resource(service).create(); - DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(mockClient, KubernetesDiscoveryProperties.DEFAULT, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient( + KubernetesDiscoveryProperties.DEFAULT, List.of("test"), mockClient); List instances = discoveryClient.getInstances("endpoint"); @@ -154,8 +144,7 @@ void getInstancesShouldBeAbleToHandleEndpointsSingleAddressAndMultiplePorts() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60, false, null, Set.of(), labels, "http_tcp", Metadata.DEFAULT, 0, true, false, null); - DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(mockClient, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), mockClient); List instances = discoveryClient.getInstances("endpoint"); @@ -210,8 +199,7 @@ void getInstancesShouldBeAbleToHandleEndpointsMultipleAddresses() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60, false, null, Set.of(443, 8443), labels, null, metadata, 0, true, false, null); - Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(mockClient, properties, - new ServicePortSecureResolver(properties), NAMESPACE_PROVIDER, x -> true); + Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), mockClient); List instances = discoveryClient.getInstances("endpoint"); @@ -249,8 +237,8 @@ void getServicesShouldReturnAllServicesWhenNoLabelsAreAppliedToTheClient() { mockClient.services().inNamespace("test").resource(service2).create(); mockClient.services().inNamespace("test").resource(service3).create(); - DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(mockClient, KubernetesDiscoveryProperties.DEFAULT, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(KubernetesDiscoveryProperties.DEFAULT, + List.of("test"), mockClient); List services = discoveryClient.getServices(); @@ -279,8 +267,8 @@ void getServicesShouldReturnOnlyMatchingServicesWhenLabelsAreAppliedToTheClient( mockClient.services().inNamespace("test").resource(service1).create(); mockClient.services().inNamespace("test").resource(service2).create(); - DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(mockClient, KubernetesDiscoveryProperties.DEFAULT, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(KubernetesDiscoveryProperties.DEFAULT, + List.of("test"), mockClient); List services = discoveryClient.getServices(); @@ -290,38 +278,37 @@ void getServicesShouldReturnOnlyMatchingServicesWhenLabelsAreAppliedToTheClient( @Test void getServicesShouldReturnServicesInNamespaces() { - String nameSpace1 = "ns1"; - String nameSpace2 = "ns2"; - String nameSpace3 = "ns3"; + String namespace1 = "ns1"; + String namespace2 = "ns2"; + String namespace3 = "ns3"; Service service1 = new ServiceBuilder().withNewMetadata() .withName("s1") - .withNamespace(nameSpace1) + .withNamespace(namespace1) .endMetadata() .build(); Service service2 = new ServiceBuilder().withNewMetadata() .withName("s2") - .withNamespace(nameSpace2) + .withNamespace(namespace2) .endMetadata() .build(); Service service3 = new ServiceBuilder().withNewMetadata() .withName("s3") - .withNamespace(nameSpace3) + .withNamespace(namespace3) .endMetadata() .build(); - mockClient.services().inNamespace(nameSpace1).resource(service1).create(); - mockClient.services().inNamespace(nameSpace2).resource(service2).create(); - mockClient.services().inNamespace(nameSpace3).resource(service3).create(); + mockClient.services().inNamespace(namespace1).resource(service1).create(); + mockClient.services().inNamespace(namespace2).resource(service2).create(); + mockClient.services().inNamespace(namespace3).resource(service3).create(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, - Set.of(nameSpace1, nameSpace2), true, 60, false, null, Set.of(), Map.of(), null, + Set.of(namespace1, namespace2), true, 60, false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); - DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(mockClient, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(namespace1, namespace2), mockClient); List services = discoveryClient.getServices(); @@ -385,8 +372,7 @@ void getInstancesShouldBeAbleToHandleEndpointsFromMultipleNamespaces() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60, false, null, Set.of(), Map.of(), null, Metadata.DEFAULT, 0, true, false, null); - DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(mockClient, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test", "test2"), mockClient); List instances = discoveryClient.getInstances("endpoint"); @@ -416,8 +402,8 @@ void instanceWithoutSubsetsShouldBeSkipped() { mockClient.endpoints().inNamespace("test").resource(endPoint).create(); - DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(mockClient, KubernetesDiscoveryProperties.DEFAULT, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(KubernetesDiscoveryProperties.DEFAULT, + List.of("test"), mockClient); List instances = discoveryClient.getInstances("endpoint1"); @@ -461,8 +447,7 @@ void getInstancesShouldBeAbleToHandleEndpointsSingleAddressAndMultiplePortsUsing KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60, false, null, Set.of(443, 8443), Map.of(), null, Metadata.DEFAULT, 0, true, false, null); - DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(mockClient, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), mockClient); List instances = discoveryClient.getInstances("endpoint2"); @@ -514,8 +499,7 @@ void instanceWithMultiplePortsAndMisconfiguredPrimaryPortNameInLabelWithoutFallb KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, null, Set.of(443, 8443), Map.of(), null, Metadata.DEFAULT, 0, true, false, null); - Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(mockClient, properties, - new ServicePortSecureResolver(properties), NAMESPACE_PROVIDER, x -> true); + Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), mockClient); List instances = discoveryClient.getInstances("endpoint3"); @@ -566,8 +550,7 @@ void instanceWithMultiplePortsAndMisconfiguredGenericPrimaryPortNameWithoutFallb KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, null, Set.of(443, 8443), Map.of(), "oops", Metadata.DEFAULT, 0, true, false, null); - Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(mockClient, properties, - new ServicePortSecureResolver(properties), NAMESPACE_PROVIDER, x -> true); + Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), mockClient); List instances = discoveryClient.getInstances("endpoint4"); @@ -616,8 +599,7 @@ void instanceWithMultiplePortsAndWithoutPrimaryPortNameSpecifiedShouldFallBackTo KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, null, Set.of(443, 8443), Map.of(), null, Metadata.DEFAULT, 0, true, false, null); - DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(mockClient, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), mockClient); List instances = discoveryClient.getInstances("endpoint5"); @@ -665,8 +647,7 @@ void instanceWithMultiplePortsAndWithoutPrimaryPortNameSpecifiedOrHttpsPortShoul mockClient.services().inNamespace("test").resource(service).create(); - DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(mockClient, KubernetesDiscoveryProperties.DEFAULT, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); + DiscoveryClient discoveryClient =fabric8DiscoveryClient(KubernetesDiscoveryProperties.DEFAULT, List.of("test"), mockClient); List instances = discoveryClient.getInstances("endpoint5"); @@ -716,8 +697,7 @@ void instanceWithMultiplePortsAndWithoutPrimaryPortNameSpecifiedShouldLogWarning KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60, true, null, Set.of(443, 8443), Map.of(), null, Metadata.DEFAULT, 0, true, false, null); - DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(mockClient, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), mockClient); List instances = discoveryClient.getInstances("endpoint5"); @@ -765,8 +745,7 @@ public void instanceWithoutPorts() { final KubernetesDiscoveryProperties properties = KubernetesDiscoveryProperties.DEFAULT; - DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(mockClient, properties, - SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), mockClient); final List instances = discoveryClient.getInstances("endpoint5"); @@ -781,10 +760,4 @@ public void instanceWithoutPorts() { .hasSize(1); } - private static Environment mockEnvironment() { - MockEnvironment environment = new MockEnvironment(); - environment.setProperty("spring.cloud.kubernetes.client.namespace", "test"); - return environment; - } - } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientServiceWithoutPortNameTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientServiceWithoutPortNameTests.java index c9c1956db..abbd32715 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientServiceWithoutPortNameTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientServiceWithoutPortNameTests.java @@ -36,6 +36,7 @@ import org.junit.jupiter.api.Test; import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; @@ -46,7 +47,7 @@ * @author wind57 */ @EnableKubernetesMockClient(crud = true, https = false) -class Fabric8DiscoveryClientServiceWithoutPortNameTests { +class Fabric8DiscoveryClientServiceWithoutPortNameTests extends Fabric8DiscoveryClientBase { private static final ServicePortSecureResolver SERVICE_PORT_SECURE_RESOLVER = new ServicePortSecureResolver( KubernetesDiscoveryProperties.DEFAULT); @@ -79,10 +80,11 @@ void testDiscoveryWithoutAServicePortName() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(NAMESPACE), true, 60, false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true, false, null); - Fabric8DiscoveryClient client = new Fabric8DiscoveryClient(mockClient, properties, SERVICE_PORT_SECURE_RESOLVER, - NAMESPACE_PROVIDER, new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties)); - List serviceInstances = client.getInstances("no-port-name-service"); + DiscoveryClient discoveryClient = fabric8DiscoveryClient( + properties, List.of(NAMESPACE), mockClient); + + List serviceInstances = discoveryClient.getInstances("no-port-name-service"); Assertions.assertThat(serviceInstances.size()).isEqualTo(1); Assertions.assertThat(serviceInstances.get(0).getMetadata()) .containsExactlyInAnyOrderEntriesOf( diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientTwoTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientTwoTests.java index 906ce6064..f26b1eaaf 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientTwoTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientTwoTests.java @@ -25,7 +25,6 @@ import io.fabric8.kubernetes.api.model.EndpointSubsetBuilder; import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.EndpointsBuilder; -import io.fabric8.kubernetes.api.model.ObjectMeta; import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.fabric8.kubernetes.api.model.ObjectReferenceBuilder; import io.fabric8.kubernetes.api.model.PodBuilder; @@ -42,22 +41,17 @@ import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; +import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.kubernetes.commons.discovery.DefaultKubernetesServiceInstance; import org.springframework.cloud.kubernetes.commons.discovery.ExternalNameKubernetesServiceInstance; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; -import org.springframework.core.env.Environment; -import org.springframework.mock.env.MockEnvironment; /** * @author wind57 */ @EnableKubernetesMockClient(crud = true, https = false) @ExtendWith(OutputCaptureExtension.class) -class Fabric8DiscoveryClientTwoTests { - - private static final KubernetesNamespaceProvider NAMESPACE_PROVIDER = new KubernetesNamespaceProvider( - mockEnvironment()); +class Fabric8DiscoveryClientTwoTests extends Fabric8DiscoveryClientBase { private static KubernetesClient client; @@ -82,8 +76,18 @@ void testAllNamespacesEmpty(CapturedOutput output) { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "serviceId", x -> true); + Service service = new ServiceBuilder().withSpec(new ServiceSpecBuilder().withType("ExternalName").build()) + .withNewMetadata() + .withName("endpoint") + .withNamespace("test") + .withLabels(serviceLabels) + .endMetadata() + .build(); + client.services().inNamespace("test").resource(service).create(); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); + List result = discoveryClient.getInstances("serviceId"); + Assertions.assertThat(result).isEmpty(); Assertions.assertThat(output.getOut()).contains("discovering endpoints in all namespaces"); } @@ -99,17 +103,22 @@ void testAllNamespacesEmpty(CapturedOutput output) { @Test void testAllNamespacesSingleEndpointsMatchExactLabels(CapturedOutput output) { - createEndpoints("default", "blue-service", Map.of("color", "blue")); - createService("default", "blue-service", Map.of("color", "blue")); + Endpoints endpoints = endpoints("default", "blue-service", Map.of("color", "blue"), Map.of()); + client.endpoints().inNamespace("default").resource(endpoints).create(); + + Service service = service("default", "blue-service", Map.of("color", "blue"), Map.of(), Map.of()); + client.services().inNamespace("default").resource(service).create(); boolean allNamespaces = true; Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); + List result = discoveryClient.getInstances("blue-service"); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "blue-service", x -> true); Assertions.assertThat(result.size()).isEqualTo(1); Assertions.assertThat(output.getOut()).contains("discovering endpoints in all namespaces"); } @@ -125,17 +134,22 @@ void testAllNamespacesSingleEndpointsMatchExactLabels(CapturedOutput output) { @Test void testAllNamespacesSingleEndpointsMatchPartialLabels(CapturedOutput output) { - createEndpoints("default", "blue-service", Map.of("color", "blue", "shape", "round")); - createService("default", "blue-service", Map.of("color", "blue", "shape", "round")); + Endpoints endpoints = endpoints("default", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of()); + client.endpoints().inNamespace("default").resource(endpoints).create(); + + Service service = service("default", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + client.services().inNamespace("default").resource(service).create(); boolean allNamespaces = true; Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, + 0, false, false, null); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); + List result = discoveryClient.getInstances("blue-service"); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "blue-service", x -> true); Assertions.assertThat(result.size()).isEqualTo(1); Assertions.assertThat(output.getOut()).contains("discovering endpoints in all namespaces"); } @@ -151,16 +165,22 @@ void testAllNamespacesSingleEndpointsMatchPartialLabels(CapturedOutput output) { @Test void testAllNamespacesSingleEndpointsNameMatchesLabelsDont(CapturedOutput output) { - createEndpoints("default", "blue-service", Map.of("color", "red", "shape", "round")); + Endpoints endpoints = endpoints("default", "blue-service", Map.of("color", "red", "shape", "round"), Map.of()); + client.endpoints().inNamespace("default").resource(endpoints).create(); + + Service service = service("default", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + client.services().inNamespace("default").resource(service).create(); boolean allNamespaces = true; Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, + 0, false, false, null); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); + List result = discoveryClient.getInstances("blue-service"); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "blue-service", x -> true); Assertions.assertThat(result).isEmpty(); Assertions.assertThat(output.getOut()).contains("discovering endpoints in all namespaces"); } @@ -176,20 +196,27 @@ void testAllNamespacesSingleEndpointsNameMatchesLabelsDont(CapturedOutput output @Test void testAllNamespacesTwoEndpointsOneMatches(CapturedOutput output) { - createEndpoints("default", "service-one", Map.of("color", "blue", "shape", "round")); - createEndpoints("default", "service-two", Map.of("color", "blue", "shape", "round")); + Endpoints endpointsOne = endpoints("default", "service-one", Map.of("color", "blue", "shape", "round"), Map.of()); + client.endpoints().inNamespace("default").resource(endpointsOne).create(); + + Endpoints endpointsTwo = endpoints("default", "service-two", Map.of("color", "blue", "shape", "round"), Map.of()); + client.endpoints().inNamespace("default").resource(endpointsTwo).create(); + + Service serviceOne = service("default", "service-one", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + client.services().inNamespace("default").resource(serviceOne).create(); - createService("default", "service-one", Map.of("color", "blue", "shape", "round")); - createService("default", "service-two", Map.of("color", "blue", "shape", "round")); + Service serviceTwo = service("default", "service-two", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + client.services().inNamespace("default").resource(serviceTwo).create(); boolean allNamespaces = true; Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); + List result = discoveryClient.getInstances("service-one"); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "service-one", x -> true); Assertions.assertThat(result.size()).isEqualTo(1); Assertions.assertThat(output.getOut()).contains("discovering endpoints in all namespaces"); } @@ -205,23 +232,29 @@ void testAllNamespacesTwoEndpointsOneMatches(CapturedOutput output) { @Test void testAllNamespacesTwoEndpointsInDifferentNamespaces(CapturedOutput output) { - createEndpoints("a", "service-one", Map.of("color", "blue", "shape", "round")); - createEndpoints("b", "service-one", Map.of("color", "blue", "shape", "round")); + Endpoints endpointsOne = endpoints("a", "service-one", Map.of("color", "blue", "shape", "round"), Map.of()); + client.endpoints().inNamespace("a").resource(endpointsOne).create(); + + Endpoints endpointsTwo = endpoints("b", "service-one", Map.of("color", "blue", "shape", "round"), Map.of()); + client.endpoints().inNamespace("b").resource(endpointsTwo).create(); - createService("a", "service-one", Map.of("color", "blue", "shape", "round")); - createService("b", "service-one", Map.of("color", "blue", "shape", "round")); + Service serviceOne = service("a", "service-one", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + client.services().inNamespace("a").resource(serviceOne).create(); + + Service serviceTwo = service("b", "service-one", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + client.services().inNamespace("b").resource(serviceTwo).create(); boolean allNamespaces = true; Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "service-one", x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); + List result = discoveryClient.getInstances("service-one"); Assertions.assertThat(result.size()).isEqualTo(2); Assertions - .assertThat(result.stream().map(Endpoints::getMetadata).map(ObjectMeta::getNamespace).sorted().toList()) + .assertThat(result.stream().map(x -> x.getMetadata().get("k8s_namespace")).sorted().toList()) .isEqualTo(List.of("a", "b")); Assertions.assertThat(output.getOut()).contains("discovering endpoints in all namespaces"); } @@ -235,14 +268,18 @@ void testAllNamespacesTwoEndpointsInDifferentNamespaces(CapturedOutput output) { */ @Test void testClientNamespaceEmpty(CapturedOutput output) { + + Service serviceOne = service("test", "serviceId", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + client.services().inNamespace("test").resource(serviceOne).create(); + boolean allNamespaces = false; - Set namespaces = Set.of(); + Set namespaces = Set.of("test"); Map serviceLabels = Map.of(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "serviceId", x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); + List result = discoveryClient.getInstances("serviceId"); Assertions.assertThat(result).isEmpty(); Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespace : test"); } @@ -258,17 +295,20 @@ void testClientNamespaceEmpty(CapturedOutput output) { @Test void testClientNamespaceSingleEndpointsMatchExactLabels(CapturedOutput output) { - createEndpoints("test", "blue-service", Map.of("color", "blue")); - createService("test", "blue-service", Map.of("color", "blue")); + Endpoints endpointsOne = endpoints("test", "blue-service", Map.of("color", "blue"), Map.of()); + client.endpoints().inNamespace("test").resource(endpointsOne).create(); + + Service serviceOne = service("test", "blue-service", Map.of("color", "blue"), Map.of(), Map.of()); + client.services().inNamespace("test").resource(serviceOne).create(); boolean allNamespaces = false; Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "blue-service", x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); + List result = discoveryClient.getInstances("blue-service"); Assertions.assertThat(result.size()).isEqualTo(1); Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespace : test"); } @@ -284,17 +324,20 @@ void testClientNamespaceSingleEndpointsMatchExactLabels(CapturedOutput output) { @Test void testClientNamespaceSingleEndpointsMatchPartialLabels(CapturedOutput output) { - createEndpoints("test", "blue-service", Map.of("color", "blue", "shape", "round")); - createService("test", "blue-service", Map.of("color", "blue", "shape", "round")); + Endpoints endpointsOne = endpoints("test", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of()); + client.endpoints().inNamespace("test").resource(endpointsOne).create(); + + Service serviceOne = service("test", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + client.services().inNamespace("test").resource(serviceOne).create(); boolean allNamespaces = false; Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "blue-service", x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); + List result = discoveryClient.getInstances("blue-service"); Assertions.assertThat(result.size()).isEqualTo(1); Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespace : test"); } @@ -310,16 +353,20 @@ void testClientNamespaceSingleEndpointsMatchPartialLabels(CapturedOutput output) @Test void testClientNamespaceSingleEndpointsNameMatchesLabelsDont(CapturedOutput output) { - createEndpoints("test", "blue-service", Map.of("color", "red", "shape", "round")); + Endpoints endpointsOne = endpoints("test", "blue-service", Map.of("color", "blue"), Map.of()); + client.endpoints().inNamespace("test").resource(endpointsOne).create(); + + Service serviceOne = service("test", "blue-service", Map.of("color", "red"), Map.of(), Map.of()); + client.services().inNamespace("test").resource(serviceOne).create(); boolean allNamespaces = false; Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "blue-service", x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); + List result = discoveryClient.getInstances("blue-service"); Assertions.assertThat(result).isEmpty(); Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespace : test"); } @@ -335,20 +382,26 @@ void testClientNamespaceSingleEndpointsNameMatchesLabelsDont(CapturedOutput outp @Test void testClientNamespaceTwoEndpointsOneMatches(CapturedOutput output) { - createEndpoints("test", "service-one", Map.of("color", "blue", "shape", "round")); - createEndpoints("test", "service-two", Map.of("color", "blue", "shape", "round")); + Endpoints endpointsOne = endpoints("test", "service-one", Map.of("color", "blue", "shape", "round"), Map.of()); + client.endpoints().inNamespace("test").resource(endpointsOne).create(); + + Endpoints endpointsTwo = endpoints("test", "service-two", Map.of("color", "blue", "shape", "round"), Map.of()); + client.endpoints().inNamespace("test").resource(endpointsTwo).create(); - createService("test", "service-one", Map.of("color", "blue", "shape", "round")); - createService("test", "service-two", Map.of("color", "blue", "shape", "round")); + Service serviceOne = service("test", "service-one", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + client.services().inNamespace("test").resource(serviceOne).create(); + + Service serviceTwo = service("test", "service-two", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + client.services().inNamespace("test").resource(serviceTwo).create(); boolean allNamespaces = false; Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "service-one", x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); + List result = discoveryClient.getInstances("service-one"); Assertions.assertThat(result.size()).isEqualTo(1); Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespace : test"); } @@ -364,23 +417,29 @@ void testClientNamespaceTwoEndpointsOneMatches(CapturedOutput output) { @Test void testClientNamespaceTwoEndpointsInDifferentNamespaces(CapturedOutput output) { - createEndpoints("test", "service-one", Map.of("color", "blue", "shape", "round")); - createEndpoints("b", "service-one", Map.of("color", "blue", "shape", "round")); + Endpoints endpointsOne = endpoints("test", "service-one", Map.of("color", "blue", "shape", "round"), Map.of()); + client.endpoints().inNamespace("test").resource(endpointsOne).create(); + + Endpoints endpointsTwo = endpoints("b", "service-one", Map.of("color", "blue", "shape", "round"), Map.of()); + client.endpoints().inNamespace("b").resource(endpointsTwo).create(); - createService("test", "service-one", Map.of("color", "blue", "shape", "round")); - createService("b", "service-one", Map.of("color", "blue", "shape", "round")); + Service serviceOne = service("test", "service-one", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + client.services().inNamespace("test").resource(serviceOne).create(); + + Service serviceTwo = service("b", "service-one", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + client.services().inNamespace("b").resource(serviceTwo).create(); boolean allNamespaces = false; Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "service-one", x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); + List result = discoveryClient.getInstances("service-one"); Assertions.assertThat(result.size()).isEqualTo(1); Assertions - .assertThat(result.stream().map(Endpoints::getMetadata).map(ObjectMeta::getNamespace).sorted().toList()) + .assertThat(result.stream().map(x -> x.getMetadata().get("k8s_namespace")).sorted().toList()) .isEqualTo(List.of("test")); Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespace : test"); } @@ -394,16 +453,20 @@ void testClientNamespaceTwoEndpointsInDifferentNamespaces(CapturedOutput output) */ @Test void testSelectiveNamespacesEmpty(CapturedOutput output) { + + Service serviceOne = service("test", "service-one", Map.of("color", "blue"), Map.of(), Map.of()); + client.services().inNamespace("test").resource(serviceOne).create(); + boolean allNamespaces = false; Set namespaces = Set.of("test"); Map serviceLabels = Map.of(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "serviceId", x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); + List result = discoveryClient.getInstances("service-one"); Assertions.assertThat(result).isEmpty(); - Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespaces : [test]"); + Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespace : test"); } /** @@ -417,19 +480,22 @@ void testSelectiveNamespacesEmpty(CapturedOutput output) { @Test void testSelectiveNamespacesSingleEndpointsMatchExactLabels(CapturedOutput output) { - createEndpoints("test", "blue-service", Map.of("color", "blue")); - createService("test", "blue-service", Map.of("color", "blue")); + Endpoints endpointsOne = endpoints("test", "blue-service", Map.of("color", "blue"), Map.of()); + client.endpoints().inNamespace("test").resource(endpointsOne).create(); + + Service serviceOne = service("test", "blue-service", Map.of("color", "blue"), Map.of(), Map.of()); + client.services().inNamespace("test").resource(serviceOne).create(); boolean allNamespaces = false; Set namespaces = Set.of("test"); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "blue-service", x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); + List result = discoveryClient.getInstances("blue-service"); Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespaces : [test]"); + Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespace : test"); } /** @@ -444,24 +510,30 @@ void testSelectiveNamespacesSingleEndpointsMatchExactLabels(CapturedOutput outpu @Test void testSelectiveNamespacesMultipleNamespacesSingleMatch(CapturedOutput output) { - createEndpoints("a", "blue-service", Map.of("color", "blue", "shape", "round")); - createEndpoints("b", "blue-service", Map.of("color", "blue", "shape", "rectangle")); + Endpoints endpointsOne = endpoints("a", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of()); + client.endpoints().inNamespace("a").resource(endpointsOne).create(); + + Endpoints endpointsTwo = endpoints("b", "blue-service", Map.of("color", "blue", "shape", "rectangle"), Map.of()); + client.endpoints().inNamespace("b").resource(endpointsTwo).create(); - createService("a", "blue-service", Map.of("color", "blue", "shape", "round")); - createService("b", "blue-service", Map.of("color", "blue", "shape", "rectangle")); + Service serviceOne = service("a", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + client.services().inNamespace("a").resource(serviceOne).create(); + + Service serviceTwo = service("b", "blue-service", Map.of("color", "blue", "shape", "rectangle"), Map.of(), Map.of()); + client.services().inNamespace("b").resource(serviceTwo).create(); boolean allNamespaces = false; Set namespaces = Set.of("a"); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "blue-service", x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("a"), client); + List result = discoveryClient.getInstances("blue-service"); Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getLabels()) - .containsExactlyInAnyOrderEntriesOf(Map.of("color", "blue", "shape", "round")); - Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespaces : [a]"); + Assertions.assertThat(result.get(0).getMetadata()) + .containsAllEntriesOf(Map.of("color", "blue", "shape", "round")); + Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespace : a"); } /** @@ -476,24 +548,29 @@ void testSelectiveNamespacesMultipleNamespacesSingleMatch(CapturedOutput output) @Test void testSelectiveNamespacesMultipleNamespacesAllMatch(CapturedOutput output) { - createEndpoints("a", "blue-service", Map.of("color", "blue")); - createEndpoints("b", "blue-service", Map.of("color", "blue")); + Endpoints endpointsOne = endpoints("a", "blue-service", Map.of("color", "blue"), Map.of()); + client.endpoints().inNamespace("a").resource(endpointsOne).create(); + + Endpoints endpointsTwo = endpoints("b", "blue-service", Map.of("color", "blue"), Map.of()); + client.endpoints().inNamespace("b").resource(endpointsTwo).create(); + + Service serviceOne = service("a", "blue-service", Map.of("color", "blue"), Map.of(), Map.of()); + client.services().inNamespace("a").resource(serviceOne).create(); - createService("a", "blue-service", Map.of("color", "blue")); - createService("b", "blue-service", Map.of("color", "blue")); + Service serviceTwo = service("b", "blue-service", Map.of("color", "blue"), Map.of(), Map.of()); + client.services().inNamespace("b").resource(serviceTwo).create(); boolean allNamespaces = false; Set namespaces = Set.of("a", "b"); - // so that assertion is correct - String namespacesAsString = namespaces.toString(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", null, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); - List result = Fabric8DiscoveryClientUtils.endpoints(properties, client, NAMESPACE_PROVIDER, - "fabric8", "blue-service", x -> true); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("a", "b"), client); + List result = discoveryClient.getInstances("blue-service"); Assertions.assertThat(result.size()).isEqualTo(2); - Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespaces : " + namespacesAsString); + Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespace : a"); + Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespace : b"); } /** @@ -504,6 +581,13 @@ void testSelectiveNamespacesMultipleNamespacesAllMatch(CapturedOutput output) { */ @Test void testGetServicesWithExternalNameService() { + + Endpoints endpointsOne = endpoints("a", "blue-service", Map.of(), Map.of()); + client.endpoints().inNamespace("a").resource(endpointsOne).create(); + + Endpoints endpointsTwo = endpoints("b", "blue-service", Map.of("color", "blue"), Map.of()); + client.endpoints().inNamespace("b").resource(endpointsTwo).create(); + Service nonExternalNameService = new ServiceBuilder() .withSpec(new ServiceSpecBuilder().withType("ClusterIP").build()) .withNewMetadata() @@ -522,14 +606,13 @@ void testGetServicesWithExternalNameService() { .build(); client.services().inNamespace("b").resource(externalNameService).create(); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of("a", "b"), true, + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("a", "b"), true, 60L, false, "", Set.of(), Map.of(), "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, true, null); - Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(client, properties, null, null, x -> true); - List result = discoveryClient.getServices(); - Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0)).isEqualTo("blue-service"); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("a", "b"), client); + List result = discoveryClient.getInstances("blue-service"); + Assertions.assertThat(result.size()).isEqualTo(3); } @Test @@ -550,7 +633,7 @@ void testExternalNameService() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of("a", "b"), true, 60L, false, "", Set.of(), Map.of(), "", metadata, 0, false, true, null); - Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(client, properties, null, null, null); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("a", "b"), client); List result = discoveryClient.getInstances("blue-service"); Assertions.assertThat(result.size()).isEqualTo(1); ExternalNameKubernetesServiceInstance externalNameServiceInstance = (ExternalNameKubernetesServiceInstance) result @@ -602,8 +685,10 @@ void testPodMetadata() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of("a", "b"), true, 60L, false, "", Set.of(), Map.of(), "", metadata, 0, false, true, null); - Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(client, properties, null, null, null); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("a", "b"), client); List result = discoveryClient.getInstances("blue-service"); + Assertions.assertThat(result.size()).isEqualTo(1); DefaultKubernetesServiceInstance serviceInstance = (DefaultKubernetesServiceInstance) result.get(0); Assertions.assertThat(serviceInstance.getServiceId()).isEqualTo("blue-service"); @@ -625,33 +710,9 @@ void testOrder() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60L, false, "", Set.of(), Map.of(), "", null, 57, false, false, null); - Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(client, properties, null, null, null); + Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); Assertions.assertThat(discoveryClient.getOrder()).isEqualTo(57); } - private void createEndpoints(String namespace, String name, Map labels) { - client.endpoints() - .inNamespace(namespace) - .resource(new EndpointsBuilder() - .withMetadata(new ObjectMetaBuilder().withName(name).withLabels(labels).build()) - .build()) - .create(); - } - - private void createService(String namespace, String name, Map labels) { - client.services() - .inNamespace(namespace) - .resource( - new ServiceBuilder().withMetadata(new ObjectMetaBuilder().withName(name).withLabels(labels).build()) - .build()) - .create(); - } - - private static Environment mockEnvironment() { - MockEnvironment environment = new MockEnvironment(); - environment.setProperty("spring.cloud.kubernetes.client.namespace", "test"); - return environment; - } - } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsFilterTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsFilterTests.java index 5f2308a08..4fc526a96 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsFilterTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsFilterTests.java @@ -16,45 +16,48 @@ package org.springframework.cloud.kubernetes.fabric8.discovery; -import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Set; import io.fabric8.kubernetes.api.model.Endpoints; -import io.fabric8.kubernetes.api.model.EndpointsBuilder; import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.api.model.ServiceBuilder; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; -import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.ALWAYS_TRUE; - /** * @author wind57 */ @EnableKubernetesMockClient(crud = true, https = false) -class Fabric8DiscoveryClientUtilsFilterTests { +class Fabric8DiscoveryClientUtilsFilterTests extends Fabric8DiscoveryClientBase { private static KubernetesClient client; - private static final KubernetesDiscoveryProperties PROPERTIES = new KubernetesDiscoveryProperties(true, true, - Set.of(), false, 60L, false, "some", Set.of(), Map.of(), "", null, 0, false, false, null); - @AfterEach void afterEach() { client.endpoints().inAnyNamespace().delete(); client.services().inAnyNamespace().delete(); } + /** + * no services, no endpoints. + */ @Test - void withFilterEmptyInput() { - List result = Fabric8DiscoveryClientUtils.withFilter(List.of(), PROPERTIES, client, ALWAYS_TRUE); + void emptyInput() { + + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of("a", "b"), true, + 60L, false, "", Set.of(), Map.of(), "", null, 0, false, true, null); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("a", "b"), client); + List result = discoveryClient.getInstances("a"); + Assertions.assertThat(result).isEmpty(); } @@ -67,11 +70,16 @@ void withFilterEmptyInput() { * */ @Test - void withFilterOneEndpointsNoMatchInService() { - Endpoints endpoints = createEndpoints("a", "namespace-a"); + void endpointsNoMatchInService() { + createEndpoints("a", "namespace-a"); createService("a", "namespace-not-a"); - List result = Fabric8DiscoveryClientUtils.withFilter(List.of(endpoints), PROPERTIES, client, - x -> true); + + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of("namespace-not-a"), + true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, true, null); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespace-not-a"), client); + List result = discoveryClient.getInstances("a"); + Assertions.assertThat(result).isEmpty(); } @@ -84,33 +92,16 @@ void withFilterOneEndpointsNoMatchInService() { * */ @Test - void withFilterOneEndpointsMatchInService() { - Endpoints endpoints = createEndpoints("a", "namespace-a"); + void endpointsMatchInService() { + createEndpoints("a", "namespace-a"); createService("a", "namespace-a"); - List result = Fabric8DiscoveryClientUtils.withFilter(List.of(endpoints), PROPERTIES, client, - ALWAYS_TRUE); - Assertions.assertThat(result.size()).isEqualTo(1); - } - /** - *
-	 *     - Endpoints with name : "a" and namespace "namespace-a", present
-	 *     - Endpoints with name : "b" and namespace "namespace-b", present
-	 *     - Service with name "a" and namespace "namespace-a" present
-	 *
-	 *     As such, there is a match, single endpoints as result.
-	 * 
- */ - @Test - void withFilterTwoEndpointsOneMatchInService() { - Endpoints endpointsA = createEndpoints("a", "namespace-a"); - Endpoints endpointsB = createEndpoints("b", "namespace-b"); - createService("a", "namespace-a"); - List result = Fabric8DiscoveryClientUtils.withFilter(List.of(endpointsA, endpointsB), PROPERTIES, - client, x -> true); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("namespace-a"), true, + 60L, false, "", Set.of(), Map.of(), "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, true, null); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespace-a"), client); + List result = discoveryClient.getInstances("a"); Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("a"); - Assertions.assertThat(result.get(0).getMetadata().getNamespace()).isEqualTo("namespace-a"); } /** @@ -118,107 +109,63 @@ void withFilterTwoEndpointsOneMatchInService() { * - Endpoints with name : "a" and namespace "namespace-a", present * - Endpoints with name : "b" and namespace "namespace-b", present * - Service with name "a" and namespace "namespace-a" present - * - Predicate that we use is "ALWAYS_TRUE", so no service filter is applied * * As such, there is a match, single endpoints as result. - * This test is the same as above with the difference in the predicate. - * It simulates Fabric8EndpointsCatalogWatch::apply * */ @Test - void withFilterTwoEndpointsOneMatchInServiceAlwaysTruePredicate() { - Endpoints endpointsA = createEndpoints("a", "namespace-a"); - Endpoints endpointsB = createEndpoints("b", "namespace-b"); - createService("a", "namespace-a"); - List result = Fabric8DiscoveryClientUtils.withFilter(List.of(endpointsA, endpointsB), PROPERTIES, - client, ALWAYS_TRUE); - Assertions.assertThat(result.size()).isEqualTo(2); - } + void endpointsOneMatchInService() { + createEndpoints("a", "namespace-a"); + createEndpoints("b", "namespace-b"); - /** - *
-	 *     - Endpoints with name : "a" and namespace "namespace-a", present
-	 *     - Endpoints with name : "b" and namespace "namespace-b", present
-	 *     - Service with name "a" and namespace "namespace-a" present
-	 *     - Service with name "b" and namespace "namespace-b" present
-	 *     - Service with name "c" and namespace "namespace-c" present
-	 *
-	 *     As such, there are two matches.
-	 * 
- */ - @Test - void withFilterTwoEndpointsAndThreeServices() { - Endpoints endpointsA = createEndpoints("a", "namespace-a"); - Endpoints endpointsB = createEndpoints("b", "namespace-b"); createService("a", "namespace-a"); - createService("b", "namespace-b"); - createService("c", "namespace-c"); - List result = Fabric8DiscoveryClientUtils.withFilter(List.of(endpointsA, endpointsB), PROPERTIES, - client, ALWAYS_TRUE); - Assertions.assertThat(result.size()).isEqualTo(2); - result = result.stream().sorted(Comparator.comparing(x -> x.getMetadata().getName())).toList(); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("a"); - Assertions.assertThat(result.get(0).getMetadata().getNamespace()).isEqualTo("namespace-a"); - Assertions.assertThat(result.get(1).getMetadata().getName()).isEqualTo("b"); - Assertions.assertThat(result.get(1).getMetadata().getNamespace()).isEqualTo("namespace-b"); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("namespace-a"), true, + 60L, false, "", Set.of(), Map.of(), "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, true, null); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespace-a"), client); + List result = discoveryClient.getInstances("a"); + + Assertions.assertThat(result.size()).isEqualTo(1); + Assertions.assertThat(result.get(0).getMetadata().get("k8s_namespace")).isEqualTo("namespace-a"); } /** *
 	 *     - Endpoints with name : "a" and namespace "namespace-a", present
-	 *     - Endpoints with name : "b" and namespace "namespace-b", present
+	 *     - Endpoints with name : "a" and namespace "namespace-b", present
 	 *     - Service with name "a" and namespace "namespace-a" present
-	 *     - Service with name "b" and namespace "namespace-b" present
+	 *     - Service with name "a" and namespace "namespace-b" present
 	 *     - Service with name "c" and namespace "namespace-c" present
 	 *
 	 *     As such, there are two matches.
 	 * 
*/ @Test - void withFilterSingleEndpointsMatchesFilter() { - Endpoints endpointsA = createEndpoints("a", "namespace-a"); + void endpointsAndThreeServices() { + createEndpoints("a", "namespace-a"); + createEndpoints("a", "namespace-b"); + createService("a", "namespace-a"); + createService("a", "namespace-b"); + createService("c", "namespace-c"); - List result = Fabric8DiscoveryClientUtils.withFilter(List.of(endpointsA), PROPERTIES, client, - x -> x.getMetadata().getNamespace().equals("namespace-a")); - Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("a"); - Assertions.assertThat(result.get(0).getMetadata().getNamespace()).isEqualTo("namespace-a"); - } + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, + Set.of("namespace-a", "namespace-b"), true, 60L, false, "", Set.of(), Map.of(), "", + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, true, null); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespace-a", "namespace-b"), client); + List result = discoveryClient.getInstances("a"); - /** - *
-	 *     - Endpoints with name : "a-1" and namespace "default", present
-	 *     - Endpoints with name : "b-1" and namespace "default", present
-	 *     - Endpoints with name : "c-2" and namespace "default", present
-	 *     - Service with name "a-1" and namespace "default" present
-	 *     - Service with name "b-1" and namespace "default" present
-	 *
-	 *     As such, there are two matches.
-	 * 
- */ - @Test - void withFilterTwoEndpointsMatchesFilter() { - Endpoints endpointsA = createEndpoints("a-1", "default"); - Endpoints endpointsB = createEndpoints("b-1", "default"); - Endpoints endpointsC = createEndpoints("c-2", "default"); - createService("a-1", "default"); - createService("b-1", "default"); - - List result = Fabric8DiscoveryClientUtils.withFilter(List.of(endpointsA, endpointsB, endpointsC), - PROPERTIES, client, x -> x.getMetadata().getName().contains("1")); Assertions.assertThat(result.size()).isEqualTo(2); - result = result.stream().sorted(Comparator.comparing(x -> x.getMetadata().getName())).toList(); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("a-1"); - Assertions.assertThat(result.get(0).getMetadata().getNamespace()).isEqualTo("default"); - Assertions.assertThat(result.get(1).getMetadata().getName()).isEqualTo("b-1"); - Assertions.assertThat(result.get(1).getMetadata().getNamespace()).isEqualTo("default"); + Assertions.assertThat(result.stream().map(x -> x.getMetadata().get("k8s_namespace")).sorted().toList()) + .isEqualTo(List.of("namespace-a", "namespace-b")); + } /** *
-	 *     - Endpoints with name : "a" and namespace "default", present
+	 *     - Endpoints with name : "a-1" and namespace "namespace-a", present
+	 *     - Endpoints with name : "a-1" and namespace "namespace-b", present
+	 *     - Endpoints with name : "a-1" and namespace "namespace-c", present
 	 *     - Service with name "a-1" and namespace "default" present
 	 *     - Service with name "b-1" and namespace "default" present
 	 *
@@ -226,32 +173,33 @@ void withFilterTwoEndpointsMatchesFilter() {
 	 * 
*/ @Test - void withFilterSingleEndpointsNoPredicateMatch() { - Endpoints endpointsA = createEndpoints("a", "default"); - createService("a-1", "default"); - createService("b-1", "default"); + void endpointsMatchesFilterAllNamespaces() { + createEndpoints("a-1", "namespace-a"); + createEndpoints("a-1", "namespace-b"); + createEndpoints("a-1", "namespace-c"); - List result = Fabric8DiscoveryClientUtils.withFilter(List.of(endpointsA), PROPERTIES, client, - x -> !x.getMetadata().getName().contains("1")); - Assertions.assertThat(result).isEmpty(); + createService("a-1", "namespace-a"); + createService("a-1", "namespace-b"); + + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, + Set.of(), true, 60L, false, "", Set.of(), Map.of(), "", + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, true, null); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); + List result = discoveryClient.getInstances("a-1"); + + Assertions.assertThat(result.size()).isEqualTo(2); + Assertions.assertThat(result.stream().map(x -> x.getMetadata().get("k8s_namespace")).sorted().toList()) + .isEqualTo(List.of("namespace-a", "namespace-b")); } - private Endpoints createEndpoints(String name, String namespace) { - Endpoints endpoints = new EndpointsBuilder().withNewMetadata() - .withName(name) - .withNamespace(namespace) - .endMetadata() - .build(); + private void createEndpoints(String name, String namespace) { + Endpoints endpoints = endpoints(namespace, name, Map.of(), Map.of()); client.endpoints().inNamespace(namespace).resource(endpoints).create(); - return endpoints; } private void createService(String name, String namespace) { - Service service = new ServiceBuilder().withNewMetadata() - .withName(name) - .withNamespace(namespace) - .endMetadata() - .build(); + Service service = service(namespace, name, Map.of(), Map.of(), Map.of()); client.services().inNamespace(namespace).resource(service).create(); } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsTests.java index 4217b0cc1..5630d0e46 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsTests.java @@ -25,6 +25,7 @@ import io.fabric8.kubernetes.api.model.EndpointPortBuilder; import io.fabric8.kubernetes.api.model.EndpointSubset; import io.fabric8.kubernetes.api.model.EndpointSubsetBuilder; +import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.ServiceBuilder; import io.fabric8.kubernetes.api.model.ServiceSpecBuilder; @@ -34,18 +35,19 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.mock.env.MockEnvironment; import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.endpointSubsetsPortData; -import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.services; /** * @author wind57 */ @EnableKubernetesMockClient(crud = true, https = false) -class Fabric8DiscoveryClientUtilsTests { +class Fabric8DiscoveryClientUtilsTests extends Fabric8DiscoveryClientBase { private static KubernetesClient client; @@ -58,7 +60,7 @@ void afterEach() { *
 	 *     - all-namespaces = true
 	 *     - serviceA present in namespace "A"
-	 *     - serviceB present in namespace "B"
+	 *     - serviceA present in namespace "B"
 	 *     - no filters are applied, so both are present
 	 * 
*/ @@ -66,382 +68,387 @@ void afterEach() { void testServicesAllNamespacesNoFilters() { boolean allNamespaces = true; KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), - true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); - service("serviceA", "A", Map.of()); - service("serviceB", "B", Map.of()); + true, 60L, false, "", Set.of(), Map.of(), "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); - List result = services(properties, client, null, x -> true, null, "fabric8-discovery"); - Assertions.assertThat(result.size()).isEqualTo(2); - Assertions.assertThat(result.stream().map(s -> s.getMetadata().getName()).sorted().toList()) - .containsExactlyInAnyOrder("serviceA", "serviceB"); - } - - /** - *
-	 *     - all-namespaces = true
-	 *     - serviceA present in namespace "A"
-	 *     - serviceB present in namespace "B"
-	 *     - we search only for "serviceA" filter, so only one is returned
-	 * 
- */ - @Test - void testServicesAllNamespacesNameFilter() { - boolean allNamespaces = true; - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), - true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); - service("serviceA", "A", Map.of()); - service("serviceB", "B", Map.of()); + createService("serviceA", "A", Map.of()); + createService("serviceA", "B", Map.of()); - List result = services(properties, client, null, x -> true, Map.of("metadata.name", "serviceA"), - "fabric8-discovery"); - Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); - } + createEndpoints("serviceA", "A", Map.of()); + createEndpoints("serviceA", "B", Map.of()); - /** - *
-	 *     - all-namespaces = true
-	 *     - serviceA present in namespace "A"
-	 *     - serviceB present in namespace "B"
-	 *     - we search with a filter where a label with name "letter" and value "b" is present
-	 * 
- */ - @Test - void testServicesAllNamespacesPredicateFilter() { - boolean allNamespaces = true; - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), - true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); - service("serviceA", "A", Map.of("letter", "a")); - service("serviceB", "B", Map.of("letter", "b")); - - List result = services(properties, client, null, - x -> x.getMetadata().getLabels().equals(Map.of("letter", "b")), null, "fabric8-discovery"); - Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceB"); - } - - /** - *
-	 *     - all-namespaces = false
-	 *     - selective namespaces : [A, B]
-	 *     - serviceA present in namespace "A"
-	 *     - serviceB present in namespace "B"
-	 *     - serviceC present in namespace "C"
-	 *     - we search in namespaces [A, B], as such two services are returned
-	 * 
- */ - @Test - void testServicesSelectiveNamespacesNoFilters() { - boolean allNamespaces = false; - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, - Set.of("A", "B"), true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); - service("serviceA", "A", Map.of()); - service("serviceB", "B", Map.of()); - service("serviceC", "C", Map.of()); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); + List result = discoveryClient.getInstances("serviceA"); - List result = services(properties, client, null, x -> true, null, "fabric8-discovery"); Assertions.assertThat(result.size()).isEqualTo(2); - Assertions.assertThat(result.stream().map(x -> x.getMetadata().getName()).sorted().toList()) - .containsExactlyInAnyOrder("serviceA", "serviceB"); - } - - /** - *
-	 *     - all-namespaces = false
-	 *     - selective namespaces : [A, B]
-	 *     - serviceA present in namespace "A"
-	 *     - serviceB present in namespace "B"
-	 *     - serviceC present in namespace "C"
-	 *     - we search in namespaces [A, B] with name filter = "serviceA", so we get a single result
-	 * 
- */ - @Test - void testServicesSelectiveNamespacesNameFilter() { - boolean allNamespaces = false; - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, - Set.of("A", "B"), true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); - service("serviceA", "A", Map.of()); - service("serviceB", "B", Map.of()); - service("serviceC", "C", Map.of()); - - List result = services(properties, client, null, x -> true, Map.of("metadata.name", "serviceA"), - "fabric8-discovery"); - Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); + Assertions.assertThat(result.stream().map(s -> s.getMetadata().get("k8s_namespace")).sorted().toList()) + .containsExactlyInAnyOrder("A", "B"); } /** *
-	 *     - all-namespaces = false
-	 *     - selective namespaces : [A, B]
-	 *     - serviceA present in namespace "A" with labels [letter, a]
-	 *     - serviceB present in namespace "B" with labels [letter, b]
-	 *     - serviceC present in namespace "C" with labels [letter, c]
-	 *     - we search in namespaces [A, B] with predicate filter = [letter, b], so we get a single result
-	 * 
- */ - @Test - void testServicesSelectiveNamespacesPredicateFilter() { - boolean allNamespaces = false; - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, - Set.of("A", "B"), true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); - service("serviceA", "A", Map.of("letter", "a")); - service("serviceB", "B", Map.of("letter", "b")); - service("serviceC", "C", Map.of("letter", "c")); - - List result = services(properties, client, null, - x -> x.getMetadata().getLabels().equals(Map.of("letter", "b")), null, "fabric8-discovery"); - Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceB"); - } - - /** - *
-	 *     - all-namespaces = false
-	 *     - selective namespaces : []
-	 *     - namespace from kubernetes namespace provider = [A]
-	 *     - serviceA present in namespace "A"
-	 *     - serviceB present in namespace "B"
-	 *     - serviceC present in namespace "C"
-	 *     - we search in namespaces [A], as such we get one service
-	 * 
- */ - @Test - void testServicesNamespaceProviderNoFilters() { - boolean allNamespaces = false; - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), - true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); - service("serviceA", "A", Map.of()); - service("serviceB", "B", Map.of()); - service("serviceC", "C", Map.of()); - - List result = services(properties, client, namespaceProvider("A"), x -> true, null, - "fabric8-discovery"); - Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); - } - - /** - *
-	 *     - all-namespaces = false
-	 *     - selective namespaces : []
-	 *     - namespace from kubernetes namespace provider = [A]
-	 *     - serviceA present in namespace "A"
-	 *     - serviceB present in namespace "A"
-	 *     - we search in namespaces [A] with name filter = "serviceA", so we get a single result
-	 * 
- */ - @Test - void testServicesNamespaceProviderNameFilter() { - boolean allNamespaces = false; - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), - true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); - service("serviceA", "A", Map.of()); - service("serviceB", "A", Map.of()); - - List result = services(properties, client, namespaceProvider("A"), x -> true, - Map.of("metadata.name", "serviceA"), "fabric8-discovery"); - Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); - } - - /** - *
-	 *     - all-namespaces = false
-	 *     - selective namespaces : []
-	 *     - namespace from kubernetes namespace provider = [A]
+	 *     - all-namespaces = true
 	 *     - serviceA present in namespace "A"
-	 *     - serviceB present in namespace "A"
-	 *     - we search in namespaces [A] with predicate filter = [letter, b], so we get a single result
+	 *     - serviceA present in namespace "B"
+	 *     - we search only for "namespaceA" filter, so only one is returned
 	 * 
*/ @Test - void testServicesNamespaceProviderPredicateFilter() { - boolean allNamespaces = false; + void testServicesAllNamespacesNameFilter() { + boolean allNamespaces = true; KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); - service("serviceA", "A", Map.of("letter", "a")); - service("serviceB", "A", Map.of("letter", "b")); - List result = services(properties, client, namespaceProvider("A"), - x -> x.getMetadata().getLabels().equals(Map.of("letter", "b")), null, "fabric8-discovery"); - Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceB"); - } + createService("serviceA", "A", Map.of()); + createService("serviceA", "B", Map.of()); - @Test - void testExternalName() { - Service service = new ServiceBuilder() - .withSpec(new ServiceSpecBuilder().withType("ExternalName").withExternalName("k8s-spring").build()) - .withNewMetadata() - .withName("external-name-service") - .and() - .build(); - client.services().inNamespace("test").resource(service).create(); + createEndpoints("serviceA", "A", Map.of()); + createEndpoints("serviceA", "B", Map.of()); - boolean allNamespaces = false; - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), - true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); + List result = discoveryClient.getInstances("serviceA"); - List result = services(properties, client, namespaceProvider("test"), - x -> x.getSpec().getType().equals("ExternalName"), Map.of(), "fabric8-discovery"); Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("external-name-service"); + Assertions.assertThat(result.get(0).getMetadata().get("k8s_namespace")).isEqualTo("namespaceA"); } - - @Test - void testPortsDataOne() { - List endpointSubsets = List.of( - new EndpointSubsetBuilder().withPorts(new EndpointPortBuilder().withPort(8081).withName("").build()) - .build(), - new EndpointSubsetBuilder() - .withPorts(new EndpointPortBuilder().withPort(8080).withName("https").build()) - .build()); - - Map portsData = endpointSubsetsPortData(endpointSubsets); - Assertions.assertThat(portsData.size()).isEqualTo(2); - Assertions.assertThat(portsData.get("https")).isEqualTo(8080); - Assertions.assertThat(portsData.get("")).isEqualTo(8081); +// +// /** +// *
+//	 *     - all-namespaces = true
+//	 *     - serviceA present in namespace "A"
+//	 *     - serviceB present in namespace "B"
+//	 *     - we search with a filter where a label with name "letter" and value "b" is present
+//	 * 
+// */ +// @Test +// void testServicesAllNamespacesPredicateFilter() { +// boolean allNamespaces = true; +// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), +// true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); +// service("serviceA", "A", Map.of("letter", "a")); +// service("serviceB", "B", Map.of("letter", "b")); +// +// List result = services(properties, client, null, +// x -> x.getMetadata().getLabels().equals(Map.of("letter", "b")), null, "fabric8-discovery"); +// Assertions.assertThat(result.size()).isEqualTo(1); +// Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceB"); +// } +// +// /** +// *
+//	 *     - all-namespaces = false
+//	 *     - selective namespaces : [A, B]
+//	 *     - serviceA present in namespace "A"
+//	 *     - serviceB present in namespace "B"
+//	 *     - serviceC present in namespace "C"
+//	 *     - we search in namespaces [A, B], as such two services are returned
+//	 * 
+// */ +// @Test +// void testServicesSelectiveNamespacesNoFilters() { +// boolean allNamespaces = false; +// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, +// Set.of("A", "B"), true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); +// service("serviceA", "A", Map.of()); +// service("serviceB", "B", Map.of()); +// service("serviceC", "C", Map.of()); +// +// List result = services(properties, client, null, x -> true, null, "fabric8-discovery"); +// Assertions.assertThat(result.size()).isEqualTo(2); +// Assertions.assertThat(result.stream().map(x -> x.getMetadata().getName()).sorted().toList()) +// .containsExactlyInAnyOrder("serviceA", "serviceB"); +// } +// +// /** +// *
+//	 *     - all-namespaces = false
+//	 *     - selective namespaces : [A, B]
+//	 *     - serviceA present in namespace "A"
+//	 *     - serviceB present in namespace "B"
+//	 *     - serviceC present in namespace "C"
+//	 *     - we search in namespaces [A, B] with name filter = "serviceA", so we get a single result
+//	 * 
+// */ +// @Test +// void testServicesSelectiveNamespacesNameFilter() { +// boolean allNamespaces = false; +// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, +// Set.of("A", "B"), true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); +// service("serviceA", "A", Map.of()); +// service("serviceB", "B", Map.of()); +// service("serviceC", "C", Map.of()); +// +// List result = services(properties, client, null, x -> true, Map.of("metadata.name", "serviceA"), +// "fabric8-discovery"); +// Assertions.assertThat(result.size()).isEqualTo(1); +// Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); +// } +// +// /** +// *
+//	 *     - all-namespaces = false
+//	 *     - selective namespaces : [A, B]
+//	 *     - serviceA present in namespace "A" with labels [letter, a]
+//	 *     - serviceB present in namespace "B" with labels [letter, b]
+//	 *     - serviceC present in namespace "C" with labels [letter, c]
+//	 *     - we search in namespaces [A, B] with predicate filter = [letter, b], so we get a single result
+//	 * 
+// */ +// @Test +// void testServicesSelectiveNamespacesPredicateFilter() { +// boolean allNamespaces = false; +// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, +// Set.of("A", "B"), true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); +// service("serviceA", "A", Map.of("letter", "a")); +// service("serviceB", "B", Map.of("letter", "b")); +// service("serviceC", "C", Map.of("letter", "c")); +// +// List result = services(properties, client, null, +// x -> x.getMetadata().getLabels().equals(Map.of("letter", "b")), null, "fabric8-discovery"); +// Assertions.assertThat(result.size()).isEqualTo(1); +// Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceB"); +// } +// +// /** +// *
+//	 *     - all-namespaces = false
+//	 *     - selective namespaces : []
+//	 *     - namespace from kubernetes namespace provider = [A]
+//	 *     - serviceA present in namespace "A"
+//	 *     - serviceB present in namespace "B"
+//	 *     - serviceC present in namespace "C"
+//	 *     - we search in namespaces [A], as such we get one service
+//	 * 
+// */ +// @Test +// void testServicesNamespaceProviderNoFilters() { +// boolean allNamespaces = false; +// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), +// true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); +// service("serviceA", "A", Map.of()); +// service("serviceB", "B", Map.of()); +// service("serviceC", "C", Map.of()); +// +// List result = services(properties, client, namespaceProvider("A"), x -> true, null, +// "fabric8-discovery"); +// Assertions.assertThat(result.size()).isEqualTo(1); +// Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); +// } +// +// /** +// *
+//	 *     - all-namespaces = false
+//	 *     - selective namespaces : []
+//	 *     - namespace from kubernetes namespace provider = [A]
+//	 *     - serviceA present in namespace "A"
+//	 *     - serviceB present in namespace "A"
+//	 *     - we search in namespaces [A] with name filter = "serviceA", so we get a single result
+//	 * 
+// */ +// @Test +// void testServicesNamespaceProviderNameFilter() { +// boolean allNamespaces = false; +// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), +// true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); +// service("serviceA", "A", Map.of()); +// service("serviceB", "A", Map.of()); +// +// List result = services(properties, client, namespaceProvider("A"), x -> true, +// Map.of("metadata.name", "serviceA"), "fabric8-discovery"); +// Assertions.assertThat(result.size()).isEqualTo(1); +// Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); +// } +// +// /** +// *
+//	 *     - all-namespaces = false
+//	 *     - selective namespaces : []
+//	 *     - namespace from kubernetes namespace provider = [A]
+//	 *     - serviceA present in namespace "A"
+//	 *     - serviceB present in namespace "A"
+//	 *     - we search in namespaces [A] with predicate filter = [letter, b], so we get a single result
+//	 * 
+// */ +// @Test +// void testServicesNamespaceProviderPredicateFilter() { +// boolean allNamespaces = false; +// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), +// true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); +// service("serviceA", "A", Map.of("letter", "a")); +// service("serviceB", "A", Map.of("letter", "b")); +// +// List result = services(properties, client, namespaceProvider("A"), +// x -> x.getMetadata().getLabels().equals(Map.of("letter", "b")), null, "fabric8-discovery"); +// Assertions.assertThat(result.size()).isEqualTo(1); +// Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceB"); +// } +// +// @Test +// void testExternalName() { +// Service service = new ServiceBuilder() +// .withSpec(new ServiceSpecBuilder().withType("ExternalName").withExternalName("k8s-spring").build()) +// .withNewMetadata() +// .withName("external-name-service") +// .and() +// .build(); +// client.services().inNamespace("test").resource(service).create(); +// +// boolean allNamespaces = false; +// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), +// true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); +// +// List result = services(properties, client, namespaceProvider("test"), +// x -> x.getSpec().getType().equals("ExternalName"), Map.of(), "fabric8-discovery"); +// Assertions.assertThat(result.size()).isEqualTo(1); +// Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("external-name-service"); +// } +// +// @Test +// void testPortsDataOne() { +// List endpointSubsets = List.of( +// new EndpointSubsetBuilder().withPorts(new EndpointPortBuilder().withPort(8081).withName("").build()) +// .build(), +// new EndpointSubsetBuilder() +// .withPorts(new EndpointPortBuilder().withPort(8080).withName("https").build()) +// .build()); +// +// Map portsData = endpointSubsetsPortData(endpointSubsets); +// Assertions.assertThat(portsData.size()).isEqualTo(2); +// Assertions.assertThat(portsData.get("https")).isEqualTo(8080); +// Assertions.assertThat(portsData.get("")).isEqualTo(8081); +// } +// +// @Test +// void testPortsDataTwo() { +// List endpointSubsets = List.of( +// new EndpointSubsetBuilder().withPorts(new EndpointPortBuilder().withPort(8081).withName("http").build()) +// .build(), +// new EndpointSubsetBuilder() +// .withPorts(new EndpointPortBuilder().withPort(8080).withName("https").build()) +// .build()); +// +// Map portsData = endpointSubsetsPortData(endpointSubsets); +// Assertions.assertThat(portsData.size()).isEqualTo(2); +// Assertions.assertThat(portsData.get("https")).isEqualTo(8080); +// Assertions.assertThat(portsData.get("http")).isEqualTo(8081); +// } +// +// @Test +// void endpointSubsetPortsDataWithoutPorts() { +// EndpointSubset endpointSubset = new EndpointSubsetBuilder().build(); +// Map result = endpointSubsetsPortData(List.of(endpointSubset)); +// +// Assertions.assertThat(result).isEmpty(); +// } +// +// @Test +// void endpointSubsetPortsDataSinglePort() { +// EndpointSubset endpointSubset = new EndpointSubsetBuilder() +// .withPorts(new EndpointPortBuilder().withName("name").withPort(80).build()) +// .build(); +// Map result = endpointSubsetsPortData(List.of(endpointSubset)); +// +// Assertions.assertThat(result.size()).isEqualTo(1); +// Assertions.assertThat(result.get("name")).isEqualTo(80); +// } +// +// @Test +// void endpointSubsetPortsDataSinglePortNoName() { +// EndpointSubset endpointSubset = new EndpointSubsetBuilder() +// .withPorts(new EndpointPortBuilder().withPort(80).build()) +// .build(); +// Map result = endpointSubsetsPortData(List.of(endpointSubset)); +// +// Assertions.assertThat(result.size()).isEqualTo(1); +// Assertions.assertThat(result.get("")).isEqualTo(80); +// } +// +// /** +// *
+//	 *      - ready addresses are empty
+//	 *      - not ready addresses are not included
+//	 * 
+// */ +// @Test +// void testEmptyAddresses() { +// boolean includeNotReadyAddresses = false; +// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, +// includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); +// EndpointSubset endpointSubset = new EndpointSubsetBuilder().build(); +// List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); +// Assertions.assertThat(addresses).isEmpty(); +// } +// +// /** +// *
+//	 *      - ready addresses has two entries
+//	 *      - not ready addresses are not included
+//	 * 
+// */ +// @Test +// void testReadyAddressesOnly() { +// boolean includeNotReadyAddresses = false; +// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, +// includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); +// EndpointSubset endpointSubset = new EndpointSubsetBuilder() +// .withAddresses(new EndpointAddressBuilder().withHostname("one").build(), +// new EndpointAddressBuilder().withHostname("two").build()) +// .build(); +// List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); +// Assertions.assertThat(addresses.size()).isEqualTo(2); +// } +// +// /** +// *
+//	 *      - ready addresses has two entries
+//	 *      - not ready addresses has a single entry, but we do not take it
+//	 * 
+// */ +// @Test +// void testReadyAddressesTakenNotReadyAddressesNotTaken() { +// boolean includeNotReadyAddresses = false; +// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, +// includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); +// EndpointSubset endpointSubset = new EndpointSubsetBuilder() +// .withAddresses(new EndpointAddressBuilder().withHostname("one").build(), +// new EndpointAddressBuilder().withHostname("two").build()) +// .withNotReadyAddresses(new EndpointAddressBuilder().withHostname("three").build()) +// .build(); +// List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); +// Assertions.assertThat(addresses.size()).isEqualTo(2); +// List hostNames = addresses.stream().map(EndpointAddress::getHostname).sorted().toList(); +// Assertions.assertThat(hostNames).containsExactlyInAnyOrder("one", "two"); +// } +// +// /** +// *
+//	 *      - ready addresses has two entries
+//	 *      - not ready addresses has a single entry, but we do not take it
+//	 * 
+// */ +// @Test +// void testBothAddressesTaken() { +// boolean includeNotReadyAddresses = true; +// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, +// includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); +// EndpointSubset endpointSubset = new EndpointSubsetBuilder() +// .withAddresses(new EndpointAddressBuilder().withHostname("one").build(), +// new EndpointAddressBuilder().withHostname("two").build()) +// .withNotReadyAddresses(new EndpointAddressBuilder().withHostname("three").build()) +// .build(); +// List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); +// Assertions.assertThat(addresses.size()).isEqualTo(3); +// List hostNames = addresses.stream().map(EndpointAddress::getHostname).sorted().toList(); +// Assertions.assertThat(hostNames).containsExactlyInAnyOrder("one", "three", "two"); +// } + + private void createEndpoints(String name, String namespace, Map labels) { + Endpoints endpoints = endpoints(namespace, name, labels, Map.of()); + client.endpoints().inNamespace(namespace).resource(endpoints).create(); } - @Test - void testPortsDataTwo() { - List endpointSubsets = List.of( - new EndpointSubsetBuilder().withPorts(new EndpointPortBuilder().withPort(8081).withName("http").build()) - .build(), - new EndpointSubsetBuilder() - .withPorts(new EndpointPortBuilder().withPort(8080).withName("https").build()) - .build()); - - Map portsData = endpointSubsetsPortData(endpointSubsets); - Assertions.assertThat(portsData.size()).isEqualTo(2); - Assertions.assertThat(portsData.get("https")).isEqualTo(8080); - Assertions.assertThat(portsData.get("http")).isEqualTo(8081); - } - - @Test - void endpointSubsetPortsDataWithoutPorts() { - EndpointSubset endpointSubset = new EndpointSubsetBuilder().build(); - Map result = endpointSubsetsPortData(List.of(endpointSubset)); - - Assertions.assertThat(result).isEmpty(); - } - - @Test - void endpointSubsetPortsDataSinglePort() { - EndpointSubset endpointSubset = new EndpointSubsetBuilder() - .withPorts(new EndpointPortBuilder().withName("name").withPort(80).build()) - .build(); - Map result = endpointSubsetsPortData(List.of(endpointSubset)); - - Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get("name")).isEqualTo(80); - } - - @Test - void endpointSubsetPortsDataSinglePortNoName() { - EndpointSubset endpointSubset = new EndpointSubsetBuilder() - .withPorts(new EndpointPortBuilder().withPort(80).build()) - .build(); - Map result = endpointSubsetsPortData(List.of(endpointSubset)); - - Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get("")).isEqualTo(80); - } - - /** - *
-	 *      - ready addresses are empty
-	 *      - not ready addresses are not included
-	 * 
- */ - @Test - void testEmptyAddresses() { - boolean includeNotReadyAddresses = false; - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, - includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); - EndpointSubset endpointSubset = new EndpointSubsetBuilder().build(); - List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); - Assertions.assertThat(addresses).isEmpty(); - } - - /** - *
-	 *      - ready addresses has two entries
-	 *      - not ready addresses are not included
-	 * 
- */ - @Test - void testReadyAddressesOnly() { - boolean includeNotReadyAddresses = false; - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, - includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); - EndpointSubset endpointSubset = new EndpointSubsetBuilder() - .withAddresses(new EndpointAddressBuilder().withHostname("one").build(), - new EndpointAddressBuilder().withHostname("two").build()) - .build(); - List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); - Assertions.assertThat(addresses.size()).isEqualTo(2); - } - - /** - *
-	 *      - ready addresses has two entries
-	 *      - not ready addresses has a single entry, but we do not take it
-	 * 
- */ - @Test - void testReadyAddressesTakenNotReadyAddressesNotTaken() { - boolean includeNotReadyAddresses = false; - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, - includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); - EndpointSubset endpointSubset = new EndpointSubsetBuilder() - .withAddresses(new EndpointAddressBuilder().withHostname("one").build(), - new EndpointAddressBuilder().withHostname("two").build()) - .withNotReadyAddresses(new EndpointAddressBuilder().withHostname("three").build()) - .build(); - List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); - Assertions.assertThat(addresses.size()).isEqualTo(2); - List hostNames = addresses.stream().map(EndpointAddress::getHostname).sorted().toList(); - Assertions.assertThat(hostNames).containsExactlyInAnyOrder("one", "two"); - } - - /** - *
-	 *      - ready addresses has two entries
-	 *      - not ready addresses has a single entry, but we do not take it
-	 * 
- */ - @Test - void testBothAddressesTaken() { - boolean includeNotReadyAddresses = true; - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, - includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); - EndpointSubset endpointSubset = new EndpointSubsetBuilder() - .withAddresses(new EndpointAddressBuilder().withHostname("one").build(), - new EndpointAddressBuilder().withHostname("two").build()) - .withNotReadyAddresses(new EndpointAddressBuilder().withHostname("three").build()) - .build(); - List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); - Assertions.assertThat(addresses.size()).isEqualTo(3); - List hostNames = addresses.stream().map(EndpointAddress::getHostname).sorted().toList(); - Assertions.assertThat(hostNames).containsExactlyInAnyOrder("one", "three", "two"); - } - - private void service(String name, String namespace, Map labels) { - Service service = new ServiceBuilder().withNewMetadata() - .withName(name) - .withLabels(labels) - .withNamespace(namespace) - .and() - .build(); + private void createService(String name, String namespace, Map labels) { + Service service = service(namespace, name, labels, Map.of(), Map.of()); client.services().inNamespace(namespace).resource(service).create(); } - private KubernetesNamespaceProvider namespaceProvider(String namespace) { - MockEnvironment mockEnvironment = new MockEnvironment(); - mockEnvironment.setProperty("spring.cloud.kubernetes.client.namespace", namespace); - return new KubernetesNamespaceProvider(mockEnvironment); - } - } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryFilterTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryFilterTests.java index addddf593..72672b47b 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryFilterTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryFilterTests.java @@ -16,52 +16,37 @@ package org.springframework.cloud.kubernetes.fabric8.discovery; -import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Set; +import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.api.model.ServiceBuilder; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; -import org.springframework.cloud.kubernetes.fabric8.Fabric8Utils; import org.springframework.core.env.Environment; import org.springframework.mock.env.MockEnvironment; -import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.services; /** * @author wind57 */ @EnableKubernetesMockClient(crud = true, https = false) -class Fabric8DiscoveryFilterTests { - - private static final KubernetesNamespaceProvider NAMESPACE_PROVIDER = new KubernetesNamespaceProvider( - mockEnvironment()); +class Fabric8DiscoveryFilterTests extends Fabric8DiscoveryClientBase { private static KubernetesClient client; - private static MockedStatic utils; - - @BeforeEach - void beforeEach() { - utils = Mockito.mockStatic(Fabric8Utils.class); - } - @AfterEach void afterEach() { client.services().inAnyNamespace().delete(); - utils.close(); + client.endpoints().inAnyNamespace().delete(); } /** @@ -71,9 +56,10 @@ void afterEach() { * - filter = null * * - serviceA exists in namespaceA with labels = {color=red} - * - serviceB exists in namespaceB with labels = {color=blue} + * - serviceA exists in namespaceB with labels = {color=blue} * - * - we get both services as a result. + * - because we have no labels filtering in the informers/properties, it means + * we get both services as a result. * */ @Test @@ -82,19 +68,21 @@ void testAllNamespacesWithoutLabelsWithoutFilter() { Map labels = Map.of(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), - true, 60L, false, null, Set.of(), labels, null, null, 0, false, false, null); + true, 60L, false, null, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, + 0, false, false, null); service("namespaceA", "serviceA", Map.of("color", "red")); - service("namespaceB", "serviceB", Map.of("color", "blue")); + service("namespaceB", "serviceA", Map.of("color", "blue")); + + endpoints("namespaceA", "serviceA", Map.of("color", "red")); + endpoints("namespaceB", "serviceA", Map.of("color", "blue")); - List result = services(properties, client, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties), null, "dummy-target"); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); + List result = discoveryClient.getInstances("serviceA"); Assertions.assertThat(result.size()).isEqualTo(2); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); - Assertions.assertThat(result.get(0).getMetadata().getNamespace()).isEqualTo("namespaceA"); - Assertions.assertThat(result.get(1).getMetadata().getName()).isEqualTo("serviceB"); - Assertions.assertThat(result.get(1).getMetadata().getNamespace()).isEqualTo("namespaceB"); + Assertions.assertThat(result.stream().map(x -> x.getMetadata().get("k8s_namespace")).sorted().toList()) + .isEqualTo(List.of("namespaceA", "namespaceB")); } /** @@ -104,7 +92,7 @@ void testAllNamespacesWithoutLabelsWithoutFilter() { * - filter = null * * - serviceA exists in namespaceA with labels = {color=red} - * - serviceB exists in namespaceB with labels = {color=blue} + * - serviceA exists in namespaceB with labels = {color=blue} * * - we get only serviceA as a result. * @@ -115,15 +103,20 @@ void testAllNamespacesWithLabelsWithoutFilter() { Map labels = Map.of("color", "red"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), - true, 60L, false, null, Set.of(), labels, null, null, 0, false, false, null); + true, 60L, false, null, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, + 0, false, false, null); + service("namespaceA", "serviceA", Map.of("color", "red")); - service("namespaceB", "serviceB", Map.of("color", "blue")); + service("namespaceB", "serviceA", Map.of("color", "blue")); + + endpoints("namespaceA", "serviceA", Map.of("color", "red")); + endpoints("namespaceB", "serviceA", Map.of("color", "blue")); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); + List result = discoveryClient.getInstances("serviceA"); - List result = services(properties, client, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties), null, "dummy-target"); Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); - Assertions.assertThat(result.get(0).getMetadata().getNamespace()).isEqualTo("namespaceA"); + Assertions.assertThat(result.get(0).getMetadata().get("k8s_namespace")).isEqualTo("namespaceA"); } /** @@ -134,7 +127,7 @@ void testAllNamespacesWithLabelsWithoutFilter() { * (ends in A) * * - serviceA exists in namespaceA with labels = {color=red} - * - serviceB exists in namespaceB with labels = {color=blue} + * - serviceA exists in namespaceB with labels = {color=blue} * * - we get only serviceA as a result. * @@ -147,18 +140,21 @@ void testAllNamespacesWithoutLabelsWithNamespaceFilter() { #root.metadata.namespace matches "^.+A$" """; - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), - true, 60L, false, spelFilter, Set.of(), labels, null, null, 0, false, false, null); - service("namespaceA", "serviceA", Map.of("color", "red")); - service("namespaceB", "serviceB", Map.of("color", "blue")); + service("namespaceB", "serviceA", Map.of("color", "blue")); + + endpoints("namespaceA", "serviceA", Map.of("color", "red")); + endpoints("namespaceB", "serviceA", Map.of("color", "blue")); - List result = services(properties, client, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties), null, "dummy-target"); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), + true, 60L, false, spelFilter, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, + 0, false, false, null); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); + List result = discoveryClient.getInstances("serviceA"); Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); - Assertions.assertThat(result.get(0).getMetadata().getNamespace()).isEqualTo("namespaceA"); + Assertions.assertThat(result.get(0).getMetadata().get("k8s_namespace")).isEqualTo("namespaceA"); } /** @@ -169,10 +165,10 @@ void testAllNamespacesWithoutLabelsWithNamespaceFilter() { * (namespaceA or namespaceB) * * - serviceA exists in namespaceA with labels = {color=red} - * - serviceB exists in namespaceB with labels = {color=blue} - * - serviceC exists in namespaceC with labels = {color=purple} + * - serviceA exists in namespaceB with labels = {color=blue} + * - serviceA exists in namespaceC with labels = {color=purple} * - * - we get only serviceA and serviceB as a result. + * - we get only serviceA from namespaceA and serviceA from namespaceB as a result. * */ @Test @@ -184,19 +180,23 @@ void testAllNamespacesWithoutLabelsWithNamespacesFilter() { """; KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), - true, 60L, false, spelFilter, Set.of(), labels, null, null, 0, false, false, null); + true, 60L, false, spelFilter, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, + 0, false, false, null); service("namespaceA", "serviceA", Map.of("color", "red")); - service("namespaceB", "serviceB", Map.of("color", "blue")); - service("namespaceC", "serviceC", Map.of("color", "purple")); + service("namespaceB", "serviceA", Map.of("color", "blue")); + service("namespaceC", "serviceA", Map.of("color", "purple")); + + endpoints("namespaceA", "serviceA", Map.of("color", "red")); + endpoints("namespaceB", "serviceA", Map.of("color", "blue")); + endpoints("namespaceC", "serviceA", Map.of("color", "purple")); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); + List result = discoveryClient.getInstances("serviceA"); - List result = services(properties, client, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties), null, "dummy-target"); Assertions.assertThat(result.size()).isEqualTo(2); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); - Assertions.assertThat(result.get(0).getMetadata().getNamespace()).isEqualTo("namespaceA"); - Assertions.assertThat(result.get(1).getMetadata().getName()).isEqualTo("serviceB"); - Assertions.assertThat(result.get(1).getMetadata().getNamespace()).isEqualTo("namespaceB"); + Assertions.assertThat(result.stream().map(x -> x.getMetadata().get("k8s_namespace")).sorted().toList()) + .isEqualTo(List.of("namespaceA", "namespaceB")); } /** @@ -206,7 +206,7 @@ void testAllNamespacesWithoutLabelsWithNamespacesFilter() { * - labels = {} * * - serviceA exists in namespaceA with labels = {color=red} - * - serviceB exists in namespaceB with labels = {color=blue} + * - serviceA exists in namespaceB with labels = {color=blue} * * - we get only serviceA as a result. * @@ -217,32 +217,32 @@ void testSpecificNamespaceWithoutLabelsWithoutFilter() { Map labels = Map.of(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), - true, 60L, false, null, Set.of(), labels, null, null, 0, false, false, null); - utils.when(() -> Fabric8Utils.getApplicationNamespace(Mockito.any(KubernetesClient.class), - Mockito.nullable(String.class), Mockito.anyString(), Mockito.any(KubernetesNamespaceProvider.class))) - .thenReturn("namespaceA"); + true, 60L, false, null, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); service("namespaceA", "serviceA", Map.of("color", "red")); service("namespaceB", "serviceB", Map.of("color", "blue")); - List result = services(properties, client, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties), null, "dummy-target"); + endpoints("namespaceA", "serviceA", Map.of("color", "red")); + endpoints("namespaceB", "serviceA", Map.of("color", "blue")); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA"), client); + List result = discoveryClient.getInstances("serviceA"); + Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); - Assertions.assertThat(result.get(0).getMetadata().getNamespace()).isEqualTo("namespaceA"); + Assertions.assertThat(result.get(0).getMetadata().get("k8s_namespace")).isEqualTo("namespaceA"); } /** *
 	 *     - all-namespaces = false
-	 *     - specific namespace = namespaceA
+	 *     - specific namespace = namespaceA, namespaceB
 	 *     - labels = {color = purple}
 	 *
 	 *     - serviceA exists in namespaceA with labels = {color=red}
-	 *     - serviceB exists in namespaceA with labels = {color=purple}
-	 *     - serviceC exists in namespaceC with labels = {color=purple}
+	 *     - serviceA exists in namespaceB with labels = {color=purple}
+	 *     - serviceA exists in namespaceC with labels = {color=purple}
 	 *
-	 *     - we get only serviceB as a result, even if such labels are also
+	 *     - we get only serviceA from namespaceB as a result, even if such labels are also
 	 *       present on a different service (but it's in a different namespace).
 	 * 
*/ @@ -252,36 +252,37 @@ void testSpecificNamespaceWithLabelsWithoutFilter() { Map labels = Map.of("color", "purple"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), - true, 60L, false, null, Set.of(), labels, null, null, 0, false, false, null); - - utils.when(() -> Fabric8Utils.getApplicationNamespace(Mockito.any(KubernetesClient.class), - Mockito.nullable(String.class), Mockito.anyString(), Mockito.any(KubernetesNamespaceProvider.class))) - .thenReturn("namespaceA"); + true, 60L, false, null, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, + 0, false, false, null); service("namespaceA", "serviceA", Map.of("color", "red")); - service("namespaceA", "serviceB", Map.of("color", "purple")); - service("namespaceC", "serviceC", Map.of("color", "purple")); + service("namespaceB", "serviceA", Map.of("color", "purple")); + service("namespaceC", "serviceA", Map.of("color", "purple")); + + endpoints("namespaceA", "serviceA", Map.of("color", "red")); + endpoints("namespaceB", "serviceA", Map.of("color", "purple")); + endpoints("namespaceC", "serviceA", Map.of("color", "purple")); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA", "namespaceB"), client); + List result = discoveryClient.getInstances("serviceA"); - List result = services(properties, client, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties), null, "dummy-target"); Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceB"); - Assertions.assertThat(result.get(0).getMetadata().getNamespace()).isEqualTo("namespaceA"); + Assertions.assertThat(result.get(0).getMetadata().get("k8s_namespace")).isEqualTo("namespaceB"); } /** *
 	 *     - all-namespaces = false
-	 *     - specific namespace = namespaceA
+	 *     - specific namespace = namespaceA, namespaceB
 	 *     - labels = {}
 	 *     - filter = "#root.metadata.labels.containsKey("number")"
-	 *       (namespaceA or namespaceB)
+	 *       (namespaceA or namespaceC)
 	 *
 	 *     - serviceA exists in namespaceA with labels = {color=red, number=1}
-	 *     - serviceB exists in namespaceA with labels = {color=purple, cycle=create}
-	 *     - serviceC exists in namespaceC with labels = {color=purple, number=1}
+	 *     - serviceA exists in namespaceB with labels = {color=purple, cycle=create}
+	 *     - serviceA exists in namespaceC with labels = {color=purple, number=1}
 	 *
-	 *     - we get only serviceB as a result (because of the filter) even if such labels are also
+	 *     - we get only serviceA from namespaceB as a result (because of the filter) even if such labels are also
 	 *       present on a different service (but it's in a different namespace).
 	 * 
*/ @@ -294,37 +295,36 @@ void testSpecificNamespaceWithoutLabelsWithFilter() { """.stripLeading(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), - true, 60L, false, spelFilter, Set.of(), labels, null, null, 0, false, false, null); - - utils.when(() -> Fabric8Utils.getApplicationNamespace(Mockito.any(KubernetesClient.class), - Mockito.nullable(String.class), Mockito.anyString(), Mockito.any(KubernetesNamespaceProvider.class))) - .thenReturn("namespaceA"); + true, 60L, false, spelFilter, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, + 0, false, false, null); service("namespaceA", "serviceA", Map.of("color", "red", "number", "1")); - service("namespaceA", "serviceB", Map.of("color", "purple", "cycle", "create")); - service("namespaceC", "serviceC", Map.of("color", "purple", "number", "1")); + service("namespaceB", "serviceA", Map.of("color", "purple", "cycle", "create")); + service("namespaceC", "serviceA", Map.of("color", "purple", "number", "1")); + + endpoints("namespaceA", "serviceA", Map.of("color", "red")); + endpoints("namespaceB", "serviceA", Map.of("color", "purple")); + endpoints("namespaceC", "serviceA", Map.of("color", "purple")); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA", "namespaceB"), client); + List result = discoveryClient.getInstances("serviceA"); - List result = services(properties, client, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties), null, "dummy-target"); Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); - Assertions.assertThat(result.get(0).getMetadata().getNamespace()).isEqualTo("namespaceA"); - Assertions.assertThat(result.get(0).getMetadata().getLabels()) - .containsExactlyInAnyOrderEntriesOf(Map.of("color", "red", "number", "1")); + Assertions.assertThat(result.get(0).getMetadata().get("k8s_namespace")).isEqualTo("namespaceA"); } /** *
 	 *     - all-namespaces = false
-	 *     - some namespaces = [namespaceA, namespaceB]
+	 *     - selective namespaces = [namespaceA, namespaceB]
 	 *     - labels = {}
 	 *     - filter = null
 	 *
 	 *     - serviceA exists in namespaceA with labels = {}
-	 *     - serviceB exists in namespaceB with labels = {}
-	 *     - serviceC exists in namespaceC with labels = {}
+	 *     - serviceA exists in namespaceB with labels = {}
+	 *     - serviceA exists in namespaceC with labels = {}
 	 *
-	 *     - we get serviceA and serviceB as a result, because their namespaces match.
+	 *     - we get serviceA in namespaceA and serviceA in namespaceB as a result, because their namespaces match.
 	 * 
*/ @Test @@ -334,19 +334,23 @@ void testSomeNamespacesWithoutLabelsWithoutFilter() { Map labels = Map.of(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, - someNamespaces, true, 60L, false, null, Set.of(), labels, null, null, 0, false, false, null); + someNamespaces, true, 60L, false, null, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, + 0, false, false, null); service("namespaceA", "serviceA", Map.of()); - service("namespaceB", "serviceB", Map.of()); - service("namespaceC", "serviceC", Map.of()); - - List result = services(properties, client, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties), null, "dummy-target"); - result = result.stream().sorted(Comparator.comparing(x -> x.getMetadata().getName())).toList(); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); - Assertions.assertThat(result.get(0).getMetadata().getNamespace()).isEqualTo("namespaceA"); - Assertions.assertThat(result.get(1).getMetadata().getName()).isEqualTo("serviceB"); - Assertions.assertThat(result.get(1).getMetadata().getNamespace()).isEqualTo("namespaceB"); + service("namespaceB", "serviceA", Map.of()); + service("namespaceC", "serviceA", Map.of()); + + endpoints("namespaceA", "serviceA", Map.of()); + endpoints("namespaceB", "serviceA", Map.of()); + endpoints("namespaceC", "serviceA", Map.of()); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA", "namespaceB"), client); + List result = discoveryClient.getInstances("serviceA"); + + Assertions.assertThat(result.size()).isEqualTo(2); + Assertions.assertThat(result.stream().map(x -> x.getMetadata().get("k8s_namespace")).sorted().toList()) + .isEqualTo(List.of("namespaceA", "namespaceB")); } /** @@ -357,10 +361,10 @@ void testSomeNamespacesWithoutLabelsWithoutFilter() { * - filter = null * * - serviceA exists in namespaceA with labels = {color=purple} - * - serviceB exists in namespaceB with labels = {color=red} - * - serviceC exists in namespaceC with labels = {color=purple} + * - serviceA exists in namespaceB with labels = {color=red} + * - serviceA exists in namespaceC with labels = {color=purple} * - * - we get serviceA as a result + * - we get serviceA in namespaceA as a result * */ @Test @@ -371,17 +375,22 @@ void testSomeNamespacesWithLabelsWithoutFilter() { String spelFilter = null; KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, - someNamespaces, true, 60L, false, spelFilter, Set.of(), labels, null, null, 0, false, false, null); + someNamespaces, true, 60L, false, spelFilter, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); service("namespaceA", "serviceA", Map.of("color", "purple")); - service("namespaceB", "serviceB", Map.of("color", "red")); - service("namespaceC", "serviceC", Map.of("color", "purple")); + service("namespaceB", "serviceA", Map.of("color", "red")); + service("namespaceC", "serviceA", Map.of("color", "purple")); + + endpoints("namespaceA", "serviceA", Map.of("color", "purple")); + endpoints("namespaceB", "serviceA", Map.of("color", "red")); + endpoints("namespaceC", "serviceA", Map.of("color", "purple")); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA", "namespaceB"), client); + List result = discoveryClient.getInstances("serviceA"); - List result = services(properties, client, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties), null, "dummy-target"); Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); - Assertions.assertThat(result.get(0).getMetadata().getNamespace()).isEqualTo("namespaceA"); + Assertions.assertThat(result.get(0).getMetadata().get("k8s_namespace")).isEqualTo("namespaceA"); } /** @@ -392,10 +401,10 @@ void testSomeNamespacesWithLabelsWithoutFilter() { * - filter = #root.metadata.labels.containsKey("number") * * - serviceA exists in namespaceA with labels = {color=purple} - * - serviceB exists in namespaceB with labels = {color=red} - * - serviceC exists in namespaceC with labels = {color=purple} + * - serviceA exists in namespaceB with labels = {color=red} + * - serviceA exists in namespaceC with labels = {color=purple} * - * - we get serviceA as a result + * - we get serviceA from namespaceA as a result * */ @Test @@ -408,23 +417,37 @@ void testSomeNamespacesWithLabelsWithFilter() { """.stripLeading(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, - someNamespaces, true, 60L, false, spelFilter, Set.of(), labels, null, null, 0, false, false, null); + someNamespaces, true, 60L, false, spelFilter, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, + 0, false, false, null); service("namespaceA", "serviceA", Map.of("color", "purple", "number", "1")); - service("namespaceB", "serviceB", Map.of("color", "purple", "cycle", "create")); - service("namespaceC", "serviceC", Map.of("color", "purple", "number", "1")); + service("namespaceB", "serviceA", Map.of("color", "purple", "cycle", "create")); + service("namespaceC", "serviceA", Map.of("color", "purple", "number", "1")); + + endpoints("namespaceA", "serviceA", Map.of("color", "purple", "number", "1")); + endpoints("namespaceB", "serviceA", Map.of("color", "purple", "cycle", "create")); + endpoints("namespaceC", "serviceA", Map.of("color", "purple", "number", "1")); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA", "namespaceB"), client); + List result = discoveryClient.getInstances("serviceA"); - List result = services(properties, client, NAMESPACE_PROVIDER, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties), null, "dummy-target"); Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); - Assertions.assertThat(result.get(0).getMetadata().getNamespace()).isEqualTo("namespaceA"); + Assertions.assertThat(result.get(0).getMetadata().get("k8s_namespace")).isEqualTo("namespaceA"); } private void service(String namespace, String name, Map labels) { + Service service = service(namespace, name, labels, Map.of(), Map.of()); client.services() .inNamespace(namespace) - .resource(new ServiceBuilder().withNewMetadata().withName(name).withLabels(labels).and().build()) + .resource(service) + .create(); + } + + private void endpoints(String namespace, String name, Map labels) { + Endpoints endpoints = endpoints(namespace, name, labels, Map.of()); + client.endpoints() + .inNamespace(namespace) + .resource(endpoints) .create(); } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientTests.java deleted file mode 100644 index 25fd38cbc..000000000 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientTests.java +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright 2019-present 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.kubernetes.fabric8.discovery; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import io.fabric8.kubernetes.api.model.Endpoints; -import io.fabric8.kubernetes.api.model.EndpointsBuilder; -import io.fabric8.kubernetes.api.model.EndpointsList; -import io.fabric8.kubernetes.api.model.ServiceBuilder; -import io.fabric8.kubernetes.api.model.ServiceList; -import io.fabric8.kubernetes.api.model.ServiceListBuilder; -import io.fabric8.kubernetes.api.model.ServiceSpecBuilder; -import io.fabric8.kubernetes.client.Config; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.test.StepVerifier; - -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; -import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; -import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; -import org.springframework.core.env.Environment; -import org.springframework.mock.env.MockEnvironment; - -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties.Metadata; - -/** - * @author Tim Ysewyn - */ -@EnableKubernetesMockClient(crud = true, https = false) -class Fabric8ReactiveDiscoveryClientTests { - - private static final ServicePortSecureResolver SERVICE_PORT_SECURE_RESOLVER = new ServicePortSecureResolver( - KubernetesDiscoveryProperties.DEFAULT); - - private static final KubernetesNamespaceProvider NAMESPACE_PROVIDER = new KubernetesNamespaceProvider( - mockEnvironment()); - - private static KubernetesMockServer kubernetesServer; - - private static KubernetesClient kubernetesClient; - - @BeforeEach - void beforeEach() { - // Configure the kubernetes master url to point to the mock server - System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, - kubernetesClient.getConfiguration().getMasterUrl()); - System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true"); - System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); - System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); - System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); - } - - @AfterEach - void afterEach() { - kubernetesServer.clearExpectations(); - } - - @Test - void verifyDefaults() { - Fabric8DiscoveryClient fabric8DiscoveryClient = new Fabric8DiscoveryClient(kubernetesClient, - KubernetesDiscoveryProperties.DEFAULT, SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); - ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); - assertThat(client.description()).isEqualTo("Fabric8 Reactive Discovery Client"); - assertThat(client.getOrder()).isEqualTo(ReactiveDiscoveryClient.DEFAULT_ORDER); - } - - @Test - void shouldReturnFluxOfServices() { - kubernetesServer.expect() - .get() - .withPath("/api/v1/namespaces/test/services") - .andReturn(200, - new ServiceListBuilder().addNewItem() - .withNewMetadata() - .withName("s1") - .withLabels(Map.of("label", "value")) - .endMetadata() - .endItem() - .addNewItem() - .withNewMetadata() - .withName("s2") - .withLabels(Map.of("label", "value", "label2", "value2")) - .endMetadata() - .endItem() - .addNewItem() - .withNewMetadata() - .withName("s3") - .endMetadata() - .endItem() - .build()) - .once(); - - Fabric8DiscoveryClient fabric8DiscoveryClient = new Fabric8DiscoveryClient(kubernetesClient, - KubernetesDiscoveryProperties.DEFAULT, SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); - ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); - - Flux services = client.getServices(); - StepVerifier.create(services).expectNext("s1", "s2", "s3").expectComplete().verify(); - } - - @Test - void shouldReturnEmptyFluxOfServicesWhenNoInstancesFound() { - kubernetesServer.expect() - .get() - .withPath("/api/v1/namespaces/test/services") - .andReturn(200, new ServiceListBuilder().build()) - .once(); - - Fabric8DiscoveryClient fabric8DiscoveryClient = new Fabric8DiscoveryClient(kubernetesClient, - KubernetesDiscoveryProperties.DEFAULT, SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); - ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); - - Flux services = client.getServices(); - StepVerifier.create(services).expectNextCount(0).expectComplete().verify(); - } - - @Test - void shouldReturnEmptyFluxForNonExistingService() { - kubernetesServer.expect() - .get() - .withPath("/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dnonexistent-service") - .andReturn(200, new EndpointsBuilder().build()) - .once(); - - Fabric8DiscoveryClient fabric8DiscoveryClient = new Fabric8DiscoveryClient(kubernetesClient, - KubernetesDiscoveryProperties.DEFAULT, SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); - ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); - - Flux instances = client.getInstances("nonexistent-service"); - StepVerifier.create(instances).expectNextCount(0).expectComplete().verify(); - } - - @Test - void shouldReturnEmptyFluxWhenServiceHasNoSubsets() { - kubernetesServer.expect() - .get() - .withPath("/api/v1/namespaces/test/services") - .andReturn(200, - new ServiceListBuilder().addNewItem() - .withNewMetadata() - .withName("existing-service") - .withLabels(Map.of("label", "value")) - .endMetadata() - .endItem() - .build()) - .once(); - - kubernetesServer.expect() - .get() - .withPath("/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dexisting-service") - .andReturn(200, new EndpointsBuilder().build()) - .once(); - - Fabric8DiscoveryClient fabric8DiscoveryClient = new Fabric8DiscoveryClient(kubernetesClient, - KubernetesDiscoveryProperties.DEFAULT, SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); - ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); - - Flux instances = client.getInstances("existing-service"); - StepVerifier.create(instances).expectNextCount(0).expectComplete().verify(); - } - - @Test - void shouldReturnFlux() { - ServiceList services = new ServiceListBuilder().addNewItem() - .withNewMetadata() - .withName("existing-service") - .withNamespace("test") - .withLabels(Map.of("label", "value")) - .endMetadata() - .withSpec(new ServiceSpecBuilder().withType("ExternalName").build()) - .endItem() - .build(); - - Endpoints endPoint = new EndpointsBuilder().withNewMetadata() - .withName("existing-service") - .withNamespace("test") - .withLabels(Map.of("label", "value")) - .endMetadata() - .addNewSubset() - .addNewAddress() - .withIp("ip1") - .withNewTargetRef() - .withUid("uid1") - .endTargetRef() - .endAddress() - .addNewPort("http", "http_tcp", 80, "TCP") - .endSubset() - .build(); - - List endpointsList = new ArrayList<>(); - endpointsList.add(endPoint); - - EndpointsList endpoints = new EndpointsList(); - endpoints.setItems(endpointsList); - - kubernetesServer.expect() - .get() - .withPath("/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dexisting-service") - .andReturn(200, endpoints) - .once(); - - kubernetesServer.expect() - .get() - .withPath("/api/v1/namespaces/test/services/existing-service") - .andReturn(200, services.getItems().get(0)) - .once(); - - kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services").andReturn(200, services).once(); - - Fabric8DiscoveryClient fabric8DiscoveryClient = new Fabric8DiscoveryClient(kubernetesClient, - KubernetesDiscoveryProperties.DEFAULT, SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); - ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); - - Flux instances = client.getInstances("existing-service"); - StepVerifier.create(instances).expectNextCount(1).expectComplete().verify(); - } - - @Test - void shouldReturnFluxWithPrefixedMetadata() { - kubernetesServer.expect() - .get() - .withPath("/api/v1/namespaces/test/services") - .andReturn(200, - new ServiceListBuilder().addNewItem() - .withNewMetadata() - .withName("existing-service") - .withLabels(Map.of("label", "value")) - .endMetadata() - .withSpec(new ServiceSpecBuilder().withType("ExternalName").build()) - .endItem() - .build()) - .once(); - - Endpoints endPoint = new EndpointsBuilder().withNewMetadata() - .withName("existing-service") - .withNamespace("test") - .endMetadata() - .addNewSubset() - .addNewAddress() - .withIp("ip1") - .withNewTargetRef() - .withUid("uid1") - .endTargetRef() - .endAddress() - .addNewPort("http", "http_tcp", 80, "TCP") - .endSubset() - .build(); - - List endpointsList = new ArrayList<>(); - endpointsList.add(endPoint); - - EndpointsList endpoints = new EndpointsList(); - endpoints.setItems(endpointsList); - - kubernetesServer.expect() - .get() - .withPath("/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dexisting-service") - .andReturn(200, endpoints) - .once(); - - kubernetesServer.expect() - .get() - .withPath("/api/v1/namespaces/test/services/existing-service") - .andReturn(200, - new ServiceBuilder().withNewMetadata() - .withName("existing-service") - .withLabels(Map.of("label", "value")) - .endMetadata() - .withSpec(new ServiceSpecBuilder().withType("ExternalName").build()) - .build()) - .once(); - - Fabric8DiscoveryClient fabric8DiscoveryClient = new Fabric8DiscoveryClient(kubernetesClient, - KubernetesDiscoveryProperties.DEFAULT, SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); - ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); - - Flux instances = client.getInstances("existing-service"); - StepVerifier.create(instances).expectNextCount(1).expectComplete().verify(); - } - - @Test - void shouldReturnFluxWhenServiceHasMultiplePortsAndPrimaryPortNameIsSet() { - kubernetesServer.expect() - .get() - .withPath("/api/v1/namespaces/test/services") - .andReturn(200, - new ServiceListBuilder().addNewItem() - .withNewMetadata() - .withName("existing-service") - .withLabels(Map.of("label", "value")) - .endMetadata() - .withSpec(new ServiceSpecBuilder().withType("ExternalName").build()) - .endItem() - .build()) - .once(); - - Endpoints endPoint = new EndpointsBuilder().withNewMetadata() - .withName("existing-service") - .withNamespace("test") - .endMetadata() - .addNewSubset() - .addNewAddress() - .withIp("ip1") - .withNewTargetRef() - .withUid("uid1") - .endTargetRef() - .endAddress() - .addNewPort("http", "http_tcp", 80, "TCP") - .addNewPort("https", "https_tcp", 443, "TCP") - .endSubset() - .build(); - - List endpointsList = new ArrayList<>(); - endpointsList.add(endPoint); - - EndpointsList endpoints = new EndpointsList(); - endpoints.setItems(endpointsList); - - kubernetesServer.expect() - .get() - .withPath("/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dexisting-service") - .andReturn(200, endpoints) - .once(); - - kubernetesServer.expect() - .get() - .withPath("/api/v1/namespaces/test/services/existing-service") - .andReturn(200, - new ServiceBuilder().withNewMetadata() - .withName("existing-service") - .withLabels(Map.of("label", "value")) - .endMetadata() - .withSpec(new ServiceSpecBuilder().withType("ExternalName").build()) - .build()) - .once(); - - Fabric8DiscoveryClient fabric8DiscoveryClient = new Fabric8DiscoveryClient(kubernetesClient, - KubernetesDiscoveryProperties.DEFAULT, SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); - ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); - - Flux instances = client.getInstances("existing-service"); - StepVerifier.create(instances).expectNextCount(1).expectComplete().verify(); - } - - @Test - void shouldReturnFluxOfServicesAcrossAllNamespaces() { - kubernetesServer.expect() - .get() - .withPath("/api/v1/namespaces/test/services") - .andReturn(200, - new ServiceListBuilder().addNewItem() - .withNewMetadata() - .withName("existing-service") - .withLabels(Map.of("label", "value")) - .endMetadata() - .withSpec(new ServiceSpecBuilder().withType("ExternalName").build()) - .endItem() - .build()) - .once(); - - Endpoints endpoints = new EndpointsBuilder().withNewMetadata() - .withName("existing-service") - .withNamespace("test") - .endMetadata() - .addNewSubset() - .addNewAddress() - .withIp("ip1") - .withNewTargetRef() - .withUid("uid1") - .endTargetRef() - .endAddress() - .addNewPort("http", "http_tcp", 80, "TCP") - .addNewPort("https", "https_tcp", 443, "TCP") - .endSubset() - .build(); - - EndpointsList endpointsList = new EndpointsList(); - endpointsList.setItems(singletonList(endpoints)); - - kubernetesServer.expect() - .get() - .withPath("/api/v1/endpoints?fieldSelector=metadata.name%3Dexisting-service") - .andReturn(200, endpointsList) - .once(); - - kubernetesServer.expect() - .get() - .withPath("/api/v1/namespaces/test/services/existing-service") - .andReturn(200, - new ServiceBuilder().withNewMetadata() - .withName("existing-service") - .withLabels(Map.of("label", "value")) - .endMetadata() - .withSpec(new ServiceSpecBuilder().withType("ExternalName").build()) - .build()) - .once(); - - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60, - false, null, Set.of(), Map.of(), "https_tcp", Metadata.DEFAULT, 0, true, false, null); - Fabric8DiscoveryClient fabric8KubernetesDiscoveryClient = new Fabric8DiscoveryClient(kubernetesClient, - properties, SERVICE_PORT_SECURE_RESOLVER, NAMESPACE_PROVIDER, x -> true); - - ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8KubernetesDiscoveryClient); - Flux instances = client.getInstances("existing-service"); - StepVerifier.create(instances).expectNextCount(1).expectComplete().verify(); - } - - private static Environment mockEnvironment() { - MockEnvironment mockEnvironment = new MockEnvironment(); - mockEnvironment.setProperty("spring.cloud.kubernetes.client.namespace", "test"); - return mockEnvironment; - } - -} From 9389d5249cbf2d23ab9cb1892339e95794c51c6e Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 4 Feb 2026 23:21:56 +0200 Subject: [PATCH 10/19] refactored tests Signed-off-by: wind57 --- .../fabric8/Fabric8AutoConfiguration.java | 8 + .../discovery/Fabric8CatalogWatchTest.java | 13 +- .../discovery/Fabric8ConfigServerTest.java | 11 + ...DiscoveryClientAutoConfigurationTests.java | 26 +- .../discovery/Fabric8DiscoveryClientBase.java | 32 +- ...ric8DiscoveryClientFilterMetadataTest.java | 33 +- .../Fabric8DiscoveryClientFilterTest.java | 15 +- .../Fabric8DiscoveryClientOneTests.java | 22 +- ...veryClientServiceWithoutPortNameTests.java | 3 +- .../Fabric8DiscoveryClientTwoTests.java | 100 ++-- ...abric8DiscoveryClientUtilsFilterTests.java | 29 +- .../Fabric8DiscoveryClientUtilsTests.java | 532 +++++++----------- .../Fabric8DiscoveryFilterTests.java | 65 ++- 13 files changed, 398 insertions(+), 491 deletions(-) diff --git a/spring-cloud-kubernetes-fabric8-autoconfig/src/main/java/org/springframework/cloud/kubernetes/fabric8/Fabric8AutoConfiguration.java b/spring-cloud-kubernetes-fabric8-autoconfig/src/main/java/org/springframework/cloud/kubernetes/fabric8/Fabric8AutoConfiguration.java index 900c04f8d..c85d8db13 100644 --- a/spring-cloud-kubernetes-fabric8-autoconfig/src/main/java/org/springframework/cloud/kubernetes/fabric8/Fabric8AutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-autoconfig/src/main/java/org/springframework/cloud/kubernetes/fabric8/Fabric8AutoConfiguration.java @@ -29,8 +29,10 @@ import org.springframework.boot.cloud.CloudPlatform; import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties; import org.springframework.cloud.kubernetes.commons.KubernetesCommonsAutoConfiguration; +import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; /** * Auto configuration for Kubernetes. @@ -105,6 +107,12 @@ Fabric8PodUtils kubernetesPodUtils(KubernetesClient client) { return new Fabric8PodUtils(client); } + @Bean + @ConditionalOnMissingBean + KubernetesNamespaceProvider kubernetesNamespaceProvider(Environment environment) { + return new KubernetesNamespaceProvider(environment); + } + private static D or(D left, D right) { return left != null ? left : right; } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8CatalogWatchTest.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8CatalogWatchTest.java index 8f8332879..8b894bf9a 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8CatalogWatchTest.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8CatalogWatchTest.java @@ -33,7 +33,6 @@ import io.fabric8.kubernetes.api.model.ServiceList; import io.fabric8.kubernetes.api.model.ServiceListBuilder; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.dsl.FilterNested; import io.fabric8.kubernetes.client.dsl.FilterWatchListDeletable; import io.fabric8.kubernetes.client.dsl.MixedOperation; import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation; @@ -80,9 +79,6 @@ class Fabric8CatalogWatchTest { private static final FilterWatchListDeletable> FILTER_WATCH_LIST_DELETABLE = Mockito .mock(FilterWatchListDeletable.class); - private static final FilterNested>> FILTER_NESTED = Mockito - .mock(FilterNested.class); - private static final ArgumentCaptor HEARTBEAT_EVENT_ARGUMENT_CAPTOR = ArgumentCaptor .forClass(HeartbeatEvent.class); @@ -411,10 +407,7 @@ private void createInAllNamespaceWatcher() { when(CLIENT.endpoints()).thenReturn(MIXED_OPERATION); when(MIXED_OPERATION.inAnyNamespace()).thenReturn(MIXED_OPERATION); - when(MIXED_OPERATION.withLabels(Map.of())).thenReturn(MIXED_OPERATION); - when(MIXED_OPERATION.withNewFilter()).thenReturn(FILTER_NESTED); - when(FILTER_NESTED.withLabels(Map.of())).thenReturn(FILTER_NESTED); - when(FILTER_NESTED.endFilter()).thenReturn(FILTER_WATCH_LIST_DELETABLE); + when(MIXED_OPERATION.withLabels(Map.of())).thenReturn(FILTER_WATCH_LIST_DELETABLE); } @@ -431,9 +424,7 @@ private void createInSpecificNamespaceWatcher() { when(namespaceProvider.getNamespace()).thenReturn("catalog-watcher-namespace"); when(CLIENT.endpoints()).thenReturn(MIXED_OPERATION); when(MIXED_OPERATION.inNamespace("catalog-watcher-namespace")).thenReturn(NON_NAMESPACE_OPERATION); - when(NON_NAMESPACE_OPERATION.withNewFilter()).thenReturn(FILTER_NESTED); - when(FILTER_NESTED.withLabels(Map.of())).thenReturn(FILTER_NESTED); - when(FILTER_NESTED.endFilter()).thenReturn(FILTER_WATCH_LIST_DELETABLE); + when(NON_NAMESPACE_OPERATION.withLabels(Map.of())).thenReturn(FILTER_WATCH_LIST_DELETABLE); } private void mockServicesCall(String name, String namespace) { diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerTest.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerTest.java index f9b971764..a58cc7a41 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerTest.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerTest.java @@ -18,6 +18,8 @@ import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -27,6 +29,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; import org.springframework.test.util.TestSocketUtils; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; @@ -45,8 +48,11 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { "spring.main.cloud-platform=KUBERNETES", "spring.config.import=kubernetes:, optional:configserver:", "dummy.config.loader.enabled=true" }) +@EnableKubernetesMockClient(crud = true, https = false) class Fabric8ConfigServerTest { + private static KubernetesClient client; + private static WireMockServer wireMockServer; @Autowired @@ -74,6 +80,11 @@ void test() { @SpringBootApplication protected static class TestConfig { + @Bean + KubernetesClient client() { + return client; + } + } } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientAutoConfigurationTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientAutoConfigurationTests.java index 657ce207b..8d4a7315a 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientAutoConfigurationTests.java @@ -16,6 +16,8 @@ package org.springframework.cloud.kubernetes.fabric8.discovery; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -24,13 +26,21 @@ import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClient; +import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; +import org.springframework.context.annotation.Bean; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { "spring.main.cloud-platform=KUBERNETES", - "spring.cloud.config.enabled=false", "spring.cloud.kubernetes.discovery.use-endpoint-slices=false" }) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, + properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false", + "spring.cloud.kubernetes.discovery.use-endpoint-slices=false" }) +@EnableKubernetesMockClient(crud = true, https = false) class Fabric8DiscoveryClientAutoConfigurationTests { + private static KubernetesClient kubernetesClient; + @Autowired private DiscoveryClient discoveryClient; @@ -46,6 +56,18 @@ void kubernetesDiscoveryClientCreated() { @SpringBootApplication protected static class TestConfig { + @Bean + KubernetesNamespaceProvider kubernetesNamespaceProvider() { + KubernetesNamespaceProvider provider = mock(KubernetesNamespaceProvider.class); + when(provider.getNamespace()).thenReturn("test"); + return provider; + } + + @Bean + KubernetesClient kubernetesClient() { + return kubernetesClient; + } + } } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientBase.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientBase.java index bf40056b0..60ea10974 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientBase.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientBase.java @@ -32,8 +32,8 @@ import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.informers.SharedIndexInformer; import io.fabric8.kubernetes.client.informers.cache.Lister; - import org.assertj.core.util.Strings; + import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import static java.util.stream.Collectors.toList; @@ -47,22 +47,23 @@ abstract class Fabric8DiscoveryClientBase { Fabric8DiscoveryClient fabric8DiscoveryClient(KubernetesDiscoveryProperties properties, List selectiveNamespaces, KubernetesClient kubernetesClient) { - List> serviceInformers = configuration.serviceSharedIndexInformers( - selectiveNamespaces, kubernetesClient, properties); - List> endpointsInformers = configuration.endpointsSharedIndexInformers( - selectiveNamespaces, kubernetesClient, properties); - List> serviceListers = configuration.serviceListers(selectiveNamespaces, serviceInformers); - List> endpointsListers = configuration.endpointsListers(selectiveNamespaces, endpointsInformers); - - return new Fabric8DiscoveryClient(kubernetesClient, serviceListers, - endpointsListers, serviceInformers, endpointsInformers, properties, - new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties)); + List> serviceInformers = configuration + .serviceSharedIndexInformers(selectiveNamespaces, kubernetesClient, properties); + List> endpointsInformers = configuration + .endpointsSharedIndexInformers(selectiveNamespaces, kubernetesClient, properties); + List> serviceListers = configuration.serviceListers(selectiveNamespaces, serviceInformers); + List> endpointsListers = configuration.endpointsListers(selectiveNamespaces, + endpointsInformers); + + return new Fabric8DiscoveryClient(kubernetesClient, serviceListers, endpointsListers, serviceInformers, + endpointsInformers, properties, + new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(properties)); } - void setupServiceWithLabelsAndAnnotationsAndPorts(KubernetesClient kubernetesClient, String serviceId, String namespace, - Map labels, Map annotations, Map ports) { + void setupServiceWithLabelsAndAnnotationsAndPorts(KubernetesClient kubernetesClient, String serviceId, + String namespace, Map labels, Map annotations, Map ports) { - Service service = service(serviceId, namespace, labels, annotations, ports); + Service service = service(namespace, serviceId, labels, annotations, ports); kubernetesClient.services().inNamespace(namespace).resource(service).create(); Endpoints endpoints = endpoints(namespace, serviceId, labels, ports); @@ -83,7 +84,8 @@ static Service service(String namespace, String serviceId, Map l .build(); } - static Endpoints endpoints(String namespace, String serviceId, Map labels, Map ports) { + static Endpoints endpoints(String namespace, String serviceId, Map labels, + Map ports) { ObjectMeta objectMeta = new ObjectMeta(); objectMeta.setNamespace(namespace); diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterMetadataTest.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterMetadataTest.java index 7fa636ba3..c5262d073 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterMetadataTest.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterMetadataTest.java @@ -54,9 +54,10 @@ void testAllExtraMetadataDisabled() { false, null, Set.of(), Map.of("label1", "one"), null, metadata, 0, true, false, null); setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one"), - Map.of("annotation1", "ann-one"), Map.of(80, "http", 5555, "")); + Map.of("annotation1", "ann-one"), Map.of(80, "http", 5555, "")); - Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), + mockClient); List instances = fabric8DiscoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); @@ -72,9 +73,10 @@ void testLabelsEnabled() { false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one"), - Map.of("annotation1", "ann-one"), Map.of(80, "http", 5555, "")); + Map.of("annotation1", "ann-one"), Map.of(80, "http", 5555, "")); - Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), + mockClient); List instances = fabric8DiscoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); @@ -90,8 +92,9 @@ void testLabelsEnabledWithPrefix() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); - setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one", "label2", "two"), - Map.of("annotation1", "ann-one"), Map.of(80, "http", 5555, "")); + setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, + Map.of("label1", "one", "label2", "two"), Map.of("annotation1", "ann-one"), + Map.of(80, "http", 5555, "")); Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); @@ -110,7 +113,7 @@ void testAnnotationsEnabled() { false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one"), - Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); @@ -129,7 +132,7 @@ void testAnnotationsEnabledWithPrefix() { false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one"), - Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); @@ -148,7 +151,7 @@ void testPortsEnabled() { false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one"), - Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); @@ -167,14 +170,14 @@ void testPortsEnabledWithPrefix() { false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one"), - Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); - assertThat(instances.get(0).getMetadata()).containsOnly(entry("p_http", "80"), entry("k8s_namespace", NAMESPACE), - entry("p_", "5555"), entry("type", "ClusterIP")); + assertThat(instances.get(0).getMetadata()).containsOnly(entry("p_http", "80"), + entry("k8s_namespace", NAMESPACE), entry("p_", "5555"), entry("type", "ClusterIP")); } @Test @@ -186,15 +189,15 @@ void testLabelsAndAnnotationsAndPortsEnabledWithPrefix() { false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); setupServiceWithLabelsAndAnnotationsAndPorts(mockClient, serviceId, NAMESPACE, Map.of("label1", "one"), - Map.of("a1", "an1", "a2", "an2"), Map.of(80, "http", 5555, "")); + Map.of("a1", "an1", "a2", "an2"), Map.of(80, "http", 5555, "")); Fabric8DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); assertThat(instances.get(0).getMetadata()).containsOnly(entry("a_a1", "an1"), entry("a_a2", "an2"), - entry("l_label1", "one"), entry("p_http", "80"), entry("k8s_namespace", NAMESPACE), entry("type", "ClusterIP"), - entry("p_", "5555")); + entry("l_label1", "one"), entry("p_http", "80"), entry("k8s_namespace", NAMESPACE), + entry("type", "ClusterIP"), entry("p_", "5555")); } } diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterTest.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterTest.java index c58660585..b5228f178 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterTest.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientFilterTest.java @@ -62,20 +62,19 @@ void testFilteredServices() { Endpoints endpoints = endpoints(NAMESPACE, "ServiceNonSpringBoot", Map.of(), Map.of()); mockClient.endpoints().inNamespace(NAMESPACE).resource(endpoints).create(); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, "metadata.additionalProperties['spring-boot']", Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true, false, null); - Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), + mockClient); List filteredServices = fabric8DiscoveryClient.getServices(); assertThat(filteredServices).containsExactlyInAnyOrder("serviceA", "serviceB"); // without filter - properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, - false, null, Set.of(), Map.of(), null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true, false, null); + properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, null, Set.of(), Map.of(), + null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true, false, null); fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); @@ -106,9 +105,9 @@ void testFilteredServicesByPrefix() { List filteredServices = client.getServices(); assertThat(filteredServices).containsExactlyInAnyOrder("serviceA", "serviceB", "serviceC"); - properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, - false, "metadata.name.startsWith('another')", Set.of(), Map.of(), null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true, false, null); + properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, false, + "metadata.name.startsWith('another')", Set.of(), Map.of(), null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true, false, null); client = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); filteredServices = client.getServices(); assertThat(filteredServices).containsExactlyInAnyOrder("anotherService"); diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientOneTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientOneTests.java index aeb584f53..148f1808e 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientOneTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientOneTests.java @@ -95,8 +95,8 @@ void getInstancesShouldBeAbleToHandleEndpointsSingleAddress() { mockClient.services().inNamespace("test").resource(service).create(); - DiscoveryClient discoveryClient = fabric8DiscoveryClient( - KubernetesDiscoveryProperties.DEFAULT, List.of("test"), mockClient); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(KubernetesDiscoveryProperties.DEFAULT, List.of("test"), + mockClient); List instances = discoveryClient.getInstances("endpoint"); @@ -237,8 +237,8 @@ void getServicesShouldReturnAllServicesWhenNoLabelsAreAppliedToTheClient() { mockClient.services().inNamespace("test").resource(service2).create(); mockClient.services().inNamespace("test").resource(service3).create(); - DiscoveryClient discoveryClient = fabric8DiscoveryClient(KubernetesDiscoveryProperties.DEFAULT, - List.of("test"), mockClient); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(KubernetesDiscoveryProperties.DEFAULT, List.of("test"), + mockClient); List services = discoveryClient.getServices(); @@ -267,8 +267,8 @@ void getServicesShouldReturnOnlyMatchingServicesWhenLabelsAreAppliedToTheClient( mockClient.services().inNamespace("test").resource(service1).create(); mockClient.services().inNamespace("test").resource(service2).create(); - DiscoveryClient discoveryClient = fabric8DiscoveryClient(KubernetesDiscoveryProperties.DEFAULT, - List.of("test"), mockClient); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(KubernetesDiscoveryProperties.DEFAULT, List.of("test"), + mockClient); List services = discoveryClient.getServices(); @@ -308,7 +308,8 @@ void getServicesShouldReturnServicesInNamespaces() { Set.of(namespace1, namespace2), true, 60, false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); - DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(namespace1, namespace2), mockClient); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(namespace1, namespace2), + mockClient); List services = discoveryClient.getServices(); @@ -402,8 +403,8 @@ void instanceWithoutSubsetsShouldBeSkipped() { mockClient.endpoints().inNamespace("test").resource(endPoint).create(); - DiscoveryClient discoveryClient = fabric8DiscoveryClient(KubernetesDiscoveryProperties.DEFAULT, - List.of("test"), mockClient); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(KubernetesDiscoveryProperties.DEFAULT, List.of("test"), + mockClient); List instances = discoveryClient.getInstances("endpoint1"); @@ -647,7 +648,8 @@ void instanceWithMultiplePortsAndWithoutPrimaryPortNameSpecifiedOrHttpsPortShoul mockClient.services().inNamespace("test").resource(service).create(); - DiscoveryClient discoveryClient =fabric8DiscoveryClient(KubernetesDiscoveryProperties.DEFAULT, List.of("test"), mockClient); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(KubernetesDiscoveryProperties.DEFAULT, List.of("test"), + mockClient); List instances = discoveryClient.getInstances("endpoint5"); diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientServiceWithoutPortNameTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientServiceWithoutPortNameTests.java index abbd32715..6ff5216d6 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientServiceWithoutPortNameTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientServiceWithoutPortNameTests.java @@ -81,8 +81,7 @@ void testDiscoveryWithoutAServicePortName() { true, 60, false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true, false, null); - DiscoveryClient discoveryClient = fabric8DiscoveryClient( - properties, List.of(NAMESPACE), mockClient); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(NAMESPACE), mockClient); List serviceInstances = discoveryClient.getInstances("no-port-name-service"); Assertions.assertThat(serviceInstances.size()).isEqualTo(1); diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientTwoTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientTwoTests.java index f26b1eaaf..0b26d46d6 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientTwoTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientTwoTests.java @@ -113,8 +113,8 @@ void testAllNamespacesSingleEndpointsMatchExactLabels(CapturedOutput output) { Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); List result = discoveryClient.getInstances("blue-service"); @@ -137,15 +137,16 @@ void testAllNamespacesSingleEndpointsMatchPartialLabels(CapturedOutput output) { Endpoints endpoints = endpoints("default", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of()); client.endpoints().inNamespace("default").resource(endpoints).create(); - Service service = service("default", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + Service service = service("default", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of(), + Map.of()); client.services().inNamespace("default").resource(service).create(); boolean allNamespaces = true; Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, - 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); List result = discoveryClient.getInstances("blue-service"); @@ -168,15 +169,16 @@ void testAllNamespacesSingleEndpointsNameMatchesLabelsDont(CapturedOutput output Endpoints endpoints = endpoints("default", "blue-service", Map.of("color", "red", "shape", "round"), Map.of()); client.endpoints().inNamespace("default").resource(endpoints).create(); - Service service = service("default", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + Service service = service("default", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of(), + Map.of()); client.services().inNamespace("default").resource(service).create(); boolean allNamespaces = true; Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, - 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); List result = discoveryClient.getInstances("blue-service"); @@ -196,23 +198,28 @@ void testAllNamespacesSingleEndpointsNameMatchesLabelsDont(CapturedOutput output @Test void testAllNamespacesTwoEndpointsOneMatches(CapturedOutput output) { - Endpoints endpointsOne = endpoints("default", "service-one", Map.of("color", "blue", "shape", "round"), Map.of()); + Endpoints endpointsOne = endpoints("default", "service-one", Map.of("color", "blue", "shape", "round"), + Map.of()); client.endpoints().inNamespace("default").resource(endpointsOne).create(); - Endpoints endpointsTwo = endpoints("default", "service-two", Map.of("color", "blue", "shape", "round"), Map.of()); + Endpoints endpointsTwo = endpoints("default", "service-two", Map.of("color", "blue", "shape", "round"), + Map.of()); client.endpoints().inNamespace("default").resource(endpointsTwo).create(); - Service serviceOne = service("default", "service-one", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + Service serviceOne = service("default", "service-one", Map.of("color", "blue", "shape", "round"), Map.of(), + Map.of()); client.services().inNamespace("default").resource(serviceOne).create(); - Service serviceTwo = service("default", "service-two", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + Service serviceTwo = service("default", "service-two", Map.of("color", "blue", "shape", "round"), Map.of(), + Map.of()); client.services().inNamespace("default").resource(serviceTwo).create(); boolean allNamespaces = true; Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); List result = discoveryClient.getInstances("service-one"); @@ -248,13 +255,13 @@ void testAllNamespacesTwoEndpointsInDifferentNamespaces(CapturedOutput output) { Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); List result = discoveryClient.getInstances("service-one"); Assertions.assertThat(result.size()).isEqualTo(2); - Assertions - .assertThat(result.stream().map(x -> x.getMetadata().get("k8s_namespace")).sorted().toList()) + Assertions.assertThat(result.stream().map(x -> x.getMetadata().get("k8s_namespace")).sorted().toList()) .isEqualTo(List.of("a", "b")); Assertions.assertThat(output.getOut()).contains("discovering endpoints in all namespaces"); } @@ -269,14 +276,16 @@ void testAllNamespacesTwoEndpointsInDifferentNamespaces(CapturedOutput output) { @Test void testClientNamespaceEmpty(CapturedOutput output) { - Service serviceOne = service("test", "serviceId", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + Service serviceOne = service("test", "serviceId", Map.of("color", "blue", "shape", "round"), Map.of(), + Map.of()); client.services().inNamespace("test").resource(serviceOne).create(); boolean allNamespaces = false; Set namespaces = Set.of("test"); Map serviceLabels = Map.of(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); List result = discoveryClient.getInstances("serviceId"); @@ -305,7 +314,8 @@ void testClientNamespaceSingleEndpointsMatchExactLabels(CapturedOutput output) { Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); List result = discoveryClient.getInstances("blue-service"); @@ -327,14 +337,16 @@ void testClientNamespaceSingleEndpointsMatchPartialLabels(CapturedOutput output) Endpoints endpointsOne = endpoints("test", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of()); client.endpoints().inNamespace("test").resource(endpointsOne).create(); - Service serviceOne = service("test", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + Service serviceOne = service("test", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of(), + Map.of()); client.services().inNamespace("test").resource(serviceOne).create(); boolean allNamespaces = false; Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); List result = discoveryClient.getInstances("blue-service"); @@ -363,7 +375,8 @@ void testClientNamespaceSingleEndpointsNameMatchesLabelsDont(CapturedOutput outp Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); List result = discoveryClient.getInstances("blue-service"); @@ -388,17 +401,20 @@ void testClientNamespaceTwoEndpointsOneMatches(CapturedOutput output) { Endpoints endpointsTwo = endpoints("test", "service-two", Map.of("color", "blue", "shape", "round"), Map.of()); client.endpoints().inNamespace("test").resource(endpointsTwo).create(); - Service serviceOne = service("test", "service-one", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + Service serviceOne = service("test", "service-one", Map.of("color", "blue", "shape", "round"), Map.of(), + Map.of()); client.services().inNamespace("test").resource(serviceOne).create(); - Service serviceTwo = service("test", "service-two", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + Service serviceTwo = service("test", "service-two", Map.of("color", "blue", "shape", "round"), Map.of(), + Map.of()); client.services().inNamespace("test").resource(serviceTwo).create(); boolean allNamespaces = false; Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); List result = discoveryClient.getInstances("service-one"); @@ -423,7 +439,8 @@ void testClientNamespaceTwoEndpointsInDifferentNamespaces(CapturedOutput output) Endpoints endpointsTwo = endpoints("b", "service-one", Map.of("color", "blue", "shape", "round"), Map.of()); client.endpoints().inNamespace("b").resource(endpointsTwo).create(); - Service serviceOne = service("test", "service-one", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + Service serviceOne = service("test", "service-one", Map.of("color", "blue", "shape", "round"), Map.of(), + Map.of()); client.services().inNamespace("test").resource(serviceOne).create(); Service serviceTwo = service("b", "service-one", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); @@ -433,13 +450,13 @@ void testClientNamespaceTwoEndpointsInDifferentNamespaces(CapturedOutput output) Set namespaces = Set.of(); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); List result = discoveryClient.getInstances("service-one"); Assertions.assertThat(result.size()).isEqualTo(1); - Assertions - .assertThat(result.stream().map(x -> x.getMetadata().get("k8s_namespace")).sorted().toList()) + Assertions.assertThat(result.stream().map(x -> x.getMetadata().get("k8s_namespace")).sorted().toList()) .isEqualTo(List.of("test")); Assertions.assertThat(output.getOut()).contains("discovering endpoints in namespace : test"); } @@ -490,7 +507,8 @@ void testSelectiveNamespacesSingleEndpointsMatchExactLabels(CapturedOutput outpu Set namespaces = Set.of("test"); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("test"), client); List result = discoveryClient.getInstances("blue-service"); @@ -513,20 +531,24 @@ void testSelectiveNamespacesMultipleNamespacesSingleMatch(CapturedOutput output) Endpoints endpointsOne = endpoints("a", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of()); client.endpoints().inNamespace("a").resource(endpointsOne).create(); - Endpoints endpointsTwo = endpoints("b", "blue-service", Map.of("color", "blue", "shape", "rectangle"), Map.of()); + Endpoints endpointsTwo = endpoints("b", "blue-service", Map.of("color", "blue", "shape", "rectangle"), + Map.of()); client.endpoints().inNamespace("b").resource(endpointsTwo).create(); - Service serviceOne = service("a", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of(), Map.of()); + Service serviceOne = service("a", "blue-service", Map.of("color", "blue", "shape", "round"), Map.of(), + Map.of()); client.services().inNamespace("a").resource(serviceOne).create(); - Service serviceTwo = service("b", "blue-service", Map.of("color", "blue", "shape", "rectangle"), Map.of(), Map.of()); + Service serviceTwo = service("b", "blue-service", Map.of("color", "blue", "shape", "rectangle"), Map.of(), + Map.of()); client.services().inNamespace("b").resource(serviceTwo).create(); boolean allNamespaces = false; Set namespaces = Set.of("a"); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("a"), client); List result = discoveryClient.getInstances("blue-service"); @@ -564,7 +586,8 @@ void testSelectiveNamespacesMultipleNamespacesAllMatch(CapturedOutput output) { Set namespaces = Set.of("a", "b"); Map serviceLabels = Map.of("color", "blue"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, namespaces, - true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + true, 60L, false, "", Set.of(), serviceLabels, "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("a", "b"), client); List result = discoveryClient.getInstances("blue-service"); @@ -606,9 +629,9 @@ void testGetServicesWithExternalNameService() { .build(); client.services().inNamespace("b").resource(externalNameService).create(); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("a", "b"), true, - 60L, false, "", Set.of(), Map.of(), "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, true, - null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("a", "b"), + true, 60L, false, "", Set.of(), Map.of(), "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, + true, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("a", "b"), client); List result = discoveryClient.getInstances("blue-service"); @@ -685,7 +708,6 @@ void testPodMetadata() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of("a", "b"), true, 60L, false, "", Set.of(), Map.of(), "", metadata, 0, false, true, null); - DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("a", "b"), client); List result = discoveryClient.getInstances("blue-service"); diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsFilterTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsFilterTests.java index 4fc526a96..6fc9f899d 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsFilterTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsFilterTests.java @@ -53,7 +53,7 @@ void afterEach() { void emptyInput() { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of("a", "b"), true, - 60L, false, "", Set.of(), Map.of(), "", null, 0, false, true, null); + 60L, false, "", Set.of(), Map.of(), "", null, 0, false, true, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("a", "b"), client); List result = discoveryClient.getInstances("a"); @@ -74,8 +74,8 @@ void endpointsNoMatchInService() { createEndpoints("a", "namespace-a"); createService("a", "namespace-not-a"); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of("namespace-not-a"), - true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, true, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, + Set.of("namespace-not-a"), true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, true, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespace-not-a"), client); List result = discoveryClient.getInstances("a"); @@ -96,8 +96,9 @@ void endpointsMatchInService() { createEndpoints("a", "namespace-a"); createService("a", "namespace-a"); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("namespace-a"), true, - 60L, false, "", Set.of(), Map.of(), "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, true, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("namespace-a"), + true, 60L, false, "", Set.of(), Map.of(), "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, + true, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespace-a"), client); List result = discoveryClient.getInstances("a"); @@ -120,8 +121,9 @@ void endpointsOneMatchInService() { createService("a", "namespace-a"); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("namespace-a"), true, - 60L, false, "", Set.of(), Map.of(), "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, true, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("namespace-a"), + true, 60L, false, "", Set.of(), Map.of(), "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, + true, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespace-a"), client); List result = discoveryClient.getInstances("a"); @@ -150,9 +152,10 @@ void endpointsAndThreeServices() { createService("c", "namespace-c"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, - Set.of("namespace-a", "namespace-b"), true, 60L, false, "", Set.of(), Map.of(), "", - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, true, null); - DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespace-a", "namespace-b"), client); + Set.of("namespace-a", "namespace-b"), true, 60L, false, "", Set.of(), Map.of(), "", + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, true, null); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespace-a", "namespace-b"), + client); List result = discoveryClient.getInstances("a"); Assertions.assertThat(result.size()).isEqualTo(2); @@ -181,9 +184,9 @@ void endpointsMatchesFilterAllNamespaces() { createService("a-1", "namespace-a"); createService("a-1", "namespace-b"); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, - Set.of(), true, 60L, false, "", Set.of(), Map.of(), "", - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, true, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, + false, "", Set.of(), Map.of(), "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, true, + null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); List result = discoveryClient.getInstances("a-1"); diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsTests.java index 5630d0e46..ebc480965 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryClientUtilsTests.java @@ -27,8 +27,6 @@ import io.fabric8.kubernetes.api.model.EndpointSubsetBuilder; import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.api.model.ServiceBuilder; -import io.fabric8.kubernetes.api.model.ServiceSpecBuilder; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; import org.assertj.core.api.Assertions; @@ -37,9 +35,7 @@ import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; -import org.springframework.mock.env.MockEnvironment; import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.endpointSubsetsPortData; @@ -54,6 +50,7 @@ class Fabric8DiscoveryClientUtilsTests extends Fabric8DiscoveryClientBase { @AfterEach void afterEach() { client.services().inAnyNamespace().delete(); + client.endpoints().inAnyNamespace().delete(); } /** @@ -68,7 +65,8 @@ void afterEach() { void testServicesAllNamespacesNoFilters() { boolean allNamespaces = true; KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), - true, 60L, false, "", Set.of(), Map.of(), "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + true, 60L, false, "", Set.of(), Map.of(), "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, + false, null); createService("serviceA", "A", Map.of()); createService("serviceA", "B", Map.of()); @@ -86,360 +84,208 @@ void testServicesAllNamespacesNoFilters() { /** *
-	 *     - all-namespaces = true
+	 *     - all-namespaces = false
+	 *     - selective namespaces : [A, B]
 	 *     - serviceA present in namespace "A"
-	 *     - serviceA present in namespace "B"
-	 *     - we search only for "namespaceA" filter, so only one is returned
+	 *     - serviceB present in namespace "B"
+	 *     - serviceC present in namespace "C"
+	 *     - we search in namespaces [A, B], as such two services are returned
 	 * 
*/ @Test - void testServicesAllNamespacesNameFilter() { - boolean allNamespaces = true; + void testServicesSelectiveNamespacesNoFilters() { + boolean allNamespaces = false; + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, + Set.of("A", "B"), true, 60L, false, "", Set.of(), Map.of(), "", + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + + createService("serviceA", "A", Map.of()); + createService("serviceA", "B", Map.of()); + createService("serviceA", "C", Map.of()); + + createEndpoints("serviceA", "A", Map.of()); + createEndpoints("serviceA", "B", Map.of()); + createEndpoints("serviceA", "C", Map.of()); + + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("A", "B"), client); + List result = discoveryClient.getInstances("serviceA"); + + Assertions.assertThat(result.size()).isEqualTo(2); + Assertions.assertThat(result.stream().map(x -> x.getMetadata().get("k8s_namespace")).sorted().toList()) + .containsExactlyInAnyOrder("A", "B"); + } + + /** + *
+	 *     - all-namespaces = false
+	 *     - selective namespaces : []
+	 *     - namespace from kubernetes namespace provider = [A]
+	 *     - serviceA present in namespace "A"
+	 *     - serviceB present in namespace "B"
+	 *     - serviceC present in namespace "C"
+	 *     - we search in namespaces [A], as such we get one service
+	 * 
+ */ + @Test + void testServicesNamespaceProviderNoFilters() { + boolean allNamespaces = false; KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), - true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); + true, 60L, false, "", Set.of(), Map.of(), "", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, + false, null); createService("serviceA", "A", Map.of()); createService("serviceA", "B", Map.of()); + createService("serviceA", "C", Map.of()); createEndpoints("serviceA", "A", Map.of()); createEndpoints("serviceA", "B", Map.of()); + createEndpoints("serviceA", "C", Map.of()); - DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("A"), client); List result = discoveryClient.getInstances("serviceA"); Assertions.assertThat(result.size()).isEqualTo(1); - Assertions.assertThat(result.get(0).getMetadata().get("k8s_namespace")).isEqualTo("namespaceA"); + Assertions.assertThat(result.get(0).getMetadata().get("k8s_namespace")).isEqualTo("A"); + } + + @Test + void testPortsDataOne() { + List endpointSubsets = List.of( + new EndpointSubsetBuilder().withPorts(new EndpointPortBuilder().withPort(8081).withName("").build()) + .build(), + new EndpointSubsetBuilder() + .withPorts(new EndpointPortBuilder().withPort(8080).withName("https").build()) + .build()); + + Map portsData = endpointSubsetsPortData(endpointSubsets); + Assertions.assertThat(portsData.size()).isEqualTo(2); + Assertions.assertThat(portsData.get("https")).isEqualTo(8080); + Assertions.assertThat(portsData.get("")).isEqualTo(8081); + } + + @Test + void testPortsDataTwo() { + List endpointSubsets = List.of( + new EndpointSubsetBuilder().withPorts(new EndpointPortBuilder().withPort(8081).withName("http").build()) + .build(), + new EndpointSubsetBuilder() + .withPorts(new EndpointPortBuilder().withPort(8080).withName("https").build()) + .build()); + + Map portsData = endpointSubsetsPortData(endpointSubsets); + Assertions.assertThat(portsData.size()).isEqualTo(2); + Assertions.assertThat(portsData.get("https")).isEqualTo(8080); + Assertions.assertThat(portsData.get("http")).isEqualTo(8081); + } + + @Test + void endpointSubsetPortsDataWithoutPorts() { + EndpointSubset endpointSubset = new EndpointSubsetBuilder().build(); + Map result = endpointSubsetsPortData(List.of(endpointSubset)); + + Assertions.assertThat(result).isEmpty(); + } + + @Test + void endpointSubsetPortsDataSinglePort() { + EndpointSubset endpointSubset = new EndpointSubsetBuilder() + .withPorts(new EndpointPortBuilder().withName("name").withPort(80).build()) + .build(); + Map result = endpointSubsetsPortData(List.of(endpointSubset)); + + Assertions.assertThat(result.size()).isEqualTo(1); + Assertions.assertThat(result.get("name")).isEqualTo(80); + } + + @Test + void endpointSubsetPortsDataSinglePortNoName() { + EndpointSubset endpointSubset = new EndpointSubsetBuilder() + .withPorts(new EndpointPortBuilder().withPort(80).build()) + .build(); + Map result = endpointSubsetsPortData(List.of(endpointSubset)); + + Assertions.assertThat(result.size()).isEqualTo(1); + Assertions.assertThat(result.get("")).isEqualTo(80); + } + + /** + *
+	 *      - ready addresses are empty
+	 *      - not ready addresses are not included
+	 * 
+ */ + @Test + void testEmptyAddresses() { + boolean includeNotReadyAddresses = false; + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, + includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); + EndpointSubset endpointSubset = new EndpointSubsetBuilder().build(); + List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); + Assertions.assertThat(addresses).isEmpty(); + } + + /** + *
+	 *      - ready addresses has two entries
+	 *      - not ready addresses are not included
+	 * 
+ */ + @Test + void testReadyAddressesOnly() { + boolean includeNotReadyAddresses = false; + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, + includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); + EndpointSubset endpointSubset = new EndpointSubsetBuilder() + .withAddresses(new EndpointAddressBuilder().withHostname("one").build(), + new EndpointAddressBuilder().withHostname("two").build()) + .build(); + List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); + Assertions.assertThat(addresses.size()).isEqualTo(2); + } + + /** + *
+	 *      - ready addresses has two entries
+	 *      - not ready addresses has a single entry, but we do not take it
+	 * 
+ */ + @Test + void testReadyAddressesTakenNotReadyAddressesNotTaken() { + boolean includeNotReadyAddresses = false; + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, + includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); + EndpointSubset endpointSubset = new EndpointSubsetBuilder() + .withAddresses(new EndpointAddressBuilder().withHostname("one").build(), + new EndpointAddressBuilder().withHostname("two").build()) + .withNotReadyAddresses(new EndpointAddressBuilder().withHostname("three").build()) + .build(); + List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); + Assertions.assertThat(addresses.size()).isEqualTo(2); + List hostNames = addresses.stream().map(EndpointAddress::getHostname).sorted().toList(); + Assertions.assertThat(hostNames).containsExactlyInAnyOrder("one", "two"); + } + + /** + *
+	 *      - ready addresses has two entries
+	 *      - not ready addresses has a single entry, but we do not take it
+	 * 
+ */ + @Test + void testBothAddressesTaken() { + boolean includeNotReadyAddresses = true; + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, + includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); + EndpointSubset endpointSubset = new EndpointSubsetBuilder() + .withAddresses(new EndpointAddressBuilder().withHostname("one").build(), + new EndpointAddressBuilder().withHostname("two").build()) + .withNotReadyAddresses(new EndpointAddressBuilder().withHostname("three").build()) + .build(); + List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); + Assertions.assertThat(addresses.size()).isEqualTo(3); + List hostNames = addresses.stream().map(EndpointAddress::getHostname).sorted().toList(); + Assertions.assertThat(hostNames).containsExactlyInAnyOrder("one", "three", "two"); } -// -// /** -// *
-//	 *     - all-namespaces = true
-//	 *     - serviceA present in namespace "A"
-//	 *     - serviceB present in namespace "B"
-//	 *     - we search with a filter where a label with name "letter" and value "b" is present
-//	 * 
-// */ -// @Test -// void testServicesAllNamespacesPredicateFilter() { -// boolean allNamespaces = true; -// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), -// true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); -// service("serviceA", "A", Map.of("letter", "a")); -// service("serviceB", "B", Map.of("letter", "b")); -// -// List result = services(properties, client, null, -// x -> x.getMetadata().getLabels().equals(Map.of("letter", "b")), null, "fabric8-discovery"); -// Assertions.assertThat(result.size()).isEqualTo(1); -// Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceB"); -// } -// -// /** -// *
-//	 *     - all-namespaces = false
-//	 *     - selective namespaces : [A, B]
-//	 *     - serviceA present in namespace "A"
-//	 *     - serviceB present in namespace "B"
-//	 *     - serviceC present in namespace "C"
-//	 *     - we search in namespaces [A, B], as such two services are returned
-//	 * 
-// */ -// @Test -// void testServicesSelectiveNamespacesNoFilters() { -// boolean allNamespaces = false; -// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, -// Set.of("A", "B"), true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); -// service("serviceA", "A", Map.of()); -// service("serviceB", "B", Map.of()); -// service("serviceC", "C", Map.of()); -// -// List result = services(properties, client, null, x -> true, null, "fabric8-discovery"); -// Assertions.assertThat(result.size()).isEqualTo(2); -// Assertions.assertThat(result.stream().map(x -> x.getMetadata().getName()).sorted().toList()) -// .containsExactlyInAnyOrder("serviceA", "serviceB"); -// } -// -// /** -// *
-//	 *     - all-namespaces = false
-//	 *     - selective namespaces : [A, B]
-//	 *     - serviceA present in namespace "A"
-//	 *     - serviceB present in namespace "B"
-//	 *     - serviceC present in namespace "C"
-//	 *     - we search in namespaces [A, B] with name filter = "serviceA", so we get a single result
-//	 * 
-// */ -// @Test -// void testServicesSelectiveNamespacesNameFilter() { -// boolean allNamespaces = false; -// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, -// Set.of("A", "B"), true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); -// service("serviceA", "A", Map.of()); -// service("serviceB", "B", Map.of()); -// service("serviceC", "C", Map.of()); -// -// List result = services(properties, client, null, x -> true, Map.of("metadata.name", "serviceA"), -// "fabric8-discovery"); -// Assertions.assertThat(result.size()).isEqualTo(1); -// Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); -// } -// -// /** -// *
-//	 *     - all-namespaces = false
-//	 *     - selective namespaces : [A, B]
-//	 *     - serviceA present in namespace "A" with labels [letter, a]
-//	 *     - serviceB present in namespace "B" with labels [letter, b]
-//	 *     - serviceC present in namespace "C" with labels [letter, c]
-//	 *     - we search in namespaces [A, B] with predicate filter = [letter, b], so we get a single result
-//	 * 
-// */ -// @Test -// void testServicesSelectiveNamespacesPredicateFilter() { -// boolean allNamespaces = false; -// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, -// Set.of("A", "B"), true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); -// service("serviceA", "A", Map.of("letter", "a")); -// service("serviceB", "B", Map.of("letter", "b")); -// service("serviceC", "C", Map.of("letter", "c")); -// -// List result = services(properties, client, null, -// x -> x.getMetadata().getLabels().equals(Map.of("letter", "b")), null, "fabric8-discovery"); -// Assertions.assertThat(result.size()).isEqualTo(1); -// Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceB"); -// } -// -// /** -// *
-//	 *     - all-namespaces = false
-//	 *     - selective namespaces : []
-//	 *     - namespace from kubernetes namespace provider = [A]
-//	 *     - serviceA present in namespace "A"
-//	 *     - serviceB present in namespace "B"
-//	 *     - serviceC present in namespace "C"
-//	 *     - we search in namespaces [A], as such we get one service
-//	 * 
-// */ -// @Test -// void testServicesNamespaceProviderNoFilters() { -// boolean allNamespaces = false; -// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), -// true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); -// service("serviceA", "A", Map.of()); -// service("serviceB", "B", Map.of()); -// service("serviceC", "C", Map.of()); -// -// List result = services(properties, client, namespaceProvider("A"), x -> true, null, -// "fabric8-discovery"); -// Assertions.assertThat(result.size()).isEqualTo(1); -// Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); -// } -// -// /** -// *
-//	 *     - all-namespaces = false
-//	 *     - selective namespaces : []
-//	 *     - namespace from kubernetes namespace provider = [A]
-//	 *     - serviceA present in namespace "A"
-//	 *     - serviceB present in namespace "A"
-//	 *     - we search in namespaces [A] with name filter = "serviceA", so we get a single result
-//	 * 
-// */ -// @Test -// void testServicesNamespaceProviderNameFilter() { -// boolean allNamespaces = false; -// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), -// true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); -// service("serviceA", "A", Map.of()); -// service("serviceB", "A", Map.of()); -// -// List result = services(properties, client, namespaceProvider("A"), x -> true, -// Map.of("metadata.name", "serviceA"), "fabric8-discovery"); -// Assertions.assertThat(result.size()).isEqualTo(1); -// Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceA"); -// } -// -// /** -// *
-//	 *     - all-namespaces = false
-//	 *     - selective namespaces : []
-//	 *     - namespace from kubernetes namespace provider = [A]
-//	 *     - serviceA present in namespace "A"
-//	 *     - serviceB present in namespace "A"
-//	 *     - we search in namespaces [A] with predicate filter = [letter, b], so we get a single result
-//	 * 
-// */ -// @Test -// void testServicesNamespaceProviderPredicateFilter() { -// boolean allNamespaces = false; -// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), -// true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); -// service("serviceA", "A", Map.of("letter", "a")); -// service("serviceB", "A", Map.of("letter", "b")); -// -// List result = services(properties, client, namespaceProvider("A"), -// x -> x.getMetadata().getLabels().equals(Map.of("letter", "b")), null, "fabric8-discovery"); -// Assertions.assertThat(result.size()).isEqualTo(1); -// Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("serviceB"); -// } -// -// @Test -// void testExternalName() { -// Service service = new ServiceBuilder() -// .withSpec(new ServiceSpecBuilder().withType("ExternalName").withExternalName("k8s-spring").build()) -// .withNewMetadata() -// .withName("external-name-service") -// .and() -// .build(); -// client.services().inNamespace("test").resource(service).create(); -// -// boolean allNamespaces = false; -// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, allNamespaces, Set.of(), -// true, 60L, false, "", Set.of(), Map.of(), "", null, 0, false, false, null); -// -// List result = services(properties, client, namespaceProvider("test"), -// x -> x.getSpec().getType().equals("ExternalName"), Map.of(), "fabric8-discovery"); -// Assertions.assertThat(result.size()).isEqualTo(1); -// Assertions.assertThat(result.get(0).getMetadata().getName()).isEqualTo("external-name-service"); -// } -// -// @Test -// void testPortsDataOne() { -// List endpointSubsets = List.of( -// new EndpointSubsetBuilder().withPorts(new EndpointPortBuilder().withPort(8081).withName("").build()) -// .build(), -// new EndpointSubsetBuilder() -// .withPorts(new EndpointPortBuilder().withPort(8080).withName("https").build()) -// .build()); -// -// Map portsData = endpointSubsetsPortData(endpointSubsets); -// Assertions.assertThat(portsData.size()).isEqualTo(2); -// Assertions.assertThat(portsData.get("https")).isEqualTo(8080); -// Assertions.assertThat(portsData.get("")).isEqualTo(8081); -// } -// -// @Test -// void testPortsDataTwo() { -// List endpointSubsets = List.of( -// new EndpointSubsetBuilder().withPorts(new EndpointPortBuilder().withPort(8081).withName("http").build()) -// .build(), -// new EndpointSubsetBuilder() -// .withPorts(new EndpointPortBuilder().withPort(8080).withName("https").build()) -// .build()); -// -// Map portsData = endpointSubsetsPortData(endpointSubsets); -// Assertions.assertThat(portsData.size()).isEqualTo(2); -// Assertions.assertThat(portsData.get("https")).isEqualTo(8080); -// Assertions.assertThat(portsData.get("http")).isEqualTo(8081); -// } -// -// @Test -// void endpointSubsetPortsDataWithoutPorts() { -// EndpointSubset endpointSubset = new EndpointSubsetBuilder().build(); -// Map result = endpointSubsetsPortData(List.of(endpointSubset)); -// -// Assertions.assertThat(result).isEmpty(); -// } -// -// @Test -// void endpointSubsetPortsDataSinglePort() { -// EndpointSubset endpointSubset = new EndpointSubsetBuilder() -// .withPorts(new EndpointPortBuilder().withName("name").withPort(80).build()) -// .build(); -// Map result = endpointSubsetsPortData(List.of(endpointSubset)); -// -// Assertions.assertThat(result.size()).isEqualTo(1); -// Assertions.assertThat(result.get("name")).isEqualTo(80); -// } -// -// @Test -// void endpointSubsetPortsDataSinglePortNoName() { -// EndpointSubset endpointSubset = new EndpointSubsetBuilder() -// .withPorts(new EndpointPortBuilder().withPort(80).build()) -// .build(); -// Map result = endpointSubsetsPortData(List.of(endpointSubset)); -// -// Assertions.assertThat(result.size()).isEqualTo(1); -// Assertions.assertThat(result.get("")).isEqualTo(80); -// } -// -// /** -// *
-//	 *      - ready addresses are empty
-//	 *      - not ready addresses are not included
-//	 * 
-// */ -// @Test -// void testEmptyAddresses() { -// boolean includeNotReadyAddresses = false; -// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, -// includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); -// EndpointSubset endpointSubset = new EndpointSubsetBuilder().build(); -// List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); -// Assertions.assertThat(addresses).isEmpty(); -// } -// -// /** -// *
-//	 *      - ready addresses has two entries
-//	 *      - not ready addresses are not included
-//	 * 
-// */ -// @Test -// void testReadyAddressesOnly() { -// boolean includeNotReadyAddresses = false; -// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, -// includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); -// EndpointSubset endpointSubset = new EndpointSubsetBuilder() -// .withAddresses(new EndpointAddressBuilder().withHostname("one").build(), -// new EndpointAddressBuilder().withHostname("two").build()) -// .build(); -// List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); -// Assertions.assertThat(addresses.size()).isEqualTo(2); -// } -// -// /** -// *
-//	 *      - ready addresses has two entries
-//	 *      - not ready addresses has a single entry, but we do not take it
-//	 * 
-// */ -// @Test -// void testReadyAddressesTakenNotReadyAddressesNotTaken() { -// boolean includeNotReadyAddresses = false; -// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, -// includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); -// EndpointSubset endpointSubset = new EndpointSubsetBuilder() -// .withAddresses(new EndpointAddressBuilder().withHostname("one").build(), -// new EndpointAddressBuilder().withHostname("two").build()) -// .withNotReadyAddresses(new EndpointAddressBuilder().withHostname("three").build()) -// .build(); -// List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); -// Assertions.assertThat(addresses.size()).isEqualTo(2); -// List hostNames = addresses.stream().map(EndpointAddress::getHostname).sorted().toList(); -// Assertions.assertThat(hostNames).containsExactlyInAnyOrder("one", "two"); -// } -// -// /** -// *
-//	 *      - ready addresses has two entries
-//	 *      - not ready addresses has a single entry, but we do not take it
-//	 * 
-// */ -// @Test -// void testBothAddressesTaken() { -// boolean includeNotReadyAddresses = true; -// KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, -// includeNotReadyAddresses, "", Set.of(), Map.of(), "", null, 0, false, false, null); -// EndpointSubset endpointSubset = new EndpointSubsetBuilder() -// .withAddresses(new EndpointAddressBuilder().withHostname("one").build(), -// new EndpointAddressBuilder().withHostname("two").build()) -// .withNotReadyAddresses(new EndpointAddressBuilder().withHostname("three").build()) -// .build(); -// List addresses = Fabric8DiscoveryClientUtils.addresses(endpointSubset, properties); -// Assertions.assertThat(addresses.size()).isEqualTo(3); -// List hostNames = addresses.stream().map(EndpointAddress::getHostname).sorted().toList(); -// Assertions.assertThat(hostNames).containsExactlyInAnyOrder("one", "three", "two"); -// } private void createEndpoints(String name, String namespace, Map labels) { Endpoints endpoints = endpoints(namespace, name, labels, Map.of()); diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryFilterTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryFilterTests.java index 72672b47b..b0a1ce141 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryFilterTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8DiscoveryFilterTests.java @@ -34,7 +34,6 @@ import org.springframework.core.env.Environment; import org.springframework.mock.env.MockEnvironment; - /** * @author wind57 */ @@ -68,8 +67,8 @@ void testAllNamespacesWithoutLabelsWithoutFilter() { Map labels = Map.of(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), - true, 60L, false, null, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, - 0, false, false, null); + true, 60L, false, null, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); service("namespaceA", "serviceA", Map.of("color", "red")); service("namespaceB", "serviceA", Map.of("color", "blue")); @@ -103,8 +102,8 @@ void testAllNamespacesWithLabelsWithoutFilter() { Map labels = Map.of("color", "red"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), - true, 60L, false, null, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, - 0, false, false, null); + true, 60L, false, null, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); service("namespaceA", "serviceA", Map.of("color", "red")); service("namespaceB", "serviceA", Map.of("color", "blue")); @@ -147,8 +146,8 @@ void testAllNamespacesWithoutLabelsWithNamespaceFilter() { endpoints("namespaceB", "serviceA", Map.of("color", "blue")); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), - true, 60L, false, spelFilter, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, - 0, false, false, null); + true, 60L, false, spelFilter, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of(""), client); List result = discoveryClient.getInstances("serviceA"); @@ -180,8 +179,8 @@ void testAllNamespacesWithoutLabelsWithNamespacesFilter() { """; KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), - true, 60L, false, spelFilter, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, - 0, false, false, null); + true, 60L, false, spelFilter, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); service("namespaceA", "serviceA", Map.of("color", "red")); service("namespaceB", "serviceA", Map.of("color", "blue")); @@ -217,7 +216,8 @@ void testSpecificNamespaceWithoutLabelsWithoutFilter() { Map labels = Map.of(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), - true, 60L, false, null, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + true, 60L, false, null, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); service("namespaceA", "serviceA", Map.of("color", "red")); service("namespaceB", "serviceB", Map.of("color", "blue")); @@ -252,8 +252,8 @@ void testSpecificNamespaceWithLabelsWithoutFilter() { Map labels = Map.of("color", "purple"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), - true, 60L, false, null, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, - 0, false, false, null); + true, 60L, false, null, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); service("namespaceA", "serviceA", Map.of("color", "red")); service("namespaceB", "serviceA", Map.of("color", "purple")); @@ -263,7 +263,8 @@ void testSpecificNamespaceWithLabelsWithoutFilter() { endpoints("namespaceB", "serviceA", Map.of("color", "purple")); endpoints("namespaceC", "serviceA", Map.of("color", "purple")); - DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA", "namespaceB"), client); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA", "namespaceB"), + client); List result = discoveryClient.getInstances("serviceA"); Assertions.assertThat(result.size()).isEqualTo(1); @@ -295,8 +296,8 @@ void testSpecificNamespaceWithoutLabelsWithFilter() { """.stripLeading(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, Set.of(), - true, 60L, false, spelFilter, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, - 0, false, false, null); + true, 60L, false, spelFilter, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + false, false, null); service("namespaceA", "serviceA", Map.of("color", "red", "number", "1")); service("namespaceB", "serviceA", Map.of("color", "purple", "cycle", "create")); @@ -306,7 +307,8 @@ void testSpecificNamespaceWithoutLabelsWithFilter() { endpoints("namespaceB", "serviceA", Map.of("color", "purple")); endpoints("namespaceC", "serviceA", Map.of("color", "purple")); - DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA", "namespaceB"), client); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA", "namespaceB"), + client); List result = discoveryClient.getInstances("serviceA"); Assertions.assertThat(result.size()).isEqualTo(1); @@ -334,8 +336,8 @@ void testSomeNamespacesWithoutLabelsWithoutFilter() { Map labels = Map.of(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, - someNamespaces, true, 60L, false, null, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, - 0, false, false, null); + someNamespaces, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); service("namespaceA", "serviceA", Map.of()); service("namespaceB", "serviceA", Map.of()); @@ -345,7 +347,8 @@ void testSomeNamespacesWithoutLabelsWithoutFilter() { endpoints("namespaceB", "serviceA", Map.of()); endpoints("namespaceC", "serviceA", Map.of()); - DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA", "namespaceB"), client); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA", "namespaceB"), + client); List result = discoveryClient.getInstances("serviceA"); Assertions.assertThat(result.size()).isEqualTo(2); @@ -375,8 +378,8 @@ void testSomeNamespacesWithLabelsWithoutFilter() { String spelFilter = null; KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, - someNamespaces, true, 60L, false, spelFilter, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + someNamespaces, true, 60L, false, spelFilter, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); service("namespaceA", "serviceA", Map.of("color", "purple")); service("namespaceB", "serviceA", Map.of("color", "red")); @@ -386,7 +389,8 @@ void testSomeNamespacesWithLabelsWithoutFilter() { endpoints("namespaceB", "serviceA", Map.of("color", "red")); endpoints("namespaceC", "serviceA", Map.of("color", "purple")); - DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA", "namespaceB"), client); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA", "namespaceB"), + client); List result = discoveryClient.getInstances("serviceA"); Assertions.assertThat(result.size()).isEqualTo(1); @@ -417,8 +421,8 @@ void testSomeNamespacesWithLabelsWithFilter() { """.stripLeading(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, allNamespaces, - someNamespaces, true, 60L, false, spelFilter, Set.of(), labels, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, - 0, false, false, null); + someNamespaces, true, 60L, false, spelFilter, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); service("namespaceA", "serviceA", Map.of("color", "purple", "number", "1")); service("namespaceB", "serviceA", Map.of("color", "purple", "cycle", "create")); @@ -428,7 +432,8 @@ void testSomeNamespacesWithLabelsWithFilter() { endpoints("namespaceB", "serviceA", Map.of("color", "purple", "cycle", "create")); endpoints("namespaceC", "serviceA", Map.of("color", "purple", "number", "1")); - DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA", "namespaceB"), client); + DiscoveryClient discoveryClient = fabric8DiscoveryClient(properties, List.of("namespaceA", "namespaceB"), + client); List result = discoveryClient.getInstances("serviceA"); Assertions.assertThat(result.size()).isEqualTo(1); @@ -437,18 +442,12 @@ void testSomeNamespacesWithLabelsWithFilter() { private void service(String namespace, String name, Map labels) { Service service = service(namespace, name, labels, Map.of(), Map.of()); - client.services() - .inNamespace(namespace) - .resource(service) - .create(); + client.services().inNamespace(namespace).resource(service).create(); } private void endpoints(String namespace, String name, Map labels) { Endpoints endpoints = endpoints(namespace, name, labels, Map.of()); - client.endpoints() - .inNamespace(namespace) - .resource(endpoints) - .create(); + client.endpoints().inNamespace(namespace).resource(endpoints).create(); } private static Environment mockEnvironment() { From 3d7cda55cbec5366ad33cf16770b809baae5519e Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 4 Feb 2026 23:50:16 +0200 Subject: [PATCH 11/19] revert test Signed-off-by: wind57 --- .../Fabric8ReactiveDiscoveryClientTests.java | 198 ++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientTests.java diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientTests.java new file mode 100644 index 000000000..5bb250b7f --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientTests.java @@ -0,0 +1,198 @@ +/* + * Copyright 2019-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.kubernetes.fabric8.discovery; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import io.fabric8.kubernetes.api.model.Endpoints; +import io.fabric8.kubernetes.api.model.EndpointsBuilder; +import io.fabric8.kubernetes.api.model.Service; +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import reactor.core.publisher.Flux; +import reactor.test.StepVerifier; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; +import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties.Metadata; + +/** + * @author Tim Ysewyn + */ +@EnableKubernetesMockClient(crud = true, https = false) +class Fabric8ReactiveDiscoveryClientTests extends Fabric8DiscoveryClientBase { + + private static KubernetesClient kubernetesClient; + + @BeforeEach + void beforeEach() { + // Configure the kubernetes master url to point to the mock server + System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, + kubernetesClient.getConfiguration().getMasterUrl()); + System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true"); + System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); + } + + @AfterEach + void afterEach() { + kubernetesClient.services().inAnyNamespace().delete(); + kubernetesClient.endpoints().inAnyNamespace().delete(); + } + + @Test + void verifyDefaults() { + + Metadata metadata = new Metadata(false, null, false, null, false, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, + false, null, Set.of(), Map.of("label1", "one"), null, metadata, 0, true, false, null); + + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of(), kubernetesClient); + ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); + assertThat(client.description()).isEqualTo("Fabric8 Reactive Discovery Client"); + assertThat(client.getOrder()).isEqualTo(ReactiveDiscoveryClient.DEFAULT_ORDER); + } + + @Test + void shouldReturnFluxOfServices() { + + Metadata metadata = new Metadata(false, null, false, null, false, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, 60, + false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); + + Service s1 = service("test", "s1", Map.of(), Map.of(), Map.of()); + kubernetesClient.services().inNamespace("test").resource(s1).create(); + + Service s2 = service("test", "s2", Map.of(), Map.of(), Map.of()); + kubernetesClient.services().inNamespace("test").resource(s2).create(); + + Service s3 = service("test", "s3", Map.of(), Map.of(), Map.of()); + kubernetesClient.services().inNamespace("test").resource(s3).create(); + + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of("test"), kubernetesClient); + ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); + + Flux services = client.getServices(); + StepVerifier.create(services) + .recordWith(ArrayList::new) + .expectNextCount(3) + .consumeRecordedWith(list -> + assertThat(list).containsExactlyInAnyOrder("s1", "s2", "s3")) + .expectComplete() + .verify(); + } + + @Test + void shouldReturnEmptyFluxOfServicesWhenNoInstancesFound() { + + Metadata metadata = new Metadata(false, null, false, null, false, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, 60, + false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); + + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of("test"), kubernetesClient); + ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); + + Flux services = client.getServices(); + StepVerifier.create(services).expectNextCount(0).expectComplete().verify(); + } + + @Test + void shouldReturnEmptyFluxForNonExistingService() { + + Metadata metadata = new Metadata(false, null, false, null, false, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, 60, + false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); + + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of("test"), kubernetesClient); + ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); + + Flux instances = client.getInstances("nonexistent-service"); + StepVerifier.create(instances).expectNextCount(0).expectComplete().verify(); + } + + @Test + void shouldReturnEmptyFluxWhenServiceHasNoSubsets() { + + Metadata metadata = new Metadata(false, null, false, null, false, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, 60, + false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); + + Service s1 = service("test", "s1", Map.of(), Map.of(), Map.of()); + kubernetesClient.services().inNamespace("test").resource(s1).create(); + + Endpoints e1 = new EndpointsBuilder().withNewMetadata().withName("s1").endMetadata().build(); + kubernetesClient.endpoints().inNamespace("test").resource(e1).create(); + + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of("test"), kubernetesClient); + ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); + + Flux instances = client.getInstances("s1"); + StepVerifier.create(instances).expectNextCount(0).expectComplete().verify(); + } + + @Test + void shouldReturnFlux() { + + Metadata metadata = new Metadata(false, null, false, null, false, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, 60, + false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); + + Service s1 = service("test", "s1", Map.of(), Map.of(), Map.of()); + kubernetesClient.services().inNamespace("test").resource(s1).create(); + + Endpoints e1 = endpoints("test", "s1", Map.of(), Map.of()); + kubernetesClient.endpoints().inNamespace("test").resource(e1).create(); + + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of("test"), kubernetesClient); + ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); + + Flux instances = client.getInstances("s1"); + StepVerifier.create(instances).expectNextCount(1).expectComplete().verify(); + } + + @Test + void shouldReturnFluxOfServicesAcrossAllNamespaces() { + + Metadata metadata = new Metadata(false, null, false, null, false, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, 60, + false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); + + Service s1 = service("test", "s1", Map.of(), Map.of(), Map.of()); + kubernetesClient.services().inNamespace("test").resource(s1).create(); + + Endpoints e1 = endpoints("test", "s1", Map.of(), Map.of()); + kubernetesClient.endpoints().inNamespace("test").resource(e1).create(); + + Fabric8DiscoveryClient fabric8KubernetesDiscoveryClient = fabric8DiscoveryClient(properties, List.of(""), kubernetesClient); + + ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8KubernetesDiscoveryClient); + Flux instances = client.getInstances("s1"); + StepVerifier.create(instances).expectNextCount(1).expectComplete().verify(); + } + +} From 1a844738ed3cec901f771d5740dafc2b52362156 Mon Sep 17 00:00:00 2001 From: wind57 Date: Thu, 5 Feb 2026 10:20:22 +0200 Subject: [PATCH 12/19] wip Signed-off-by: wind57 --- ...veryClientServiceLabelsFilteringTests.java | 30 ++---------- .../Fabric8ReactiveDiscoveryClientTests.java | 49 ++++++++++--------- 2 files changed, 32 insertions(+), 47 deletions(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java index 881bcca1c..674d5c149 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java @@ -16,8 +16,11 @@ package org.springframework.cloud.kubernetes.client.discovery; -<<<<<<< Updated upstream -======= +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + import com.github.tomakehurst.wiremock.client.WireMock; import com.github.tomakehurst.wiremock.junit5.WireMockExtension; import io.kubernetes.client.informer.SharedIndexInformer; @@ -43,28 +46,15 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; - ->>>>>>> Stashed changes -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -<<<<<<< Updated upstream -import org.junit.jupiter.api.Test; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; -======= import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; ->>>>>>> Stashed changes import static org.assertj.core.api.Assertions.assertThat; /** @@ -73,8 +63,6 @@ class KubernetesClientDiscoveryClientServiceLabelsFilteringTests extends KubernetesClientDiscoveryClientServiceLabelsFiltering { -<<<<<<< Updated upstream -======= private static final String NAMESPACE_A = "namespaceA"; private static final String NAMESPACE_B = "namespaceB"; @@ -118,7 +106,6 @@ void afterEach() { /** * //TODO */ ->>>>>>> Stashed changes @Test void namespaceARedLabels() { @@ -126,7 +113,6 @@ void namespaceARedLabels() { List namespaces = List.of("namespaceA"); Set namespacesAsSet = Set.of("namespaceA"); boolean discoveryInAllNamespaces = false; -<<<<<<< Updated upstream KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, @@ -473,7 +459,6 @@ void allNamespacesNoLabels() { assertThat(serviceInstancesXX.stream().map(x -> x.getMetadata().get("namespace")).toList()) .containsExactlyInAnyOrder("a", "b"); -======= Set selectiveNamespaces = Set.of(NAMESPACE_A, NAMESPACE_B); List selectiveNamespacesAsList = List.of(NAMESPACE_A, NAMESPACE_B); @@ -504,10 +489,6 @@ void allNamespacesNoLabels() { startInformers(sharedInformerFactories, serviceSharedIndexInformers, endpointsSharedIndexInformers); - KubernetesClientInformerDiscoveryClient discoveryClient = new KubernetesClientInformerDiscoveryClient( - sharedInformerFactories, serviceListers, endpointsListers, null, null, - properties, coreV1Api, x -> true); - List serviceInstances = discoveryClient.getInstances(SERVICE_NAME); assertThat(serviceInstances.size()).isEqualTo(1); assertThat(serviceInstances.get(0).getMetadata().get("k8s_namespace")).isEqualTo("namespaceA"); @@ -570,7 +551,6 @@ private static void mockServicesCall(String namespace, String labelSelector, .withQueryParam("watch", equalTo("true")) .withQueryParam("labelSelector", equalTo(labelSelector)) .willReturn(aResponse().withStatus(200).withBody(""))); ->>>>>>> Stashed changes } private String labelSelector(Map labels) { diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientTests.java index 5bb250b7f..1338e5d14 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ReactiveDiscoveryClientTests.java @@ -52,7 +52,7 @@ class Fabric8ReactiveDiscoveryClientTests extends Fabric8DiscoveryClientBase { void beforeEach() { // Configure the kubernetes master url to point to the mock server System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, - kubernetesClient.getConfiguration().getMasterUrl()); + kubernetesClient.getConfiguration().getMasterUrl()); System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true"); System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); @@ -70,7 +70,7 @@ void verifyDefaults() { Metadata metadata = new Metadata(false, null, false, null, false, null); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, - false, null, Set.of(), Map.of("label1", "one"), null, metadata, 0, true, false, null); + false, null, Set.of(), Map.of("label1", "one"), null, metadata, 0, true, false, null); Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of(), kubernetesClient); ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); @@ -82,8 +82,8 @@ void verifyDefaults() { void shouldReturnFluxOfServices() { Metadata metadata = new Metadata(false, null, false, null, false, null); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, 60, - false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, + 60, false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); Service s1 = service("test", "s1", Map.of(), Map.of(), Map.of()); kubernetesClient.services().inNamespace("test").resource(s1).create(); @@ -94,15 +94,15 @@ void shouldReturnFluxOfServices() { Service s3 = service("test", "s3", Map.of(), Map.of(), Map.of()); kubernetesClient.services().inNamespace("test").resource(s3).create(); - Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of("test"), kubernetesClient); + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of("test"), + kubernetesClient); ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); Flux services = client.getServices(); StepVerifier.create(services) .recordWith(ArrayList::new) .expectNextCount(3) - .consumeRecordedWith(list -> - assertThat(list).containsExactlyInAnyOrder("s1", "s2", "s3")) + .consumeRecordedWith(list -> assertThat(list).containsExactlyInAnyOrder("s1", "s2", "s3")) .expectComplete() .verify(); } @@ -111,10 +111,11 @@ void shouldReturnFluxOfServices() { void shouldReturnEmptyFluxOfServicesWhenNoInstancesFound() { Metadata metadata = new Metadata(false, null, false, null, false, null); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, 60, - false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, + 60, false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); - Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of("test"), kubernetesClient); + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of("test"), + kubernetesClient); ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); Flux services = client.getServices(); @@ -125,10 +126,11 @@ void shouldReturnEmptyFluxOfServicesWhenNoInstancesFound() { void shouldReturnEmptyFluxForNonExistingService() { Metadata metadata = new Metadata(false, null, false, null, false, null); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, 60, - false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, + 60, false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); - Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of("test"), kubernetesClient); + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of("test"), + kubernetesClient); ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); Flux instances = client.getInstances("nonexistent-service"); @@ -139,8 +141,8 @@ void shouldReturnEmptyFluxForNonExistingService() { void shouldReturnEmptyFluxWhenServiceHasNoSubsets() { Metadata metadata = new Metadata(false, null, false, null, false, null); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, 60, - false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, + 60, false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); Service s1 = service("test", "s1", Map.of(), Map.of(), Map.of()); kubernetesClient.services().inNamespace("test").resource(s1).create(); @@ -148,7 +150,8 @@ void shouldReturnEmptyFluxWhenServiceHasNoSubsets() { Endpoints e1 = new EndpointsBuilder().withNewMetadata().withName("s1").endMetadata().build(); kubernetesClient.endpoints().inNamespace("test").resource(e1).create(); - Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of("test"), kubernetesClient); + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of("test"), + kubernetesClient); ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); Flux instances = client.getInstances("s1"); @@ -159,8 +162,8 @@ void shouldReturnEmptyFluxWhenServiceHasNoSubsets() { void shouldReturnFlux() { Metadata metadata = new Metadata(false, null, false, null, false, null); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, 60, - false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, + 60, false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); Service s1 = service("test", "s1", Map.of(), Map.of(), Map.of()); kubernetesClient.services().inNamespace("test").resource(s1).create(); @@ -168,7 +171,8 @@ void shouldReturnFlux() { Endpoints e1 = endpoints("test", "s1", Map.of(), Map.of()); kubernetesClient.endpoints().inNamespace("test").resource(e1).create(); - Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of("test"), kubernetesClient); + Fabric8DiscoveryClient fabric8DiscoveryClient = fabric8DiscoveryClient(properties, List.of("test"), + kubernetesClient); ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8DiscoveryClient); Flux instances = client.getInstances("s1"); @@ -179,8 +183,8 @@ void shouldReturnFlux() { void shouldReturnFluxOfServicesAcrossAllNamespaces() { Metadata metadata = new Metadata(false, null, false, null, false, null); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, 60, - false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("test"), true, + 60, false, null, Set.of(), Map.of(), null, metadata, 0, true, false, null); Service s1 = service("test", "s1", Map.of(), Map.of(), Map.of()); kubernetesClient.services().inNamespace("test").resource(s1).create(); @@ -188,7 +192,8 @@ void shouldReturnFluxOfServicesAcrossAllNamespaces() { Endpoints e1 = endpoints("test", "s1", Map.of(), Map.of()); kubernetesClient.endpoints().inNamespace("test").resource(e1).create(); - Fabric8DiscoveryClient fabric8KubernetesDiscoveryClient = fabric8DiscoveryClient(properties, List.of(""), kubernetesClient); + Fabric8DiscoveryClient fabric8KubernetesDiscoveryClient = fabric8DiscoveryClient(properties, List.of(""), + kubernetesClient); ReactiveDiscoveryClient client = new Fabric8ReactiveDiscoveryClient(fabric8KubernetesDiscoveryClient); Flux instances = client.getInstances("s1"); From a1daeeedc27aaeaf9f124847345a347fab112b3c Mon Sep 17 00:00:00 2001 From: wind57 Date: Thu, 5 Feb 2026 10:21:06 +0200 Subject: [PATCH 13/19] fix Signed-off-by: wind57 --- ...veryClientServiceLabelsFilteringTests.java | 274 +++--------------- 1 file changed, 44 insertions(+), 230 deletions(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java index 674d5c149..21c6e2b6a 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java @@ -19,93 +19,20 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; - -import com.github.tomakehurst.wiremock.client.WireMock; -import com.github.tomakehurst.wiremock.junit5.WireMockExtension; -import io.kubernetes.client.informer.SharedIndexInformer; -import io.kubernetes.client.informer.SharedInformerFactory; -import io.kubernetes.client.informer.cache.Lister; -import io.kubernetes.client.openapi.ApiClient; -import io.kubernetes.client.openapi.JSON; -import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.models.CoreV1EndpointPort; -import io.kubernetes.client.openapi.models.V1EndpointAddress; -import io.kubernetes.client.openapi.models.V1EndpointSubset; -import io.kubernetes.client.openapi.models.V1Endpoints; -import io.kubernetes.client.openapi.models.V1EndpointsList; -import io.kubernetes.client.openapi.models.V1ListMeta; -import io.kubernetes.client.openapi.models.V1ObjectMeta; -import io.kubernetes.client.openapi.models.V1Service; -import io.kubernetes.client.openapi.models.V1ServiceList; -import io.kubernetes.client.openapi.models.V1ServiceSpec; -import io.kubernetes.client.util.ClientBuilder; -import org.awaitility.Awaitility; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; + import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; import static org.assertj.core.api.Assertions.assertThat; /** * @author wind57 */ class KubernetesClientDiscoveryClientServiceLabelsFilteringTests - extends KubernetesClientDiscoveryClientServiceLabelsFiltering { - - private static final String NAMESPACE_A = "namespaceA"; - - private static final String NAMESPACE_B = "namespaceB"; - - private static final String SERVICE_NAME = "serviceX"; - - private static final String ENDPOINTS_NAME = "endpointsX"; - - private static final Map SHAPE_CIRCLE = Map.of("shape", "circle"); - - private static final Map SHAPE_TRIANGLE = Map.of("shape", "triangle"); + extends KubernetesClientDiscoveryClientServiceLabelsFiltering { - private static final KubernetesClientInformerAutoConfiguration CONFIGURATION = new KubernetesClientInformerAutoConfiguration(); - - private static ApiClient apiClient; - - private static CoreV1Api coreV1Api; - - @RegisterExtension - private static final WireMockExtension API_SERVER = WireMockExtension.newInstance() - .options(options().dynamicPort()) - .build(); - - @BeforeAll - static void beforeAll() { - WireMock.configureFor("localhost", API_SERVER.getPort()); - apiClient = new ClientBuilder().setBasePath("http://localhost:" + API_SERVER.getPort()).build(); - coreV1Api = new CoreV1Api(apiClient); - } - - @AfterAll - static void afterAll() { - API_SERVER.shutdownServer(); - } - - @AfterEach - void afterEach() { - API_SERVER.resetAll(); - } - - /** - * //TODO - */ @Test void namespaceARedLabels() { @@ -115,11 +42,11 @@ void namespaceARedLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstances = discoveryClient.getInstances("serviceX"); // only the service with { namespace=a } is returned assertThat(serviceInstances).hasSize(1); @@ -138,11 +65,11 @@ void namespaceAGreenLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstances = discoveryClient.getInstances("serviceXX"); // only the service with { namespace=a } is returned assertThat(serviceInstances).hasSize(1); @@ -161,11 +88,11 @@ void namespaceANoLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesA = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesA).hasSize(1); assertThat(serviceInstancesA.get(0).getMetadata().get("color")).isEqualTo("red"); @@ -186,11 +113,11 @@ void namespaceANullLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesX = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesX).hasSize(1); assertThat(serviceInstancesX.get(0).getMetadata().get("color")).isEqualTo("red"); @@ -211,11 +138,11 @@ void namespaceBRedLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstances = discoveryClient.getInstances("serviceX"); // only the service with { namespace=b } is returned assertThat(serviceInstances).hasSize(1); @@ -234,11 +161,11 @@ void namespaceBGreenLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstances = discoveryClient.getInstances("serviceXX"); // only the service with { namespace=b } is returned assertThat(serviceInstances).hasSize(1); @@ -257,11 +184,11 @@ void namespaceBNoLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesX = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesX).hasSize(1); assertThat(serviceInstancesX.get(0).getMetadata().get("color")).isEqualTo("red"); @@ -282,11 +209,11 @@ void namespaceBNullLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesX = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesX).hasSize(1); assertThat(serviceInstancesX.get(0).getMetadata().get("color")).isEqualTo("red"); @@ -307,11 +234,11 @@ void namespaceAndBRedLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstances = discoveryClient.getInstances("serviceX"); assertThat(serviceInstances).hasSize(2); assertThat(serviceInstances.get(0).getMetadata().get("color")).isEqualTo("red"); @@ -329,11 +256,11 @@ void namespaceAndBGreenLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstances = discoveryClient.getInstances("serviceXX"); assertThat(serviceInstances).hasSize(2); assertThat(serviceInstances.get(0).getMetadata().get("color")).isEqualTo("green"); @@ -351,11 +278,11 @@ void namespaceAndBNoLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesX = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesX).hasSize(2); @@ -383,11 +310,11 @@ void allNamespacesRedLabel() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesX = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesX).hasSize(2); @@ -411,11 +338,11 @@ void allNamespacesGreenLabel() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesX = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesX).hasSize(0); @@ -439,11 +366,11 @@ void allNamespacesNoLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesX = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesX).hasSize(2); @@ -459,119 +386,6 @@ void allNamespacesNoLabels() { assertThat(serviceInstancesXX.stream().map(x -> x.getMetadata().get("namespace")).toList()) .containsExactlyInAnyOrder("a", "b"); - Set selectiveNamespaces = Set.of(NAMESPACE_A, NAMESPACE_B); - List selectiveNamespacesAsList = List.of(NAMESPACE_A, NAMESPACE_B); - - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(false, discoveryInAllNamespaces, - selectiveNamespaces, true, 60L, false, null, Set.of(), SHAPE_CIRCLE, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); - - service(NAMESPACE_A, SHAPE_CIRCLE); - service(NAMESPACE_B, SHAPE_CIRCLE); - service(NAMESPACE_B, SHAPE_TRIANGLE); - - endpoints(NAMESPACE_A, SHAPE_CIRCLE); - endpoints(NAMESPACE_B, SHAPE_CIRCLE); - endpoints(NAMESPACE_B, SHAPE_TRIANGLE); - - List sharedInformerFactories = - CONFIGURATION.sharedInformerFactories(apiClient, selectiveNamespacesAsList); - - List> serviceSharedIndexInformers = CONFIGURATION.serviceSharedIndexInformers( - sharedInformerFactories, selectiveNamespacesAsList, coreV1Api , properties); - List> endpointsSharedIndexInformers = CONFIGURATION.endpointsSharedIndexInformers( - sharedInformerFactories, selectiveNamespacesAsList, coreV1Api , properties); - - List> serviceListers = CONFIGURATION.serviceListers(selectiveNamespacesAsList, - serviceSharedIndexInformers); - List> endpointsListers = CONFIGURATION.endpointsListers(selectiveNamespacesAsList, - endpointsSharedIndexInformers); - - startInformers(sharedInformerFactories, serviceSharedIndexInformers, endpointsSharedIndexInformers); - - List serviceInstances = discoveryClient.getInstances(SERVICE_NAME); - assertThat(serviceInstances.size()).isEqualTo(1); - assertThat(serviceInstances.get(0).getMetadata().get("k8s_namespace")).isEqualTo("namespaceA"); - } - - private void service(String namespace, Map labels) { - V1Service service = new V1Service().metadata(new V1ObjectMeta().name(SERVICE_NAME).namespace(namespace).labels(labels)) - .spec(new V1ServiceSpec().type("ClusterIP")); - mockServicesCall(namespace, labelSelector(labels), service); - } - - private void endpoints(String namespace, Map labels) { - V1Endpoints endpoints = new V1Endpoints().metadata(new V1ObjectMeta().name(ENDPOINTS_NAME).namespace(namespace).labels(labels)) - .addSubsetsItem(new V1EndpointSubset().addPortsItem(new CoreV1EndpointPort().port(8080)) - .addAddressesItem(new V1EndpointAddress().ip("2.2.2.2"))); - mockEndpointsCall(namespace, labelSelector(labels), endpoints); - } - - private static void mockEndpointsCall(String namespace, String labelSelector, - V1Endpoints endpoints) { - - // watch=false, first call to populate watcher cache - // this is when we provide the Endpoints - KubernetesClientDiscoveryClientServiceLabelsFilteringTests.API_SERVER - .stubFor(get(urlPathEqualTo("/api/v1/namespaces/" + namespace + "/endpoints")) - .withQueryParam("watch", equalTo("false")) - .withQueryParam("labelSelector", equalTo(labelSelector)) - .willReturn(aResponse() - .withStatus(200) - .withBody(JSON.serialize(new V1EndpointsList().metadata(new V1ListMeta().resourceVersion("0")) - .addItemsItem(endpoints))))); - - // watch=true, call to re-sync - // nothing new is incoming when we re-sync - KubernetesClientDiscoveryClientServiceLabelsFilteringTests.API_SERVER - .stubFor(get(urlPathEqualTo("/api/v1/namespaces/" + namespace + "/endpoints")) - .withQueryParam("watch", equalTo("true")) - .withQueryParam("labelSelector", equalTo(labelSelector)) - .willReturn(aResponse().withStatus(200).withBody(""))); - } - - private static void mockServicesCall(String namespace, String labelSelector, - V1Service service) { - - // watch=false, first call to populate watcher cache - // this is when we provide the Service - KubernetesClientDiscoveryClientServiceLabelsFilteringTests.API_SERVER - .stubFor(get(urlPathEqualTo("/api/v1/namespaces/" + namespace + "/services")) - .withQueryParam("watch", equalTo("false")) - .withQueryParam("labelSelector", equalTo(labelSelector)) - .willReturn(aResponse() - .withStatus(200) - .withBody(JSON.serialize(new V1ServiceList().metadata(new V1ListMeta().resourceVersion("0")) - .addItemsItem(service))))); - - // watch=true, call to re-sync - // nothing new is incoming when we re-sync - KubernetesClientDiscoveryClientServiceLabelsFilteringTests.API_SERVER - .stubFor(get(urlPathEqualTo("/api/v1/namespaces/" + namespace + "/services")) - .withQueryParam("watch", equalTo("true")) - .withQueryParam("labelSelector", equalTo(labelSelector)) - .willReturn(aResponse().withStatus(200).withBody(""))); - } - - private String labelSelector(Map labels) { - return labels.entrySet().stream().map(entry -> entry.getKey() + "=" + entry.getValue()) - .collect(Collectors.joining("&")); - } - - private void startInformers(List sharedInformerFactories, - List> serviceSharedIndexInformers, - List> endpointsSharedIndexInformers) { - sharedInformerFactories.forEach(SharedInformerFactory::startAllRegisteredInformers); - - Awaitility.await().until(() -> serviceSharedIndexInformers.stream() - .map(SharedIndexInformer::hasSynced) - .reduce(Boolean::logicalAnd) - .orElse(false)); - - Awaitility.await().until(() -> endpointsSharedIndexInformers.stream() - .map(SharedIndexInformer::hasSynced) - .reduce(Boolean::logicalAnd) - .orElse(false)); } } From dfe993002bb7a3d5578c31ac275b5769c4a5a7fb Mon Sep 17 00:00:00 2001 From: wind57 Date: Thu, 5 Feb 2026 10:28:52 +0200 Subject: [PATCH 14/19] checkstyle Signed-off-by: wind57 --- ...veryClientServiceLabelsFilteringTests.java | 86 +++++++++---------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java index 21c6e2b6a..130c392c9 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientDiscoveryClientServiceLabelsFilteringTests.java @@ -31,7 +31,7 @@ * @author wind57 */ class KubernetesClientDiscoveryClientServiceLabelsFilteringTests - extends KubernetesClientDiscoveryClientServiceLabelsFiltering { + extends KubernetesClientDiscoveryClientServiceLabelsFiltering { @Test void namespaceARedLabels() { @@ -42,11 +42,11 @@ void namespaceARedLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstances = discoveryClient.getInstances("serviceX"); // only the service with { namespace=a } is returned assertThat(serviceInstances).hasSize(1); @@ -65,11 +65,11 @@ void namespaceAGreenLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstances = discoveryClient.getInstances("serviceXX"); // only the service with { namespace=a } is returned assertThat(serviceInstances).hasSize(1); @@ -88,11 +88,11 @@ void namespaceANoLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesA = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesA).hasSize(1); assertThat(serviceInstancesA.get(0).getMetadata().get("color")).isEqualTo("red"); @@ -113,11 +113,11 @@ void namespaceANullLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesX = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesX).hasSize(1); assertThat(serviceInstancesX.get(0).getMetadata().get("color")).isEqualTo("red"); @@ -138,11 +138,11 @@ void namespaceBRedLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstances = discoveryClient.getInstances("serviceX"); // only the service with { namespace=b } is returned assertThat(serviceInstances).hasSize(1); @@ -161,11 +161,11 @@ void namespaceBGreenLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstances = discoveryClient.getInstances("serviceXX"); // only the service with { namespace=b } is returned assertThat(serviceInstances).hasSize(1); @@ -184,11 +184,11 @@ void namespaceBNoLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesX = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesX).hasSize(1); assertThat(serviceInstancesX.get(0).getMetadata().get("color")).isEqualTo("red"); @@ -209,11 +209,11 @@ void namespaceBNullLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesX = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesX).hasSize(1); assertThat(serviceInstancesX.get(0).getMetadata().get("color")).isEqualTo("red"); @@ -234,11 +234,11 @@ void namespaceAndBRedLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstances = discoveryClient.getInstances("serviceX"); assertThat(serviceInstances).hasSize(2); assertThat(serviceInstances.get(0).getMetadata().get("color")).isEqualTo("red"); @@ -256,11 +256,11 @@ void namespaceAndBGreenLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstances = discoveryClient.getInstances("serviceXX"); assertThat(serviceInstances).hasSize(2); assertThat(serviceInstances.get(0).getMetadata().get("color")).isEqualTo("green"); @@ -278,11 +278,11 @@ void namespaceAndBNoLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesX = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesX).hasSize(2); @@ -310,11 +310,11 @@ void allNamespacesRedLabel() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesX = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesX).hasSize(2); @@ -338,11 +338,11 @@ void allNamespacesGreenLabel() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesX = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesX).hasSize(0); @@ -366,11 +366,11 @@ void allNamespacesNoLabels() { boolean discoveryInAllNamespaces = false; KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(false, - discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, - KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); + discoveryInAllNamespaces, namespacesAsSet, true, 60L, false, null, Set.of(), labels, null, + KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, false, false, null); KubernetesClientInformerDiscoveryClient discoveryClient = createAndStartListers(namespaces, - discoveryProperties); + discoveryProperties); List serviceInstancesX = discoveryClient.getInstances("serviceX"); assertThat(serviceInstancesX).hasSize(2); From 8d618e1bf72c3b4131bb8cdfa7ad34772c7a432f Mon Sep 17 00:00:00 2001 From: wind57 Date: Thu, 5 Feb 2026 11:56:46 +0200 Subject: [PATCH 15/19] add auto-configuration Signed-off-by: wind57 --- ....springframework.boot.autoconfigure.AutoConfiguration.imports | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-kubernetes-fabric8-discovery/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index ca3dd8dce..ee78badac 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -4,3 +4,4 @@ org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8ReactiveDiscoveryC org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientSpelAutoConfiguration org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8ReactiveDiscoveryClientAutoConfiguration org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8ReactiveDiscoveryHealthAutoConfiguration +org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8InformerAutoConfiguration From e83916795be2eb93f3cf3d1b0cc5682f78bd3adc Mon Sep 17 00:00:00 2001 From: wind57 Date: Thu, 5 Feb 2026 12:55:58 +0200 Subject: [PATCH 16/19] checkstyle Signed-off-by: wind57 --- .../fabric8/client/discovery/TestAssertions.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/discovery/TestAssertions.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/discovery/TestAssertions.java index 4dd9fcba7..288dbbb43 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/discovery/TestAssertions.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/discovery/TestAssertions.java @@ -22,12 +22,16 @@ import java.util.Map; import java.util.Objects; +import org.apache.commons.logging.LogFactory; + import org.springframework.boot.test.json.BasicJsonTester; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; import org.springframework.cloud.kubernetes.commons.discovery.DefaultKubernetesServiceInstance; +import org.springframework.cloud.kubernetes.integration.tests.commons.Awaitilities; +import org.springframework.core.log.LogAccessor; import org.springframework.http.HttpMethod; import org.springframework.web.reactive.function.client.WebClient; @@ -49,6 +53,8 @@ final class TestAssertions { private static final BasicJsonTester BASIC_JSON_TESTER = new BasicJsonTester(TestAssertions.class); + private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(Fabric8DiscoveryAllServicesIT.class)); + private TestAssertions() { } @@ -98,7 +104,17 @@ static void assertPodMetadata(DiscoveryClient discoveryClient) { static void assertAllServices(DiscoveryClient discoveryClient) { + Awaitilities.awaitUntil(5, 100, () -> { + List innerServices = discoveryClient.getServices(); + if (innerServices.size() != 3) { + LOG.info(() -> "Not yet 3 services : " + innerServices); + return false; + } + return true; + }); + List services = discoveryClient.getServices(); + assertThat(services).containsExactlyInAnyOrder("kubernetes", "busybox-service", "external-name-service"); ServiceInstance externalNameInstance = discoveryClient.getInstances("external-name-service").get(0); From 4b0a9a6bfe841133df49a764a2dfed045700b96f Mon Sep 17 00:00:00 2001 From: wind57 Date: Thu, 5 Feb 2026 13:22:54 +0200 Subject: [PATCH 17/19] trigger Signed-off-by: wind57 From b68952cf45c9e31d5ff13416c5e8ffaeb5c30855 Mon Sep 17 00:00:00 2001 From: wind57 Date: Thu, 5 Feb 2026 14:08:32 +0200 Subject: [PATCH 18/19] trigger Signed-off-by: wind57 From b1045d0afae6cce87714752af655acbaa5b76174 Mon Sep 17 00:00:00 2001 From: wind57 Date: Thu, 5 Feb 2026 23:19:44 +0200 Subject: [PATCH 19/19] fix Signed-off-by: wind57 --- .../leader/election/PodReadyRunnerTests.java | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/leader/election/PodReadyRunnerTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/leader/election/PodReadyRunnerTests.java index 49a2bea29..1df154709 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/leader/election/PodReadyRunnerTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/leader/election/PodReadyRunnerTests.java @@ -56,9 +56,8 @@ void readinessOKFromTheFirstCycle(CapturedOutput output) throws Exception { CompletableFuture readinessFuture = podReadyRunner.podReady(readinessSupplier); readinessFuture.get(); - assertThat(output.getOut()).contains("Pod : identity in namespace : namespace is ready"); - assertThat(output.getOut()).contains("canceling scheduled future because readiness succeeded"); - + awaitUntil(3, 100, () -> output.getOut().contains("Pod : identity in namespace : namespace is ready")); + awaitUntil(3, 100, () -> output.getOut().contains("canceling scheduled future because readiness succeeded")); awaitUntil(3, 200, () -> output.getOut().contains("Shutting down executor : podReadyExecutor")); } @@ -80,10 +79,10 @@ void readinessOKFromTheSecondCycle(CapturedOutput output) throws Exception { CompletableFuture readinessFuture = podReadyRunner.podReady(readinessSupplier); readinessFuture.get(); - assertThat(output.getOut()) - .contains("Pod : identity in namespace : namespace is not ready, will retry in one second"); - assertThat(output.getOut()).contains("Pod : identity in namespace : namespace is ready"); - assertThat(output.getOut()).contains("canceling scheduled future because readiness succeeded"); + awaitUntil(3, 100, () -> output.getOut() + .contains("Pod : identity in namespace : namespace is not ready, will retry in one second")); + awaitUntil(3, 100, () -> output.getOut().contains("Pod : identity in namespace : namespace is ready")); + awaitUntil(3, 100, () -> output.getOut().contains("canceling scheduled future because readiness succeeded")); awaitUntil(3, 200, () -> output.getOut().contains("Shutting down executor : podReadyExecutor")); } @@ -110,12 +109,11 @@ void readinessFailsOnTheSecondCycle(CapturedOutput output) { } catch (Exception e) { caught = true; - assertThat(output.getOut()) - .contains("Pod : identity in namespace : namespace is not ready, will retry in one second"); - assertThat(output.getOut()).contains("exception waiting for pod : identity"); - assertThat(output.getOut()).contains("pod readiness for : identity failed with : fail on the second cycle"); - assertThat(output.getOut()).contains("canceling scheduled future because readiness failed"); - + awaitUntil(3, 100, () -> output.getOut() + .contains("Pod : identity in namespace : namespace is not ready, will retry in one second")); + awaitUntil(3, 100, () -> output.getOut().contains("exception waiting for pod : identity")); + awaitUntil(3, 100, () -> output.getOut().contains("pod readiness for : identity failed with : fail on the second cycle")); + awaitUntil(3, 100, () -> output.getOut().contains("canceling scheduled future because readiness failed")); awaitUntil(3, 200, () -> output.getOut().contains("Shutting down executor : podReadyExecutor")); } assertThat(caught).isTrue(); @@ -155,14 +153,13 @@ void readinessFailsOnTheSecondCycleAttachNewPipeline(CapturedOutput output) { } catch (Exception e) { caught = true; - assertThat(output.getOut()) - .contains("Pod : identity in namespace : namespace is not ready, will retry in one second"); - assertThat(output.getOut()).contains("exception waiting for pod : identity"); - assertThat(output.getOut()).contains("pod readiness for : identity failed with : fail on the second cycle"); - assertThat(output.getOut()).contains("readiness failed and we caught that"); - + awaitUntil(3, 100, () -> output.getOut() + .contains("Pod : identity in namespace : namespace is not ready, will retry in one second")); + awaitUntil(3, 100, () -> output.getOut().contains("exception waiting for pod : identity")); + awaitUntil(3, 100, () -> output.getOut().contains("pod readiness for : identity failed with : fail on the second cycle")); + awaitUntil(3, 100, () -> output.getOut().contains("readiness failed and we caught that")); awaitUntil(3, 200, () -> output.getOut().contains("Shutting down executor : podReadyExecutor")); - assertThat(output.getOut()).contains("canceling scheduled future because readiness failed"); + awaitUntil(3, 100, () -> output.getOut().contains("canceling scheduled future because readiness failed")); } assertThat(caught).isTrue(); } @@ -210,14 +207,14 @@ void readinessCanceledOnTheSecondCycleAttachNewPipeline(CapturedOutput output) t assertThat(output.getOut()) .contains("Pod : identity in namespace : namespace is not ready, will retry in one second"); // this is a cancel of the future, not an exception per se - assertThat(output.getOut()).doesNotContain("leader election for : identity was not successful"); - assertThat(output.getOut()).contains("readiness failed and we caught that"); + awaitUntil(3, 100, () -> !output.getOut().contains("leader election for : identity was not successful")); + awaitUntil(3, 100, () -> output.getOut().contains("readiness failed and we caught that")); awaitUntil(3, 200, () -> output.getOut().contains("Shutting down executor : podReadyExecutor")); - assertThat(output.getOut()).contains("canceling scheduled future because completable future was cancelled"); - assertThat(output.getOut()).doesNotContain("canceling scheduled future because readiness failed"); - assertThat(output.getOut()).contains("scheduledFuture is canceled: true"); + awaitUntil(3, 100, () -> output.getOut().contains("canceling scheduled future because completable future was cancelled")); + awaitUntil(3, 100, () -> !output.getOut().contains("canceling scheduled future because readiness failed")); + awaitUntil(3, 100, () -> output.getOut().contains("scheduledFuture is canceled: true")); } assertThat(caught).isTrue();