From fad373cc2a755164e04330e584faaaec4ef9be74 Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 3 Nov 2023 18:55:23 +0200 Subject: [PATCH 01/53] correct order --- .../Fabric8KubernetesDiscoveryClientUtils.java | 12 ++++++------ .../fabric8/discovery/KubernetesDiscoveryClient.java | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtils.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtils.java index d58931f000..e82d0ecc0b 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtils.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtils.java @@ -75,17 +75,17 @@ static List endpoints(KubernetesDiscoveryProperties properties, Kuber List endpoints; - if (properties.allNamespaces()) { - LOG.debug(() -> "discovering endpoints in all namespaces"); - endpoints = filteredEndpoints(client.endpoints().inAnyNamespace().withNewFilter(), properties, serviceName); - } - else if (!properties.namespaces().isEmpty()) { + 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))); + 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); diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClient.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClient.java index a18d70e202..c3f5a8c139 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClient.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClient.java @@ -187,7 +187,9 @@ private List serviceInstances(EndpointSubsetNS es, String servi @Override public List getServices() { - return adapter.apply(client).stream().map(s -> s.getMetadata().getName()).distinct().toList(); + List services = adapter.apply(client).stream().map(s -> s.getMetadata().getName()).distinct().toList(); + LOG.debug(() -> "will return services : " + services); + return services; } @Deprecated(forRemoval = true) From eb7a681ef589c7c833516cff12bde4930fa3c2c8 Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 3 Nov 2023 18:56:55 +0200 Subject: [PATCH 02/53] checkstyle --- .../discovery/Fabric8KubernetesDiscoveryClientUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtils.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtils.java index e82d0ecc0b..f7f98525a1 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtils.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtils.java @@ -79,7 +79,7 @@ static List endpoints(KubernetesDiscoveryProperties properties, Kuber 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))); + client.endpoints().inNamespace(namespace).withNewFilter(), properties, serviceName))); endpoints = inner; } else if (properties.allNamespaces()) { From 042e72241eac71e2ab8c3c8eb6fb423d9e37721d Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 3 Nov 2023 19:06:11 +0200 Subject: [PATCH 03/53] trigger From 8efbd5845bde5733f358d86639957f30e86c02a5 Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 3 Nov 2023 20:15:52 +0200 Subject: [PATCH 04/53] fix test --- .../discovery/Fabric8KubernetesCatalogWatchEndpointsTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesCatalogWatchEndpointsTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesCatalogWatchEndpointsTests.java index 92eda531a0..07267b4031 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesCatalogWatchEndpointsTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesCatalogWatchEndpointsTests.java @@ -143,7 +143,7 @@ void testInAllNamespacesWithoutServiceLabels() { @Override void testAllNamespacesTrueOtherBranchesNotCalled() { - KubernetesCatalogWatch watch = createWatcherInAllNamespacesWithLabels(Map.of("color", "blue"), Set.of("B"), + KubernetesCatalogWatch watch = createWatcherInAllNamespacesWithLabels(Map.of("color", "blue"), Set.of(), ENDPOINT_SLICES); endpoints("namespaceA", Map.of(), "podA"); From 57fc9c3379315dcc2b6afe51af19635e5b28324e Mon Sep 17 00:00:00 2001 From: wind57 Date: Sat, 4 Nov 2023 07:31:23 +0200 Subject: [PATCH 05/53] trigger From 598c46eba9b1922c5bb929e4fb9b2537a4866ce9 Mon Sep 17 00:00:00 2001 From: wind57 Date: Sat, 4 Nov 2023 11:29:58 +0200 Subject: [PATCH 06/53] drop a record used internally only --- .../fabric8/discovery/EndpointSubsetNS.java | 27 ------------------ ...Fabric8KubernetesDiscoveryClientUtils.java | 4 --- .../discovery/KubernetesDiscoveryClient.java | 15 +++++----- .../KubernetesDiscoveryClientUtilsTests.java | 28 ------------------- 4 files changed, 7 insertions(+), 67 deletions(-) delete mode 100644 spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/EndpointSubsetNS.java diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/EndpointSubsetNS.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/EndpointSubsetNS.java deleted file mode 100644 index 8a7de4b74a..0000000000 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/EndpointSubsetNS.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2012-2022 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 io.fabric8.kubernetes.api.model.EndpointSubset; - -/** - * @author Haytham Mohamed - **/ -record EndpointSubsetNS(String namespace, List endpointSubset) { -} diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtils.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtils.java index f7f98525a1..7895f8cf99 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtils.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtils.java @@ -65,10 +65,6 @@ private Fabric8KubernetesDiscoveryClientUtils() { } - static EndpointSubsetNS subsetsFromEndpoints(Endpoints endpoints) { - return new EndpointSubsetNS(endpoints.getMetadata().getNamespace(), endpoints.getSubsets()); - } - static List endpoints(KubernetesDiscoveryProperties properties, KubernetesClient client, KubernetesNamespaceProvider namespaceProvider, String target, @Nullable String serviceName, Predicate filter) { diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClient.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClient.java index c3f5a8c139..6a5a786cf2 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClient.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClient.java @@ -113,13 +113,12 @@ public String description() { public List getInstances(String serviceId) { Objects.requireNonNull(serviceId); - List subsetsNS = getEndPointsList(serviceId).stream() - .map(Fabric8KubernetesDiscoveryClientUtils::subsetsFromEndpoints).toList(); + List allEndpoints = getEndPointsList(serviceId).stream().toList(); List instances = new ArrayList<>(); - for (EndpointSubsetNS es : subsetsNS) { - // subsetsNS are only those that matched the serviceId - instances.addAll(serviceInstances(es, serviceId)); + for (Endpoints endpoints : allEndpoints) { + // endpoints are only those that matched the serviceId + instances.addAll(serviceInstances(endpoints, serviceId)); } if (properties.includeExternalNameServices()) { @@ -148,15 +147,15 @@ public List getEndPointsList(String serviceId) { return endpoints(properties, client, namespaceProvider, "fabric8-discovery", serviceId, adapter.filter()); } - private List serviceInstances(EndpointSubsetNS es, String serviceId) { + private List serviceInstances(Endpoints endpoints, String serviceId) { - List subsets = es.endpointSubset(); + List subsets = endpoints.getSubsets(); if (subsets.isEmpty()) { LOG.debug(() -> "serviceId : " + serviceId + " does not have any subsets"); return List.of(); } - String namespace = es.namespace(); + String namespace = endpoints.getMetadata().getNamespace(); List instances = new ArrayList<>(); Service service = client.services().inNamespace(namespace).withName(serviceId).get(); diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientUtilsTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientUtilsTests.java index 96d9c76302..f1068dbcb9 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientUtilsTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientUtilsTests.java @@ -22,12 +22,8 @@ import io.fabric8.kubernetes.api.model.EndpointAddress; import io.fabric8.kubernetes.api.model.EndpointAddressBuilder; -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.EndpointsBuilder; -import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -41,30 +37,6 @@ @ExtendWith(OutputCaptureExtension.class) class KubernetesDiscoveryClientUtilsTests { - @Test - void testSubsetsFromEndpointsEmptySubsets() { - Endpoints endpoints = new EndpointsBuilder() - .withMetadata(new ObjectMetaBuilder().withNamespace("non-default").build()).build(); - EndpointSubsetNS result = Fabric8KubernetesDiscoveryClientUtils.subsetsFromEndpoints(endpoints); - Assertions.assertNotNull(result); - Assertions.assertEquals(result.endpointSubset(), List.of()); - Assertions.assertEquals(result.namespace(), "non-default"); - } - - @Test - void testSubsetsFromEndpointsNonEmptySubsets() { - Endpoints endpoints = new EndpointsBuilder().withSubsets((List) null) - .withMetadata(new ObjectMetaBuilder().withNamespace("default").build()) - .withSubsets( - new EndpointSubsetBuilder().withPorts(new EndpointPortBuilder().withPort(8080).build()).build()) - .build(); - EndpointSubsetNS result = Fabric8KubernetesDiscoveryClientUtils.subsetsFromEndpoints(endpoints); - Assertions.assertNotNull(result); - Assertions.assertEquals(result.endpointSubset().size(), 1); - Assertions.assertEquals(result.endpointSubset().get(0).getPorts().get(0).getPort(), 8080); - Assertions.assertEquals(result.namespace(), "default"); - } - /** *
 	 *      - ready addresses are empty

From 01165e640d8bb80d4aba181d1369fe15c1ab4558 Mon Sep 17 00:00:00 2001
From: wind57 
Date: Mon, 6 Nov 2023 16:02:48 +0200
Subject: [PATCH 07/53] dirty

---
 .../K8sInstanceIdHostPodNameSupplier.java     |  78 ++++++
 .../K8sPodLabelsAndAnnotationsSupplier.java   |  80 ++++++
 .../KubernetesDiscoveryClientUtils.java       |  81 +++---
 .../KubernetesInformerDiscoveryClient.java    | 158 +++++-------
 ...K8sInstanceIdHostPodNameSupplierTests.java | 135 ++++++++++
 ...sPodLabelsAndAnnotationsSupplierTests.java |  74 ++++++
 ...esDiscoveryClientServiceMetadataTests.java | 233 ------------------
 .../KubernetesDiscoveryClientUtilsTests.java  | 140 +++++++++++
 ...c8KubernetesDiscoveryClientUtilsTests.java |   4 +-
 .../KubernetesDiscoveryClientUtilsTests.java  |   3 -
 10 files changed, 611 insertions(+), 375 deletions(-)
 create mode 100644 spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/K8sInstanceIdHostPodNameSupplier.java
 create mode 100644 spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/K8sPodLabelsAndAnnotationsSupplier.java
 create mode 100644 spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/K8sInstanceIdHostPodNameSupplierTests.java
 create mode 100644 spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/K8sPodLabelsAndAnnotationsSupplierTests.java
 delete mode 100644 spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceMetadataTests.java

diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/K8sInstanceIdHostPodNameSupplier.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/K8sInstanceIdHostPodNameSupplier.java
new file mode 100644
index 0000000000..49628ebd71
--- /dev/null
+++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/K8sInstanceIdHostPodNameSupplier.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2013-2023 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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.client.discovery;
+
+import java.util.Optional;
+import java.util.function.Supplier;
+
+import io.kubernetes.client.openapi.models.V1EndpointAddress;
+import io.kubernetes.client.openapi.models.V1ObjectReference;
+import io.kubernetes.client.openapi.models.V1Service;
+
+import org.springframework.cloud.kubernetes.commons.discovery.InstanceIdHostPodName;
+
+/**
+ * @author wind57
+ */
+final class K8sInstanceIdHostPodNameSupplier implements Supplier {
+
+	private final V1EndpointAddress endpointAddress;
+
+	private final V1Service service;
+
+	private K8sInstanceIdHostPodNameSupplier(V1EndpointAddress endpointAddress, V1Service service) {
+		this.endpointAddress = endpointAddress;
+		this.service = service;
+	}
+
+	@Override
+	public InstanceIdHostPodName get() {
+		return new InstanceIdHostPodName(instanceId(), host(), podName());
+	}
+
+	/**
+	 * to be used when .spec.type of the Service is != 'ExternalName'.
+	 */
+	static K8sInstanceIdHostPodNameSupplier nonExternalName(V1EndpointAddress endpointAddress, V1Service service) {
+		return new K8sInstanceIdHostPodNameSupplier(endpointAddress, service);
+	}
+
+	/**
+	 * to be used when .spec.type of the Service is == 'ExternalName'.
+	 */
+	static K8sInstanceIdHostPodNameSupplier externalName(V1Service service) {
+		return new K8sInstanceIdHostPodNameSupplier(null, service);
+	}
+
+	// instanceId is usually the pod-uid as seen in the .metadata.uid
+	private String instanceId() {
+		return Optional.ofNullable(endpointAddress).map(V1EndpointAddress::getTargetRef).map(V1ObjectReference::getUid)
+				.orElseGet(() -> service.getMetadata().getUid());
+	}
+
+	private String host() {
+		return Optional.ofNullable(endpointAddress).map(V1EndpointAddress::getIp)
+				.orElseGet(() -> service.getSpec().getExternalName());
+	}
+
+	private String podName() {
+		return Optional.ofNullable(endpointAddress).map(V1EndpointAddress::getTargetRef)
+				.filter(objectReference -> "Pod".equals(objectReference.getKind())).map(V1ObjectReference::getName)
+				.orElse(null);
+	}
+
+}
diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/K8sPodLabelsAndAnnotationsSupplier.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/K8sPodLabelsAndAnnotationsSupplier.java
new file mode 100644
index 0000000000..21c32f8f8a
--- /dev/null
+++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/K8sPodLabelsAndAnnotationsSupplier.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2013-2023 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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.client.discovery;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+
+import io.kubernetes.client.openapi.ApiException;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1ObjectMeta;
+import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.cloud.kubernetes.commons.discovery.PodLabelsAndAnnotations;
+import org.springframework.core.log.LogAccessor;
+
+/**
+ * @author wind57
+ */
+final class K8sPodLabelsAndAnnotationsSupplier implements Function {
+
+	private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(K8sPodLabelsAndAnnotationsSupplier.class));
+
+	private final CoreV1Api coreV1Api;
+
+	private final String namespace;
+
+	private K8sPodLabelsAndAnnotationsSupplier(CoreV1Api coreV1Api, String namespace) {
+		this.coreV1Api = coreV1Api;
+		this.namespace = namespace;
+	}
+
+	/**
+	 * to be used when .spec.type of the Service is != 'ExternalName'.
+	 */
+	static K8sPodLabelsAndAnnotationsSupplier nonExternalName(CoreV1Api coreV1Api, String namespace) {
+		return new K8sPodLabelsAndAnnotationsSupplier(coreV1Api, namespace);
+	}
+
+	/**
+	 * to be used when .spec.type of the Service is == 'ExternalName'.
+	 */
+	static K8sPodLabelsAndAnnotationsSupplier externalName() {
+		return new K8sPodLabelsAndAnnotationsSupplier(null, null);
+	}
+
+	@Override
+	public PodLabelsAndAnnotations apply(String podName) {
+
+		V1ObjectMeta objectMeta;
+
+		try {
+			objectMeta = Optional.ofNullable(coreV1Api.readNamespacedPod(podName, namespace, null).getMetadata())
+					.orElse(new V1ObjectMetaBuilder().withLabels(Map.of()).withAnnotations(Map.of()).build());
+		}
+		catch (ApiException e) {
+			LOG.warn(e, "Could not get pod metadata");
+			objectMeta = new V1ObjectMetaBuilder().withLabels(Map.of()).withAnnotations(Map.of()).build();
+		}
+
+		return new PodLabelsAndAnnotations(Optional.ofNullable(objectMeta.getLabels()).orElse(Map.of()),
+				Optional.ofNullable(objectMeta.getAnnotations()).orElse(Map.of()));
+	}
+
+}
diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientUtils.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientUtils.java
index 9e0a88aeae..864d469dc5 100644
--- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientUtils.java
+++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientUtils.java
@@ -17,15 +17,19 @@
 package org.springframework.cloud.kubernetes.client.discovery;
 
 import java.time.Duration;
-import java.util.HashMap;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
 
 import io.kubernetes.client.informer.SharedInformerFactory;
 import io.kubernetes.client.informer.cache.Lister;
+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.V1ObjectMeta;
 import io.kubernetes.client.openapi.models.V1Service;
 import io.kubernetes.client.openapi.models.V1ServiceSpec;
@@ -33,14 +37,15 @@
 import org.apache.commons.logging.LogFactory;
 
 import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties;
+import org.springframework.cloud.kubernetes.commons.discovery.ServiceMetadata;
 import org.springframework.core.log.LogAccessor;
 import org.springframework.expression.Expression;
 import org.springframework.expression.spel.standard.SpelExpressionParser;
 import org.springframework.expression.spel.support.SimpleEvaluationContext;
+import org.springframework.util.CollectionUtils;
 
-import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.keysWithPrefix;
-import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryConstants.NAMESPACE_METADATA_KEY;
-import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryConstants.SERVICE_TYPE;
+import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryConstants.UNSET_PORT_NAME;
+import static org.springframework.util.StringUtils.hasText;
 
 /**
  * @author wind57
@@ -82,40 +87,6 @@ static boolean matchesServiceLabels(V1Service service, KubernetesDiscoveryProper
 
 	}
 
-	/**
-	 * This adds the following metadata. 
-	 *     - labels (if requested)
-	 *     - annotations (if requested)
-	 *     - metadata
-	 *     - service type
-	 * 
- */ - static Map serviceMetadata(KubernetesDiscoveryProperties properties, V1Service service, - String serviceId) { - - Map serviceMetadata = new HashMap<>(); - KubernetesDiscoveryProperties.Metadata metadataProps = properties.metadata(); - if (metadataProps.addLabels()) { - Map labelMetadata = keysWithPrefix(service.getMetadata().getLabels(), - metadataProps.labelsPrefix()); - LOG.debug(() -> "Adding labels metadata: " + labelMetadata + " for serviceId: " + serviceId); - serviceMetadata.putAll(labelMetadata); - } - if (metadataProps.addAnnotations()) { - Map annotationMetadata = keysWithPrefix(service.getMetadata().getAnnotations(), - metadataProps.annotationsPrefix()); - LOG.debug(() -> "Adding annotations metadata: " + annotationMetadata + " for serviceId: " + serviceId); - serviceMetadata.putAll(annotationMetadata); - } - - serviceMetadata.put(NAMESPACE_METADATA_KEY, - Optional.ofNullable(service.getMetadata()).map(V1ObjectMeta::getNamespace).orElse(null)); - serviceMetadata.put(SERVICE_TYPE, - Optional.ofNullable(service.getSpec()).map(V1ServiceSpec::getType).orElse(null)); - - return serviceMetadata; - } - static Predicate filter(KubernetesDiscoveryProperties properties) { String spelExpression = properties.filter(); Predicate predicate; @@ -159,4 +130,38 @@ static void postConstruct(List sharedInformerFactories, } + static ServiceMetadata serviceMetadata(V1Service service) { + V1ObjectMeta metadata = service.getMetadata(); + V1ServiceSpec serviceSpec = service.getSpec(); + return new ServiceMetadata(metadata.getName(), metadata.getNamespace(), serviceSpec.getType(), + metadata.getLabels(), metadata.getAnnotations()); + } + + /** + * a service is allowed to have a single port defined without a name. + */ + static Map endpointSubsetsPortData(List endpointSubsets) { + return endpointSubsets.stream() + .flatMap(endpointSubset -> Optional.ofNullable(endpointSubset.getPorts()).orElse(List.of()).stream()) + .collect(Collectors.toMap( + endpointPort -> hasText(endpointPort.getName()) ? endpointPort.getName() : UNSET_PORT_NAME, + CoreV1EndpointPort::getPort)); + } + + static List addresses(V1EndpointSubset endpointSubset, + KubernetesDiscoveryProperties properties) { + List addresses = Optional.ofNullable(endpointSubset.getAddresses()).map(ArrayList::new) + .orElse(new ArrayList<>()); + + if (properties.includeNotReadyAddresses()) { + List notReadyAddresses = endpointSubset.getNotReadyAddresses(); + if (CollectionUtils.isEmpty(notReadyAddresses)) { + return addresses; + } + addresses.addAll(notReadyAddresses); + } + + return addresses; + } + } diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java index 572ecd3510..d148d69df8 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java @@ -17,21 +17,18 @@ package org.springframework.cloud.kubernetes.client.discovery; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.function.Predicate; import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.Stream; import io.kubernetes.client.informer.SharedInformer; import io.kubernetes.client.informer.SharedInformerFactory; import io.kubernetes.client.informer.cache.Lister; -import io.kubernetes.client.openapi.models.CoreV1EndpointPort; +import io.kubernetes.client.openapi.apis.CoreV1Api; 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.V1Service; import jakarta.annotation.PostConstruct; @@ -39,21 +36,23 @@ import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.kubernetes.commons.discovery.DefaultKubernetesServiceInstance; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; +import org.springframework.cloud.kubernetes.commons.discovery.ServiceMetadata; +import org.springframework.cloud.kubernetes.commons.discovery.ServicePortNameAndNumber; +import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; import org.springframework.core.log.LogAccessor; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; +import static org.springframework.cloud.kubernetes.client.discovery.K8sInstanceIdHostPodNameSupplier.nonExternalName; +import static org.springframework.cloud.kubernetes.client.discovery.K8sPodLabelsAndAnnotationsSupplier.nonExternalName; +import static org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryClientUtils.addresses; +import static org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryClientUtils.endpointSubsetsPortData; import static org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryClientUtils.filter; import static org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryClientUtils.matchesServiceLabels; import static org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryClientUtils.postConstruct; import static org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryClientUtils.serviceMetadata; -import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryConstants.HTTP; -import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryConstants.HTTPS; -import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryConstants.PRIMARY_PORT_NAME_LABEL_KEY; -import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryConstants.SECURED; -import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryConstants.UNSET_PORT_NAME; +import static org.springframework.cloud.kubernetes.commons.discovery.DiscoveryClientUtils.endpointsPort; +import static org.springframework.cloud.kubernetes.commons.discovery.DiscoveryClientUtils.serviceInstance; +import static org.springframework.cloud.kubernetes.commons.discovery.DiscoveryClientUtils.serviceInstanceMetadata; /** * @author Min Kim @@ -76,6 +75,10 @@ public class KubernetesInformerDiscoveryClient implements DiscoveryClient { private final Predicate filter; + private final ServicePortSecureResolver servicePortSecureResolver; + + private final CoreV1Api coreV1Api; + @Deprecated(forRemoval = true) public KubernetesInformerDiscoveryClient(String namespace, SharedInformerFactory sharedInformerFactory, Lister serviceLister, Lister endpointsLister, @@ -87,6 +90,8 @@ public KubernetesInformerDiscoveryClient(String namespace, SharedInformerFactory this.informersReadyFunc = () -> serviceInformer.hasSynced() && endpointsInformer.hasSynced(); this.properties = properties; filter = filter(properties); + servicePortSecureResolver = new ServicePortSecureResolver(properties); + coreV1Api = new CoreV1Api(); } public KubernetesInformerDiscoveryClient(SharedInformerFactory sharedInformerFactory, @@ -99,6 +104,8 @@ public KubernetesInformerDiscoveryClient(SharedInformerFactory sharedInformerFac this.informersReadyFunc = () -> serviceInformer.hasSynced() && endpointsInformer.hasSynced(); this.properties = properties; filter = filter(properties); + servicePortSecureResolver = new ServicePortSecureResolver(properties); + coreV1Api = new CoreV1Api(); } public KubernetesInformerDiscoveryClient(List sharedInformerFactories, @@ -119,6 +126,8 @@ public KubernetesInformerDiscoveryClient(List sharedInfor this.properties = properties; filter = filter(properties); + servicePortSecureResolver = new ServicePortSecureResolver(properties); + coreV1Api = new CoreV1Api(); } @Override @@ -133,101 +142,52 @@ public List getInstances(String serviceId) { List services = serviceListers.stream().flatMap(x -> x.list().stream()) .filter(scv -> scv.getMetadata() != null).filter(svc -> serviceId.equals(svc.getMetadata().getName())) .filter(scv -> matchesServiceLabels(scv, properties)).filter(filter).toList(); - return services.stream().flatMap(service -> getServiceInstanceDetails(service, serviceId)).toList(); + + return services.stream().flatMap(service -> serviceInstances(service, serviceId).stream()).toList(); + } - private Stream getServiceInstanceDetails(V1Service service, String serviceId) { - Map serviceMetadata = serviceMetadata(properties, service, serviceId); + private List serviceInstances(V1Service service, String serviceId) { - List endpoints = endpointsListers.stream() - .map(endpointsLister -> endpointsLister.namespace(service.getMetadata().getNamespace()) - .get(service.getMetadata().getName())) - .filter(Objects::nonNull).filter(ep -> ep.getSubsets() != null).toList(); + List instances = new ArrayList<>(); - Optional discoveredPrimaryPortName = Optional.empty(); - if (service.getMetadata() != null && service.getMetadata().getLabels() != null) { - discoveredPrimaryPortName = Optional - .ofNullable(service.getMetadata().getLabels().get(PRIMARY_PORT_NAME_LABEL_KEY)); - } - final String primaryPortName = discoveredPrimaryPortName.orElse(properties.primaryPortName()); - - final boolean secured = isSecured(service); - - return endpoints.stream() - .flatMap(ep -> ep.getSubsets().stream() - .filter(subset -> subset.getPorts() != null && subset.getPorts().size() > 0) // safeguard - .flatMap(subset -> { - Map metadata = new HashMap<>(serviceMetadata); - List endpointPorts = subset.getPorts(); - if (properties.metadata() != null && properties.metadata().addPorts()) { - endpointPorts.forEach(p -> metadata.put( - StringUtils.hasText(p.getName()) ? p.getName() : UNSET_PORT_NAME, - Integer.toString(p.getPort()))); - } - List addresses = subset.getAddresses(); - if (addresses == null) { - addresses = new ArrayList<>(); - } - if (properties.includeNotReadyAddresses() - && !CollectionUtils.isEmpty(subset.getNotReadyAddresses())) { - addresses.addAll(subset.getNotReadyAddresses()); - } - - final int port = findEndpointPort(endpointPorts, primaryPortName, serviceId); - return addresses.stream() - .map(addr -> new DefaultKubernetesServiceInstance( - addr.getTargetRef() != null ? addr.getTargetRef().getUid() : "", serviceId, - addr.getIp(), port, metadata, secured, service.getMetadata().getNamespace(), - // TODO find out how to get cluster name - // possibly from - // KubeConfig - null)); - })); - } + List allEndpoints = endpointsListers.stream() + .map(endpointsLister -> endpointsLister.get(serviceId)).filter(Objects::nonNull) + .filter(one -> service.getMetadata().getNamespace().equals(one.getMetadata().getNamespace())).toList(); - private static boolean isSecured(V1Service service) { - Optional securedOpt = Optional.empty(); - if (service.getMetadata() != null && service.getMetadata().getAnnotations() != null) { - securedOpt = Optional.ofNullable(service.getMetadata().getAnnotations().get(SECURED)); - } - if (!securedOpt.isPresent() && service.getMetadata() != null && service.getMetadata().getLabels() != null) { - securedOpt = Optional.ofNullable(service.getMetadata().getLabels().get(SECURED)); - } - return Boolean.parseBoolean(securedOpt.orElse("false")); - } + for (V1Endpoints endpoints : allEndpoints) { + List subsets = endpoints.getSubsets(); + if (subsets == null || subsets.isEmpty()) { + LOG.debug(() -> "serviceId : " + serviceId + " does not have any subsets"); + } + else { + ServiceMetadata serviceMetadata = serviceMetadata(service); + Map portsData = endpointSubsetsPortData(subsets); + Map serviceInstanceMetadata = serviceInstanceMetadata(portsData, serviceMetadata, + properties); - private int findEndpointPort(List endpointPorts, String primaryPortName, String serviceId) { - if (endpointPorts.size() == 1) { - return endpointPorts.get(0).getPort(); - } - else { - Map ports = endpointPorts.stream().filter(p -> StringUtils.hasText(p.getName())) - .collect(Collectors.toMap(CoreV1EndpointPort::getName, CoreV1EndpointPort::getPort)); - // This oneliner is looking for a port with a name equal to the primary port - // name specified in the service label - // or in spring.cloud.kubernetes.discovery.primary-port-name, equal to https, - // or equal to http. - // In case no port has been found return -1 to log a warning and fall back to - // the first port in the list. - int discoveredPort = ports.getOrDefault(primaryPortName, - ports.getOrDefault(HTTPS, ports.getOrDefault(HTTP, -1))); - - if (discoveredPort == -1) { - if (StringUtils.hasText(primaryPortName)) { - LOG.warn(() -> "Could not find a port named '" + primaryPortName - + "', 'https', or 'http' for service '" + serviceId + "'."); - } - else { - LOG.warn(() -> "Could not find a port named 'https' or 'http' for service '" + serviceId + "'."); + for (V1EndpointSubset endpointSubset : subsets) { + + Map endpointsPortData = endpointSubsetsPortData(List.of(endpointSubset)); + ServicePortNameAndNumber portData = endpointsPort(endpointsPortData, serviceMetadata, properties); + + List addresses = addresses(endpointSubset, properties); + for (V1EndpointAddress endpointAddress : addresses) { + + K8sInstanceIdHostPodNameSupplier supplierOne = nonExternalName(endpointAddress, service); + K8sPodLabelsAndAnnotationsSupplier supplierTwo = nonExternalName(coreV1Api, + service.getMetadata().getNamespace()); + + ServiceInstance serviceInstance = serviceInstance(servicePortSecureResolver, serviceMetadata, + supplierOne, supplierTwo, portData, serviceInstanceMetadata, properties); + instances.add(serviceInstance); + } } - LOG.warn( - () -> "Make sure that either the primary-port-name label has been added to the service, or that spring.cloud.kubernetes.discovery.primary-port-name has been configured."); - LOG.warn(() -> "Alternatively name the primary port 'https' or 'http'"); - LOG.warn(() -> "An incorrect configuration may result in non-deterministic behaviour."); - discoveredPort = endpointPorts.get(0).getPort(); + } - return discoveredPort; } + + return instances; } @Override diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/K8sInstanceIdHostPodNameSupplierTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/K8sInstanceIdHostPodNameSupplierTests.java new file mode 100644 index 0000000000..fd9ce80b59 --- /dev/null +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/K8sInstanceIdHostPodNameSupplierTests.java @@ -0,0 +1,135 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.client.discovery; + +import io.kubernetes.client.openapi.models.V1EndpointAddress; +import io.kubernetes.client.openapi.models.V1EndpointAddressBuilder; +import io.kubernetes.client.openapi.models.V1ObjectMeta; +import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder; +import io.kubernetes.client.openapi.models.V1ObjectReferenceBuilder; +import io.kubernetes.client.openapi.models.V1Service; +import io.kubernetes.client.openapi.models.V1ServiceBuilder; +import io.kubernetes.client.openapi.models.V1ServiceSpecBuilder; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import org.springframework.cloud.kubernetes.commons.discovery.InstanceIdHostPodName; + +/** + * @author wind57 + */ +class K8sInstanceIdHostPodNameSupplierTests { + + @Test + void instanceIdNoEndpointAddress() { + V1Service service = new V1ServiceBuilder().withSpec(new V1ServiceSpecBuilder().build()) + .withMetadata(new V1ObjectMetaBuilder().withUid("123").build()).build(); + + K8sInstanceIdHostPodNameSupplier supplier = K8sInstanceIdHostPodNameSupplier.externalName(service); + InstanceIdHostPodName result = supplier.get(); + + Assertions.assertNotNull(result); + Assertions.assertEquals(result.instanceId(), "123"); + } + + @Test + void instanceIdWithEndpointAddress() { + V1EndpointAddress endpointAddress = new V1EndpointAddressBuilder() + .withTargetRef(new V1ObjectReferenceBuilder().withUid("456").build()).build(); + V1Service service = new V1ServiceBuilder().withSpec(new V1ServiceSpecBuilder().build()) + .withMetadata(new V1ObjectMetaBuilder().withUid("123").build()).build(); + + K8sInstanceIdHostPodNameSupplier supplier = K8sInstanceIdHostPodNameSupplier.nonExternalName(endpointAddress, + service); + InstanceIdHostPodName result = supplier.get(); + + Assertions.assertNotNull(result); + Assertions.assertEquals(result.instanceId(), "456"); + } + + @Test + void hostNoEndpointAddress() { + V1Service service = new V1ServiceBuilder() + .withSpec(new V1ServiceSpecBuilder().withExternalName("external-name").build()) + .withMetadata(new V1ObjectMeta()).build(); + + K8sInstanceIdHostPodNameSupplier supplier = K8sInstanceIdHostPodNameSupplier.externalName(service); + InstanceIdHostPodName result = supplier.get(); + + Assertions.assertNotNull(result); + Assertions.assertEquals(result.host(), "external-name"); + } + + @Test + void hostWithEndpointAddress() { + V1EndpointAddress endpointAddress = new V1EndpointAddressBuilder().withIp("127.0.0.1").build(); + V1Service service = new V1ServiceBuilder() + .withSpec(new V1ServiceSpecBuilder().withExternalName("external-name").build()) + .withMetadata(new V1ObjectMeta()).build(); + + K8sInstanceIdHostPodNameSupplier supplier = K8sInstanceIdHostPodNameSupplier.nonExternalName(endpointAddress, + service); + InstanceIdHostPodName result = supplier.get(); + + Assertions.assertNotNull(result); + Assertions.assertEquals(result.host(), "127.0.0.1"); + } + + @Test + void testPodNameIsNull() { + V1Service service = new V1ServiceBuilder().withMetadata(new V1ObjectMetaBuilder().withUid("123").build()) + .withSpec(new V1ServiceSpecBuilder().withExternalName("external-name").build()).build(); + K8sInstanceIdHostPodNameSupplier supplier = K8sInstanceIdHostPodNameSupplier.externalName(service); + InstanceIdHostPodName result = supplier.get(); + + Assertions.assertNotNull(result); + Assertions.assertNull(result.podName()); + } + + @Test + void podNameKindNotPod() { + V1EndpointAddress endpointAddress = new V1EndpointAddressBuilder() + .withTargetRef(new V1ObjectReferenceBuilder().withKind("Service").build()).build(); + V1Service service = new V1ServiceBuilder() + .withSpec(new V1ServiceSpecBuilder().withExternalName("external-name").build()) + .withMetadata(new V1ObjectMeta()).build(); + + K8sInstanceIdHostPodNameSupplier supplier = K8sInstanceIdHostPodNameSupplier.nonExternalName(endpointAddress, + service); + InstanceIdHostPodName result = supplier.get(); + + Assertions.assertNotNull(result); + Assertions.assertNull(result.podName()); + } + + @Test + void podNameKindIsPod() { + V1EndpointAddress endpointAddress = new V1EndpointAddressBuilder() + .withTargetRef(new V1ObjectReferenceBuilder().withKind("Pod").withName("my-pod").build()).build(); + V1Service service = new V1ServiceBuilder() + .withSpec(new V1ServiceSpecBuilder().withExternalName("external-name").build()) + .withMetadata(new V1ObjectMeta()).build(); + + K8sInstanceIdHostPodNameSupplier supplier = K8sInstanceIdHostPodNameSupplier.nonExternalName(endpointAddress, + service); + InstanceIdHostPodName result = supplier.get(); + + Assertions.assertNotNull(result); + Assertions.assertEquals(result.podName(), "my-pod"); + } + +} diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/K8sPodLabelsAndAnnotationsSupplierTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/K8sPodLabelsAndAnnotationsSupplierTests.java new file mode 100644 index 0000000000..8b9ad13589 --- /dev/null +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/K8sPodLabelsAndAnnotationsSupplierTests.java @@ -0,0 +1,74 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.client.discovery; + +import java.util.Map; + +import io.kubernetes.client.openapi.apis.CoreV1Api; +import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder; +import io.kubernetes.client.openapi.models.V1PodBuilder; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import org.springframework.cloud.kubernetes.commons.discovery.PodLabelsAndAnnotations; + +/** + * @author wind57 + */ +class K8sPodLabelsAndAnnotationsSupplierTests { + + private static final String NAMESPACE = "spring-k8s"; + + private static final String POD_NAME = "my-pod"; + + private final CoreV1Api coreV1Api = Mockito.mock(CoreV1Api.class); + + @AfterEach + void afterEach() { + Mockito.reset(coreV1Api); + } + + @Test + void noObjetMeta() throws Exception { + + Mockito.when(coreV1Api.readNamespacedPod(POD_NAME, NAMESPACE, null)).thenReturn( + new V1PodBuilder().withMetadata(new V1ObjectMetaBuilder().withName(POD_NAME).build()).build()); + + PodLabelsAndAnnotations result = K8sPodLabelsAndAnnotationsSupplier.nonExternalName(coreV1Api, NAMESPACE) + .apply(POD_NAME); + Assertions.assertNotNull(result); + Assertions.assertTrue(result.labels().isEmpty()); + Assertions.assertTrue(result.annotations().isEmpty()); + } + + @Test + void labelsAndAnnotationsPresent() throws Exception { + + Mockito.when(coreV1Api.readNamespacedPod(POD_NAME, NAMESPACE, null)) + .thenReturn(new V1PodBuilder().withMetadata(new V1ObjectMetaBuilder().withName(POD_NAME) + .withLabels(Map.of("a", "b")).withAnnotations(Map.of("c", "d")).build()).build()); + + PodLabelsAndAnnotations result = K8sPodLabelsAndAnnotationsSupplier.nonExternalName(coreV1Api, NAMESPACE) + .apply(POD_NAME); + Assertions.assertNotNull(result); + Assertions.assertEquals(result.labels(), Map.of("a", "b")); + Assertions.assertEquals(result.annotations(), Map.of("c", "d")); + } + +} diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceMetadataTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceMetadataTests.java deleted file mode 100644 index 5d6b904aa1..0000000000 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceMetadataTests.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2013-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * 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.client.discovery; - -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import io.kubernetes.client.openapi.models.V1ObjectMeta; -import io.kubernetes.client.openapi.models.V1Service; -import io.kubernetes.client.openapi.models.V1ServiceSpec; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import org.springframework.boot.test.system.CapturedOutput; -import org.springframework.boot.test.system.OutputCaptureExtension; -import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; - -/** - * @author wind57 - */ -@ExtendWith(OutputCaptureExtension.class) -class KubernetesDiscoveryClientServiceMetadataTests { - - /** - *
-	 *     - labels are not added
-	 *     - annotations are not added
-	 * 
- */ - @Test - void testServiceMetadataEmpty() { - boolean addLabels = false; - String labelsPrefix = ""; - boolean addAnnotations = false; - String annotationsPrefix = ""; - boolean addPorts = false; - String portsPrefix = ""; - - KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(addLabels, - labelsPrefix, addAnnotations, annotationsPrefix, addPorts, portsPrefix); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, - true, "", Set.of(), Map.of(), "", metadata, 0, false, false); - V1Service service = new V1Service().spec(new V1ServiceSpec().type("ClusterIP")) - .metadata(new V1ObjectMeta().namespace("default")); - - Map result = KubernetesDiscoveryClientUtils.serviceMetadata(properties, service, "my-service"); - Assertions.assertEquals(result.size(), 2); - Assertions.assertEquals(result, Map.of("k8s_namespace", "default", "type", "ClusterIP")); - } - - /** - *
-	 *     - labels are added without a prefix
-	 *     - annotations are not added
-	 * 
- */ - @Test - void testServiceMetadataAddLabelsNoPrefix(CapturedOutput output) { - boolean addLabels = true; - String labelsPrefix = ""; - boolean addAnnotations = false; - String annotationsPrefix = ""; - boolean addPorts = false; - String portsPrefix = ""; - - KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(addLabels, - labelsPrefix, addAnnotations, annotationsPrefix, addPorts, portsPrefix); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, - true, "", Set.of(), Map.of(), "", metadata, 0, false, false); - V1Service service = new V1Service().spec(new V1ServiceSpec().type("ClusterIP")) - .metadata(new V1ObjectMeta().namespace("default").labels(Map.of("a", "b"))); - - Map result = KubernetesDiscoveryClientUtils.serviceMetadata(properties, service, "my-service"); - Assertions.assertEquals(result.size(), 3); - Assertions.assertEquals(result, Map.of("a", "b", "k8s_namespace", "default", "type", "ClusterIP")); - String labelsMetadata = filterOnK8sNamespaceAndType(result); - Assertions.assertTrue( - output.getOut().contains("Adding labels metadata: " + labelsMetadata + " for serviceId: my-service")); - } - - /** - *
-	 *     - labels are added with prefix
-	 *     - annotations are not added
-	 * 
- */ - @Test - void testServiceMetadataAddLabelsWithPrefix(CapturedOutput output) { - boolean addLabels = true; - String labelsPrefix = "prefix-"; - boolean addAnnotations = false; - String annotationsPrefix = ""; - boolean addPorts = false; - String portsPrefix = ""; - - KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(addLabels, - labelsPrefix, addAnnotations, annotationsPrefix, addPorts, portsPrefix); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, - true, "", Set.of(), Map.of(), "", metadata, 0, false, false); - V1Service service = new V1Service().spec(new V1ServiceSpec().type("ClusterIP")) - .metadata(new V1ObjectMeta().namespace("default").labels(Map.of("a", "b", "c", "d"))); - - Map result = KubernetesDiscoveryClientUtils.serviceMetadata(properties, service, "my-service"); - Assertions.assertEquals(result.size(), 4); - Assertions.assertEquals(result, - Map.of("prefix-a", "b", "prefix-c", "d", "k8s_namespace", "default", "type", "ClusterIP")); - // so that result is deterministic in assertion - String labelsMetadata = filterOnK8sNamespaceAndType(result); - Assertions.assertTrue( - output.getOut().contains("Adding labels metadata: " + labelsMetadata + " for serviceId: my-service")); - } - - /** - *
-	 *     - labels are not added
-	 *     - annotations are added without prefix
-	 * 
- */ - @Test - void testServiceMetadataAddAnnotationsNoPrefix(CapturedOutput output) { - boolean addLabels = false; - String labelsPrefix = ""; - boolean addAnnotations = true; - String annotationsPrefix = ""; - boolean addPorts = false; - String portsPrefix = ""; - - KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(addLabels, - labelsPrefix, addAnnotations, annotationsPrefix, addPorts, portsPrefix); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, - true, "", Set.of(), Map.of(), "", metadata, 0, false, false); - V1Service service = new V1Service().spec(new V1ServiceSpec().type("ClusterIP")).metadata( - new V1ObjectMeta().namespace("default").labels(Map.of("a", "b")).annotations(Map.of("aa", "bb"))); - - Map result = KubernetesDiscoveryClientUtils.serviceMetadata(properties, service, "my-service"); - Assertions.assertEquals(result.size(), 3); - Assertions.assertEquals(result, Map.of("aa", "bb", "k8s_namespace", "default", "type", "ClusterIP")); - Assertions - .assertTrue(output.getOut().contains("Adding annotations metadata: {aa=bb} for serviceId: my-service")); - } - - /** - *
-	 *     - labels are not added
-	 *     - annotations are added with prefix
-	 * 
- */ - @Test - void testServiceMetadataAddAnnotationsWithPrefix(CapturedOutput output) { - boolean addLabels = false; - String labelsPrefix = ""; - boolean addAnnotations = true; - String annotationsPrefix = "prefix-"; - boolean addPorts = false; - String portsPrefix = ""; - - KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(addLabels, - labelsPrefix, addAnnotations, annotationsPrefix, addPorts, portsPrefix); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, - true, "", Set.of(), Map.of(), "", metadata, 0, false, false); - V1Service service = new V1Service().spec(new V1ServiceSpec().type("ClusterIP")).metadata(new V1ObjectMeta() - .namespace("default").labels(Map.of("a", "b")).annotations(Map.of("aa", "bb", "cc", "dd"))); - - Map result = KubernetesDiscoveryClientUtils.serviceMetadata(properties, service, "my-service"); - Assertions.assertEquals(result.size(), 4); - Assertions.assertEquals(result, - Map.of("prefix-aa", "bb", "prefix-cc", "dd", "k8s_namespace", "default", "type", "ClusterIP")); - // so that result is deterministic in assertion - String annotations = filterOnK8sNamespaceAndType(result); - Assertions.assertTrue( - output.getOut().contains("Adding annotations metadata: " + annotations + " for serviceId: my-service")); - } - - /** - *
-	 *     - labels are added with prefix
-	 *     - annotations are added with prefix
-	 * 
- */ - @Test - void testServiceMetadataAddLabelsAndAnnotationsWithPrefix(CapturedOutput output) { - boolean addLabels = true; - String labelsPrefix = "label-"; - boolean addAnnotations = true; - String annotationsPrefix = "annotation-"; - boolean addPorts = false; - String portsPrefix = ""; - - KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(addLabels, - labelsPrefix, addAnnotations, annotationsPrefix, addPorts, portsPrefix); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, - true, "", Set.of(), Map.of(), "", metadata, 0, false, false); - V1Service service = new V1Service().spec(new V1ServiceSpec().type("ClusterIP")).metadata(new V1ObjectMeta() - .namespace("default").labels(Map.of("a", "b", "c", "d")).annotations(Map.of("aa", "bb", "cc", "dd"))); - - Map result = KubernetesDiscoveryClientUtils.serviceMetadata(properties, service, "my-service"); - Assertions.assertEquals(result.size(), 6); - Assertions.assertEquals(result, Map.of("annotation-aa", "bb", "annotation-cc", "dd", "label-a", "b", "label-c", - "d", "k8s_namespace", "default", "type", "ClusterIP")); - // so that result is deterministic in assertion - String labels = result.entrySet().stream().filter(en -> en.getKey().contains("label")) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)).toString(); - String annotations = result.entrySet().stream().filter(en -> en.getKey().contains("annotation")) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)).toString(); - Assertions.assertTrue( - output.getOut().contains("Adding labels metadata: " + labels + " for serviceId: my-service")); - Assertions.assertTrue( - output.getOut().contains("Adding annotations metadata: " + annotations + " for serviceId: my-service")); - } - - private String filterOnK8sNamespaceAndType(Map result) { - return result.entrySet().stream().filter(en -> !en.getKey().contains("k8s_namespace")) - .filter(en -> !en.getKey().equals("type")) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)).toString(); - } - -} diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientUtilsTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientUtilsTests.java index 4f3551e628..4cf2620b7a 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientUtilsTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientUtilsTests.java @@ -17,10 +17,16 @@ package org.springframework.cloud.kubernetes.client.discovery; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import io.kubernetes.client.openapi.models.CoreV1EndpointPortBuilder; +import io.kubernetes.client.openapi.models.V1EndpointAddress; +import io.kubernetes.client.openapi.models.V1EndpointAddressBuilder; +import io.kubernetes.client.openapi.models.V1EndpointSubset; +import io.kubernetes.client.openapi.models.V1EndpointSubsetBuilder; import io.kubernetes.client.openapi.models.V1ObjectMeta; import io.kubernetes.client.openapi.models.V1Service; import io.kubernetes.client.openapi.models.V1ServiceBuilder; @@ -32,6 +38,7 @@ import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; +import static org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryClientUtils.endpointSubsetsPortData; import static org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryClientUtils.matchesServiceLabels; /** @@ -161,6 +168,139 @@ void testFour(CapturedOutput output) { Assertions.assertTrue(output.getOut().contains("Service labels from service : {a=b, c=d}")); } + @Test + void testPortsDataOne() { + List endpointSubsets = List.of( + new V1EndpointSubsetBuilder() + .withPorts(new CoreV1EndpointPortBuilder().withPort(8081).withName("").build()).build(), + new V1EndpointSubsetBuilder() + .withPorts(new CoreV1EndpointPortBuilder().withPort(8080).withName("https").build()).build()); + + Map portsData = endpointSubsetsPortData(endpointSubsets); + Assertions.assertEquals(portsData.size(), 2); + Assertions.assertEquals(portsData.get("https"), 8080); + Assertions.assertEquals(portsData.get(""), 8081); + } + + @Test + void testPortsDataTwo() { + List endpointSubsets = List.of( + new V1EndpointSubsetBuilder() + .withPorts(new CoreV1EndpointPortBuilder().withPort(8081).withName("http").build()).build(), + new V1EndpointSubsetBuilder() + .withPorts(new CoreV1EndpointPortBuilder().withPort(8080).withName("https").build()).build()); + + Map portsData = endpointSubsetsPortData(endpointSubsets); + Assertions.assertEquals(portsData.size(), 2); + Assertions.assertEquals(portsData.get("https"), 8080); + Assertions.assertEquals(portsData.get("http"), 8081); + } + + @Test + void endpointSubsetPortsDataWithoutPorts() { + V1EndpointSubset endpointSubset = new V1EndpointSubsetBuilder().build(); + Map result = endpointSubsetsPortData(List.of(endpointSubset)); + + Assertions.assertEquals(result.size(), 0); + } + + @Test + void endpointSubsetPortsDataSinglePort() { + V1EndpointSubset endpointSubset = new V1EndpointSubsetBuilder() + .withPorts(new CoreV1EndpointPortBuilder().withName("name").withPort(80).build()).build(); + Map result = endpointSubsetsPortData(List.of(endpointSubset)); + + Assertions.assertEquals(result.size(), 1); + Assertions.assertEquals(result.get("name"), 80); + } + + @Test + void endpointSubsetPortsDataSinglePortNoName() { + V1EndpointSubset endpointSubset = new V1EndpointSubsetBuilder() + .withPorts(new CoreV1EndpointPortBuilder().withPort(80).build()).build(); + Map result = endpointSubsetsPortData(List.of(endpointSubset)); + + Assertions.assertEquals(result.size(), 1); + Assertions.assertEquals(result.get(""), 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); + V1EndpointSubset endpointSubset = new V1EndpointSubsetBuilder().build(); + List addresses = KubernetesDiscoveryClientUtils.addresses(endpointSubset, properties); + Assertions.assertEquals(addresses.size(), 0); + } + + /** + *
+	 *      - 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); + V1EndpointSubset endpointSubset = new V1EndpointSubsetBuilder() + .withAddresses(new V1EndpointAddressBuilder().withHostname("one").build(), + new V1EndpointAddressBuilder().withHostname("two").build()) + .build(); + List addresses = KubernetesDiscoveryClientUtils.addresses(endpointSubset, properties); + Assertions.assertEquals(addresses.size(), 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); + V1EndpointSubset endpointSubset = new V1EndpointSubsetBuilder() + .withAddresses(new V1EndpointAddressBuilder().withHostname("one").build(), + new V1EndpointAddressBuilder().withHostname("two").build()) + .withNotReadyAddresses(new V1EndpointAddressBuilder().withHostname("three").build()).build(); + List addresses = KubernetesDiscoveryClientUtils.addresses(endpointSubset, properties); + Assertions.assertEquals(addresses.size(), 2); + List hostNames = addresses.stream().map(V1EndpointAddress::getHostname).sorted().toList(); + Assertions.assertEquals(hostNames, List.of("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); + V1EndpointSubset endpointSubset = new V1EndpointSubsetBuilder() + .withAddresses(new V1EndpointAddressBuilder().withHostname("one").build(), + new V1EndpointAddressBuilder().withHostname("two").build()) + .withNotReadyAddresses(new V1EndpointAddressBuilder().withHostname("three").build()).build(); + List addresses = KubernetesDiscoveryClientUtils.addresses(endpointSubset, properties); + Assertions.assertEquals(addresses.size(), 3); + List hostNames = addresses.stream().map(V1EndpointAddress::getHostname).sorted().toList(); + Assertions.assertEquals(hostNames, List.of("one", "three", "two")); + } + // preserve order for testing reasons private Map ordered(Map input) { return input.entrySet().stream().sorted(Map.Entry.comparingByKey()).collect( diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtilsTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtilsTests.java index 5dcb172a83..a19db4f5e3 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtilsTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientUtilsTests.java @@ -292,7 +292,7 @@ void testPortsDataOne() { new EndpointSubsetBuilder() .withPorts(new EndpointPortBuilder().withPort(8080).withName("https").build()).build()); - Map portsData = Fabric8KubernetesDiscoveryClientUtils.endpointSubsetsPortData(endpointSubsets); + Map portsData = endpointSubsetsPortData(endpointSubsets); Assertions.assertEquals(portsData.size(), 2); Assertions.assertEquals(portsData.get("https"), 8080); Assertions.assertEquals(portsData.get(""), 8081); @@ -306,7 +306,7 @@ void testPortsDataTwo() { new EndpointSubsetBuilder() .withPorts(new EndpointPortBuilder().withPort(8080).withName("https").build()).build()); - Map portsData = Fabric8KubernetesDiscoveryClientUtils.endpointSubsetsPortData(endpointSubsets); + Map portsData = endpointSubsetsPortData(endpointSubsets); Assertions.assertEquals(portsData.size(), 2); Assertions.assertEquals(portsData.get("https"), 8080); Assertions.assertEquals(portsData.get("http"), 8081); diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientUtilsTests.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientUtilsTests.java index f1068dbcb9..f7abe74f7c 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientUtilsTests.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientUtilsTests.java @@ -26,15 +26,12 @@ import io.fabric8.kubernetes.api.model.EndpointSubsetBuilder; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; /** * @author wind57 */ -@ExtendWith(OutputCaptureExtension.class) class KubernetesDiscoveryClientUtilsTests { /** From 952a5c9de132594285cd22372920363aae61f55a Mon Sep 17 00:00:00 2001 From: wind57 Date: Mon, 6 Nov 2023 17:41:52 +0200 Subject: [PATCH 08/53] dirty --- .../discovery/KubernetesInformerDiscoveryClient.java | 4 ++-- .../KubernetesInformerDiscoveryClientTests.java | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java index d148d69df8..90bf7f8c78 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java @@ -152,8 +152,8 @@ private List serviceInstances(V1Service service, String service List instances = new ArrayList<>(); List allEndpoints = endpointsListers.stream() - .map(endpointsLister -> endpointsLister.get(serviceId)).filter(Objects::nonNull) - .filter(one -> service.getMetadata().getNamespace().equals(one.getMetadata().getNamespace())).toList(); + .map(endpointsLister -> endpointsLister.namespace(service.getMetadata().getNamespace()) + .get(serviceId)).filter(Objects::nonNull).toList(); for (V1Endpoints endpoints : allEndpoints) { List subsets = endpoints.getSubsets(); diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java index 626009fa2b..16f8cdddf0 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java @@ -188,8 +188,8 @@ void testDiscoveryGetInstanceAllNamespaceShouldWork() { SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")) - .containsOnly(new DefaultKubernetesServiceInstance("", "test-svc-1", "2.2.2.2", 8080, - Map.of("", "8080", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, + .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "2.2.2.2", 8080, + Map.of("port.", "8080", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, "namespace1", null)); } @@ -202,8 +202,8 @@ void testDiscoveryGetInstanceOneNamespaceShouldWork() { SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")) - .containsOnly(new DefaultKubernetesServiceInstance("", "test-svc-1", "2.2.2.2", 8080, - Map.of("", "8080", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, + .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "2.2.2.2", 8080, + Map.of("port.", "8080", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, "namespace1", null)); } @@ -303,7 +303,7 @@ void instanceWithMultiplePortsAndGenericPrimaryPortNameConfiguredShouldWork() { SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")) - .containsOnly(new DefaultKubernetesServiceInstance("", "test-svc-1", "1.1.1.1", 443, + .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "1.1.1.1", 443, Map.of("http", "80", "https", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, "namespace1", null)); } From edd5bd472fbb66d7285cf0f2ec618b2ec9a4ed24 Mon Sep 17 00:00:00 2001 From: wind57 Date: Mon, 6 Nov 2023 17:56:31 +0200 Subject: [PATCH 09/53] dirty --- ...ubernetesInformerDiscoveryClientTests.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java index 16f8cdddf0..05de125fa9 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java @@ -89,8 +89,8 @@ void testServiceWithUnsetPortNames() { SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1").toArray()) - .containsOnly(new DefaultKubernetesServiceInstance("", "test-svc-1", "1.1.1.1", 80, - Map.of("", "80", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, + .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "1.1.1.1", 80, + Map.of("port.", "80", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, "namespace1", null)); } @@ -138,7 +138,7 @@ void testDiscoveryInstancesWithServiceLabels() { assertThat(discoveryClient.getInstances("test-svc-3").toArray()) .containsOnly( new DefaultKubernetesServiceInstance( - "", "test-svc-3", "2.2.2.2", 8080, Map.of("spring", "true", "", "8080", "k8s", + null, "test-svc-3", "2.2.2.2", 8080, Map.of("spring", "true", "port.", "8080", "k8s", "true", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, "namespace1", null)); } @@ -232,8 +232,8 @@ void testDiscoveryGetInstanceWithNotReadyAddressesIncludedShouldWork() { SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); assertThat(discoveryClient.getInstances("test-svc-1")) - .containsOnly(new DefaultKubernetesServiceInstance("", "test-svc-1", "2.2.2.2", 8080, - Map.of("", "8080", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, + .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "2.2.2.2", 8080, + Map.of("port.", "8080", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, "namespace1", null)); } @@ -289,8 +289,8 @@ void instanceWithMultiplePortsAndMisconfiguredPrimaryPortNameInLabelShouldReturn assertThat(discoveryClient.getInstances("test-svc-1")) .containsOnly( new DefaultKubernetesServiceInstance( - "", "test-svc-1", "1.1.1.1", 80, Map.of("tcp1", "80", "primary-port-name", "oops", - "tcp2", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), + null, "test-svc-1", "1.1.1.1", 80, Map.of("port.tcp1", "80", "primary-port-name", "oops", + "port.tcp2", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, "namespace1", null)); } @@ -304,7 +304,7 @@ void instanceWithMultiplePortsAndGenericPrimaryPortNameConfiguredShouldWork() { assertThat(discoveryClient.getInstances("test-svc-1")) .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "1.1.1.1", 443, - Map.of("http", "80", "https", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, + Map.of("port.http", "80", "port.https", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), true, "namespace1", null)); } @@ -318,8 +318,8 @@ void instanceWithMultiplePortsAndMisconfiguredGenericPrimaryPortNameShouldReturn SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")) - .containsOnly(new DefaultKubernetesServiceInstance("", "test-svc-1", "1.1.1.1", 80, - Map.of("tcp1", "80", "tcp2", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, + .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "1.1.1.1", 80, + Map.of("port.tcp1", "80", "port.tcp2", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, "namespace1", null)); } @@ -332,9 +332,9 @@ void instanceWithMultiplePortsAndWithoutPrimaryPortNameSpecifiedShouldFallBackTo SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")) - .containsOnly(new DefaultKubernetesServiceInstance("", "test-svc-1", "1.1.1.1", 443, - Map.of("http", "80", "https", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, - "namespace1", null)); + .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "1.1.1.1", 443, + Map.of("port.http", "80", "port.https", "443", + "k8s_namespace", "namespace1", "type", "ClusterIP"), true, "namespace1", null)); } @Test @@ -361,8 +361,8 @@ void instanceWithMultiplePortsAndWithoutAnyConfigurationShouldPickTheFirstPort() SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")) - .containsOnly(new DefaultKubernetesServiceInstance("", "test-svc-1", "1.1.1.1", 80, - Map.of("tcp1", "80", "tcp2", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, + .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "1.1.1.1", 80, + Map.of("port.tcp1", "80", "port.tcp2", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, "namespace1", null)); } @@ -375,11 +375,11 @@ void getInstancesShouldReturnInstancesWithTheSameServiceIdFromNamespaces() { SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly( - new DefaultKubernetesServiceInstance("", "test-svc-1", "2.2.2.2", 8080, - Map.of("", "8080", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, + new DefaultKubernetesServiceInstance(null, "test-svc-1", "2.2.2.2", 8080, + Map.of("port.", "8080", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, "namespace1", null), - new DefaultKubernetesServiceInstance("", "test-svc-1", "2.2.2.2", 8080, - Map.of("", "8080", "k8s_namespace", "namespace2", "type", "ClusterIP"), false, + new DefaultKubernetesServiceInstance(null, "test-svc-1", "2.2.2.2", 8080, + Map.of("port.", "8080", "k8s_namespace", "namespace2", "type", "ClusterIP"), false, "namespace2", null)); } From a17e1c76d25610b8fdb75f7ba7bb4ddc5f704eef Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 7 Nov 2023 15:03:33 +0200 Subject: [PATCH 10/53] dirty --- ...ubernetesInformerDiscoveryClientTests.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java index 05de125fa9..6c700f0638 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java @@ -250,7 +250,7 @@ void instanceWithoutEndpointsShouldBeSkipped() { } @Test - void instanceWithoutPortsShouldBeSkipped() { + void instanceWithoutPortsWillNotBeSkipped() { Lister serviceLister = setupServiceLister(SERVICE_1); Lister endpointsLister = setupEndpointsLister(ENDPOINTS_NO_PORTS); @@ -258,7 +258,11 @@ void instanceWithoutPortsShouldBeSkipped() { SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, KubernetesDiscoveryProperties.DEFAULT); - assertThat(discoveryClient.getInstances("test-svc-1")).isEmpty(); + assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly( + new DefaultKubernetesServiceInstance( + null, "test-svc-1", "1.1.1.1", 0, Map.of("k8s_namespace", "namespace1", "type", "ClusterIP"), + false, "namespace1", null) + ); } @Test @@ -272,9 +276,9 @@ void instanceWithMultiplePortsAndPrimaryPortNameConfiguredWithLabelShouldWork() assertThat(discoveryClient.getInstances("test-svc-1")) .containsOnly( new DefaultKubernetesServiceInstance( - "", "test-svc-1", "1.1.1.1", 443, Map.of("http", "80", "primary-port-name", "https", - "https", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), - false, "namespace1", null)); + null, "test-svc-1", "1.1.1.1", 443, Map.of("port.http", "80", "primary-port-name", + "https", "port.https", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), + true, "namespace1", null)); } @Test @@ -346,9 +350,9 @@ void instanceWithMultiplePortsAndWithoutPrimaryPortNameSpecifiedOrHttpsPortShoul SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")) - .containsOnly(new DefaultKubernetesServiceInstance("", "test-svc-1", "1.1.1.1", 80, - Map.of("http", "80", "tcp", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, - "namespace1", null)); + .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "1.1.1.1", 80, + Map.of("port.http", "80", "port.tcp", "443", "k8s_namespace", "namespace1", + "type", "ClusterIP"), false, "namespace1", null)); } @Test From 45ca67b86962d3937490f957bf9dbd268f92d5c5 Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 7 Nov 2023 20:13:15 +0200 Subject: [PATCH 11/53] dirty --- .../KubernetesInformerDiscoveryClient.java | 24 ++++++++++++++++++- ...sInformerReactiveDiscoveryClientTests.java | 21 +++++++++------- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java index 90bf7f8c78..b7f0ddafd8 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java @@ -53,6 +53,7 @@ import static org.springframework.cloud.kubernetes.commons.discovery.DiscoveryClientUtils.endpointsPort; import static org.springframework.cloud.kubernetes.commons.discovery.DiscoveryClientUtils.serviceInstance; import static org.springframework.cloud.kubernetes.commons.discovery.DiscoveryClientUtils.serviceInstanceMetadata; +import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryConstants.EXTERNAL_NAME; /** * @author Min Kim @@ -143,8 +144,29 @@ public List getInstances(String serviceId) { .filter(scv -> scv.getMetadata() != null).filter(svc -> serviceId.equals(svc.getMetadata().getName())) .filter(scv -> matchesServiceLabels(scv, properties)).filter(filter).toList(); - return services.stream().flatMap(service -> serviceInstances(service, serviceId).stream()).toList(); + List serviceInstances = + services.stream().flatMap(service -> serviceInstances(service, serviceId).stream()).toList(); + 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) { + ServiceMetadata serviceMetadata = serviceMetadata(service); + Map serviceInstanceMetadata = serviceInstanceMetadata(Map.of(), serviceMetadata, + properties); + + Fabric8InstanceIdHostPodNameSupplier supplierOne = externalName(service); + Fabric8PodLabelsAndAnnotationsSupplier supplierTwo = externalName(); + + ServiceInstance externalNameServiceInstance = serviceInstance(null, serviceMetadata, supplierOne, + supplierTwo, new ServicePortNameAndNumber(-1, null), serviceInstanceMetadata, properties); + instances.add(externalNameServiceInstance); + } + } + + return serviceInstances; } private List serviceInstances(V1Service service, String serviceId) { diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClientTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClientTests.java index 16d98059e3..a5b9e32124 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClientTests.java @@ -30,6 +30,7 @@ import io.kubernetes.client.openapi.models.V1ObjectMeta; import io.kubernetes.client.openapi.models.V1Service; import io.kubernetes.client.openapi.models.V1ServiceSpec; +import io.kubernetes.client.openapi.models.V1ServiceSpecBuilder; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -128,8 +129,8 @@ void testDiscoveryGetInstanceAllNamespaceShouldWork() { kubernetesDiscoveryProperties)); StepVerifier.create(discoveryClient.getInstances("test-svc-1")) - .expectNext(new DefaultKubernetesServiceInstance("", "test-svc-1", "2.2.2.2", 8080, - Map.of("type", "ClusterIP", "", "8080", "k8s_namespace", "namespace1"), false, + .expectNext(new DefaultKubernetesServiceInstance(null, "test-svc-1", "2.2.2.2", 8080, + Map.of("type", "ClusterIP", "port.", "8080", "k8s_namespace", "namespace1"), false, "namespace1", null)) .expectComplete().verify(); @@ -149,8 +150,8 @@ void testDiscoveryGetInstanceOneNamespaceShouldWork() { kubernetesDiscoveryProperties)); StepVerifier.create(discoveryClient.getInstances("test-svc-1")) - .expectNext(new DefaultKubernetesServiceInstance("", "test-svc-1", "2.2.2.2", 8080, - Map.of("type", "ClusterIP", "", "8080", "k8s_namespace", "namespace1"), false, + .expectNext(new DefaultKubernetesServiceInstance(null, "test-svc-1", "2.2.2.2", 8080, + Map.of("type", "ClusterIP", "port.", "8080", "k8s_namespace", "namespace1"), false, "namespace1", null)) .expectComplete().verify(); @@ -237,9 +238,11 @@ void testAllNamespacesTwoEndpointsPresent() { boolean allNamespaces = true; V1Service serviceXNamespaceA = new V1Service() - .metadata(new V1ObjectMeta().name("endpoints-x").namespace("namespace-a")); + .metadata(new V1ObjectMeta().name("endpoints-x").namespace("namespace-a")) + .spec(new V1ServiceSpecBuilder().withType("ClusterIP").build()); V1Service serviceXNamespaceB = new V1Service() - .metadata(new V1ObjectMeta().name("endpoints-x").namespace("namespace-b")); + .metadata(new V1ObjectMeta().name("endpoints-x").namespace("namespace-b")) + .spec(new V1ServiceSpecBuilder().withType("ClusterIP").build()); serviceCache.add(serviceXNamespaceA); serviceCache.add(serviceXNamespaceB); @@ -286,9 +289,11 @@ void testAllSingleTwoEndpointsPresent() { boolean allNamespaces = true; V1Service serviceXNamespaceA = new V1Service() - .metadata(new V1ObjectMeta().name("endpoints-x").namespace("namespace-a")); + .metadata(new V1ObjectMeta().name("endpoints-x").namespace("namespace-a")) + .spec(new V1ServiceSpecBuilder().withType("ClusterIP").build()); V1Service serviceXNamespaceB = new V1Service() - .metadata(new V1ObjectMeta().name("endpoints-x").namespace("namespace-b")); + .metadata(new V1ObjectMeta().name("endpoints-x").namespace("namespace-b")) + .spec(new V1ServiceSpecBuilder().withType("ClusterIP").build()); serviceCache.add(serviceXNamespaceA); serviceCache.add(serviceXNamespaceB); From 39dd56cf5dd3f49e1c2893bb1388f1bb1300c555 Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 8 Nov 2023 12:08:54 +0200 Subject: [PATCH 12/53] before tests and IT --- .../KubernetesInformerDiscoveryClient.java | 33 ++++---- ...ubernetesInformerDiscoveryClientTests.java | 76 +++++++++---------- 2 files changed, 53 insertions(+), 56 deletions(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java index b7f0ddafd8..44ce41123c 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java @@ -22,6 +22,7 @@ import java.util.Objects; import java.util.function.Predicate; import java.util.function.Supplier; +import java.util.stream.Collectors; import io.kubernetes.client.informer.SharedInformer; import io.kubernetes.client.informer.SharedInformerFactory; @@ -42,7 +43,9 @@ import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; import org.springframework.core.log.LogAccessor; +import static org.springframework.cloud.kubernetes.client.discovery.K8sInstanceIdHostPodNameSupplier.externalName; import static org.springframework.cloud.kubernetes.client.discovery.K8sInstanceIdHostPodNameSupplier.nonExternalName; +import static org.springframework.cloud.kubernetes.client.discovery.K8sPodLabelsAndAnnotationsSupplier.externalName; import static org.springframework.cloud.kubernetes.client.discovery.K8sPodLabelsAndAnnotationsSupplier.nonExternalName; import static org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryClientUtils.addresses; import static org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryClientUtils.endpointSubsetsPortData; @@ -140,29 +143,29 @@ public String description() { public List getInstances(String serviceId) { Objects.requireNonNull(serviceId, "serviceId must be provided"); - List services = serviceListers.stream().flatMap(x -> x.list().stream()) + List allServices = serviceListers.stream().flatMap(x -> x.list().stream()) .filter(scv -> scv.getMetadata() != null).filter(svc -> serviceId.equals(svc.getMetadata().getName())) - .filter(scv -> matchesServiceLabels(scv, properties)).filter(filter).toList(); + .filter(scv -> matchesServiceLabels(scv, properties)).toList(); - List serviceInstances = - services.stream().flatMap(service -> serviceInstances(service, serviceId).stream()).toList(); + List serviceInstances = allServices.stream().filter(filter) + .flatMap(service -> serviceInstances(service, serviceId).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 (V1Service service : externalNameServices) { ServiceMetadata serviceMetadata = serviceMetadata(service); Map serviceInstanceMetadata = serviceInstanceMetadata(Map.of(), serviceMetadata, - properties); + properties); - Fabric8InstanceIdHostPodNameSupplier supplierOne = externalName(service); - Fabric8PodLabelsAndAnnotationsSupplier supplierTwo = externalName(); + K8sInstanceIdHostPodNameSupplier supplierOne = externalName(service); + K8sPodLabelsAndAnnotationsSupplier supplierTwo = externalName(); ServiceInstance externalNameServiceInstance = serviceInstance(null, serviceMetadata, supplierOne, - supplierTwo, new ServicePortNameAndNumber(-1, null), serviceInstanceMetadata, properties); - instances.add(externalNameServiceInstance); + supplierTwo, new ServicePortNameAndNumber(-1, null), serviceInstanceMetadata, properties); + serviceInstances.add(externalNameServiceInstance); } } @@ -174,8 +177,8 @@ private List serviceInstances(V1Service service, String service List instances = new ArrayList<>(); List allEndpoints = endpointsListers.stream() - .map(endpointsLister -> endpointsLister.namespace(service.getMetadata().getNamespace()) - .get(serviceId)).filter(Objects::nonNull).toList(); + .map(endpointsLister -> endpointsLister.namespace(service.getMetadata().getNamespace()).get(serviceId)) + .filter(Objects::nonNull).toList(); for (V1Endpoints endpoints : allEndpoints) { List subsets = endpoints.getSubsets(); diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java index 6c700f0638..1efe3c6b76 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java @@ -136,11 +136,10 @@ void testDiscoveryInstancesWithServiceLabels() { assertThat(discoveryClient.getInstances("test-svc-1").toArray()).isEmpty(); assertThat(discoveryClient.getInstances("test-svc-3").toArray()) - .containsOnly( - new DefaultKubernetesServiceInstance( - null, "test-svc-3", "2.2.2.2", 8080, Map.of("spring", "true", "port.", "8080", "k8s", - "true", "k8s_namespace", "namespace1", "type", "ClusterIP"), - false, "namespace1", null)); + .containsOnly(new DefaultKubernetesServiceInstance( + null, "test-svc-3", "2.2.2.2", 8080, Map.of("spring", "true", "port.", "8080", "k8s", + "true", "k8s_namespace", "namespace1", "type", "ClusterIP"), + false, "namespace1", null)); } @Test @@ -258,11 +257,9 @@ void instanceWithoutPortsWillNotBeSkipped() { SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, KubernetesDiscoveryProperties.DEFAULT); - assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly( - new DefaultKubernetesServiceInstance( - null, "test-svc-1", "1.1.1.1", 0, Map.of("k8s_namespace", "namespace1", "type", "ClusterIP"), - false, "namespace1", null) - ); + assertThat(discoveryClient.getInstances("test-svc-1")) + .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "1.1.1.1", 0, + Map.of("k8s_namespace", "namespace1", "type", "ClusterIP"), false, "namespace1", null)); } @Test @@ -273,12 +270,10 @@ void instanceWithMultiplePortsAndPrimaryPortNameConfiguredWithLabelShouldWork() KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient( SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); - assertThat(discoveryClient.getInstances("test-svc-1")) - .containsOnly( - new DefaultKubernetesServiceInstance( - null, "test-svc-1", "1.1.1.1", 443, Map.of("port.http", "80", "primary-port-name", - "https", "port.https", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), - true, "namespace1", null)); + assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance( + null, "test-svc-1", "1.1.1.1", 443, Map.of("port.http", "80", "primary-port-name", "https", + "port.https", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), + true, "namespace1", null)); } @Test @@ -291,11 +286,10 @@ void instanceWithMultiplePortsAndMisconfiguredPrimaryPortNameInLabelShouldReturn SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); assertThat(discoveryClient.getInstances("test-svc-1")) - .containsOnly( - new DefaultKubernetesServiceInstance( - null, "test-svc-1", "1.1.1.1", 80, Map.of("port.tcp1", "80", "primary-port-name", "oops", - "port.tcp2", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), - false, "namespace1", null)); + .containsOnly(new DefaultKubernetesServiceInstance( + null, "test-svc-1", "1.1.1.1", 80, Map.of("port.tcp1", "80", "primary-port-name", "oops", + "port.tcp2", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), + false, "namespace1", null)); } @Test @@ -306,10 +300,10 @@ void instanceWithMultiplePortsAndGenericPrimaryPortNameConfiguredShouldWork() { KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient( SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); - assertThat(discoveryClient.getInstances("test-svc-1")) - .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "1.1.1.1", 443, - Map.of("port.http", "80", "port.https", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), true, - "namespace1", null)); + assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance(null, + "test-svc-1", "1.1.1.1", 443, + Map.of("port.http", "80", "port.https", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), + true, "namespace1", null)); } @Test @@ -321,10 +315,10 @@ void instanceWithMultiplePortsAndMisconfiguredGenericPrimaryPortNameShouldReturn KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient( SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); - assertThat(discoveryClient.getInstances("test-svc-1")) - .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "1.1.1.1", 80, - Map.of("port.tcp1", "80", "port.tcp2", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, - "namespace1", null)); + assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance(null, + "test-svc-1", "1.1.1.1", 80, + Map.of("port.tcp1", "80", "port.tcp2", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), + false, "namespace1", null)); } @Test @@ -335,10 +329,10 @@ void instanceWithMultiplePortsAndWithoutPrimaryPortNameSpecifiedShouldFallBackTo KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient( SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); - assertThat(discoveryClient.getInstances("test-svc-1")) - .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "1.1.1.1", 443, - Map.of("port.http", "80", "port.https", "443", - "k8s_namespace", "namespace1", "type", "ClusterIP"), true, "namespace1", null)); + assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance(null, + "test-svc-1", "1.1.1.1", 443, + Map.of("port.http", "80", "port.https", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), + true, "namespace1", null)); } @Test @@ -349,10 +343,10 @@ void instanceWithMultiplePortsAndWithoutPrimaryPortNameSpecifiedOrHttpsPortShoul KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient( SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); - assertThat(discoveryClient.getInstances("test-svc-1")) - .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "1.1.1.1", 80, - Map.of("port.http", "80", "port.tcp", "443", "k8s_namespace", "namespace1", - "type", "ClusterIP"), false, "namespace1", null)); + assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance(null, + "test-svc-1", "1.1.1.1", 80, + Map.of("port.http", "80", "port.tcp", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, + "namespace1", null)); } @Test @@ -364,10 +358,10 @@ void instanceWithMultiplePortsAndWithoutAnyConfigurationShouldPickTheFirstPort() KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient( SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, NOT_ALL_NAMESPACES); - assertThat(discoveryClient.getInstances("test-svc-1")) - .containsOnly(new DefaultKubernetesServiceInstance(null, "test-svc-1", "1.1.1.1", 80, - Map.of("port.tcp1", "80", "port.tcp2", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), false, - "namespace1", null)); + assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(new DefaultKubernetesServiceInstance(null, + "test-svc-1", "1.1.1.1", 80, + Map.of("port.tcp1", "80", "port.tcp2", "443", "k8s_namespace", "namespace1", "type", "ClusterIP"), + false, "namespace1", null)); } @Test From 1ffe776f5e90dfcacc720a3f7202c5d6261f01d9 Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 8 Nov 2023 21:46:37 +0200 Subject: [PATCH 13/53] started working on tests --- ...etesDiscoveryClientFilterMetadataTest.java | 285 ++++++++++++++++++ ...ubernetesInformerDiscoveryClientTests.java | 95 ++++++ .../discovery/SharedInformerFactoryStub.java | 31 ++ .../client/discovery/SharedInformerStub.java | 65 ++++ 4 files changed, 476 insertions(+) create mode 100644 spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientFilterMetadataTest.java create mode 100644 spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/SharedInformerFactoryStub.java create mode 100644 spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/SharedInformerStub.java diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientFilterMetadataTest.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientFilterMetadataTest.java new file mode 100644 index 0000000000..62d38a2e5c --- /dev/null +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientFilterMetadataTest.java @@ -0,0 +1,285 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.client.discovery; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import io.kubernetes.client.informer.cache.Cache; +import io.kubernetes.client.informer.cache.Lister; +import io.kubernetes.client.openapi.models.CoreV1EndpointPort; +import io.kubernetes.client.openapi.models.CoreV1EndpointPortBuilder; +import io.kubernetes.client.openapi.models.V1Endpoints; +import io.kubernetes.client.openapi.models.V1EndpointsBuilder; +import io.kubernetes.client.openapi.models.V1ObjectMeta; +import io.kubernetes.client.openapi.models.V1Service; +import io.kubernetes.client.openapi.models.V1ServiceBuilder; +import io.kubernetes.client.openapi.models.V1ServicePort; +import io.kubernetes.client.openapi.models.V1ServicePortBuilder; +import io.kubernetes.client.openapi.models.V1ServiceSpecBuilder; +import org.assertj.core.util.Strings; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; + +import static java.util.Map.entry; +import static java.util.stream.Collectors.toList; +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +class KubernetesDiscoveryClientFilterMetadataTest { + + private static final SharedInformerFactoryStub STUB = new SharedInformerFactoryStub(); + + private static final SharedInformerStub SERVICE_SHARED_INFORMER_STUB = new SharedInformerStub<>(); + + private static final SharedInformerStub ENDPOINTS_SHARED_INFORMER_STUB = new SharedInformerStub<>(); + + private Cache servicesCache; + + private Lister servicesLister; + + private Cache endpointsCache; + + private Lister endpointsLister; + + @BeforeEach + void beforeEach() { + servicesCache = new Cache<>(); + servicesLister = new Lister<>(servicesCache); + + endpointsCache = new Cache<>(); + endpointsLister = new Lister<>(endpointsCache); + } + + @Test + void testAllExtraMetadataDisabled() { + String serviceId = "s"; + + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.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); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "lab"), Map.of("l1", "lab"), + Map.of(80, "http", 5555, "")); + + List instances = discoveryClient.getInstances(serviceId); + assertThat(instances).hasSize(1); + assertThat(instances.get(0).getMetadata()).isEqualTo(Map.of("k8s_namespace", "ns", "type", "ClusterIP")); + } + + @Test + void testLabelsEnabled() { + String serviceId = "s"; + + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(true, 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); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "v1", "l2", "v2"), + Map.of("l1", "lab"), Map.of(80, "http", 5555, "")); + + List instances = discoveryClient.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")); + } + + @Test + void testLabelsEnabledWithPrefix() { + String serviceId = "s"; + + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(true, "l_", false, + null, false, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, + false, null, Set.of(), Map.of(), null, metadata, 0, true); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "v1", "l2", "v2"), + Map.of("l1", "lab"), Map.of(80, "http", 5555, "")); + + 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")); + } + + @Test + void testAnnotationsEnabled() { + String serviceId = "s"; + + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(false, 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); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "v1"), + Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + + 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")); + } + + @Test + void testAnnotationsEnabledWithPrefix() { + String serviceId = "s"; + + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(false, null, true, + "a_", false, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, + false, null, Set.of(), Map.of(), null, metadata, 0, true); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "v1"), + Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + + 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")); + } + + @Test + void testPortsEnabled() { + String serviceId = "s"; + + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(false, null, false, + null, true, null); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, + false, null, Set.of(), Map.of(), null, metadata, 0, true); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "test", Map.of("l1", "v1"), + Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + + List instances = discoveryClient.getInstances(serviceId); + assertThat(instances).hasSize(1); + assertThat(instances.get(0).getMetadata()).containsOnly(entry("http", "80"), entry("k8s_namespace", "test"), + entry("", "5555"), entry("type", "ClusterIP")); + } + + @Test + void testPortsEnabledWithPrefix() { + String serviceId = "s"; + + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(false, null, false, + null, true, "p_"); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, + false, null, Set.of(), Map.of(), null, metadata, 0, true); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "v1"), + Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + + List instances = discoveryClient.getInstances(serviceId); + assertThat(instances).hasSize(1); + assertThat(instances.get(0).getMetadata()).containsOnly(entry("p_http", "80"), entry("k8s_namespace", "ns"), + entry("p_", "5555"), entry("type", "ClusterIP")); + } + + @Test + void testLabelsAndAnnotationsAndPortsEnabledWithPrefix() { + String serviceId = "s"; + + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(true, "l_", true, + "a_", true, "p_"); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, + false, null, Set.of(), Map.of(), null, metadata, 0, true); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "la1"), + Map.of("a1", "an1", "a2", "an2"), Map.of(80, "http", 5555, "")); + + 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("p_", "5555")); + } + + private void setupServiceWithLabelsAndAnnotationsAndPorts(String serviceId, String namespace, + Map labels, Map annotations, Map ports) { + + V1Service service = new V1ServiceBuilder() + .withSpec(new V1ServiceSpecBuilder().withType("ClusterIP").withPorts(getServicePorts(ports)).build()) + .withNewMetadata().withName(serviceId).withNamespace(namespace).withLabels(labels) + .withAnnotations(annotations).endMetadata().build(); + + servicesCache.add(service); + + V1ObjectMeta objectMeta = new V1ObjectMeta(); + objectMeta.setNamespace(namespace); + objectMeta.setName(serviceId); + + V1Endpoints endpoints = new V1EndpointsBuilder().withMetadata(objectMeta).addNewSubset() + .addAllToPorts(getEndpointPorts(ports)).addNewAddress().endAddress().endSubset().build(); + + endpointsCache.add(endpoints); + + } + + private List getServicePorts(Map ports) { + return ports.entrySet().stream().map(e -> { + V1ServicePortBuilder servicePortBuilder = new V1ServicePortBuilder(); + 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 -> { + CoreV1EndpointPortBuilder endpointPortBuilder = new CoreV1EndpointPortBuilder(); + endpointPortBuilder.withPort(e.getKey()); + if (!Strings.isNullOrEmpty(e.getValue())) { + endpointPortBuilder.withName(e.getValue()); + } + return endpointPortBuilder.build(); + }).collect(toList()); + } + +} diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java index 1efe3c6b76..423a614347 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java @@ -21,16 +21,35 @@ import java.util.Map; import java.util.Set; +import io.fabric8.kubernetes.api.model.EndpointAddressBuilder; +import io.fabric8.kubernetes.api.model.EndpointPortBuilder; +import io.fabric8.kubernetes.api.model.EndpointSubsetBuilder; +import io.fabric8.kubernetes.api.model.EndpointsBuilder; +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.fabric8.kubernetes.api.model.ObjectReferenceBuilder; +import io.fabric8.kubernetes.api.model.PodBuilder; +import io.fabric8.kubernetes.api.model.Service; +import io.fabric8.kubernetes.api.model.ServiceBuilder; +import io.fabric8.kubernetes.api.model.ServiceSpecBuilder; import io.kubernetes.client.informer.SharedInformerFactory; import io.kubernetes.client.informer.cache.Cache; import io.kubernetes.client.informer.cache.Lister; import io.kubernetes.client.openapi.models.CoreV1EndpointPort; +import io.kubernetes.client.openapi.models.CoreV1EndpointPortBuilder; import io.kubernetes.client.openapi.models.V1EndpointAddress; +import io.kubernetes.client.openapi.models.V1EndpointAddressBuilder; import io.kubernetes.client.openapi.models.V1EndpointSubset; +import io.kubernetes.client.openapi.models.V1EndpointSubsetBuilder; import io.kubernetes.client.openapi.models.V1Endpoints; +import io.kubernetes.client.openapi.models.V1EndpointsBuilder; import io.kubernetes.client.openapi.models.V1ObjectMeta; +import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder; +import io.kubernetes.client.openapi.models.V1ObjectReferenceBuilder; import io.kubernetes.client.openapi.models.V1Service; +import io.kubernetes.client.openapi.models.V1ServiceBuilder; import io.kubernetes.client.openapi.models.V1ServiceSpec; +import io.kubernetes.client.openapi.models.V1ServiceSpecBuilder; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -494,6 +513,82 @@ void testServicesWithSameMetadataLabels() { assertThat(serviceInstances.get(1).getMetadata().get("k8s_namespace")).isEqualTo("namespaceB"); } + @Test + void testExternalNameService() { + V1Service externalNameService = new V1ServiceBuilder() + .withSpec(new V1ServiceSpecBuilder().withType("ExternalName").withExternalName("k8s-spring-b").build()) + .withNewMetadata().withLabels(Map.of("label-key", "label-value")).withAnnotations(Map.of("abc", "def")) + .withName("blue-service").withNamespace("b").endMetadata().build(); + + V1Endpoints endpoints = new V1EndpointsBuilder() + .withMetadata(new V1ObjectMeta().namespace("irrelevant")).build(); + + Lister serviceLister = setupServiceLister(externalNameService); + Lister endpointsLister = setupEndpointsLister(endpoints); + + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(true, + "labels-prefix-", true, "annotations-prefix-", true, "ports-prefix"); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of("a", "b"), true, + 60L, false, "", Set.of(), Map.of(), "", metadata, 0, false, true); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient( + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, properties); + + List result = discoveryClient.getInstances("blue-service"); + Assertions.assertEquals(result.size(), 1); + DefaultKubernetesServiceInstance externalNameServiceInstance = (DefaultKubernetesServiceInstance) result.get(0); + Assertions.assertEquals(externalNameServiceInstance.getServiceId(), "blue-service"); + Assertions.assertEquals(externalNameServiceInstance.getHost(), "k8s-spring-b"); + Assertions.assertEquals(externalNameServiceInstance.getPort(), -1); + Assertions.assertFalse(externalNameServiceInstance.isSecure()); + Assertions.assertEquals(externalNameServiceInstance.getUri().toASCIIString(), "k8s-spring-b"); + Assertions.assertEquals(externalNameServiceInstance.getMetadata(), Map.of("k8s_namespace", "b", + "labels-prefix-label-key", "label-value", "annotations-prefix-abc", "def", "type", "ExternalName")); + } + + @Test + void testPodMetadata() { + V1Service nonExternalNameService = new V1ServiceBuilder() + .withSpec(new V1ServiceSpecBuilder().withType("ClusterIP").build()).withNewMetadata() + .withName("blue-service").withNamespace("a").endMetadata().build(); + + V1Endpoints endpoints = new V1EndpointsBuilder() + .withMetadata(new V1ObjectMetaBuilder().withName("blue-service").withNamespace("a").build()) + .withSubsets(new V1EndpointSubsetBuilder().withPorts(new CoreV1EndpointPortBuilder().withPort(8080).build()) + .withAddresses(new V1EndpointAddressBuilder().withIp("127.0.0.1") + .withTargetRef(new V1ObjectReferenceBuilder().withKind("Pod").withName("my-pod").build()) + .build()) + .build()) + .build(); + + Lister serviceLister = setupServiceLister(nonExternalNameService); + Lister endpointsLister = setupEndpointsLister(endpoints); + +// client.pods().inNamespace("a").resource(new PodBuilder().withMetadata(new ObjectMetaBuilder().withName("my-pod") +// .withLabels(Map.of("a", "b")).withAnnotations(Map.of("c", "d")).build()).build()).create(); + + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(true, + "labels-prefix-", true, "annotations-prefix-", true, "ports-prefix", true, true); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("a", "b"), true, + 60L, false, "", Set.of(), Map.of(), "", metadata, 0, false, true); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient( + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, properties); + + List result = discoveryClient.getInstances("blue-service"); + Assertions.assertEquals(result.size(), 1); + DefaultKubernetesServiceInstance serviceInstance = (DefaultKubernetesServiceInstance) result.get(0); + Assertions.assertEquals(serviceInstance.getServiceId(), "blue-service"); + Assertions.assertEquals(serviceInstance.getHost(), "127.0.0.1"); + Assertions.assertEquals(serviceInstance.getPort(), 8080); + Assertions.assertFalse(serviceInstance.isSecure()); + Assertions.assertEquals(serviceInstance.getUri().toASCIIString(), "http://127.0.0.1:8080"); + Assertions.assertEquals(serviceInstance.getMetadata(), + Map.of("k8s_namespace", "a", "type", "ClusterIP", "ports-prefix", "8080")); + Assertions.assertEquals(serviceInstance.podMetadata().get("labels"), Map.of("a", "b")); + Assertions.assertEquals(serviceInstance.podMetadata().get("annotations"), Map.of("c", "d")); + } + private Lister setupServiceLister(V1Service... services) { Cache serviceCache = new Cache<>(); Lister serviceLister = new Lister<>(serviceCache); diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/SharedInformerFactoryStub.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/SharedInformerFactoryStub.java new file mode 100644 index 0000000000..cae63d6ece --- /dev/null +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/SharedInformerFactoryStub.java @@ -0,0 +1,31 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.client.discovery; + +import io.kubernetes.client.informer.SharedInformerFactory; + +/** + * @author wind57 + */ +final class SharedInformerFactoryStub extends SharedInformerFactory { + + @Override + public void startAllRegisteredInformers() { + + } + +} diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/SharedInformerStub.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/SharedInformerStub.java new file mode 100644 index 0000000000..1aea2b6036 --- /dev/null +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/SharedInformerStub.java @@ -0,0 +1,65 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.client.discovery; + +import io.kubernetes.client.common.KubernetesObject; +import io.kubernetes.client.informer.ResourceEventHandler; +import io.kubernetes.client.informer.SharedInformer; +import io.kubernetes.client.informer.TransformFunc; + +/** + * @author wind57 + */ +final class SharedInformerStub implements SharedInformer { + + @Override + public void addEventHandler(ResourceEventHandler handler) { + + } + + @Override + public void addEventHandlerWithResyncPeriod(ResourceEventHandler handler, long resyncPeriod) { + + } + + @Override + public void run() { + + } + + @Override + public void stop() { + + } + + // this is the only method we care about + @Override + public boolean hasSynced() { + return true; + } + + @Override + public String lastSyncResourceVersion() { + return null; + } + + @Override + public void setTransform(TransformFunc transformFunc) { + + } + +} From f6a22e1310256a4874d25c5a1184afaf757371ec Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 8 Nov 2023 22:53:26 +0200 Subject: [PATCH 14/53] started working on tests --- ...ubernetesInformerDiscoveryClientTests.java | 81 +++++++++++-------- 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java index 423a614347..7934b4bece 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java @@ -21,19 +21,13 @@ import java.util.Map; import java.util.Set; -import io.fabric8.kubernetes.api.model.EndpointAddressBuilder; -import io.fabric8.kubernetes.api.model.EndpointPortBuilder; -import io.fabric8.kubernetes.api.model.EndpointSubsetBuilder; -import io.fabric8.kubernetes.api.model.EndpointsBuilder; -import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; -import io.fabric8.kubernetes.api.model.ObjectReferenceBuilder; -import io.fabric8.kubernetes.api.model.PodBuilder; -import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.api.model.ServiceBuilder; -import io.fabric8.kubernetes.api.model.ServiceSpecBuilder; +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; import io.kubernetes.client.informer.SharedInformerFactory; import io.kubernetes.client.informer.cache.Cache; import io.kubernetes.client.informer.cache.Lister; +import io.kubernetes.client.openapi.ApiClient; +import io.kubernetes.client.openapi.JSON; import io.kubernetes.client.openapi.models.CoreV1EndpointPort; import io.kubernetes.client.openapi.models.CoreV1EndpointPortBuilder; import io.kubernetes.client.openapi.models.V1EndpointAddress; @@ -45,10 +39,13 @@ import io.kubernetes.client.openapi.models.V1ObjectMeta; import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder; import io.kubernetes.client.openapi.models.V1ObjectReferenceBuilder; +import io.kubernetes.client.openapi.models.V1Pod; +import io.kubernetes.client.openapi.models.V1PodBuilder; import io.kubernetes.client.openapi.models.V1Service; import io.kubernetes.client.openapi.models.V1ServiceBuilder; import io.kubernetes.client.openapi.models.V1ServiceSpec; import io.kubernetes.client.openapi.models.V1ServiceSpecBuilder; +import io.kubernetes.client.util.ClientBuilder; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -57,6 +54,7 @@ import org.springframework.cloud.kubernetes.commons.discovery.DefaultKubernetesServiceInstance; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; import static org.assertj.core.api.Assertions.assertThat; class KubernetesInformerDiscoveryClientTests { @@ -516,23 +514,23 @@ void testServicesWithSameMetadataLabels() { @Test void testExternalNameService() { V1Service externalNameService = new V1ServiceBuilder() - .withSpec(new V1ServiceSpecBuilder().withType("ExternalName").withExternalName("k8s-spring-b").build()) - .withNewMetadata().withLabels(Map.of("label-key", "label-value")).withAnnotations(Map.of("abc", "def")) - .withName("blue-service").withNamespace("b").endMetadata().build(); + .withSpec(new V1ServiceSpecBuilder().withType("ExternalName").withExternalName("k8s-spring-b").build()) + .withNewMetadata().withLabels(Map.of("label-key", "label-value")).withAnnotations(Map.of("abc", "def")) + .withName("blue-service").withNamespace("b").endMetadata().build(); - V1Endpoints endpoints = new V1EndpointsBuilder() - .withMetadata(new V1ObjectMeta().namespace("irrelevant")).build(); + V1Endpoints endpoints = new V1EndpointsBuilder().withMetadata(new V1ObjectMeta().namespace("irrelevant")) + .build(); Lister serviceLister = setupServiceLister(externalNameService); Lister endpointsLister = setupEndpointsLister(endpoints); KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(true, - "labels-prefix-", true, "annotations-prefix-", true, "ports-prefix"); + "labels-prefix-", true, "annotations-prefix-", true, "ports-prefix"); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of("a", "b"), true, - 60L, false, "", Set.of(), Map.of(), "", metadata, 0, false, true); + 60L, false, "", Set.of(), Map.of(), "", metadata, 0, false, true); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient( - SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, properties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, properties); List result = discoveryClient.getInstances("blue-service"); Assertions.assertEquals(result.size(), 1); @@ -543,37 +541,48 @@ void testExternalNameService() { Assertions.assertFalse(externalNameServiceInstance.isSecure()); Assertions.assertEquals(externalNameServiceInstance.getUri().toASCIIString(), "k8s-spring-b"); Assertions.assertEquals(externalNameServiceInstance.getMetadata(), Map.of("k8s_namespace", "b", - "labels-prefix-label-key", "label-value", "annotations-prefix-abc", "def", "type", "ExternalName")); + "labels-prefix-label-key", "label-value", "annotations-prefix-abc", "def", "type", "ExternalName")); } @Test void testPodMetadata() { V1Service nonExternalNameService = new V1ServiceBuilder() - .withSpec(new V1ServiceSpecBuilder().withType("ClusterIP").build()).withNewMetadata() - .withName("blue-service").withNamespace("a").endMetadata().build(); + .withSpec(new V1ServiceSpecBuilder().withType("ClusterIP").build()).withNewMetadata() + .withName("blue-service").withNamespace("a").endMetadata().build(); V1Endpoints endpoints = new V1EndpointsBuilder() - .withMetadata(new V1ObjectMetaBuilder().withName("blue-service").withNamespace("a").build()) - .withSubsets(new V1EndpointSubsetBuilder().withPorts(new CoreV1EndpointPortBuilder().withPort(8080).build()) - .withAddresses(new V1EndpointAddressBuilder().withIp("127.0.0.1") - .withTargetRef(new V1ObjectReferenceBuilder().withKind("Pod").withName("my-pod").build()) - .build()) - .build()) - .build(); + .withMetadata(new V1ObjectMetaBuilder().withName("blue-service").withNamespace("a").build()) + .withSubsets( + new V1EndpointSubsetBuilder().withPorts(new CoreV1EndpointPortBuilder().withPort(8080).build()) + .withAddresses(new V1EndpointAddressBuilder().withIp("127.0.0.1").withTargetRef( + new V1ObjectReferenceBuilder().withKind("Pod").withName("my-pod").build()) + .build()) + .build()) + .build(); Lister serviceLister = setupServiceLister(nonExternalNameService); Lister endpointsLister = setupEndpointsLister(endpoints); -// client.pods().inNamespace("a").resource(new PodBuilder().withMetadata(new ObjectMetaBuilder().withName("my-pod") -// .withLabels(Map.of("a", "b")).withAnnotations(Map.of("c", "d")).build()).build()).create(); + WireMockServer server = new WireMockServer(options().dynamicPort()); + server.start(); + WireMock.configureFor("localhost", server.port()); + ApiClient apiClient = new ClientBuilder().setBasePath("http://localhost:" + server.port()).build(); + io.kubernetes.client.openapi.Configuration.setDefaultApiClient(apiClient); + apiClient.setDebugging(true); + + V1Pod pod = new V1PodBuilder().withNewMetadata().withName("my-pod").withLabels(Map.of("a", "b")) + .withAnnotations(Map.of("c", "d")).endMetadata().build(); + + WireMock.stubFor(WireMock.get("/api/v1/namespaces/a/pods/my-pod") + .willReturn(WireMock.aResponse().withStatus(200).withBody(new JSON().serialize(pod)))); KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(true, - "labels-prefix-", true, "annotations-prefix-", true, "ports-prefix", true, true); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("a", "b"), true, - 60L, false, "", Set.of(), Map.of(), "", metadata, 0, false, true); + "labels-prefix-", true, "annotations-prefix-", true, "ports-prefix", true, true); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of("a", "b"), + true, 60L, false, "", Set.of(), Map.of(), "", metadata, 0, false, true); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient( - SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, properties); + SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, properties); List result = discoveryClient.getInstances("blue-service"); Assertions.assertEquals(result.size(), 1); @@ -584,9 +593,11 @@ void testPodMetadata() { Assertions.assertFalse(serviceInstance.isSecure()); Assertions.assertEquals(serviceInstance.getUri().toASCIIString(), "http://127.0.0.1:8080"); Assertions.assertEquals(serviceInstance.getMetadata(), - Map.of("k8s_namespace", "a", "type", "ClusterIP", "ports-prefix", "8080")); + Map.of("k8s_namespace", "a", "type", "ClusterIP", "ports-prefix", "8080")); Assertions.assertEquals(serviceInstance.podMetadata().get("labels"), Map.of("a", "b")); Assertions.assertEquals(serviceInstance.podMetadata().get("annotations"), Map.of("c", "d")); + + server.shutdown(); } private Lister setupServiceLister(V1Service... services) { From dba5c67ca195ed004faccf6bfecad51f4a217587 Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 10 Nov 2023 17:22:00 +0200 Subject: [PATCH 15/53] added one more tests --- ...etesDiscoveryClientFilterMetadataTest.java | 28 +- .../KubernetesDiscoveryClientTests.java | 457 ++++++++++++++++++ .../Fabric8KubernetesDiscoveryClientTest.java | 2 +- 3 files changed, 468 insertions(+), 19 deletions(-) create mode 100644 spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientTests.java diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientFilterMetadataTest.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientFilterMetadataTest.java index 62d38a2e5c..3071b3671e 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientFilterMetadataTest.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientFilterMetadataTest.java @@ -83,8 +83,7 @@ void testAllExtraMetadataDisabled() { KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "lab"), Map.of("l1", "lab"), - Map.of(80, "http", 5555, "")); + setup(serviceId, "ns", Map.of("l1", "lab"), Map.of("l1", "lab"), Map.of(80, "http", 5555, "")); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); @@ -103,8 +102,7 @@ void testLabelsEnabled() { KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "v1", "l2", "v2"), - Map.of("l1", "lab"), Map.of(80, "http", 5555, "")); + setup(serviceId, "ns", Map.of("l1", "v1", "l2", "v2"), Map.of("l1", "lab"), Map.of(80, "http", 5555, "")); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); @@ -124,8 +122,7 @@ void testLabelsEnabledWithPrefix() { KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "v1", "l2", "v2"), - Map.of("l1", "lab"), Map.of(80, "http", 5555, "")); + setup(serviceId, "ns", Map.of("l1", "v1", "l2", "v2"), Map.of("l1", "lab"), Map.of(80, "http", 5555, "")); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); @@ -145,8 +142,7 @@ void testAnnotationsEnabled() { KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "v1"), - Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + setup(serviceId, "ns", Map.of("l1", "v1"), Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); @@ -166,8 +162,7 @@ void testAnnotationsEnabledWithPrefix() { KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "v1"), - Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + setup(serviceId, "ns", Map.of("l1", "v1"), Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); @@ -187,8 +182,7 @@ void testPortsEnabled() { KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "test", Map.of("l1", "v1"), - Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + setup(serviceId, "test", Map.of("l1", "v1"), Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); @@ -208,8 +202,7 @@ void testPortsEnabledWithPrefix() { KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "v1"), - Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); + setup(serviceId, "ns", Map.of("l1", "v1"), Map.of("a1", "v1", "a2", "v2"), Map.of(80, "http", 5555, "")); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); @@ -229,8 +222,7 @@ void testLabelsAndAnnotationsAndPortsEnabledWithPrefix() { KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", Map.of("l1", "la1"), - Map.of("a1", "an1", "a2", "an2"), Map.of(80, "http", 5555, "")); + setup(serviceId, "ns", Map.of("l1", "la1"), Map.of("a1", "an1", "a2", "an2"), Map.of(80, "http", 5555, "")); List instances = discoveryClient.getInstances(serviceId); assertThat(instances).hasSize(1); @@ -239,8 +231,8 @@ void testLabelsAndAnnotationsAndPortsEnabledWithPrefix() { entry("p_", "5555")); } - private void setupServiceWithLabelsAndAnnotationsAndPorts(String serviceId, String namespace, - Map labels, Map annotations, Map ports) { + private void setup(String serviceId, String namespace, Map labels, Map annotations, + Map ports) { V1Service service = new V1ServiceBuilder() .withSpec(new V1ServiceSpecBuilder().withType("ClusterIP").withPorts(getServicePorts(ports)).build()) diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientTests.java new file mode 100644 index 0000000000..b531bf3083 --- /dev/null +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientTests.java @@ -0,0 +1,457 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.client.discovery; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import io.kubernetes.client.informer.cache.Cache; +import io.kubernetes.client.informer.cache.Lister; +import io.kubernetes.client.openapi.models.CoreV1EndpointPort; +import io.kubernetes.client.openapi.models.CoreV1EndpointPortBuilder; +import io.kubernetes.client.openapi.models.V1EndpointAddress; +import io.kubernetes.client.openapi.models.V1EndpointAddressBuilder; +import io.kubernetes.client.openapi.models.V1EndpointSubset; +import io.kubernetes.client.openapi.models.V1Endpoints; +import io.kubernetes.client.openapi.models.V1EndpointsBuilder; +import io.kubernetes.client.openapi.models.V1ObjectMeta; +import io.kubernetes.client.openapi.models.V1Service; +import io.kubernetes.client.openapi.models.V1ServiceBuilder; +import io.kubernetes.client.openapi.models.V1ServiceSpecBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; +import org.springframework.cloud.kubernetes.commons.discovery.KubernetesServiceInstance; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +class KubernetesDiscoveryClientTests { + + private static final SharedInformerFactoryStub STUB = new SharedInformerFactoryStub(); + + private static final SharedInformerStub SERVICE_SHARED_INFORMER_STUB = new SharedInformerStub<>(); + + private static final SharedInformerStub ENDPOINTS_SHARED_INFORMER_STUB = new SharedInformerStub<>(); + + private Cache servicesCache; + + private Lister servicesLister; + + private Cache endpointsCache; + + private Lister endpointsLister; + + @BeforeEach + void beforeEach() { + servicesCache = new Cache<>(); + servicesLister = new Lister<>(servicesCache); + + endpointsCache = new Cache<>(); + endpointsLister = new Lister<>(endpointsCache); + } + + @Test + void getInstancesShouldBeAbleToHandleEndpointsSingleAddress() { + Map labels = Map.of("l", "v"); + String serviceId = "id"; + String serviceType = "ExternalName"; + String namespace = "test"; + List ips = List.of("ip1"); + List uuids = List.of("10"); + List names = List.of("http"); + List protocols = List.of("TCP"); + List ports = List.of(80); + List appProtocols = List.of("appTCP"); + + setup(serviceId, serviceType, namespace, labels, ips, uuids, names, protocols, ports, appProtocols); + + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.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); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + List instances = discoveryClient.getInstances("id"); + + assertThat(instances).hasSize(1).filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1) + .filteredOn(s -> s.getInstanceId().equals("10")).hasSize(1); + } + + @Test + void getInstancesShouldBeAbleToHandleEndpointsSingleAddressAndMultiplePorts() { + Map labels = Map.of("l2", "v2"); + String serviceId = "endpoint"; + String serviceType = "ExternalName"; + String namespace = "test"; + List ips = List.of("ip1"); + List uuids = List.of("20"); + List names = List.of("http", "mgmt"); + List protocols = List.of("TCP", "TCP"); + List ports = List.of(80, 900); + List appProtocols = List.of("http_tcp", "mgmt_tcp"); + + setup(serviceId, serviceType, namespace, labels, ips, uuids, names, protocols, ports, appProtocols); + + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60, + false, null, Set.of(), labels, "http_tcp", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + List instances = discoveryClient.getInstances("endpoint"); + + assertThat(instances).hasSize(1).filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1) + .filteredOn(s -> s.getInstanceId().equals("20")).hasSize(1).filteredOn(s -> 80 == s.getPort()) + .hasSize(1); + } + + @Test + void getInstancesShouldBeAbleToHandleEndpointsMultipleAddresses() { + Map labels = Map.of("l1", "v1"); + String serviceId = "endpoint"; + String serviceType = "ExternalName"; + String namespace = "test"; + List ips = List.of("ip1", "ip2"); + List uuids = List.of("40", "50"); + List names = List.of("https"); + List protocols = List.of("TCP"); + List ports = List.of(443); + List appProtocols = List.of("https_tcp"); + + setup(serviceId, serviceType, namespace, labels, ips, uuids, names, protocols, ports, appProtocols); + + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(false, null, false, + null, true, "port."); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60, + false, null, Set.of(443, 8443), labels, null, metadata, 0, true); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + List instances = discoveryClient.getInstances("endpoint"); + + assertThat(instances).hasSize(2).filteredOn(ServiceInstance::isSecure).extracting(ServiceInstance::getHost) + .containsOnly("ip1", "ip2"); + } + + @Test + void getInstancesShouldBeAbleToHandleEndpointsFromMultipleNamespaces() { + + Map labels = Map.of("l", "v"); + String serviceId = "endpoint"; + String serviceType = "ExternalName"; + String namespace = "test"; + List ips = List.of("ip1"); + List uuids = List.of("60"); + List names = List.of("http"); + List protocols = List.of("TCP"); + List ports = List.of(80); + List appProtocols = List.of("https_tcp"); + + setup(serviceId, serviceType, namespace, labels, ips, uuids, names, protocols, ports, appProtocols); + + ips = List.of("ip2"); + uuids = List.of("70"); + namespace = "test2"; + + setup(serviceId, serviceType, namespace, labels, ips, uuids, names, protocols, ports, appProtocols); + + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60, + false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + List instances = discoveryClient.getInstances("endpoint"); + + assertThat(instances).hasSize(2); + assertThat(instances).filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1); + assertThat(instances).filteredOn(s -> s.getHost().equals("ip2") && !s.isSecure()).hasSize(1); + assertThat(instances).filteredOn(s -> s.getServiceId().contains("endpoint") + && ((KubernetesServiceInstance) s).getNamespace().equals("test")).hasSize(1); + assertThat(instances).filteredOn(s -> s.getServiceId().contains("endpoint") + && ((KubernetesServiceInstance) s).getNamespace().equals("test2")).hasSize(1); + assertThat(instances).filteredOn(s -> s.getInstanceId().equals("60")).hasSize(1); + assertThat(instances).filteredOn(s -> s.getInstanceId().equals("70")).hasSize(1); + } + + @Test + void instanceWithoutSubsetsShouldBeSkipped() { + V1Endpoints endpoints = new V1EndpointsBuilder().withNewMetadata().withName("endpoint1").withNamespace("test") + .withLabels(Collections.emptyMap()).endMetadata().build(); + endpointsCache.add(endpoints); + + V1Service service = new V1ServiceBuilder().withNewMetadata().withName("endpoint1").withNamespace("test").and() + .build(); + servicesCache.add(service); + + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60, + false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true); + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + List instances = discoveryClient.getInstances("endpoint1"); + + assertThat(instances).isEmpty(); + } + + @Test + void getInstancesShouldBeAbleToHandleEndpointsSingleAddressAndMultiplePortsUsingPrimaryPortNameLabel() { + Map labels = Map.of("primary-port-name", "https"); + String serviceId = "endpoint2"; + String serviceType = "ExternalName"; + String namespace = "test"; + List ips = List.of("ip1"); + List uuids = List.of("80"); + List names = List.of("http", "https"); + List protocols = List.of("TCP", "TCP"); + List ports = List.of(80, 443); + List appProtocols = List.of("http", "https"); + + setup(serviceId, serviceType, namespace, labels, ips, uuids, names, protocols, ports, appProtocols); + + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60, + false, null, Set.of(443, 8443), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + true); + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + List instances = discoveryClient.getInstances("endpoint2"); + + assertThat(instances).hasSize(1).filteredOn(s -> s.getHost().equals("ip1") && s.isSecure()).hasSize(1) + .filteredOn(s -> s.getInstanceId().equals("80")).hasSize(1).filteredOn(s -> 443 == s.getPort()) + .hasSize(1); + } + + @Test + void instanceWithMultiplePortsAndMisconfiguredPrimaryPortNameInLabelWithoutFallbackShouldLogWarning() { + Map labels = Map.of("primary-port-name", "oops"); + String serviceId = "endpoint3"; + String serviceType = "ExternalName"; + String namespace = "test"; + List ips = List.of("ip1"); + List uuids = List.of("90"); + List names = List.of("httpA", "httpB", "httpC", "httpD"); + List protocols = List.of("TCP", "TCP", "TCP", "TCP"); + List ports = List.of(8443, 443, 80, 8080); + List appProtocols = List.of("https1", "https2", "http1", "http2"); + + setup(serviceId, serviceType, namespace, labels, ips, uuids, names, protocols, ports, appProtocols); + + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, + false, null, Set.of(443, 8443), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + true); + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + List instances = discoveryClient.getInstances("endpoint3"); + + assertThat(instances).hasSize(1).filteredOn(s -> s.getHost().equals("ip1") && s.isSecure()).hasSize(1) + .filteredOn(s -> s.getInstanceId().equals("90")).hasSize(1).hasSize(1); + } + + @Test + void instanceWithMultiplePortsAndMisconfiguredGenericPrimaryPortNameWithoutFallbackShouldLogWarning() { + Map labels = Map.of(); + String serviceId = "endpoint4"; + String serviceType = "ExternalName"; + String namespace = "test"; + List ips = List.of("ip1"); + List uuids = List.of("100"); + List names = List.of("httpA", "httpB", "httpC", "httpD"); + List protocols = List.of("TCP", "TCP", "TCP", "TCP"); + List ports = List.of(8443, 443, 80, 8080); + List appProtocols = List.of("https1", "https2", "http1", "http2"); + + setup(serviceId, serviceType, namespace, labels, ips, uuids, names, protocols, ports, appProtocols); + + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, + false, null, Set.of(443, 8443), Map.of(), "oops", KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + true); + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + List instances = discoveryClient.getInstances("endpoint4"); + + assertThat(instances).hasSize(1).filteredOn(s -> s.getHost().equals("ip1") && s.isSecure()).hasSize(1) + .filteredOn(s -> s.getInstanceId().equals("100")).hasSize(1).hasSize(1); + } + + @Test + void instanceWithMultiplePortsAndWithoutPrimaryPortNameSpecifiedShouldFallBackToHttps() { + Map labels = Map.of(); + String serviceId = "endpoint5"; + String serviceType = "ExternalName"; + String namespace = "test"; + List ips = List.of("ip1"); + List uuids = List.of("110"); + List names = List.of("httpA", "httpB"); + List protocols = List.of("TCP", "TCP"); + List ports = List.of(443, 80); + List appProtocols = List.of("http", "https"); + + setup(serviceId, serviceType, namespace, labels, ips, uuids, names, protocols, ports, appProtocols); + + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60, + false, null, Set.of(443, 8443), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + true); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + List instances = discoveryClient.getInstances("endpoint5"); + + assertThat(instances).hasSize(1).filteredOn(s -> s.getHost().equals("ip1") && s.isSecure()).hasSize(1) + .filteredOn(s -> s.getInstanceId().equals("110")).hasSize(1).filteredOn(s -> 443 == s.getPort()) + .hasSize(1); + } + + @Test + void instanceWithMultiplePortsAndWithoutPrimaryPortNameSpecifiedOrHttpsPortShouldFallBackToHttp() { + Map labels = Map.of(); + String serviceId = "endpoint5"; + String serviceType = "ExternalName"; + String namespace = "test"; + List ips = List.of("ip1"); + List uuids = List.of("120"); + List names = List.of("httpA", "httpB", "httpC"); + List protocols = List.of("http", "http", "http"); + List ports = List.of(80, 8443, 80); + List appProtocols = List.of("TCP", "TCP", "TCP"); + + setup(serviceId, serviceType, namespace, labels, ips, uuids, names, protocols, ports, appProtocols); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, + KubernetesDiscoveryProperties.DEFAULT); + + List instances = discoveryClient.getInstances("endpoint5"); + + assertThat(instances).hasSize(1).filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1) + .filteredOn(s -> s.getInstanceId().equals("120")).hasSize(1).filteredOn(s -> 80 == s.getPort()) + .hasSize(1); + } + + @Test + void instanceWithMultiplePortsAndWithoutPrimaryPortNameSpecifiedShouldLogWarning() { + Map labels = Map.of(); + String serviceId = "endpoint5"; + String serviceType = "ExternalName"; + String namespace = "test"; + List ips = List.of("ip1"); + List uuids = List.of("130"); + List names = List.of("http", "https"); + List protocols = List.of("http", "https"); + List ports = List.of(80, 443); + List appProtocols = List.of("TCP", "TCP"); + + setup(serviceId, serviceType, namespace, labels, ips, uuids, names, protocols, ports, appProtocols); + + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60, + true, null, Set.of(443, 8443), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, true); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + List instances = discoveryClient.getInstances("endpoint5"); + + // We're returning the first discovered port to not change previous behaviour + assertThat(instances).hasSize(1).filteredOn(s -> s.getHost().equals("ip1") && s.isSecure()).hasSize(1) + .filteredOn(s -> s.getInstanceId().equals("130")).hasSize(1).filteredOn(s -> 443 == s.getPort()) + .hasSize(1); + } + + @Test + public void instanceWithoutPorts() { + Map labels = Map.of(); + String serviceId = "endpoint5"; + String serviceType = "ExternalName"; + String namespace = "test"; + List ips = List.of("ip1"); + List uuids = List.of("130"); + List names = List.of(); + List protocols = List.of(); + List ports = List.of(); + List appProtocols = List.of(); + + setup(serviceId, serviceType, namespace, labels, ips, uuids, names, protocols, ports, appProtocols); + + KubernetesDiscoveryProperties properties = KubernetesDiscoveryProperties.DEFAULT; + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + List instances = discoveryClient.getInstances("endpoint5"); + + // We're returning the first discovered port to not change previous behaviour + assertThat(instances).hasSize(1).filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1) + .filteredOn(s -> s.getUri().toASCIIString().equals("http://ip1")) + .filteredOn(s -> s.getInstanceId().equals("130")).hasSize(1).filteredOn(s -> 0 == s.getPort()) + .hasSize(1); + } + + private void setup(String serviceId, String serviceType, String namespace, Map labels, + List ips, List uuids, List names, List protocols, List ports, + List appProtocols) { + + V1Service service = new V1ServiceBuilder().withSpec(new V1ServiceSpecBuilder().withType(serviceType).build()) + .withNewMetadata().withName(serviceId).withNamespace(namespace).withLabels(labels).endMetadata() + .build(); + + servicesCache.add(service); + + V1ObjectMeta objectMeta = new V1ObjectMeta(); + objectMeta.setNamespace(namespace); + objectMeta.setName(serviceId); + + V1Endpoints endpoints = new V1EndpointsBuilder().withNewMetadata().withName(serviceId).withNamespace(namespace) + .withLabels(labels).endMetadata().build(); + + List addresses = new ArrayList<>(); + for (int i = 0; i < ips.size(); ++i) { + V1EndpointAddress address = new V1EndpointAddressBuilder().withIp(ips.get(i)).withNewTargetRef() + .withUid(uuids.get(i)).endTargetRef().build(); + addresses.add(address); + } + + V1EndpointSubset subset = new V1EndpointSubset(); + subset.setAddresses(addresses); + + List corePorts = new ArrayList<>(); + for (int i = 0; i < names.size(); ++i) { + CoreV1EndpointPort port = new CoreV1EndpointPortBuilder().withName(names.get(i)) + .withProtocol(protocols.get(i)).withPort(ports.get(i)).withAppProtocol(appProtocols.get(i)).build(); + corePorts.add(port); + } + subset.setPorts(corePorts); + endpoints.setSubsets(List.of(subset)); + + endpointsCache.add(endpoints); + + } + +} diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientTest.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientTest.java index 16e0bc53a5..fcf276a4fe 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientTest.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8KubernetesDiscoveryClientTest.java @@ -375,7 +375,7 @@ void getInstancesShouldBeAbleToHandleEndpointsFromMultipleNamespaces() { } @Test - void instanceWithoutPortsShouldBeSkipped() { + void instanceWithoutSubsetsShouldBeSkipped() { Endpoints endPoint = new EndpointsBuilder().withNewMetadata().withName("endpoint1").withNamespace("test") .withLabels(Collections.emptyMap()).endMetadata().build(); From 846306734bce621379d7f0a59d8af5a10a96ecd2 Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 10 Nov 2023 17:38:58 +0200 Subject: [PATCH 16/53] before integration tests --- ...veryClientServiceWithoutPortNameTests.java | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceWithoutPortNameTests.java diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceWithoutPortNameTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceWithoutPortNameTests.java new file mode 100644 index 0000000000..8970957808 --- /dev/null +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceWithoutPortNameTests.java @@ -0,0 +1,100 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.client.discovery; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import io.kubernetes.client.informer.cache.Cache; +import io.kubernetes.client.informer.cache.Lister; +import io.kubernetes.client.openapi.models.CoreV1EndpointPortBuilder; +import io.kubernetes.client.openapi.models.V1EndpointAddressBuilder; +import io.kubernetes.client.openapi.models.V1EndpointSubsetBuilder; +import io.kubernetes.client.openapi.models.V1Endpoints; +import io.kubernetes.client.openapi.models.V1EndpointsBuilder; +import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder; +import io.kubernetes.client.openapi.models.V1Service; +import io.kubernetes.client.openapi.models.V1ServiceBuilder; +import io.kubernetes.client.openapi.models.V1ServicePortBuilder; +import io.kubernetes.client.openapi.models.V1ServiceSpecBuilder; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; + +/** + * @author wind57 + */ +class KubernetesDiscoveryClientServiceWithoutPortNameTests { + + private static final String NAMESPACE = "spring-k8s"; + + private static final SharedInformerFactoryStub STUB = new SharedInformerFactoryStub(); + + private static final SharedInformerStub SERVICE_SHARED_INFORMER_STUB = new SharedInformerStub<>(); + + private static final SharedInformerStub ENDPOINTS_SHARED_INFORMER_STUB = new SharedInformerStub<>(); + + private Cache servicesCache; + + private Lister servicesLister; + + private Cache endpointsCache; + + private Lister endpointsLister; + + @BeforeEach + void beforeEach() { + servicesCache = new Cache<>(); + servicesLister = new Lister<>(servicesCache); + + endpointsCache = new Cache<>(); + endpointsLister = new Lister<>(endpointsCache); + } + + @Test + void testDiscoveryWithoutAServicePortName() { + + V1Endpoints endpoints = new V1EndpointsBuilder() + .withSubsets(new V1EndpointSubsetBuilder().withPorts(new CoreV1EndpointPortBuilder().withPort(8080).build()) + .withAddresses(new V1EndpointAddressBuilder().withIp("127.0.0.1").build()).build()) + .withMetadata(new V1ObjectMetaBuilder().withName("no-port-name-service").withNamespace(NAMESPACE).build()) + .build(); + endpointsCache.add(endpoints); + + V1Service service = new V1ServiceBuilder() + .withSpec(new V1ServiceSpecBuilder().withPorts(new V1ServicePortBuilder().withPort(8080).build()).build()) + .withMetadata(new V1ObjectMetaBuilder().withName("no-port-name-service").withNamespace(NAMESPACE).build()) + .withSpec(new V1ServiceSpecBuilder().withType("ClusterIP").build()).build(); + servicesCache.add(service); + + + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(NAMESPACE), + true, 60, false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + true); + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + + List serviceInstances = discoveryClient.getInstances("no-port-name-service"); + Assertions.assertEquals(serviceInstances.size(), 1); + Assertions.assertEquals(serviceInstances.get(0).getMetadata(), + Map.of("port.", "8080", "k8s_namespace", "spring-k8s", "type", "ClusterIP")); + } + +} From f986628900ca4ed046f9551980d59eca5c6fa527 Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 10 Nov 2023 18:29:39 +0200 Subject: [PATCH 17/53] fix checkstyle --- .../KubernetesDiscoveryClientServiceWithoutPortNameTests.java | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceWithoutPortNameTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceWithoutPortNameTests.java index 8970957808..a0195822f4 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceWithoutPortNameTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceWithoutPortNameTests.java @@ -35,6 +35,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; + import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; From 847ae3484f7e9e9eb6413fb135181674c74ff613 Mon Sep 17 00:00:00 2001 From: wind57 Date: Mon, 13 Nov 2023 11:57:15 +0200 Subject: [PATCH 18/53] started work on integration tests --- ...veryClientServiceWithoutPortNameTests.java | 27 +++++++----- .../KubernetesClientDiscoveryClientIT.java | 44 +++++++++++++++++-- 2 files changed, 56 insertions(+), 15 deletions(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceWithoutPortNameTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceWithoutPortNameTests.java index a0195822f4..5bfcc509f2 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceWithoutPortNameTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientServiceWithoutPortNameTests.java @@ -73,29 +73,32 @@ void beforeEach() { void testDiscoveryWithoutAServicePortName() { V1Endpoints endpoints = new V1EndpointsBuilder() - .withSubsets(new V1EndpointSubsetBuilder().withPorts(new CoreV1EndpointPortBuilder().withPort(8080).build()) - .withAddresses(new V1EndpointAddressBuilder().withIp("127.0.0.1").build()).build()) - .withMetadata(new V1ObjectMetaBuilder().withName("no-port-name-service").withNamespace(NAMESPACE).build()) - .build(); + .withSubsets( + new V1EndpointSubsetBuilder().withPorts(new CoreV1EndpointPortBuilder().withPort(8080).build()) + .withAddresses(new V1EndpointAddressBuilder().withIp("127.0.0.1").build()).build()) + .withMetadata( + new V1ObjectMetaBuilder().withName("no-port-name-service").withNamespace(NAMESPACE).build()) + .build(); endpointsCache.add(endpoints); V1Service service = new V1ServiceBuilder() - .withSpec(new V1ServiceSpecBuilder().withPorts(new V1ServicePortBuilder().withPort(8080).build()).build()) - .withMetadata(new V1ObjectMetaBuilder().withName("no-port-name-service").withNamespace(NAMESPACE).build()) - .withSpec(new V1ServiceSpecBuilder().withType("ClusterIP").build()).build(); + .withSpec( + new V1ServiceSpecBuilder().withPorts(new V1ServicePortBuilder().withPort(8080).build()).build()) + .withMetadata( + new V1ObjectMetaBuilder().withName("no-port-name-service").withNamespace(NAMESPACE).build()) + .withSpec(new V1ServiceSpecBuilder().withType("ClusterIP").build()).build(); servicesCache.add(service); - KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(NAMESPACE), - true, 60, false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, - true); + true, 60, false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, + true); KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(STUB, servicesLister, - endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); + endpointsLister, SERVICE_SHARED_INFORMER_STUB, ENDPOINTS_SHARED_INFORMER_STUB, properties); List serviceInstances = discoveryClient.getInstances("no-port-name-service"); Assertions.assertEquals(serviceInstances.size(), 1); Assertions.assertEquals(serviceInstances.get(0).getMetadata(), - Map.of("port.", "8080", "k8s_namespace", "spring-k8s", "type", "ClusterIP")); + Map.of("port.", "8080", "k8s_namespace", "spring-k8s", "type", "ClusterIP")); } } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientIT.java index 031922d694..ceff434c67 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientIT.java @@ -98,10 +98,20 @@ static void afterAll() throws Exception { */ @Test @Order(1) - void testSimple() { + void testSimple() throws Exception { util.busybox(NAMESPACE, Phase.CREATE); + // find both pods + String[] both = K3S.execInContainer("sh", "-c", "kubectl get pods -l app=busybox -o=name --no-headers") + .getStdout().split("\n"); + // add a label to first pod + K3S.execInContainer("sh", "-c", + "kubectl label pods " + both[0].split("/")[1] + " custom-label=custom-label-value"); + // add annotation to the second pod + K3S.execInContainer("sh", "-c", + "kubectl annotate pods " + both[1].split("/")[1] + " custom-annotation=custom-annotation-value"); + Commons.waitForLogStatement("serviceSharedInformer will use namespace : default", K3S, IMAGE_NAME); WebClient servicesClient = builder().baseUrl("http://localhost/services").build(); @@ -131,8 +141,8 @@ void testSimple() { Assertions.assertEquals(serviceInstance.getServiceId(), "spring-cloud-kubernetes-k8s-client-discovery"); Assertions.assertNotNull(serviceInstance.getHost()); Assertions.assertEquals(serviceInstance.getMetadata(), - Map.of("app", "spring-cloud-kubernetes-k8s-client-discovery", "custom-spring-k8s", "spring-k8s", "http", - "8080", "k8s_namespace", "default", "type", "ClusterIP")); + Map.of("app", "spring-cloud-kubernetes-k8s-client-discovery", "custom-spring-k8s", "spring-k8s", + "port.http", "8080", "k8s_namespace", "default", "type", "ClusterIP")); Assertions.assertEquals(serviceInstance.getPort(), 8080); Assertions.assertEquals(serviceInstance.getNamespace(), "default"); @@ -145,6 +155,26 @@ void testSimple() { Assertions.assertEquals(busyBoxServiceInstances.size(), 2); + DefaultKubernetesServiceInstance withCustomLabel = busyBoxServiceInstances.stream() + .filter(x -> x.podMetadata().getOrDefault("annotations", Map.of()).isEmpty()).toList().get(0); + Assertions.assertEquals(withCustomLabel.getServiceId(), "busybox-service"); + Assertions.assertNotNull(withCustomLabel.getInstanceId()); + Assertions.assertNotNull(withCustomLabel.getHost()); + Assertions.assertEquals(withCustomLabel.getMetadata(), + Map.of("k8s_namespace", "default", "type", "ClusterIP", "port.busybox-port", "80")); + Assertions.assertTrue(withCustomLabel.podMetadata().get("labels").entrySet().stream() + .anyMatch(x -> x.getKey().equals("custom-label") && x.getValue().equals("custom-label-value"))); + + DefaultKubernetesServiceInstance withCustomAnnotation = busyBoxServiceInstances.stream() + .filter(x -> !x.podMetadata().getOrDefault("annotations", Map.of()).isEmpty()).toList().get(0); + Assertions.assertEquals(withCustomAnnotation.getServiceId(), "busybox-service"); + Assertions.assertNotNull(withCustomAnnotation.getInstanceId()); + Assertions.assertNotNull(withCustomAnnotation.getHost()); + Assertions.assertEquals(withCustomAnnotation.getMetadata(), + Map.of("k8s_namespace", "default", "type", "ClusterIP", "port.busybox-port", "80")); + Assertions.assertTrue(withCustomAnnotation.podMetadata().get("annotations").entrySet().stream().anyMatch( + x -> x.getKey().equals("custom-annotation") && x.getValue().equals("custom-annotation-value"))); + // enforces this : // https://github.com/spring-cloud/spring-cloud-kubernetes/issues/1286 WebClient clientForNonExistentService = builder().baseUrl("http://localhost/service-instances/non-existent") @@ -370,8 +400,16 @@ private static void manifests(Phase phase) { V1EnvVar debugLevelForClient = new V1EnvVar() .name("LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT").value("DEBUG"); + V1EnvVar addLabels = new V1EnvVar().name("SPRING_CLOUD_KUBERNETES_DISCOVERY_METADATA_ADDPODLABELS") + .value("TRUE"); + + V1EnvVar addAnnotations = new V1EnvVar() + .name("SPRING_CLOUD_KUBERNETES_DISCOVERY_METADATA_ADDPODANNOTATIONS").value("TRUE"); + envVars.add(debugLevel); envVars.add(debugLevelForClient); + envVars.add(addLabels); + envVars.add(addAnnotations); deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(envVars); util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); From 485e39e74fa166a0e30b159489bb03708d6f1ef2 Mon Sep 17 00:00:00 2001 From: wind57 Date: Mon, 13 Nov 2023 22:01:52 +0200 Subject: [PATCH 19/53] integration tests --- .../KubernetesInformerDiscoveryClient.java | 8 +-- .../discovery/DiscoveryClientUtils.java | 3 + .../KubernetesClientDiscoveryClientIT.java | 33 ++++++++++- .../KubernetesClientDiscoveryClientUtils.java | 17 ++++-- ...rnetesClientDiscoveryFilterITDelegate.java | 6 +- ...rnetesClientDiscoveryHealthITDelegate.java | 16 +++-- ...sClientDiscoveryPodMetadataITDelegate.java | 5 +- .../test/resources/external-name-service.yaml | 7 +++ .../tests/commons/native_client/Util.java | 58 +++++++++++-------- 9 files changed, 109 insertions(+), 44 deletions(-) create mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/resources/external-name-service.yaml diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java index 44ce41123c..1d52c5ea4d 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java @@ -35,6 +35,7 @@ import jakarta.annotation.PostConstruct; import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; @@ -81,7 +82,9 @@ public class KubernetesInformerDiscoveryClient implements DiscoveryClient { private final ServicePortSecureResolver servicePortSecureResolver; - private final CoreV1Api coreV1Api; + // should be constructor injected in a future release + @Autowired + private CoreV1Api coreV1Api; @Deprecated(forRemoval = true) public KubernetesInformerDiscoveryClient(String namespace, SharedInformerFactory sharedInformerFactory, @@ -95,7 +98,6 @@ public KubernetesInformerDiscoveryClient(String namespace, SharedInformerFactory this.properties = properties; filter = filter(properties); servicePortSecureResolver = new ServicePortSecureResolver(properties); - coreV1Api = new CoreV1Api(); } public KubernetesInformerDiscoveryClient(SharedInformerFactory sharedInformerFactory, @@ -109,7 +111,6 @@ public KubernetesInformerDiscoveryClient(SharedInformerFactory sharedInformerFac this.properties = properties; filter = filter(properties); servicePortSecureResolver = new ServicePortSecureResolver(properties); - coreV1Api = new CoreV1Api(); } public KubernetesInformerDiscoveryClient(List sharedInformerFactories, @@ -131,7 +132,6 @@ public KubernetesInformerDiscoveryClient(List sharedInfor this.properties = properties; filter = filter(properties); servicePortSecureResolver = new ServicePortSecureResolver(properties); - coreV1Api = new CoreV1Api(); } @Override 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 35ebfcea02..62d1d0a0e3 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 @@ -185,7 +185,10 @@ static Map> podMetadata(String podName, Map "Pod labels/annotations were requested"); + if (podName != null) { + LOG.debug(() -> "getting labels/annotation for pod: " + podName); PodLabelsAndAnnotations both = podLabelsAndMetadata.apply(podName); Map> result = new HashMap<>(); if (properties.metadata().addPodLabels() && !both.labels().isEmpty()) { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientIT.java index ceff434c67..a844f47506 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientIT.java @@ -121,10 +121,11 @@ void testSimple() throws Exception { }).retryWhen(retrySpec()).block(); - Assertions.assertEquals(servicesResult.size(), 3); + Assertions.assertEquals(servicesResult.size(), 4); Assertions.assertTrue(servicesResult.contains("kubernetes")); Assertions.assertTrue(servicesResult.contains("spring-cloud-kubernetes-k8s-client-discovery")); Assertions.assertTrue(servicesResult.contains("busybox-service")); + Assertions.assertTrue(servicesResult.contains("external-name-service")); WebClient ourServiceClient = builder() .baseUrl("http://localhost/service-instances/spring-cloud-kubernetes-k8s-client-discovery").build(); @@ -142,7 +143,7 @@ void testSimple() throws Exception { Assertions.assertNotNull(serviceInstance.getHost()); Assertions.assertEquals(serviceInstance.getMetadata(), Map.of("app", "spring-cloud-kubernetes-k8s-client-discovery", "custom-spring-k8s", "spring-k8s", - "port.http", "8080", "k8s_namespace", "default", "type", "ClusterIP")); + "port.http", "8080", "k8s_namespace", "default", "type", "ClusterIP")); Assertions.assertEquals(serviceInstance.getPort(), 8080); Assertions.assertEquals(serviceInstance.getNamespace(), "default"); @@ -195,6 +196,8 @@ void testSimple() throws Exception { * - config server is enabled for all namespaces * - wiremock service is deployed in namespace-a * - busybox service is deployed in namespace-b + * - external-name-service is deployed in namespace "default" and such a service type is requested, + * thus found also. * * Our discovery searches in all namespaces, thus finds them both. *
@@ -217,11 +220,12 @@ void testAllNamespaces() { .bodyToMono(new ParameterizedTypeReference>() { }).retryWhen(retrySpec()).block(); - Assertions.assertEquals(servicesResult.size(), 7); + Assertions.assertEquals(servicesResult.size(), 8); Assertions.assertTrue(servicesResult.contains("kubernetes")); Assertions.assertTrue(servicesResult.contains("spring-cloud-kubernetes-k8s-client-discovery")); Assertions.assertTrue(servicesResult.contains("busybox-service")); Assertions.assertTrue(servicesResult.contains("service-wiremock")); + Assertions.assertTrue(servicesResult.contains("external-name-service")); // enforces this : // https://github.com/spring-cloud/spring-cloud-kubernetes/issues/1286 @@ -234,6 +238,23 @@ void testAllNamespaces() { Assertions.assertEquals(resultForNonExistentService.size(), 0); + // test ExternalName fields + WebClient externalNameClient = builder().baseUrl("http://localhost/service-instances/external-name-service") + .build(); + List externalNameServices = externalNameClient.method(HttpMethod.GET) + .retrieve().bodyToMono(new ParameterizedTypeReference>() { + + }).retryWhen(retrySpec()).block(); + DefaultKubernetesServiceInstance externalNameService = externalNameServices.get(0); + Assertions.assertNotNull(externalNameService.getInstanceId()); + Assertions.assertEquals(externalNameService.getHost(), "spring.io"); + Assertions.assertEquals(externalNameService.getPort(), -1); + Assertions.assertEquals(externalNameService.getMetadata(), + Map.of("k8s_namespace", "default", "type", "ExternalName")); + Assertions.assertFalse(externalNameService.isSecure()); + Assertions.assertEquals(externalNameService.getUri().toASCIIString(), "spring.io"); + Assertions.assertEquals(externalNameService.getScheme(), "http"); + // do not remove wiremock in namespace a, it is required in the next test util.busybox(NAMESPACE_B, Phase.DELETE); util.deleteClusterWideClusterRoleBinding(NAMESPACE); @@ -382,10 +403,12 @@ private void deleteNamespacesAndWiremock() { private static void manifests(Phase phase) { V1Deployment deployment = (V1Deployment) util.yaml("kubernetes-discovery-deployment.yaml"); V1Service service = (V1Service) util.yaml("kubernetes-discovery-service.yaml"); + V1Service externalNameService = (V1Service) util.yaml("external-name-service.yaml"); V1Ingress ingress = (V1Ingress) util.yaml("kubernetes-discovery-ingress.yaml"); if (phase.equals(Phase.DELETE)) { util.deleteAndWait(NAMESPACE, deployment, service, ingress); + util.deleteAndWait(NAMESPACE, null, externalNameService, null); return; } @@ -396,6 +419,8 @@ private static void manifests(Phase phase) { .orElse(List.of())); V1EnvVar debugLevel = new V1EnvVar() .name("LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_DISCOVERY").value("DEBUG"); + V1EnvVar commonsLevel = new V1EnvVar() + .name("LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS_DISCOVERY").value("DEBUG"); V1EnvVar debugLevelForClient = new V1EnvVar() .name("LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT").value("DEBUG"); @@ -410,9 +435,11 @@ private static void manifests(Phase phase) { envVars.add(debugLevelForClient); envVars.add(addLabels); envVars.add(addAnnotations); + envVars.add(commonsLevel); deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(envVars); util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); + util.createAndWait(NAMESPACE, null, null, externalNameService, null, true); } } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientUtils.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientUtils.java index b127e58f1a..7e18bbe72e 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientUtils.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientUtils.java @@ -144,7 +144,7 @@ final class KubernetesClientDiscoveryClientUtils { } """; - // patch to include all namespaces + // patch to include all namespaces + external name services private static final String BODY_FIVE = """ { "spec": { @@ -152,10 +152,16 @@ final class KubernetesClientDiscoveryClientUtils { "spec": { "containers": [{ "name": "spring-cloud-kubernetes-k8s-client-discovery", - "env": [{ - "name": "SPRING_CLOUD_KUBERNETES_DISCOVERY_ALL_NAMESPACES", - "value": "TRUE" - }] + "env": [ + { + "name": "SPRING_CLOUD_KUBERNETES_DISCOVERY_ALL_NAMESPACES", + "value": "TRUE" + }, + { + "name": "SPRING_CLOUD_KUBERNETES_DISCOVERY_INCLUDEEXTERNALNAMESERVICES", + "value": "TRUE" + } + ] }] } } @@ -373,6 +379,7 @@ static void patchForBlockingHealth(String image, String deploymentName, String n } // add SPRING_CLOUD_KUBERNETES_DISCOVERY_ALL_NAMESPACES=TRUE + // and SPRING_CLOUD_KUBERNETES_DISCOVERY_INCLUDEEXTERNALNAMESERVICES=TRUE static void patchForAllNamespaces(String deploymentName, String namespace) { patchWithMerge(deploymentName, namespace, BODY_FIVE, POD_LABELS); } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryFilterITDelegate.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryFilterITDelegate.java index 1a09df4b43..5e6c6f4bc9 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryFilterITDelegate.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryFilterITDelegate.java @@ -81,7 +81,7 @@ void filterMatchesOneNamespaceViaThePredicate(Util util) { Assertions.assertEquals(first.getPort(), 8080); Assertions.assertEquals(first.getNamespace(), "a-uat"); Assertions.assertEquals(first.getMetadata(), - Map.of("app", "service-wiremock", "http", "8080", "k8s_namespace", "a-uat", "type", "ClusterIP")); + Map.of("app", "service-wiremock", "port.http", "8080", "k8s_namespace", "a-uat", "type", "ClusterIP")); } @@ -125,7 +125,7 @@ void filterMatchesBothNamespacesViaThePredicate() { Assertions.assertEquals(first.getPort(), 8080); Assertions.assertEquals(first.getNamespace(), "a-uat"); Assertions.assertEquals(first.getMetadata(), - Map.of("app", "service-wiremock", "http", "8080", "k8s_namespace", "a-uat", "type", "ClusterIP")); + Map.of("app", "service-wiremock", "port.http", "8080", "k8s_namespace", "a-uat", "type", "ClusterIP")); DefaultKubernetesServiceInstance second = sorted.get(1); Assertions.assertEquals(second.getServiceId(), "service-wiremock"); @@ -133,7 +133,7 @@ void filterMatchesBothNamespacesViaThePredicate() { Assertions.assertEquals(second.getPort(), 8080); Assertions.assertEquals(second.getNamespace(), "b-uat"); Assertions.assertEquals(second.getMetadata(), - Map.of("app", "service-wiremock", "http", "8080", "k8s_namespace", "b-uat", "type", "ClusterIP")); + Map.of("app", "service-wiremock", "port.http", "8080", "k8s_namespace", "b-uat", "type", "ClusterIP")); } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryHealthITDelegate.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryHealthITDelegate.java index e5e534dc61..f38f2f2080 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryHealthITDelegate.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryHealthITDelegate.java @@ -41,6 +41,10 @@ */ class KubernetesClientDiscoveryHealthITDelegate { + KubernetesClientDiscoveryHealthITDelegate() { + + } + private static final String REACTIVE_STATUS = "$.components.reactiveDiscoveryClients.components.['Kubernetes Reactive Discovery Client'].status"; private static final String BLOCKING_STATUS = "$.components.discoveryComposite.components.discoveryClient.status"; @@ -82,7 +86,8 @@ void testBlockingConfiguration(K3sContainer container) { Assertions.assertThat(BASIC_JSON_TESTER.from(healthResult)) .extractingJsonPathArrayValue( "$.components.discoveryComposite.components.discoveryClient.details.services") - .containsExactlyInAnyOrder("spring-cloud-kubernetes-k8s-client-discovery", "kubernetes"); + .containsExactlyInAnyOrder("spring-cloud-kubernetes-k8s-client-discovery", "kubernetes", + "external-name-service"); Assertions.assertThat(BASIC_JSON_TESTER.from(healthResult)).doesNotHaveJsonPath(REACTIVE_STATUS); @@ -119,7 +124,8 @@ void testReactiveConfiguration(K3sContainer container) { Assertions.assertThat(BASIC_JSON_TESTER.from(healthResult)).extractingJsonPathArrayValue( "$.components.reactiveDiscoveryClients.components.['Kubernetes Reactive Discovery Client'].details.services") - .containsExactlyInAnyOrder("spring-cloud-kubernetes-k8s-client-discovery", "kubernetes"); + .containsExactlyInAnyOrder("spring-cloud-kubernetes-k8s-client-discovery", "kubernetes", + "external-name-service"); Assertions.assertThat(BASIC_JSON_TESTER.from(healthResult)).doesNotHaveJsonPath(BLOCKING_STATUS); @@ -167,7 +173,8 @@ void testDefaultConfiguration(K3sContainer container) { Assertions.assertThat(BASIC_JSON_TESTER.from(healthResult)) .extractingJsonPathArrayValue( "$.components.discoveryComposite.components.discoveryClient.details.services") - .containsExactlyInAnyOrder("spring-cloud-kubernetes-k8s-client-discovery", "kubernetes"); + .containsExactlyInAnyOrder("spring-cloud-kubernetes-k8s-client-discovery", "kubernetes", + "external-name-service"); Assertions.assertThat(BASIC_JSON_TESTER.from(healthResult)) .extractingJsonPathStringValue("$.components.reactiveDiscoveryClients.status").isEqualTo("UP"); @@ -178,7 +185,8 @@ void testDefaultConfiguration(K3sContainer container) { Assertions.assertThat(BASIC_JSON_TESTER.from(healthResult)).extractingJsonPathArrayValue( "$.components.reactiveDiscoveryClients.components.['Kubernetes Reactive Discovery Client'].details.services") - .containsExactlyInAnyOrder("spring-cloud-kubernetes-k8s-client-discovery", "kubernetes"); + .containsExactlyInAnyOrder("spring-cloud-kubernetes-k8s-client-discovery", "kubernetes", + "external-name-service"); // assert health/info also assertHealth(healthResult); diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryPodMetadataITDelegate.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryPodMetadataITDelegate.java index f1d1f931a7..a67dc95c2a 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryPodMetadataITDelegate.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryPodMetadataITDelegate.java @@ -50,9 +50,10 @@ void testSimple() { }).retryWhen(retrySpec()).block(); - Assertions.assertEquals(servicesResult.size(), 2); + Assertions.assertEquals(servicesResult.size(), 3); Assertions.assertTrue(servicesResult.contains("kubernetes")); Assertions.assertTrue(servicesResult.contains("spring-cloud-kubernetes-k8s-client-discovery")); + Assertions.assertTrue(servicesResult.contains("external-name-service")); WebClient ourServiceClient = builder() .baseUrl("http://localhost//service-instances/spring-cloud-kubernetes-k8s-client-discovery").build(); @@ -69,7 +70,7 @@ void testSimple() { Assertions.assertEquals(serviceInstance.getServiceId(), "spring-cloud-kubernetes-k8s-client-discovery"); Assertions.assertNotNull(serviceInstance.getHost()); Assertions.assertEquals(serviceInstance.getMetadata(), - Map.of("http", "8080", "k8s_namespace", "default", "type", "ClusterIP", "label-app", + Map.of("port.http", "8080", "k8s_namespace", "default", "type", "ClusterIP", "label-app", "spring-cloud-kubernetes-k8s-client-discovery", "annotation-custom-spring-k8s", "spring-k8s")); Assertions.assertEquals(serviceInstance.getPort(), 8080); Assertions.assertEquals(serviceInstance.getNamespace(), "default"); diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/resources/external-name-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/resources/external-name-service.yaml new file mode 100644 index 0000000000..649d5da75c --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/resources/external-name-service.yaml @@ -0,0 +1,7 @@ +kind: Service +apiVersion: v1 +metadata: + name: external-name-service +spec: + type: ExternalName + externalName: spring.io diff --git a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/native_client/Util.java b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/native_client/Util.java index e9d3dcebd3..9ad2fe9ad8 100644 --- a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/native_client/Util.java +++ b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/native_client/Util.java @@ -116,20 +116,25 @@ public void createAndWait(String namespace, String name, V1Deployment deployment @Nullable V1Ingress ingress, boolean changeVersion) { try { - String imageFromDeployment = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - if (changeVersion) { - deployment.getSpec().getTemplate().getSpec().getContainers().get(0) - .setImage(imageFromDeployment + ":" + pomVersion()); - } - else { - String[] image = imageFromDeployment.split(":", 2); - pullImage(image[0], image[1], container); - loadImage(image[0], image[1], name, container); + coreV1Api.createNamespacedService(namespace, service, null, null, null, null); + + if (deployment != null) { + String imageFromDeployment = deployment.getSpec().getTemplate().getSpec().getContainers().get(0) + .getImage(); + if (changeVersion) { + deployment.getSpec().getTemplate().getSpec().getContainers().get(0) + .setImage(imageFromDeployment + ":" + pomVersion()); + } + else { + String[] image = imageFromDeployment.split(":", 2); + pullImage(image[0], image[1], container); + loadImage(image[0], image[1], name, container); + } + + appsV1Api.createNamespacedDeployment(namespace, deployment, null, null, null, null); + waitForDeployment(namespace, deployment); } - appsV1Api.createNamespacedDeployment(namespace, deployment, null, null, null, null); - coreV1Api.createNamespacedService(namespace, service, null, null, null, null); - waitForDeployment(namespace, deployment); if (ingress != null) { networkingV1Api.createNamespacedIngress(namespace, ingress, null, null, null, null); waitForIngress(namespace, ingress); @@ -193,20 +198,27 @@ public void createNamespace(String name) { public void deleteAndWait(String namespace, V1Deployment deployment, V1Service service, @Nullable V1Ingress ingress) { - String deploymentName = deploymentName(deployment); - String serviceName = serviceName(service); - try { - Map podLabels = appsV1Api.readNamespacedDeployment(deploymentName, namespace, null) - .getSpec().getTemplate().getMetadata().getLabels(); + if (deployment != null) { + try { + String deploymentName = deploymentName(deployment); + Map podLabels = appsV1Api.readNamespacedDeployment(deploymentName, namespace, null) + .getSpec().getTemplate().getMetadata().getLabels(); + appsV1Api.deleteNamespacedDeployment(deploymentName, namespace, null, null, null, null, null, null); + coreV1Api.deleteCollectionNamespacedPod(namespace, null, null, null, null, null, + labelSelector(podLabels), null, null, null, null, null, null, null); + waitForDeploymentToBeDeleted(deploymentName, namespace); + waitForDeploymentPodsToBeDeleted(podLabels, namespace); + } + catch (Exception e) { + throw new RuntimeException(e); + } - appsV1Api.deleteNamespacedDeployment(deploymentName, namespace, null, null, null, null, null, null); - coreV1Api.deleteNamespacedService(serviceName, namespace, null, null, null, null, null, null); - coreV1Api.deleteCollectionNamespacedPod(namespace, null, null, null, null, null, labelSelector(podLabels), - null, null, null, null, null, null, null); - waitForDeploymentToBeDeleted(deploymentName, namespace); - waitForDeploymentPodsToBeDeleted(podLabels, namespace); + } + String serviceName = serviceName(service); + try { + coreV1Api.deleteNamespacedService(serviceName, namespace, null, null, null, null, null, null); if (ingress != null) { String ingressName = ingressName(ingress); networkingV1Api.deleteNamespacedIngress(ingressName, namespace, null, null, null, null, null, null); From f0c3bcd175b8ec3c3e74b7fad75e7894a810b8ea Mon Sep 17 00:00:00 2001 From: wind57 Date: Mon, 13 Nov 2023 22:28:49 +0200 Subject: [PATCH 20/53] fix test --- .../client/KubernetesClientAutoConfiguration.java | 1 + .../discovery/KubernetesInformerDiscoveryClient.java | 9 +++++---- .../KubernetesInformerDiscoveryClientTests.java | 1 - 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java b/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java index 26c5c3a4d5..b5bd43e834 100644 --- a/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java +++ b/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java @@ -54,6 +54,7 @@ public ApiClient apiClient(Environment environment) { // are missing. For the time being work-around with reading from the environment. apiClient.setUserAgent(environment.getProperty("spring.cloud.kubernetes.client.user-agent", KubernetesClientProperties.DEFAULT_USER_AGENT)); + io.kubernetes.client.openapi.Configuration.setDefaultApiClient(apiClient); return apiClient; } diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java index 1d52c5ea4d..b6ca1f2024 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java @@ -27,6 +27,7 @@ import io.kubernetes.client.informer.SharedInformer; import io.kubernetes.client.informer.SharedInformerFactory; import io.kubernetes.client.informer.cache.Lister; +import io.kubernetes.client.openapi.Configuration; import io.kubernetes.client.openapi.apis.CoreV1Api; import io.kubernetes.client.openapi.models.V1EndpointAddress; import io.kubernetes.client.openapi.models.V1EndpointSubset; @@ -35,7 +36,6 @@ import jakarta.annotation.PostConstruct; import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; @@ -82,9 +82,7 @@ public class KubernetesInformerDiscoveryClient implements DiscoveryClient { private final ServicePortSecureResolver servicePortSecureResolver; - // should be constructor injected in a future release - @Autowired - private CoreV1Api coreV1Api; + private final CoreV1Api coreV1Api; @Deprecated(forRemoval = true) public KubernetesInformerDiscoveryClient(String namespace, SharedInformerFactory sharedInformerFactory, @@ -98,6 +96,7 @@ public KubernetesInformerDiscoveryClient(String namespace, SharedInformerFactory this.properties = properties; filter = filter(properties); servicePortSecureResolver = new ServicePortSecureResolver(properties); + coreV1Api = new CoreV1Api(Configuration.getDefaultApiClient()); } public KubernetesInformerDiscoveryClient(SharedInformerFactory sharedInformerFactory, @@ -111,6 +110,7 @@ public KubernetesInformerDiscoveryClient(SharedInformerFactory sharedInformerFac this.properties = properties; filter = filter(properties); servicePortSecureResolver = new ServicePortSecureResolver(properties); + coreV1Api = new CoreV1Api(Configuration.getDefaultApiClient()); } public KubernetesInformerDiscoveryClient(List sharedInformerFactories, @@ -132,6 +132,7 @@ public KubernetesInformerDiscoveryClient(List sharedInfor this.properties = properties; filter = filter(properties); servicePortSecureResolver = new ServicePortSecureResolver(properties); + coreV1Api = new CoreV1Api(Configuration.getDefaultApiClient()); } @Override diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java index 7934b4bece..862c613d64 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java @@ -568,7 +568,6 @@ void testPodMetadata() { WireMock.configureFor("localhost", server.port()); ApiClient apiClient = new ClientBuilder().setBasePath("http://localhost:" + server.port()).build(); io.kubernetes.client.openapi.Configuration.setDefaultApiClient(apiClient); - apiClient.setDebugging(true); V1Pod pod = new V1PodBuilder().withNewMetadata().withName("my-pod").withLabels(Map.of("a", "b")) .withAnnotations(Map.of("c", "d")).endMetadata().build(); From b2a56ac11f9ae48c5b3cd2f9f483d21826d55e1c Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 14 Nov 2023 07:09:20 +0200 Subject: [PATCH 21/53] fix test --- .../client/KubernetesClientAutoConfiguration.java | 1 - .../discovery/KubernetesInformerDiscoveryClient.java | 9 +++++---- .../KubernetesInformerDiscoveryClientTests.java | 3 ++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java b/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java index b5bd43e834..26c5c3a4d5 100644 --- a/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java +++ b/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java @@ -54,7 +54,6 @@ public ApiClient apiClient(Environment environment) { // are missing. For the time being work-around with reading from the environment. apiClient.setUserAgent(environment.getProperty("spring.cloud.kubernetes.client.user-agent", KubernetesClientProperties.DEFAULT_USER_AGENT)); - io.kubernetes.client.openapi.Configuration.setDefaultApiClient(apiClient); return apiClient; } diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java index b6ca1f2024..9d5aab5a4a 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java @@ -36,6 +36,7 @@ import jakarta.annotation.PostConstruct; import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; @@ -82,7 +83,10 @@ public class KubernetesInformerDiscoveryClient implements DiscoveryClient { private final ServicePortSecureResolver servicePortSecureResolver; - private final CoreV1Api coreV1Api; + // visible only for testing and + // must be constructor injected in a future release + @Autowired + CoreV1Api coreV1Api; @Deprecated(forRemoval = true) public KubernetesInformerDiscoveryClient(String namespace, SharedInformerFactory sharedInformerFactory, @@ -96,7 +100,6 @@ public KubernetesInformerDiscoveryClient(String namespace, SharedInformerFactory this.properties = properties; filter = filter(properties); servicePortSecureResolver = new ServicePortSecureResolver(properties); - coreV1Api = new CoreV1Api(Configuration.getDefaultApiClient()); } public KubernetesInformerDiscoveryClient(SharedInformerFactory sharedInformerFactory, @@ -110,7 +113,6 @@ public KubernetesInformerDiscoveryClient(SharedInformerFactory sharedInformerFac this.properties = properties; filter = filter(properties); servicePortSecureResolver = new ServicePortSecureResolver(properties); - coreV1Api = new CoreV1Api(Configuration.getDefaultApiClient()); } public KubernetesInformerDiscoveryClient(List sharedInformerFactories, @@ -132,7 +134,6 @@ public KubernetesInformerDiscoveryClient(List sharedInfor this.properties = properties; filter = filter(properties); servicePortSecureResolver = new ServicePortSecureResolver(properties); - coreV1Api = new CoreV1Api(Configuration.getDefaultApiClient()); } @Override diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java index 862c613d64..a83aeeac37 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientTests.java @@ -28,6 +28,7 @@ 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.CoreV1EndpointPortBuilder; import io.kubernetes.client.openapi.models.V1EndpointAddress; @@ -567,7 +568,6 @@ void testPodMetadata() { server.start(); WireMock.configureFor("localhost", server.port()); ApiClient apiClient = new ClientBuilder().setBasePath("http://localhost:" + server.port()).build(); - io.kubernetes.client.openapi.Configuration.setDefaultApiClient(apiClient); V1Pod pod = new V1PodBuilder().withNewMetadata().withName("my-pod").withLabels(Map.of("a", "b")) .withAnnotations(Map.of("c", "d")).endMetadata().build(); @@ -582,6 +582,7 @@ void testPodMetadata() { KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient( SHARED_INFORMER_FACTORY, serviceLister, endpointsLister, null, null, properties); + discoveryClient.coreV1Api = new CoreV1Api(apiClient); List result = discoveryClient.getInstances("blue-service"); Assertions.assertEquals(result.size(), 1); From c2039fd6d3faaf73fe3b8fa84693e2f7f5181f60 Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 14 Nov 2023 07:32:54 +0200 Subject: [PATCH 22/53] checkstyle --- .../client/discovery/KubernetesInformerDiscoveryClient.java | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java index 9d5aab5a4a..251d4a3a56 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java @@ -27,7 +27,6 @@ import io.kubernetes.client.informer.SharedInformer; import io.kubernetes.client.informer.SharedInformerFactory; import io.kubernetes.client.informer.cache.Lister; -import io.kubernetes.client.openapi.Configuration; import io.kubernetes.client.openapi.apis.CoreV1Api; import io.kubernetes.client.openapi.models.V1EndpointAddress; import io.kubernetes.client.openapi.models.V1EndpointSubset; From 80a0380c0360498a7be7547bc13aa6762d463405 Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 14 Nov 2023 10:05:50 +0200 Subject: [PATCH 23/53] fix test --- ...coveryClientConfigClientBootstrapConfigurationTests.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests.java index 312f396fc0..f04a3b9299 100644 --- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests.java +++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests.java @@ -20,6 +20,7 @@ import io.kubernetes.client.openapi.ApiClient; import io.kubernetes.client.openapi.JSON; +import io.kubernetes.client.openapi.apis.CoreV1Api; import okhttp3.OkHttpClient; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; @@ -91,6 +92,11 @@ private void setup(String... env) { @Configuration(proxyBeanMethods = false) protected static class EnvironmentKnobbler { + @Bean + CoreV1Api coreV1Api(ApiClient apiClient) { + return new CoreV1Api(apiClient); + } + @Bean ApiClient apiClient() { ApiClient apiClient = mock(ApiClient.class); From a7597c2b7b536e248d1eadf51ffbdc97bc350866 Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 14 Nov 2023 10:44:33 +0200 Subject: [PATCH 24/53] minor clean-up --- .../discovery/DiscoveryServerUrlInvalidException.java | 2 +- .../cloud/kubernetes/discovery/KubernetesDiscoveryClient.java | 4 ++-- .../discovery/KubernetesReactiveDiscoveryClient.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/DiscoveryServerUrlInvalidException.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/DiscoveryServerUrlInvalidException.java index e1629d5218..c6b79b3cc0 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/DiscoveryServerUrlInvalidException.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/DiscoveryServerUrlInvalidException.java @@ -22,7 +22,7 @@ public class DiscoveryServerUrlInvalidException extends RuntimeException { public DiscoveryServerUrlInvalidException() { - super("spring.cloud.kubernetes.discovery.discovery-server-url must be specified and a valid URL."); + super("'spring.cloud.kubernetes.discovery.discovery-server-url' must be specified and be a valid URL."); } } diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClient.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClient.java index 62d11665da..2b09a2b2b7 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClient.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClient.java @@ -32,9 +32,9 @@ */ public class KubernetesDiscoveryClient implements DiscoveryClient { - private RestTemplate rest; + private final RestTemplate rest; - private KubernetesDiscoveryClientProperties properties; + private final KubernetesDiscoveryClientProperties properties; public KubernetesDiscoveryClient(RestTemplate rest, KubernetesDiscoveryClientProperties properties) { if (!StringUtils.hasText(properties.getDiscoveryServerUrl())) { diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClient.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClient.java index e0e830b3bf..2e5d8b8cde 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClient.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClient.java @@ -29,7 +29,7 @@ */ public class KubernetesReactiveDiscoveryClient implements ReactiveDiscoveryClient { - private WebClient webClient; + private final WebClient webClient; public KubernetesReactiveDiscoveryClient(WebClient.Builder webClientBuilder, KubernetesDiscoveryClientProperties properties) { From 1cd547fecf1bba0162a546312c18990094535dc3 Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 14 Nov 2023 10:47:37 +0200 Subject: [PATCH 25/53] fix test --- ...bernetesClientLoadBalancerPodModeTests.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientLoadBalancerPodModeTests.java b/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientLoadBalancerPodModeTests.java index bfc95cf5bb..68b8471e8b 100644 --- a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientLoadBalancerPodModeTests.java +++ b/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientLoadBalancerPodModeTests.java @@ -20,6 +20,7 @@ import java.util.Collections; import io.kubernetes.client.openapi.ApiClient; +import io.kubernetes.client.openapi.apis.CoreV1Api; import io.kubernetes.client.util.ClientBuilder; import org.junit.jupiter.api.Test; @@ -52,13 +53,13 @@ */ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = KubernetesClientLoadBalancerPodModeTests.App.class) -public class KubernetesClientLoadBalancerPodModeTests { +class KubernetesClientLoadBalancerPodModeTests { @Autowired private RestTemplate restTemplate; @Test - public void testLoadBalancer() { + void testLoadBalancer() { String resp = restTemplate.getForObject("http://servicea-wiremock", String.class); assertThat(resp).isEqualTo("hello"); } @@ -67,12 +68,17 @@ public void testLoadBalancer() { static class App { @Bean - public ApiClient apiClient() { + CoreV1Api coreV1Api(ApiClient apiClient) { + return new CoreV1Api(apiClient); + } + + @Bean + ApiClient apiClient() { return new ClientBuilder().build(); } @Bean - public BlockingLoadBalancerClient blockingLoadBalancerClient() { + BlockingLoadBalancerClient blockingLoadBalancerClient() { BlockingLoadBalancerClient client = mock(BlockingLoadBalancerClient.class); try { ClientHttpResponse response = new MockClientHttpResponse("hello".getBytes(), HttpStatus.OK); @@ -87,14 +93,14 @@ public BlockingLoadBalancerClient blockingLoadBalancerClient() { } @Bean - public KubernetesNamespaceProvider kubernetesNamespaceProvider() { + KubernetesNamespaceProvider kubernetesNamespaceProvider() { KubernetesNamespaceProvider provider = mock(KubernetesNamespaceProvider.class); when(provider.getNamespace()).thenReturn("test"); return provider; } @Bean - public KubernetesInformerDiscoveryClient kubernetesInformerDiscoveryClient() { + KubernetesInformerDiscoveryClient kubernetesInformerDiscoveryClient() { KubernetesInformerDiscoveryClient client = mock(KubernetesInformerDiscoveryClient.class); ServiceInstance instance = new DefaultServiceInstance("servicea-wiremock1", "servicea-wiremock", "fake", 8888, false); From 29031f57a3702e9442f7cc9c98e6dc548421646c Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 14 Nov 2023 15:42:28 +0200 Subject: [PATCH 26/53] minor clean-up --- .../discovery/KubernetesClientConfigServerBootstrapper.java | 3 +-- .../commons/config/KubernetesConfigServerBootstrapper.java | 2 +- .../commons/discovery/KubernetesDiscoveryProperties.java | 4 +++- .../cloud/kubernetes/discovery/ConfigServerBootstrapper.java | 3 +-- .../fabric8/discovery/Fabric8ConfigServerBootstrapper.java | 3 +-- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java index 282b843817..5e1d53a1cd 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java @@ -46,7 +46,6 @@ import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.core.env.AbstractEnvironment; import org.springframework.core.env.Environment; -import org.springframework.util.ClassUtils; import static org.springframework.cloud.kubernetes.client.KubernetesClientUtils.kubernetesApiClient; @@ -57,7 +56,7 @@ class KubernetesClientConfigServerBootstrapper extends KubernetesConfigServerBoo @Override public void initialize(BootstrapRegistry registry) { - if (!ClassUtils.isPresent("org.springframework.cloud.config.client.ConfigServerInstanceProvider", null)) { + if (hasConfigServerInstanceProvider()) { return; } // We need to pass a lambda here rather than create a new instance of diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigServerBootstrapper.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigServerBootstrapper.java index 3e82989911..d9d38096e4 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigServerBootstrapper.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigServerBootstrapper.java @@ -37,7 +37,7 @@ public static boolean hasConfigServerInstanceProvider() { public static KubernetesDiscoveryProperties createKubernetesDiscoveryProperties(Binder binder, BindHandler bindHandler) { - return binder.bind("spring.cloud.kubernetes.discovery", Bindable.of(KubernetesDiscoveryProperties.class), + return binder.bind(KubernetesDiscoveryProperties.PREFIX, Bindable.of(KubernetesDiscoveryProperties.class), bindHandler).orElseGet(() -> KubernetesDiscoveryProperties.DEFAULT); } diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/KubernetesDiscoveryProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/KubernetesDiscoveryProperties.java index f5f0dfbaa6..1b3c6e01ec 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/KubernetesDiscoveryProperties.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/KubernetesDiscoveryProperties.java @@ -48,7 +48,7 @@ * have "type: ExternalName" in their spec. */ // @formatter:off -@ConfigurationProperties("spring.cloud.kubernetes.discovery") +@ConfigurationProperties(KubernetesDiscoveryProperties.PREFIX) public record KubernetesDiscoveryProperties( @DefaultValue("true") boolean enabled, boolean allNamespaces, @DefaultValue Set namespaces, @@ -63,6 +63,8 @@ public record KubernetesDiscoveryProperties( boolean includeExternalNameServices) { // @formatter:on + public static final String PREFIX = "spring.cloud.kubernetes.discovery"; + @ConstructorBinding public KubernetesDiscoveryProperties { diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapper.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapper.java index a68d89b85f..6b6820124e 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapper.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapper.java @@ -33,7 +33,6 @@ import org.springframework.cloud.kubernetes.commons.config.KubernetesConfigServerBootstrapper; import org.springframework.cloud.kubernetes.commons.config.KubernetesConfigServerInstanceProvider; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; -import org.springframework.util.ClassUtils; /** * @author Ryan Baxter @@ -42,7 +41,7 @@ class ConfigServerBootstrapper extends KubernetesConfigServerBootstrapper { @Override public void initialize(BootstrapRegistry registry) { - if (!ClassUtils.isPresent("org.springframework.cloud.config.client.ConfigServerInstanceProvider", null)) { + if (hasConfigServerInstanceProvider()) { return; } // We need to pass a lambda here rather than create a new instance of 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 dc2d6528c5..67cf04943f 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 @@ -35,7 +35,6 @@ 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.util.ClassUtils; /** * @author Ryan Baxter @@ -44,7 +43,7 @@ class Fabric8ConfigServerBootstrapper extends KubernetesConfigServerBootstrapper @Override public void initialize(BootstrapRegistry registry) { - if (!ClassUtils.isPresent("org.springframework.cloud.config.client.ConfigServerInstanceProvider", null)) { + if (hasConfigServerInstanceProvider()) { return; } // We need to pass a lambda here rather than create a new instance of From e22960dd6a2c54087ea1aa0db9699e583881fcda Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 14 Nov 2023 15:43:27 +0200 Subject: [PATCH 27/53] minor clean-up --- .../KubernetesClientConfigServerBootstrapper.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java index 5e1d53a1cd..aa9cc8f399 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java @@ -95,9 +95,9 @@ public List apply(String serviceId, Binder binder, BindHandler .getInstances(serviceId); } - protected KubernetesConfigServerInstanceProvider getInstanceProvider( - KubernetesDiscoveryProperties discoveryProperties, KubernetesClientProperties clientProperties, - BootstrapContext context, Binder binder, BindHandler bindHandler, Log log) { + private KubernetesConfigServerInstanceProvider getInstanceProvider( + KubernetesDiscoveryProperties discoveryProperties, KubernetesClientProperties clientProperties, + BootstrapContext context, Binder binder, BindHandler bindHandler, Log log) { if (context.isRegistered(KubernetesInformerDiscoveryClient.class)) { KubernetesInformerDiscoveryClient client = context.get(KubernetesInformerDiscoveryClient.class); return client::getInstances; @@ -115,12 +115,12 @@ protected KubernetesConfigServerInstanceProvider getInstanceProvider( String namespace = getInformerNamespace(kubernetesNamespaceProvider, discoveryProperties); SharedInformerFactory sharedInformerFactory = new SharedInformerFactory(apiClient); - final GenericKubernetesApi servicesApi = new GenericKubernetesApi<>( + GenericKubernetesApi servicesApi = new GenericKubernetesApi<>( V1Service.class, V1ServiceList.class, "", "v1", "services", apiClient); SharedIndexInformer serviceSharedIndexInformer = sharedInformerFactory .sharedIndexInformerFor(servicesApi, V1Service.class, 0L, namespace); Lister serviceLister = new Lister<>(serviceSharedIndexInformer.getIndexer()); - final GenericKubernetesApi endpointsApi = new GenericKubernetesApi<>( + GenericKubernetesApi endpointsApi = new GenericKubernetesApi<>( V1Endpoints.class, V1EndpointsList.class, "", "v1", "endpoints", apiClient); SharedIndexInformer endpointsSharedIndexInformer = sharedInformerFactory .sharedIndexInformerFor(endpointsApi, V1Endpoints.class, 0L, namespace); From 897e0060ec14509d6a78807c0aaf4cd033086fd9 Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 14 Nov 2023 17:02:31 +0200 Subject: [PATCH 28/53] dirty --- .../discovery/ConfigServerBootstrapper.java | 20 +++++-------------- .../ConfigServerBootstrapperTests.java | 12 ++++++++--- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapper.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapper.java index 6b6820124e..30e4817ca4 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapper.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapper.java @@ -29,7 +29,6 @@ import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.config.client.ConfigServerInstanceProvider; -import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties; import org.springframework.cloud.kubernetes.commons.config.KubernetesConfigServerBootstrapper; import org.springframework.cloud.kubernetes.commons.config.KubernetesConfigServerInstanceProvider; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; @@ -53,14 +52,11 @@ public void initialize(BootstrapRegistry registry) { final static class KubernetesFunction implements ConfigServerInstanceProvider.Function { - private final BootstrapContext context; - - private KubernetesFunction(BootstrapContext context) { - this.context = context; + private KubernetesFunction() { } static KubernetesFunction create(BootstrapContext context) { - return new KubernetesFunction(context); + return new KubernetesFunction(); } @Override @@ -73,18 +69,12 @@ public List apply(String serviceId, Binder binder, BindHandler // Kubernetes DiscoveryClient return Collections.emptyList(); } - KubernetesDiscoveryProperties discoveryProperties = createKubernetesDiscoveryProperties(binder, - bindHandler); - KubernetesClientProperties clientProperties = createKubernetesClientProperties(binder, bindHandler); - return getInstanceProvider(discoveryProperties, clientProperties, context, binder, bindHandler, log) - .getInstances(serviceId); + return getInstanceProvider(binder, bindHandler).getInstances(serviceId); } - private KubernetesConfigServerInstanceProvider getInstanceProvider( - KubernetesDiscoveryProperties discoveryProperties, KubernetesClientProperties clientProperties, - BootstrapContext context, Binder binder, BindHandler bindHandler, Log log) { + private KubernetesConfigServerInstanceProvider getInstanceProvider(Binder binder, BindHandler bindHandler) { KubernetesDiscoveryClientProperties kubernetesDiscoveryClientProperties = binder - .bind("spring.cloud.kubernetes.discovery", Bindable.of(KubernetesDiscoveryClientProperties.class), + .bind(KubernetesDiscoveryProperties.PREFIX, Bindable.of(KubernetesDiscoveryClientProperties.class), bindHandler) .orElseGet(KubernetesDiscoveryClientProperties::new); KubernetesDiscoveryClientAutoConfiguration.Servlet autoConfiguration = new KubernetesDiscoveryClientAutoConfiguration.Servlet(); diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java index d911c0cce0..26eab1e694 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java @@ -68,9 +68,15 @@ void beforeAll() throws JsonProcessingException { wireMockServer = new WireMockServer(options().dynamicPort()); wireMockServer.start(); WireMock.configureFor(wireMockServer.port()); - String APPS_NAME = "[{\"instanceId\":\"uid2\",\"serviceId\":\"spring-cloud-kubernetes-configserver\",\"host\":\"localhost\",\"port\":" - + wireMockServer.port() + ",\"uri\":\"" + wireMockServer.baseUrl() - + "\",\"secure\":false,\"metadata\":{\"spring\":\"true\",\"http\":\"8080\",\"k8s\":\"true\"},\"namespace\":\"namespace1\",\"cluster\":null,\"scheme\":\"http\"}]"; + String APPS_NAME = """ + [{ + "instanceId": "uid2", + "serviceId": "spring-cloud-kubernetes-configserver", + "host": "localhost", + "port":" + wireMockServer.port() + ","uri":"" + wireMockServer.baseUrl() + + "","secure":false,"metadata":{"spring":"true","http":"8080","k8s":"true"},"namespace":"namespace1","cluster":null,"scheme":"http"}] + """; + stubFor(get("/apps/spring-cloud-kubernetes-configserver").willReturn( aResponse().withStatus(200).withBody(APPS_NAME).withHeader("content-type", "application/json"))); Environment environment = new Environment("test", "default"); From 6ba109a70829332bd1902580904be0a5823be8df Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 14 Nov 2023 17:09:50 +0200 Subject: [PATCH 29/53] dirty --- .../ConfigServerBootstrapperTests.java | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java index 26eab1e694..5bdc5f208a 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java @@ -69,13 +69,21 @@ void beforeAll() throws JsonProcessingException { wireMockServer.start(); WireMock.configureFor(wireMockServer.port()); String APPS_NAME = """ - [{ - "instanceId": "uid2", - "serviceId": "spring-cloud-kubernetes-configserver", - "host": "localhost", - "port":" + wireMockServer.port() + ","uri":"" + wireMockServer.baseUrl() - + "","secure":false,"metadata":{"spring":"true","http":"8080","k8s":"true"},"namespace":"namespace1","cluster":null,"scheme":"http"}] - """; + [{ + "instanceId": "uid2", + "serviceId": "spring-cloud-kubernetes-configserver", + "host": "localhost", + "port":" %s, + "uri": "%s", + "secure":false, + "metadata":{"spring": "true", "http": "8080", "k8s": "true"}, + "namespace": "namespace1", + "cluster": null, + "scheme":"http" + }] + """.formatted(wireMockServer.port(), wireMockServer.baseUrl()); + + System.out.println(APPS_NAME); stubFor(get("/apps/spring-cloud-kubernetes-configserver").willReturn( aResponse().withStatus(200).withBody(APPS_NAME).withHeader("content-type", "application/json"))); From 3b9bdb78d1ff54e5ca25f3146679c2a1fe3cf4dc Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 14 Nov 2023 17:32:02 +0200 Subject: [PATCH 30/53] minor clean-up --- .../ConfigServerBootstrapperTests.java | 2 +- ...DiscoveryClientAutoConfigurationTests.java | 16 +++--- .../KubernetesDiscoveryClientTests.java | 52 +++++++++++++++++-- ...ubernetesReactiveDiscoveryClientTests.java | 50 +++++++++++++++++- 4 files changed, 106 insertions(+), 14 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java index 5bdc5f208a..ab4d97f7e0 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java @@ -73,7 +73,7 @@ void beforeAll() throws JsonProcessingException { "instanceId": "uid2", "serviceId": "spring-cloud-kubernetes-configserver", "host": "localhost", - "port":" %s, + "port": "%s", "uri": "%s", "secure":false, "metadata":{"spring": "true", "http": "8080", "k8s": "true"}, diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java index e634d9e953..5662f0cbe9 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java @@ -34,12 +34,12 @@ */ class KubernetesDiscoveryClientAutoConfigurationTests { - private ApplicationContextRunner contextRunner = new ApplicationContextRunner() + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withConfiguration(AutoConfigurations.of(UtilAutoConfiguration.class, ReactiveCommonsClientAutoConfiguration.class, KubernetesDiscoveryClientAutoConfiguration.class)); @Test - public void shouldWorkWithDefaults() { + void shouldWorkWithDefaults() { contextRunner .withPropertyValues("spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver") @@ -51,7 +51,7 @@ public void shouldWorkWithDefaults() { } @Test - public void shouldNotHaveDiscoveryClientWhenDiscoveryDisabled() { + void shouldNotHaveDiscoveryClientWhenDiscoveryDisabled() { contextRunner .withPropertyValues("spring.cloud.discovery.enabled=false", "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver") @@ -63,7 +63,7 @@ public void shouldNotHaveDiscoveryClientWhenDiscoveryDisabled() { } @Test - public void shouldNotHaveDiscoveryClientWhenKubernetesDiscoveryDisabled() { + void shouldNotHaveDiscoveryClientWhenKubernetesDiscoveryDisabled() { contextRunner .withPropertyValues("spring.cloud.kubernetes.discovery.enabled=false", "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver") @@ -75,7 +75,7 @@ public void shouldNotHaveDiscoveryClientWhenKubernetesDiscoveryDisabled() { } @Test - public void shouldHaveReactiveDiscoveryClient() { + void shouldHaveReactiveDiscoveryClient() { contextRunner .withPropertyValues("spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver") @@ -87,7 +87,7 @@ public void shouldHaveReactiveDiscoveryClient() { } @Test - public void shouldNotHaveDiscoveryClientWhenReactiveDiscoveryDisabled() { + void shouldNotHaveDiscoveryClientWhenReactiveDiscoveryDisabled() { contextRunner.withPropertyValues("spring.cloud.discovery.reactive.enabled=false").run(context -> { assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class); @@ -95,7 +95,7 @@ public void shouldNotHaveDiscoveryClientWhenReactiveDiscoveryDisabled() { } @Test - public void shouldNotHaveDiscoveryClientWhenKubernetesDisabled() { + void shouldNotHaveDiscoveryClientWhenKubernetesDisabled() { contextRunner.run(context -> { assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class); @@ -103,7 +103,7 @@ public void shouldNotHaveDiscoveryClientWhenKubernetesDisabled() { } @Test - public void worksWithoutActuator() { + void worksWithoutActuator() { contextRunner .withPropertyValues("spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver") diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTests.java index 16c17404f7..f620c0c8c1 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTests.java @@ -45,9 +45,55 @@ */ class KubernetesDiscoveryClientTests { - private static final String APPS = "[{\"name\":\"test-svc-1\",\"serviceInstances\":[{\"instanceId\":\"uid1\",\"serviceId\":\"test-svc-1\",\"host\":\"2.2.2.2\",\"port\":8080,\"uri\":\"http://2.2.2.2:8080\",\"secure\":false,\"metadata\":{\"http\":\"8080\"},\"namespace\":\"namespace1\",\"cluster\":null,\"scheme\":\"http\"}]},{\"name\":\"test-svc-3\",\"serviceInstances\":[{\"instanceId\":\"uid2\",\"serviceId\":\"test-svc-3\",\"host\":\"2.2.2.2\",\"port\":8080,\"uri\":\"http://2.2.2.2:8080\",\"secure\":false,\"metadata\":{\"spring\":\"true\",\"http\":\"8080\",\"k8s\":\"true\"},\"namespace\":\"namespace2\",\"cluster\":null,\"scheme\":\"http\"}]}]"; - - private static final String APPS_NAME = "[{\"instanceId\":\"uid2\",\"serviceId\":\"test-svc-3\",\"host\":\"2.2.2.2\",\"port\":8080,\"uri\":\"http://2.2.2.2:8080\",\"secure\":false,\"metadata\":{\"spring\":\"true\",\"http\":\"8080\",\"k8s\":\"true\"},\"namespace\":\"namespace2\",\"cluster\":null,\"scheme\":\"http\"}]"; + private static final String APPS = """ + [{ + "name": "test-svc-1", + "serviceInstances": + [{ + "instanceId": "uid1", + "serviceId": "test-svc-1", + "host": "2.2.2.2", + "port": 8080, + "uri": "http://2.2.2.2:8080", + "secure": false, + "metadata":{"http": "8080"}, + "namespace": "namespace1", + "cluster": null, + "scheme": "http" + }] + }, + { + "name": "test-svc-3", + "serviceInstances": + [{ + "instanceId": "uid2", + "serviceId": "test-svc-3", + "host": "2.2.2.2", + "port": 8080, + "uri": "http://2.2.2.2:8080", + "secure": false, + "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, + "namespace": "namespace2", + "cluster":null, + "scheme":"http" + }] + }] + """; + + private static final String APPS_NAME = """ + [{ + "instanceId": "uid2", + "serviceId": "test-svc-3", + "host": "2.2.2.2", + "port": 8080, + "uri": "http://2.2.2.2:8080", + "secure": false, + "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, + "namespace": "namespace2", + "cluster": null, + "scheme": "http" + }] + """; private static WireMockServer wireMockServer; diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClientTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClientTests.java index 9f6adf6b4d..9af8e51c25 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClientTests.java @@ -38,9 +38,55 @@ */ class KubernetesReactiveDiscoveryClientTests { - private static final String APPS = "[{\"name\":\"test-svc-1\",\"serviceInstances\":[{\"instanceId\":\"uid1\",\"serviceId\":\"test-svc-1\",\"host\":\"2.2.2.2\",\"port\":8080,\"uri\":\"http://2.2.2.2:8080\",\"secure\":false,\"metadata\":{\"http\":\"8080\"},\"namespace\":\"namespace1\",\"cluster\":null,\"scheme\":\"http\"}]},{\"name\":\"test-svc-3\",\"serviceInstances\":[{\"instanceId\":\"uid2\",\"serviceId\":\"test-svc-3\",\"host\":\"2.2.2.2\",\"port\":8080,\"uri\":\"http://2.2.2.2:8080\",\"secure\":false,\"metadata\":{\"spring\":\"true\",\"http\":\"8080\",\"k8s\":\"true\"},\"namespace\":\"namespace1\",\"cluster\":null,\"scheme\":\"http\"}]}]"; + private static final String APPS = """ + [{ + "name": "test-svc-1", + "serviceInstances": + [{ + "instanceId": "uid1", + "serviceId": "test-svc-1", + "host": "2.2.2.2", + "port": 8080, + "uri": "http://2.2.2.2:8080", + "secure": false, + "metadata": {"http":"8080"}, + "namespace": "namespace1", + "cluster": null, + "scheme": "http" + }] + }, + { + "name": "test-svc-3", + "serviceInstances": + [{ + "instanceId": "uid2", + "serviceId": "test-svc-3", + "host": "2.2.2.2", + "port": 8080, + "uri": "http://2.2.2.2:8080", + "secure": false, + "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, + "namespace": "namespace1", + "cluster": null, + "scheme": "http" + }] + }] + """; - private static final String APPS_NAME = "[{\"instanceId\":\"uid2\",\"serviceId\":\"test-svc-3\",\"host\":\"2.2.2.2\",\"port\":8080,\"uri\":\"http://2.2.2.2:8080\",\"secure\":false,\"metadata\":{\"spring\":\"true\",\"http\":\"8080\",\"k8s\":\"true\"},\"namespace\":\"namespace1\",\"cluster\":null,\"scheme\":\"http\"}]"; + private static final String APPS_NAME = """ + [{ + "instanceId": "uid2", + "serviceId": "test-svc-3", + "host": "2.2.2.2", + "port": 8080, + "uri": "http://2.2.2.2:8080", + "secure": false, + "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, + "namespace": "namespace1", + "cluster": null, + "scheme": "http" + }] + """; private static WireMockServer wireMockServer; From e2cec3c4355c671e931e75f7fa98cfe8ce654a5d Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 15 Nov 2023 18:43:20 +0200 Subject: [PATCH 31/53] checkstyle --- .../commons/discovery/KubernetesDiscoveryProperties.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/KubernetesDiscoveryProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/KubernetesDiscoveryProperties.java index 1b3c6e01ec..0d8b803222 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/KubernetesDiscoveryProperties.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/KubernetesDiscoveryProperties.java @@ -63,6 +63,9 @@ public record KubernetesDiscoveryProperties( boolean includeExternalNameServices) { // @formatter:on + /** + * Prefix of the properties. + */ public static final String PREFIX = "spring.cloud.kubernetes.discovery"; @ConstructorBinding From 6e5f667855094c68c4f1413b1bf06af735208096 Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 15 Nov 2023 18:47:03 +0200 Subject: [PATCH 32/53] formatting --- ...ernetesClientConfigServerBootstrapper.java | 8 +- .../ConfigServerBootstrapperTests.java | 26 +++--- .../KubernetesDiscoveryClientTests.java | 80 +++++++++---------- ...ubernetesReactiveDiscoveryClientTests.java | 72 ++++++++--------- 4 files changed, 93 insertions(+), 93 deletions(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java index aa9cc8f399..41c16d67ad 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java @@ -96,8 +96,8 @@ public List apply(String serviceId, Binder binder, BindHandler } private KubernetesConfigServerInstanceProvider getInstanceProvider( - KubernetesDiscoveryProperties discoveryProperties, KubernetesClientProperties clientProperties, - BootstrapContext context, Binder binder, BindHandler bindHandler, Log log) { + KubernetesDiscoveryProperties discoveryProperties, KubernetesClientProperties clientProperties, + BootstrapContext context, Binder binder, BindHandler bindHandler, Log log) { if (context.isRegistered(KubernetesInformerDiscoveryClient.class)) { KubernetesInformerDiscoveryClient client = context.get(KubernetesInformerDiscoveryClient.class); return client::getInstances; @@ -115,8 +115,8 @@ private KubernetesConfigServerInstanceProvider getInstanceProvider( String namespace = getInformerNamespace(kubernetesNamespaceProvider, discoveryProperties); SharedInformerFactory sharedInformerFactory = new SharedInformerFactory(apiClient); - GenericKubernetesApi servicesApi = new GenericKubernetesApi<>( - V1Service.class, V1ServiceList.class, "", "v1", "services", apiClient); + GenericKubernetesApi servicesApi = new GenericKubernetesApi<>(V1Service.class, + V1ServiceList.class, "", "v1", "services", apiClient); SharedIndexInformer serviceSharedIndexInformer = sharedInformerFactory .sharedIndexInformerFor(servicesApi, V1Service.class, 0L, namespace); Lister serviceLister = new Lister<>(serviceSharedIndexInformer.getIndexer()); diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java index ab4d97f7e0..ff57b137e3 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java @@ -69,19 +69,19 @@ void beforeAll() throws JsonProcessingException { wireMockServer.start(); WireMock.configureFor(wireMockServer.port()); String APPS_NAME = """ - [{ - "instanceId": "uid2", - "serviceId": "spring-cloud-kubernetes-configserver", - "host": "localhost", - "port": "%s", - "uri": "%s", - "secure":false, - "metadata":{"spring": "true", "http": "8080", "k8s": "true"}, - "namespace": "namespace1", - "cluster": null, - "scheme":"http" - }] - """.formatted(wireMockServer.port(), wireMockServer.baseUrl()); + [{ + "instanceId": "uid2", + "serviceId": "spring-cloud-kubernetes-configserver", + "host": "localhost", + "port": "%s", + "uri": "%s", + "secure":false, + "metadata":{"spring": "true", "http": "8080", "k8s": "true"}, + "namespace": "namespace1", + "cluster": null, + "scheme":"http" + }] + """.formatted(wireMockServer.port(), wireMockServer.baseUrl()); System.out.println(APPS_NAME); diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTests.java index f620c0c8c1..6a81b48352 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTests.java @@ -46,54 +46,54 @@ class KubernetesDiscoveryClientTests { private static final String APPS = """ - [{ - "name": "test-svc-1", - "serviceInstances": [{ - "instanceId": "uid1", - "serviceId": "test-svc-1", + "name": "test-svc-1", + "serviceInstances": + [{ + "instanceId": "uid1", + "serviceId": "test-svc-1", + "host": "2.2.2.2", + "port": 8080, + "uri": "http://2.2.2.2:8080", + "secure": false, + "metadata":{"http": "8080"}, + "namespace": "namespace1", + "cluster": null, + "scheme": "http" + }] + }, + { + "name": "test-svc-3", + "serviceInstances": + [{ + "instanceId": "uid2", + "serviceId": "test-svc-3", + "host": "2.2.2.2", + "port": 8080, + "uri": "http://2.2.2.2:8080", + "secure": false, + "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, + "namespace": "namespace2", + "cluster":null, + "scheme":"http" + }] + }] + """; + + private static final String APPS_NAME = """ + [{ + "instanceId": "uid2", + "serviceId": "test-svc-3", "host": "2.2.2.2", "port": 8080, "uri": "http://2.2.2.2:8080", "secure": false, - "metadata":{"http": "8080"}, - "namespace": "namespace1", + "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, + "namespace": "namespace2", "cluster": null, "scheme": "http" }] - }, - { - "name": "test-svc-3", - "serviceInstances": - [{ - "instanceId": "uid2", - "serviceId": "test-svc-3", - "host": "2.2.2.2", - "port": 8080, - "uri": "http://2.2.2.2:8080", - "secure": false, - "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, - "namespace": "namespace2", - "cluster":null, - "scheme":"http" - }] - }] - """; - - private static final String APPS_NAME = """ - [{ - "instanceId": "uid2", - "serviceId": "test-svc-3", - "host": "2.2.2.2", - "port": 8080, - "uri": "http://2.2.2.2:8080", - "secure": false, - "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, - "namespace": "namespace2", - "cluster": null, - "scheme": "http" - }] - """; + """; private static WireMockServer wireMockServer; diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClientTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClientTests.java index 9af8e51c25..376ff2d422 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClientTests.java @@ -39,25 +39,41 @@ class KubernetesReactiveDiscoveryClientTests { private static final String APPS = """ - [{ - "name": "test-svc-1", - "serviceInstances": - [{ - "instanceId": "uid1", - "serviceId": "test-svc-1", - "host": "2.2.2.2", - "port": 8080, - "uri": "http://2.2.2.2:8080", - "secure": false, - "metadata": {"http":"8080"}, - "namespace": "namespace1", - "cluster": null, - "scheme": "http" - }] - }, - { - "name": "test-svc-3", - "serviceInstances": + [{ + "name": "test-svc-1", + "serviceInstances": + [{ + "instanceId": "uid1", + "serviceId": "test-svc-1", + "host": "2.2.2.2", + "port": 8080, + "uri": "http://2.2.2.2:8080", + "secure": false, + "metadata": {"http":"8080"}, + "namespace": "namespace1", + "cluster": null, + "scheme": "http" + }] + }, + { + "name": "test-svc-3", + "serviceInstances": + [{ + "instanceId": "uid2", + "serviceId": "test-svc-3", + "host": "2.2.2.2", + "port": 8080, + "uri": "http://2.2.2.2:8080", + "secure": false, + "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, + "namespace": "namespace1", + "cluster": null, + "scheme": "http" + }] + }] + """; + + private static final String APPS_NAME = """ [{ "instanceId": "uid2", "serviceId": "test-svc-3", @@ -70,23 +86,7 @@ class KubernetesReactiveDiscoveryClientTests { "cluster": null, "scheme": "http" }] - }] - """; - - private static final String APPS_NAME = """ - [{ - "instanceId": "uid2", - "serviceId": "test-svc-3", - "host": "2.2.2.2", - "port": 8080, - "uri": "http://2.2.2.2:8080", - "secure": false, - "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, - "namespace": "namespace1", - "cluster": null, - "scheme": "http" - }] - """; + """; private static WireMockServer wireMockServer; From 2f8d744ecf21216d6150c9bedc032accd4d8915b Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 15 Nov 2023 18:59:56 +0200 Subject: [PATCH 33/53] before tests --- ...netesDiscoveryClientAutoConfiguration.java | 1 + ...coveryClientBlockingAutoConfiguration.java | 75 ++++++++++++++++++ ...coveryClientReactiveAutoConfiguration.java | 76 +++++++++++++++++++ ...ot.autoconfigure.AutoConfiguration.imports | 3 +- 4 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java create mode 100644 spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfiguration.java index a14929ff08..8eeb07c685 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfiguration.java @@ -50,6 +50,7 @@ @ConditionalOnKubernetesDiscoveryEnabled @EnableConfigurationProperties({ DiscoveryClientHealthIndicatorProperties.class, KubernetesDiscoveryClientProperties.class }) +@Deprecated(forRemoval = true) public class KubernetesDiscoveryClientAutoConfiguration { @Configuration(proxyBeanMethods = false) diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java new file mode 100644 index 0000000000..974d76276a --- /dev/null +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java @@ -0,0 +1,75 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.discovery; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; +import org.springframework.boot.cloud.CloudPlatform; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled; +import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; +import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicatorProperties; +import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnKubernetesDiscoveryEnabled; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +/** + * @author wind57 + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnDiscoveryEnabled +@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) +@ConditionalOnKubernetesDiscoveryEnabled +@EnableConfigurationProperties({ DiscoveryClientHealthIndicatorProperties.class, + KubernetesDiscoveryClientProperties.class }) +class KubernetesDiscoveryClientBlockingAutoConfiguration { + + @Bean + @ConditionalOnMissingClass("org.springframework.web.reactive.function.client.WebClient") + @ConditionalOnMissingBean(RestTemplate.class) + RestTemplate restTemplate() { + return new RestTemplateBuilder().build(); + } + + @Bean + @ConditionalOnMissingClass("org.springframework.web.reactive.function.client.WebClient") + DiscoveryClient kubernetesDiscoveryClient(RestTemplate restTemplate, + KubernetesDiscoveryClientProperties properties) { + return new KubernetesDiscoveryClient(restTemplate, properties); + } + + @Bean + @ConditionalOnClass({ HealthIndicator.class }) + @ConditionalOnDiscoveryHealthIndicatorEnabled + InitializingBean indicatorInitializer(ApplicationEventPublisher applicationEventPublisher, + ApplicationContext applicationContext) { + return () -> applicationEventPublisher + .publishEvent(new InstanceRegisteredEvent<>(applicationContext.getId(), null)); + + } + +} diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java new file mode 100644 index 0000000000..841916306b --- /dev/null +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java @@ -0,0 +1,76 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.discovery; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.cloud.CloudPlatform; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled; +import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled; +import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled; +import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; +import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; +import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicatorProperties; +import org.springframework.cloud.client.discovery.health.reactive.ReactiveDiscoveryClientHealthIndicator; +import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnKubernetesDiscoveryEnabled; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.function.client.WebClient; + +/** + * @author wind57 + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnDiscoveryEnabled +@ConditionalOnReactiveDiscoveryEnabled +@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) +@ConditionalOnKubernetesDiscoveryEnabled +@EnableConfigurationProperties({ DiscoveryClientHealthIndicatorProperties.class, + KubernetesDiscoveryClientProperties.class }) +class KubernetesDiscoveryClientReactiveAutoConfiguration { + + @Bean + @ConditionalOnClass(name = { "org.springframework.web.reactive.function.client.WebClient" }) + @ConditionalOnMissingBean(WebClient.Builder.class) + WebClient.Builder webClientBuilder() { + return WebClient.builder(); + } + + @Bean + @ConditionalOnClass(name = { "org.springframework.web.reactive.function.client.WebClient" }) + ReactiveDiscoveryClient kubernetesReactiveDiscoveryClient(WebClient.Builder webClientBuilder, + KubernetesDiscoveryClientProperties properties) { + return new KubernetesReactiveDiscoveryClient(webClientBuilder, properties); + } + + @Bean + @ConditionalOnClass(name = "org.springframework.boot.actuate.health.ReactiveHealthIndicator") + @ConditionalOnDiscoveryHealthIndicatorEnabled + ReactiveDiscoveryClientHealthIndicator kubernetesReactiveDiscoveryClientHealthIndicator( + KubernetesReactiveDiscoveryClient client, DiscoveryClientHealthIndicatorProperties properties, + ApplicationContext applicationContext) { + ReactiveDiscoveryClientHealthIndicator healthIndicator = new ReactiveDiscoveryClientHealthIndicator(client, + properties); + InstanceRegisteredEvent event = new InstanceRegisteredEvent(applicationContext.getId(), null); + healthIndicator.onApplicationEvent(event); + return healthIndicator; + } + +} diff --git a/spring-cloud-kubernetes-discovery/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-kubernetes-discovery/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index d9d4dd270d..67bac3b304 100644 --- a/spring-cloud-kubernetes-discovery/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-cloud-kubernetes-discovery/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1,2 @@ -org.springframework.cloud.kubernetes.discovery.KubernetesDiscoveryClientAutoConfiguration +org.springframework.cloud.kubernetes.discovery.KubernetesDiscoveryClientBlockingAutoConfiguration +org.springframework.cloud.kubernetes.discovery.KubernetesDiscoveryClientReactiveAutoConfiguration From ea909595326fa6db2f7aa1bc6a3e76792de1f136 Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 15 Nov 2023 19:05:05 +0200 Subject: [PATCH 34/53] align --- .../KubernetesDiscoveryClientBlockingAutoConfiguration.java | 2 +- .../KubernetesDiscoveryClientReactiveAutoConfiguration.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java index 974d76276a..84c265a1eb 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java @@ -42,8 +42,8 @@ */ @Configuration(proxyBeanMethods = false) @ConditionalOnDiscoveryEnabled -@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) @ConditionalOnKubernetesDiscoveryEnabled +@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) @EnableConfigurationProperties({ DiscoveryClientHealthIndicatorProperties.class, KubernetesDiscoveryClientProperties.class }) class KubernetesDiscoveryClientBlockingAutoConfiguration { diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java index 841916306b..a4ac9013b3 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java @@ -40,8 +40,8 @@ @Configuration(proxyBeanMethods = false) @ConditionalOnDiscoveryEnabled @ConditionalOnReactiveDiscoveryEnabled -@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) @ConditionalOnKubernetesDiscoveryEnabled +@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) @EnableConfigurationProperties({ DiscoveryClientHealthIndicatorProperties.class, KubernetesDiscoveryClientProperties.class }) class KubernetesDiscoveryClientReactiveAutoConfiguration { From 6464751c7e9afe09729c6c84c67bcf5d9de8e900 Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 15 Nov 2023 20:18:08 +0200 Subject: [PATCH 35/53] started work on tests --- ...coveryClientReactiveAutoConfiguration.java | 2 +- ...rnetesDiscoveryAutoConfigurationTests.java | 75 +++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java index a4ac9013b3..0e71a21257 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java @@ -39,8 +39,8 @@ */ @Configuration(proxyBeanMethods = false) @ConditionalOnDiscoveryEnabled -@ConditionalOnReactiveDiscoveryEnabled @ConditionalOnKubernetesDiscoveryEnabled +@ConditionalOnReactiveDiscoveryEnabled @ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) @EnableConfigurationProperties({ DiscoveryClientHealthIndicatorProperties.class, KubernetesDiscoveryClientProperties.class }) diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java new file mode 100644 index 0000000000..f5b0244abd --- /dev/null +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java @@ -0,0 +1,75 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.discovery; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.FilteredClassLoader; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.reactive.function.client.WebClient; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +class KubernetesDiscoveryAutoConfigurationTests { + + /** + *
+	 *     '@ConditionalOnDiscoveryEnabled' is not matched, thus no beans are created
+	 *     from either blocking or reactive configurations.
+	 * 
+ */ + @Test + void discoveryEnabledDefault() { + setupWithFilteredClassLoader(null, "spring.main.cloud-platform=KUBERNETES", + "spring.cloud.discovery.enabled=false"); + applicationContextRunner.run(context -> { + assertThat(context).doesNotHaveBean(RestTemplate.class); + assertThat(context).doesNotHaveBean(DiscoveryClient.class); + + assertThat(context).doesNotHaveBean(WebClient.Builder.class); + assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); + + }); + } + + private ApplicationContextRunner applicationContextRunner; + + private void setupWithFilteredClassLoader(Class cls, String... properties) { + + if (cls != null) { + applicationContextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(KubernetesDiscoveryClientBlockingAutoConfiguration.class, + KubernetesDiscoveryClientReactiveAutoConfiguration.class)) + .withClassLoader(new FilteredClassLoader(cls)) + .withPropertyValues(properties); + } + else { + applicationContextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(KubernetesDiscoveryClientBlockingAutoConfiguration.class, + KubernetesDiscoveryClientReactiveAutoConfiguration.class)) + .withPropertyValues(properties); + } + + } + +} From a9428d6338bd106a6f792d4d78cec0b06c6d7dcf Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 15 Nov 2023 21:20:48 +0200 Subject: [PATCH 36/53] trigger From 57a7280c9eb9056e1d0ddfa6a2684e8c27a4d3d9 Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 15 Nov 2023 21:27:41 +0200 Subject: [PATCH 37/53] formatting --- .../KubernetesClientConfigServerBootstrapper.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java index aa9cc8f399..41c16d67ad 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java @@ -96,8 +96,8 @@ public List apply(String serviceId, Binder binder, BindHandler } private KubernetesConfigServerInstanceProvider getInstanceProvider( - KubernetesDiscoveryProperties discoveryProperties, KubernetesClientProperties clientProperties, - BootstrapContext context, Binder binder, BindHandler bindHandler, Log log) { + KubernetesDiscoveryProperties discoveryProperties, KubernetesClientProperties clientProperties, + BootstrapContext context, Binder binder, BindHandler bindHandler, Log log) { if (context.isRegistered(KubernetesInformerDiscoveryClient.class)) { KubernetesInformerDiscoveryClient client = context.get(KubernetesInformerDiscoveryClient.class); return client::getInstances; @@ -115,8 +115,8 @@ private KubernetesConfigServerInstanceProvider getInstanceProvider( String namespace = getInformerNamespace(kubernetesNamespaceProvider, discoveryProperties); SharedInformerFactory sharedInformerFactory = new SharedInformerFactory(apiClient); - GenericKubernetesApi servicesApi = new GenericKubernetesApi<>( - V1Service.class, V1ServiceList.class, "", "v1", "services", apiClient); + GenericKubernetesApi servicesApi = new GenericKubernetesApi<>(V1Service.class, + V1ServiceList.class, "", "v1", "services", apiClient); SharedIndexInformer serviceSharedIndexInformer = sharedInformerFactory .sharedIndexInformerFor(servicesApi, V1Service.class, 0L, namespace); Lister serviceLister = new Lister<>(serviceSharedIndexInformer.getIndexer()); From 90b04451d5e2315ec11e66a0e1a247972a5f2e09 Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 17 Nov 2023 10:13:33 +0200 Subject: [PATCH 38/53] wip --- .../KubernetesDiscoveryClientBlockingAutoConfiguration.java | 5 ++--- .../KubernetesDiscoveryClientAutoConfigurationTests.java | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java index 84c265a1eb..02d0266a02 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java @@ -65,10 +65,9 @@ DiscoveryClient kubernetesDiscoveryClient(RestTemplate restTemplate, @Bean @ConditionalOnClass({ HealthIndicator.class }) @ConditionalOnDiscoveryHealthIndicatorEnabled - InitializingBean indicatorInitializer(ApplicationEventPublisher applicationEventPublisher, - ApplicationContext applicationContext) { + InitializingBean indicatorInitializer(ApplicationEventPublisher applicationEventPublisher) { return () -> applicationEventPublisher - .publishEvent(new InstanceRegisteredEvent<>(applicationContext.getId(), null)); + .publishEvent(new InstanceRegisteredEvent<>("", null)); } diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java index 5662f0cbe9..c0f515a745 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java @@ -36,7 +36,9 @@ class KubernetesDiscoveryClientAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withConfiguration(AutoConfigurations.of(UtilAutoConfiguration.class, - ReactiveCommonsClientAutoConfiguration.class, KubernetesDiscoveryClientAutoConfiguration.class)); + ReactiveCommonsClientAutoConfiguration.class, + KubernetesDiscoveryClientReactiveAutoConfiguration.class, + KubernetesDiscoveryClientBlockingAutoConfiguration.class)); @Test void shouldWorkWithDefaults() { From f933c4573aa9a4c97950d0bcff734883fe924d39 Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 17 Nov 2023 10:18:29 +0200 Subject: [PATCH 39/53] wip --- ...DiscoveryClientBlockingAutoConfiguration.java | 5 +++-- ...ubernetesDiscoveryAutoConfigurationTests.java | 16 ++++++++-------- ...tesDiscoveryClientAutoConfigurationTests.java | 5 ++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java index 02d0266a02..84c265a1eb 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java @@ -65,9 +65,10 @@ DiscoveryClient kubernetesDiscoveryClient(RestTemplate restTemplate, @Bean @ConditionalOnClass({ HealthIndicator.class }) @ConditionalOnDiscoveryHealthIndicatorEnabled - InitializingBean indicatorInitializer(ApplicationEventPublisher applicationEventPublisher) { + InitializingBean indicatorInitializer(ApplicationEventPublisher applicationEventPublisher, + ApplicationContext applicationContext) { return () -> applicationEventPublisher - .publishEvent(new InstanceRegisteredEvent<>("", null)); + .publishEvent(new InstanceRegisteredEvent<>(applicationContext.getId(), null)); } diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java index f5b0244abd..ed5fa83955 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java @@ -17,6 +17,7 @@ package org.springframework.cloud.kubernetes.discovery; import org.junit.jupiter.api.Test; + import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -41,7 +42,7 @@ class KubernetesDiscoveryAutoConfigurationTests { @Test void discoveryEnabledDefault() { setupWithFilteredClassLoader(null, "spring.main.cloud-platform=KUBERNETES", - "spring.cloud.discovery.enabled=false"); + "spring.cloud.discovery.enabled=false"); applicationContextRunner.run(context -> { assertThat(context).doesNotHaveBean(RestTemplate.class); assertThat(context).doesNotHaveBean(DiscoveryClient.class); @@ -58,16 +59,15 @@ private void setupWithFilteredClassLoader(Class cls, String... properties) { if (cls != null) { applicationContextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(KubernetesDiscoveryClientBlockingAutoConfiguration.class, - KubernetesDiscoveryClientReactiveAutoConfiguration.class)) - .withClassLoader(new FilteredClassLoader(cls)) - .withPropertyValues(properties); + .withConfiguration(AutoConfigurations.of(KubernetesDiscoveryClientBlockingAutoConfiguration.class, + KubernetesDiscoveryClientReactiveAutoConfiguration.class)) + .withClassLoader(new FilteredClassLoader(cls)).withPropertyValues(properties); } else { applicationContextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(KubernetesDiscoveryClientBlockingAutoConfiguration.class, - KubernetesDiscoveryClientReactiveAutoConfiguration.class)) - .withPropertyValues(properties); + .withConfiguration(AutoConfigurations.of(KubernetesDiscoveryClientBlockingAutoConfiguration.class, + KubernetesDiscoveryClientReactiveAutoConfiguration.class)) + .withPropertyValues(properties); } } diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java index c0f515a745..0f9c2698dc 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java @@ -34,9 +34,8 @@ */ class KubernetesDiscoveryClientAutoConfigurationTests { - private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(UtilAutoConfiguration.class, - ReactiveCommonsClientAutoConfiguration.class, + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration( + AutoConfigurations.of(UtilAutoConfiguration.class, ReactiveCommonsClientAutoConfiguration.class, KubernetesDiscoveryClientReactiveAutoConfiguration.class, KubernetesDiscoveryClientBlockingAutoConfiguration.class)); From 672516e85f6514312536ac758b45eeabfccd645e Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 17 Nov 2023 10:23:04 +0200 Subject: [PATCH 40/53] merge 3.0.x --- .../ConfigServerBootstrapperTests.java | 26 +++--- .../KubernetesDiscoveryClientTests.java | 80 +++++++++---------- ...ubernetesReactiveDiscoveryClientTests.java | 72 ++++++++--------- 3 files changed, 89 insertions(+), 89 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java index ab4d97f7e0..ff57b137e3 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java @@ -69,19 +69,19 @@ void beforeAll() throws JsonProcessingException { wireMockServer.start(); WireMock.configureFor(wireMockServer.port()); String APPS_NAME = """ - [{ - "instanceId": "uid2", - "serviceId": "spring-cloud-kubernetes-configserver", - "host": "localhost", - "port": "%s", - "uri": "%s", - "secure":false, - "metadata":{"spring": "true", "http": "8080", "k8s": "true"}, - "namespace": "namespace1", - "cluster": null, - "scheme":"http" - }] - """.formatted(wireMockServer.port(), wireMockServer.baseUrl()); + [{ + "instanceId": "uid2", + "serviceId": "spring-cloud-kubernetes-configserver", + "host": "localhost", + "port": "%s", + "uri": "%s", + "secure":false, + "metadata":{"spring": "true", "http": "8080", "k8s": "true"}, + "namespace": "namespace1", + "cluster": null, + "scheme":"http" + }] + """.formatted(wireMockServer.port(), wireMockServer.baseUrl()); System.out.println(APPS_NAME); diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTests.java index f620c0c8c1..6a81b48352 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTests.java @@ -46,54 +46,54 @@ class KubernetesDiscoveryClientTests { private static final String APPS = """ - [{ - "name": "test-svc-1", - "serviceInstances": [{ - "instanceId": "uid1", - "serviceId": "test-svc-1", + "name": "test-svc-1", + "serviceInstances": + [{ + "instanceId": "uid1", + "serviceId": "test-svc-1", + "host": "2.2.2.2", + "port": 8080, + "uri": "http://2.2.2.2:8080", + "secure": false, + "metadata":{"http": "8080"}, + "namespace": "namespace1", + "cluster": null, + "scheme": "http" + }] + }, + { + "name": "test-svc-3", + "serviceInstances": + [{ + "instanceId": "uid2", + "serviceId": "test-svc-3", + "host": "2.2.2.2", + "port": 8080, + "uri": "http://2.2.2.2:8080", + "secure": false, + "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, + "namespace": "namespace2", + "cluster":null, + "scheme":"http" + }] + }] + """; + + private static final String APPS_NAME = """ + [{ + "instanceId": "uid2", + "serviceId": "test-svc-3", "host": "2.2.2.2", "port": 8080, "uri": "http://2.2.2.2:8080", "secure": false, - "metadata":{"http": "8080"}, - "namespace": "namespace1", + "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, + "namespace": "namespace2", "cluster": null, "scheme": "http" }] - }, - { - "name": "test-svc-3", - "serviceInstances": - [{ - "instanceId": "uid2", - "serviceId": "test-svc-3", - "host": "2.2.2.2", - "port": 8080, - "uri": "http://2.2.2.2:8080", - "secure": false, - "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, - "namespace": "namespace2", - "cluster":null, - "scheme":"http" - }] - }] - """; - - private static final String APPS_NAME = """ - [{ - "instanceId": "uid2", - "serviceId": "test-svc-3", - "host": "2.2.2.2", - "port": 8080, - "uri": "http://2.2.2.2:8080", - "secure": false, - "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, - "namespace": "namespace2", - "cluster": null, - "scheme": "http" - }] - """; + """; private static WireMockServer wireMockServer; diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClientTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClientTests.java index 9af8e51c25..376ff2d422 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesReactiveDiscoveryClientTests.java @@ -39,25 +39,41 @@ class KubernetesReactiveDiscoveryClientTests { private static final String APPS = """ - [{ - "name": "test-svc-1", - "serviceInstances": - [{ - "instanceId": "uid1", - "serviceId": "test-svc-1", - "host": "2.2.2.2", - "port": 8080, - "uri": "http://2.2.2.2:8080", - "secure": false, - "metadata": {"http":"8080"}, - "namespace": "namespace1", - "cluster": null, - "scheme": "http" - }] - }, - { - "name": "test-svc-3", - "serviceInstances": + [{ + "name": "test-svc-1", + "serviceInstances": + [{ + "instanceId": "uid1", + "serviceId": "test-svc-1", + "host": "2.2.2.2", + "port": 8080, + "uri": "http://2.2.2.2:8080", + "secure": false, + "metadata": {"http":"8080"}, + "namespace": "namespace1", + "cluster": null, + "scheme": "http" + }] + }, + { + "name": "test-svc-3", + "serviceInstances": + [{ + "instanceId": "uid2", + "serviceId": "test-svc-3", + "host": "2.2.2.2", + "port": 8080, + "uri": "http://2.2.2.2:8080", + "secure": false, + "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, + "namespace": "namespace1", + "cluster": null, + "scheme": "http" + }] + }] + """; + + private static final String APPS_NAME = """ [{ "instanceId": "uid2", "serviceId": "test-svc-3", @@ -70,23 +86,7 @@ class KubernetesReactiveDiscoveryClientTests { "cluster": null, "scheme": "http" }] - }] - """; - - private static final String APPS_NAME = """ - [{ - "instanceId": "uid2", - "serviceId": "test-svc-3", - "host": "2.2.2.2", - "port": 8080, - "uri": "http://2.2.2.2:8080", - "secure": false, - "metadata": {"spring": "true", "http": "8080", "k8s": "true"}, - "namespace": "namespace1", - "cluster": null, - "scheme": "http" - }] - """; + """; private static WireMockServer wireMockServer; From d4f9582201c8c1caf6597c738505f40422a808b6 Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 17 Nov 2023 18:46:24 +0200 Subject: [PATCH 41/53] tests added --- ...coveryClientBlockingAutoConfiguration.java | 6 +- ...coveryClientReactiveAutoConfiguration.java | 3 +- ...rnetesDiscoveryAutoConfigurationTests.java | 180 +++++++++++++++++- 3 files changed, 179 insertions(+), 10 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java index 84c265a1eb..0a6089ca0b 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java @@ -27,7 +27,6 @@ import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled; import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled; -import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicatorProperties; import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnKubernetesDiscoveryEnabled; @@ -57,7 +56,7 @@ RestTemplate restTemplate() { @Bean @ConditionalOnMissingClass("org.springframework.web.reactive.function.client.WebClient") - DiscoveryClient kubernetesDiscoveryClient(RestTemplate restTemplate, + KubernetesDiscoveryClient kubernetesDiscoveryClient(RestTemplate restTemplate, KubernetesDiscoveryClientProperties properties) { return new KubernetesDiscoveryClient(restTemplate, properties); } @@ -67,8 +66,9 @@ DiscoveryClient kubernetesDiscoveryClient(RestTemplate restTemplate, @ConditionalOnDiscoveryHealthIndicatorEnabled InitializingBean indicatorInitializer(ApplicationEventPublisher applicationEventPublisher, ApplicationContext applicationContext) { - return () -> applicationEventPublisher + InitializingBean bean = () -> applicationEventPublisher .publishEvent(new InstanceRegisteredEvent<>(applicationContext.getId(), null)); + return bean; } diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java index 0e71a21257..d9140d5146 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java @@ -24,7 +24,6 @@ import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled; import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled; import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled; -import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicatorProperties; import org.springframework.cloud.client.discovery.health.reactive.ReactiveDiscoveryClientHealthIndicator; @@ -55,7 +54,7 @@ WebClient.Builder webClientBuilder() { @Bean @ConditionalOnClass(name = { "org.springframework.web.reactive.function.client.WebClient" }) - ReactiveDiscoveryClient kubernetesReactiveDiscoveryClient(WebClient.Builder webClientBuilder, + KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient(WebClient.Builder webClientBuilder, KubernetesDiscoveryClientProperties properties) { return new KubernetesReactiveDiscoveryClient(webClientBuilder, properties); } diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java index ed5fa83955..646e6fb0c0 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java @@ -18,11 +18,10 @@ import org.junit.jupiter.api.Test; +import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; import org.springframework.web.client.RestTemplate; import org.springframework.web.reactive.function.client.WebClient; @@ -40,19 +39,190 @@ class KubernetesDiscoveryAutoConfigurationTests { * */ @Test - void discoveryEnabledDefault() { + void discoveryDisabled() { setupWithFilteredClassLoader(null, "spring.main.cloud-platform=KUBERNETES", "spring.cloud.discovery.enabled=false"); applicationContextRunner.run(context -> { assertThat(context).doesNotHaveBean(RestTemplate.class); - assertThat(context).doesNotHaveBean(DiscoveryClient.class); + assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); assertThat(context).doesNotHaveBean(WebClient.Builder.class); - assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); + assertThat(context).doesNotHaveBean(KubernetesReactiveDiscoveryClient.class); }); } + /** + *
+	 *     '@ConditionalOnKubernetesDiscoveryEnabled' is not matched, thus no beans are created
+	 *     from either blocking or reactive configurations.
+	 * 
+ */ + @Test + void kubernetesDiscoveryDisabled() { + setupWithFilteredClassLoader(null, "spring.main.cloud-platform=KUBERNETES", + "spring.cloud.kubernetes.discovery.enabled=false"); + applicationContextRunner.run(context -> { + assertThat(context).doesNotHaveBean(RestTemplate.class); + assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); + + assertThat(context).doesNotHaveBean(WebClient.Builder.class); + assertThat(context).doesNotHaveBean(KubernetesReactiveDiscoveryClient.class); + + }); + } + + /** + *
+	 *     '@ConditionalOnCloudPlatform' does not match 'KUBERNETES', thus no beans are created
+	 *     from either blocking or reactive configurations.
+	 * 
+ */ + @Test + void cloudPlatformDisabled() { + setupWithFilteredClassLoader(null, "spring.main.cloud-platform=none"); + applicationContextRunner.run(context -> { + assertThat(context).doesNotHaveBean(RestTemplate.class); + assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); + + assertThat(context).doesNotHaveBean(WebClient.Builder.class); + assertThat(context).doesNotHaveBean(KubernetesReactiveDiscoveryClient.class); + + }); + } + + /** + *
+	 *     - reactive config is disabled, blocking is defaulted.
+	 *     - WebClient class is not present
+	 * 
+ */ + @Test + void reactiveDisabledBlockingEnabledWebClientPresent() { + setupWithFilteredClassLoader(WebClient.class, "spring.main.cloud-platform=KUBERNETES", + "spring.cloud.discovery.reactive.enabled=false", + "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); + applicationContextRunner.run(context -> { + assertThat(context).hasSingleBean(RestTemplate.class); + assertThat(context).hasSingleBean(KubernetesDiscoveryClient.class); + assertThat(context).getBean("indicatorInitializer").isNotNull(); + + assertThat(context).doesNotHaveBean(WebClient.Builder.class); + assertThat(context).doesNotHaveBean(KubernetesReactiveDiscoveryClient.class); + + }); + } + + /** + *
+	 *     - reactive config is disabled, blocking is defaulted.
+	 *     - WebClient class is present
+	 * 
+ */ + @Test + void reactiveDisabledBlockingEnabledWebClientMissing() { + setupWithFilteredClassLoader(null, "spring.main.cloud-platform=KUBERNETES", + "spring.cloud.discovery.reactive.enabled=false", + "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); + applicationContextRunner.run(context -> { + assertThat(context).doesNotHaveBean(RestTemplate.class); + assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); + assertThat(context).getBean("indicatorInitializer").isNotNull(); + + assertThat(context).doesNotHaveBean(WebClient.Builder.class); + assertThat(context).doesNotHaveBean(KubernetesReactiveDiscoveryClient.class); + + }); + } + + /** + *
+	 *     - reactive config is disabled, blocking is defaulted.
+	 *     - WebClient class is present
+	 * 
+ */ + @Test + void reactiveDisabledBlockingEnabledWebClientMissingHealthIndicatorMissing() { + setupWithFilteredClassLoader(HealthIndicator.class, "spring.main.cloud-platform=KUBERNETES", + "spring.cloud.discovery.reactive.enabled=false", + "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); + applicationContextRunner.run(context -> { + assertThat(context).doesNotHaveBean(RestTemplate.class); + assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); + assertThat(context).doesNotHaveBean("indicatorInitializer"); + + assertThat(context).doesNotHaveBean(WebClient.Builder.class); + assertThat(context).doesNotHaveBean(KubernetesReactiveDiscoveryClient.class); + + }); + } + + /** + *
+	 *     '@ConditionalOnDiscoveryHealthIndicatorEnabled' not matched.
+	 * 
+ */ + @Test + void blockingHealthIndicatorDisabled() { + setupWithFilteredClassLoader(null, "spring.main.cloud-platform=KUBERNETES", + "spring.cloud.discovery.reactive.enabled=true", + "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver", + "spring.cloud.discovery.client.health-indicator.enabled=false"); + applicationContextRunner.run(context -> { + assertThat(context).doesNotHaveBean(RestTemplate.class); + assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); + assertThat(context).doesNotHaveBean("indicatorInitializer"); + + assertThat(context).hasSingleBean(WebClient.Builder.class); + assertThat(context).hasSingleBean(KubernetesReactiveDiscoveryClient.class); + + }); + } + + /** + *
+	 *     - reactive config is enabled, blocking is defaulted.
+	 *     - WebClient class is present
+	 * 
+ */ + @Test + void reactiveEnabledBlockingEnabledWebClientPresent() { + setupWithFilteredClassLoader(null, "spring.main.cloud-platform=KUBERNETES", + "spring.cloud.discovery.reactive.enabled=true", + "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); + applicationContextRunner.run(context -> { + assertThat(context).doesNotHaveBean(RestTemplate.class); + assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); + assertThat(context).getBean("indicatorInitializer").isNotNull(); + + assertThat(context).hasSingleBean(WebClient.Builder.class); + assertThat(context).hasSingleBean(KubernetesReactiveDiscoveryClient.class); + assertThat(context).getBean("kubernetesReactiveDiscoveryClientHealthIndicator").isNotNull(); + }); + } + + /** + *
+	 *     - reactive config is enabled, blocking is defaulted.
+	 *     - WebClient class is missing
+	 * 
+ */ + @Test + void reactiveEnabledBlockingEnabledWebClientMissing() { + setupWithFilteredClassLoader(WebClient.class, "spring.main.cloud-platform=KUBERNETES", + "spring.cloud.discovery.reactive.enabled=true", + "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); + applicationContextRunner.run(context -> { + assertThat(context).hasSingleBean(RestTemplate.class); + assertThat(context).hasSingleBean(KubernetesDiscoveryClient.class); + assertThat(context).getBean("indicatorInitializer").isNotNull(); + + assertThat(context).doesNotHaveBean(WebClient.Builder.class); + assertThat(context).doesNotHaveBean(KubernetesReactiveDiscoveryClient.class); + assertThat(context).getBean("kubernetesReactiveDiscoveryClientHealthIndicator").isNull(); + }); + } + private ApplicationContextRunner applicationContextRunner; private void setupWithFilteredClassLoader(Class cls, String... properties) { From e36b471decb44b59466e2a9c477475e0ec72cea9 Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 17 Nov 2023 18:47:27 +0200 Subject: [PATCH 42/53] remove sout --- .../kubernetes/discovery/ConfigServerBootstrapperTests.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java index ff57b137e3..c60af2f3bb 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/ConfigServerBootstrapperTests.java @@ -83,8 +83,6 @@ void beforeAll() throws JsonProcessingException { }] """.formatted(wireMockServer.port(), wireMockServer.baseUrl()); - System.out.println(APPS_NAME); - stubFor(get("/apps/spring-cloud-kubernetes-configserver").willReturn( aResponse().withStatus(200).withBody(APPS_NAME).withHeader("content-type", "application/json"))); Environment environment = new Environment("test", "default"); From bfc099beb264c40b7791694c0c4620de23532d4f Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 17 Nov 2023 18:51:16 +0200 Subject: [PATCH 43/53] fix --- .../KubernetesDiscoveryClientReactiveAutoConfiguration.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java index d9140d5146..85212d6f19 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java @@ -46,14 +46,12 @@ class KubernetesDiscoveryClientReactiveAutoConfiguration { @Bean - @ConditionalOnClass(name = { "org.springframework.web.reactive.function.client.WebClient" }) @ConditionalOnMissingBean(WebClient.Builder.class) WebClient.Builder webClientBuilder() { return WebClient.builder(); } @Bean - @ConditionalOnClass(name = { "org.springframework.web.reactive.function.client.WebClient" }) KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient(WebClient.Builder webClientBuilder, KubernetesDiscoveryClientProperties properties) { return new KubernetesReactiveDiscoveryClient(webClientBuilder, properties); From 97232749e258e3ccbb3506674885e5e21d338162 Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 17 Nov 2023 18:58:59 +0200 Subject: [PATCH 44/53] simplify --- .../KubernetesDiscoveryClientBlockingAutoConfiguration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java index 0a6089ca0b..79f607a180 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java @@ -48,13 +48,14 @@ class KubernetesDiscoveryClientBlockingAutoConfiguration { @Bean + @ConditionalOnMissingBean @ConditionalOnMissingClass("org.springframework.web.reactive.function.client.WebClient") - @ConditionalOnMissingBean(RestTemplate.class) RestTemplate restTemplate() { return new RestTemplateBuilder().build(); } @Bean + @ConditionalOnMissingBean @ConditionalOnMissingClass("org.springframework.web.reactive.function.client.WebClient") KubernetesDiscoveryClient kubernetesDiscoveryClient(RestTemplate restTemplate, KubernetesDiscoveryClientProperties properties) { From 8ab264ecf7fe93628089dac039c8c53d8f560d6f Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 17 Nov 2023 19:08:16 +0200 Subject: [PATCH 45/53] fix --- .../KubernetesDiscoveryClientBlockingAutoConfiguration.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java index 79f607a180..1b2752226b 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java @@ -21,10 +21,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.cloud.CloudPlatform; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled; import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled; import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled; import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; @@ -42,6 +42,7 @@ @Configuration(proxyBeanMethods = false) @ConditionalOnDiscoveryEnabled @ConditionalOnKubernetesDiscoveryEnabled +@ConditionalOnBlockingDiscoveryEnabled @ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) @EnableConfigurationProperties({ DiscoveryClientHealthIndicatorProperties.class, KubernetesDiscoveryClientProperties.class }) @@ -49,14 +50,12 @@ class KubernetesDiscoveryClientBlockingAutoConfiguration { @Bean @ConditionalOnMissingBean - @ConditionalOnMissingClass("org.springframework.web.reactive.function.client.WebClient") RestTemplate restTemplate() { return new RestTemplateBuilder().build(); } @Bean @ConditionalOnMissingBean - @ConditionalOnMissingClass("org.springframework.web.reactive.function.client.WebClient") KubernetesDiscoveryClient kubernetesDiscoveryClient(RestTemplate restTemplate, KubernetesDiscoveryClientProperties properties) { return new KubernetesDiscoveryClient(restTemplate, properties); From 87b87f7e623d2eeef2b361e7e5c3e5242e37a019 Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 17 Nov 2023 23:59:25 +0200 Subject: [PATCH 46/53] started work --- ...rnetesDiscoveryAutoConfigurationTests.java | 3 ++- ...DiscoveryClientAutoConfigurationTests.java | 25 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java index 646e6fb0c0..b87457ef7a 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java @@ -123,11 +123,12 @@ void reactiveDisabledBlockingEnabledWebClientPresent() { void reactiveDisabledBlockingEnabledWebClientMissing() { setupWithFilteredClassLoader(null, "spring.main.cloud-platform=KUBERNETES", "spring.cloud.discovery.reactive.enabled=false", + "spring.cloud.discovery.blocking.enabled=false", "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); applicationContextRunner.run(context -> { assertThat(context).doesNotHaveBean(RestTemplate.class); assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); - assertThat(context).getBean("indicatorInitializer").isNotNull(); + assertThat(context).getBean("indicatorInitializer").isNull(); assertThat(context).doesNotHaveBean(WebClient.Builder.class); assertThat(context).doesNotHaveBean(KubernetesReactiveDiscoveryClient.class); diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java index 0f9c2698dc..54fb77860e 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java @@ -22,8 +22,6 @@ import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration; -import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; import org.springframework.cloud.client.discovery.health.reactive.ReactiveDiscoveryClientHealthIndicator; import org.springframework.cloud.commons.util.UtilAutoConfiguration; @@ -45,8 +43,8 @@ void shouldWorkWithDefaults() { .withPropertyValues("spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver") .withClassLoader(new FilteredClassLoader("org.springframework.web.reactive")).run(context -> { - assertThat(context).hasSingleBean(DiscoveryClient.class); - assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); + assertThat(context).hasSingleBean(KubernetesDiscoveryClient.class); + assertThat(context).doesNotHaveBean(KubernetesReactiveDiscoveryClient.class); assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class); }); } @@ -57,8 +55,8 @@ void shouldNotHaveDiscoveryClientWhenDiscoveryDisabled() { .withPropertyValues("spring.cloud.discovery.enabled=false", "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver") .run(context -> { - assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); - assertThat(context).doesNotHaveBean(DiscoveryClient.class); + assertThat(context).doesNotHaveBean(KubernetesReactiveDiscoveryClient.class); + assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class); }); } @@ -69,8 +67,8 @@ void shouldNotHaveDiscoveryClientWhenKubernetesDiscoveryDisabled() { .withPropertyValues("spring.cloud.kubernetes.discovery.enabled=false", "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver") .run(context -> { - assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); - assertThat(context).doesNotHaveBean(DiscoveryClient.class); + assertThat(context).doesNotHaveBean(KubernetesReactiveDiscoveryClient.class); + assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class); }); } @@ -79,10 +77,11 @@ void shouldNotHaveDiscoveryClientWhenKubernetesDiscoveryDisabled() { void shouldHaveReactiveDiscoveryClient() { contextRunner .withPropertyValues("spring.main.cloud-platform=KUBERNETES", + "spring.cloud.discovery.blocking.enabled=false", "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver") .run(context -> { - assertThat(context).hasSingleBean(ReactiveDiscoveryClient.class); - assertThat(context).doesNotHaveBean(DiscoveryClient.class); + assertThat(context).hasSingleBean(KubernetesReactiveDiscoveryClient.class); + assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); assertThat(context).hasSingleBean(ReactiveDiscoveryClientHealthIndicator.class); }); } @@ -90,7 +89,7 @@ void shouldHaveReactiveDiscoveryClient() { @Test void shouldNotHaveDiscoveryClientWhenReactiveDiscoveryDisabled() { contextRunner.withPropertyValues("spring.cloud.discovery.reactive.enabled=false").run(context -> { - assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); + assertThat(context).doesNotHaveBean(KubernetesReactiveDiscoveryClient.class); assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class); }); } @@ -98,7 +97,7 @@ void shouldNotHaveDiscoveryClientWhenReactiveDiscoveryDisabled() { @Test void shouldNotHaveDiscoveryClientWhenKubernetesDisabled() { contextRunner.run(context -> { - assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); + assertThat(context).doesNotHaveBean(KubernetesReactiveDiscoveryClient.class); assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class); }); } @@ -109,7 +108,7 @@ void worksWithoutActuator() { .withPropertyValues("spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver") .withClassLoader(new FilteredClassLoader("org.springframework.boot.actuate")).run(context -> { - assertThat(context).hasSingleBean(ReactiveDiscoveryClient.class); + assertThat(context).hasSingleBean(KubernetesReactiveDiscoveryClient.class); assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class); }); } From 100c351252a1413937353b8904654683176ab57c Mon Sep 17 00:00:00 2001 From: wind57 Date: Sat, 18 Nov 2023 00:02:25 +0200 Subject: [PATCH 47/53] review comments --- ...netesDiscoveryClientAutoConfiguration.java | 2 ++ ...rnetesDiscoveryAutoConfigurationTests.java | 28 +++++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfiguration.java index 8eeb07c685..a6b2aa73d7 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfiguration.java @@ -43,6 +43,8 @@ /** * @author Ryan Baxter + * @deprecated in favor of {@link KubernetesDiscoveryClientBlockingAutoConfiguration} and + * {@link KubernetesDiscoveryClientReactiveAutoConfiguration} */ @Configuration(proxyBeanMethods = false) @ConditionalOnDiscoveryEnabled diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java index 646e6fb0c0..c62e61ef58 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java @@ -61,7 +61,7 @@ void discoveryDisabled() { @Test void kubernetesDiscoveryDisabled() { setupWithFilteredClassLoader(null, "spring.main.cloud-platform=KUBERNETES", - "spring.cloud.kubernetes.discovery.enabled=false"); + "spring.cloud.kubernetes.discovery.enabled=false"); applicationContextRunner.run(context -> { assertThat(context).doesNotHaveBean(RestTemplate.class); assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); @@ -100,8 +100,8 @@ void cloudPlatformDisabled() { @Test void reactiveDisabledBlockingEnabledWebClientPresent() { setupWithFilteredClassLoader(WebClient.class, "spring.main.cloud-platform=KUBERNETES", - "spring.cloud.discovery.reactive.enabled=false", - "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); + "spring.cloud.discovery.reactive.enabled=false", + "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); applicationContextRunner.run(context -> { assertThat(context).hasSingleBean(RestTemplate.class); assertThat(context).hasSingleBean(KubernetesDiscoveryClient.class); @@ -122,8 +122,8 @@ void reactiveDisabledBlockingEnabledWebClientPresent() { @Test void reactiveDisabledBlockingEnabledWebClientMissing() { setupWithFilteredClassLoader(null, "spring.main.cloud-platform=KUBERNETES", - "spring.cloud.discovery.reactive.enabled=false", - "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); + "spring.cloud.discovery.reactive.enabled=false", + "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); applicationContextRunner.run(context -> { assertThat(context).doesNotHaveBean(RestTemplate.class); assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); @@ -144,8 +144,8 @@ void reactiveDisabledBlockingEnabledWebClientMissing() { @Test void reactiveDisabledBlockingEnabledWebClientMissingHealthIndicatorMissing() { setupWithFilteredClassLoader(HealthIndicator.class, "spring.main.cloud-platform=KUBERNETES", - "spring.cloud.discovery.reactive.enabled=false", - "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); + "spring.cloud.discovery.reactive.enabled=false", + "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); applicationContextRunner.run(context -> { assertThat(context).doesNotHaveBean(RestTemplate.class); assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); @@ -165,9 +165,9 @@ void reactiveDisabledBlockingEnabledWebClientMissingHealthIndicatorMissing() { @Test void blockingHealthIndicatorDisabled() { setupWithFilteredClassLoader(null, "spring.main.cloud-platform=KUBERNETES", - "spring.cloud.discovery.reactive.enabled=true", - "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver", - "spring.cloud.discovery.client.health-indicator.enabled=false"); + "spring.cloud.discovery.reactive.enabled=true", + "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver", + "spring.cloud.discovery.client.health-indicator.enabled=false"); applicationContextRunner.run(context -> { assertThat(context).doesNotHaveBean(RestTemplate.class); assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); @@ -188,8 +188,8 @@ void blockingHealthIndicatorDisabled() { @Test void reactiveEnabledBlockingEnabledWebClientPresent() { setupWithFilteredClassLoader(null, "spring.main.cloud-platform=KUBERNETES", - "spring.cloud.discovery.reactive.enabled=true", - "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); + "spring.cloud.discovery.reactive.enabled=true", + "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); applicationContextRunner.run(context -> { assertThat(context).doesNotHaveBean(RestTemplate.class); assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); @@ -210,8 +210,8 @@ void reactiveEnabledBlockingEnabledWebClientPresent() { @Test void reactiveEnabledBlockingEnabledWebClientMissing() { setupWithFilteredClassLoader(WebClient.class, "spring.main.cloud-platform=KUBERNETES", - "spring.cloud.discovery.reactive.enabled=true", - "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); + "spring.cloud.discovery.reactive.enabled=true", + "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); applicationContextRunner.run(context -> { assertThat(context).hasSingleBean(RestTemplate.class); assertThat(context).hasSingleBean(KubernetesDiscoveryClient.class); From bf45bcc6a5ddac1ebfb416e15af03d605bbb6f36 Mon Sep 17 00:00:00 2001 From: wind57 Date: Sat, 18 Nov 2023 15:22:47 +0200 Subject: [PATCH 48/53] dirty --- ...netesDiscoveryClientBlockingAutoConfiguration.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java index 1b2752226b..397c6cbf0d 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java @@ -39,11 +39,12 @@ /** * @author wind57 */ -@Configuration(proxyBeanMethods = false) -@ConditionalOnDiscoveryEnabled -@ConditionalOnKubernetesDiscoveryEnabled -@ConditionalOnBlockingDiscoveryEnabled -@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) +//@Configuration(proxyBeanMethods = false) +//@ConditionalOnDiscoveryEnabled +//@ConditionalOnKubernetesDiscoveryEnabled +//@ConditionalOnBlockingDiscoveryEnabled +//@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) + dadasdsa replace with single annotation in all 3 places and place it in commond @EnableConfigurationProperties({ DiscoveryClientHealthIndicatorProperties.class, KubernetesDiscoveryClientProperties.class }) class KubernetesDiscoveryClientBlockingAutoConfiguration { From 8772e5cf7dcab562f6b494c3a1710e1afb1c2477 Mon Sep 17 00:00:00 2001 From: wind57 Date: Sat, 18 Nov 2023 16:31:32 +0200 Subject: [PATCH 49/53] started working on tests --- .../KubernetesDiscoveryAutoConfigurationTests.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java index 454538d67c..e39240c850 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java @@ -148,8 +148,8 @@ void reactiveDisabledBlockingEnabledWebClientMissingHealthIndicatorMissing() { "spring.cloud.discovery.reactive.enabled=false", "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); applicationContextRunner.run(context -> { - assertThat(context).doesNotHaveBean(RestTemplate.class); - assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); + assertThat(context).hasSingleBean(RestTemplate.class); + assertThat(context).hasSingleBean(KubernetesDiscoveryClient.class); assertThat(context).doesNotHaveBean("indicatorInitializer"); assertThat(context).doesNotHaveBean(WebClient.Builder.class); @@ -170,8 +170,8 @@ void blockingHealthIndicatorDisabled() { "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver", "spring.cloud.discovery.client.health-indicator.enabled=false"); applicationContextRunner.run(context -> { - assertThat(context).doesNotHaveBean(RestTemplate.class); - assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); + assertThat(context).hasSingleBean(RestTemplate.class); + assertThat(context).hasSingleBean(KubernetesDiscoveryClient.class); assertThat(context).doesNotHaveBean("indicatorInitializer"); assertThat(context).hasSingleBean(WebClient.Builder.class); @@ -192,8 +192,8 @@ void reactiveEnabledBlockingEnabledWebClientPresent() { "spring.cloud.discovery.reactive.enabled=true", "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); applicationContextRunner.run(context -> { - assertThat(context).doesNotHaveBean(RestTemplate.class); - assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); + assertThat(context).hasSingleBean(RestTemplate.class); + assertThat(context).hasSingleBean(KubernetesDiscoveryClient.class); assertThat(context).getBean("indicatorInitializer").isNotNull(); assertThat(context).hasSingleBean(WebClient.Builder.class); From dc47efaac1e6c5370eb025485cedf883afacb505 Mon Sep 17 00:00:00 2001 From: wind57 Date: Sat, 18 Nov 2023 17:16:43 +0200 Subject: [PATCH 50/53] add one annotation --- .../KubernetesDiscoveryClientReactiveAutoConfiguration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java index 85212d6f19..4be0e1a89e 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java @@ -46,12 +46,13 @@ class KubernetesDiscoveryClientReactiveAutoConfiguration { @Bean - @ConditionalOnMissingBean(WebClient.Builder.class) + @ConditionalOnMissingBean WebClient.Builder webClientBuilder() { return WebClient.builder(); } @Bean + @ConditionalOnMissingBean KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient(WebClient.Builder webClientBuilder, KubernetesDiscoveryClientProperties properties) { return new KubernetesReactiveDiscoveryClient(webClientBuilder, properties); From d13dfc8e4979aa4faa56e75971c5e7f66d8f6551 Mon Sep 17 00:00:00 2001 From: wind57 Date: Sat, 18 Nov 2023 18:30:27 +0200 Subject: [PATCH 51/53] fix 1426 --- ...rnetesDiscoveryAutoConfigurationTests.java | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java index e39240c850..e7e6c50202 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryAutoConfigurationTests.java @@ -122,9 +122,8 @@ void reactiveDisabledBlockingEnabledWebClientPresent() { @Test void reactiveDisabledBlockingEnabledWebClientMissing() { setupWithFilteredClassLoader(null, "spring.main.cloud-platform=KUBERNETES", - "spring.cloud.discovery.reactive.enabled=false", - "spring.cloud.discovery.blocking.enabled=false", - "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); + "spring.cloud.discovery.reactive.enabled=false", "spring.cloud.discovery.blocking.enabled=false", + "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); applicationContextRunner.run(context -> { assertThat(context).doesNotHaveBean(RestTemplate.class); assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); @@ -224,6 +223,48 @@ void reactiveEnabledBlockingEnabledWebClientMissing() { }); } + /** + *
+	 *     '@ConditionalOnBlockingDiscoveryEnabled' is not matched.
+	 * 
+ */ + @Test + void testBlockingDisabled() { + setupWithFilteredClassLoader(WebClient.class, "spring.main.cloud-platform=KUBERNETES", + "spring.cloud.discovery.reactive.enabled=true", "spring.cloud.discovery.blocking.enabled=false", + "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); + applicationContextRunner.run(context -> { + assertThat(context).doesNotHaveBean(RestTemplate.class); + assertThat(context).doesNotHaveBean(KubernetesDiscoveryClient.class); + assertThat(context).getBean("indicatorInitializer").isNull(); + + assertThat(context).doesNotHaveBean(WebClient.Builder.class); + assertThat(context).doesNotHaveBean(KubernetesReactiveDiscoveryClient.class); + assertThat(context).getBean("kubernetesReactiveDiscoveryClientHealthIndicator").isNull(); + }); + } + + /** + *
+	 *     - WebClient is on the classpath (this is asserted via the presence of beans that come
+	 *       from the reactive auto-configuration)
+	 *     - This has no impact of the creation of the blocking discovery client
+	 * 
+ */ + @Test + void testFor1426Issue() { + setupWithFilteredClassLoader(null, "spring.main.cloud-platform=KUBERNETES", + "spring.cloud.discovery.reactive.enabled=true", "spring.cloud.discovery.blocking.enabled=true", + "spring.cloud.kubernetes.discovery.discovery-server-url=http://k8sdiscoveryserver"); + applicationContextRunner.run(context -> { + // blocking client is present + assertThat(context).hasSingleBean(KubernetesDiscoveryClient.class); + + // reactive client is present + assertThat(context).hasSingleBean(KubernetesReactiveDiscoveryClient.class); + }); + } + private ApplicationContextRunner applicationContextRunner; private void setupWithFilteredClassLoader(Class cls, String... properties) { From 942a144172010ae13529e3995ca249198e05618b Mon Sep 17 00:00:00 2001 From: wind57 Date: Sat, 18 Nov 2023 21:20:30 +0200 Subject: [PATCH 52/53] common annotation for all blocking discovery implementations --- ...ormerDiscoveryClientAutoConfiguration.java | 11 +---- ...pringCloudKubernetesBlockingDiscovery.java | 46 +++++++++++++++++++ ...coveryClientBlockingAutoConfiguration.java | 15 ++---- ...netesDiscoveryClientAutoConfiguration.java | 11 +---- 4 files changed, 54 insertions(+), 29 deletions(-) create mode 100644 spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/ConditionalOnSpringCloudKubernetesBlockingDiscovery.java diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientAutoConfiguration.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientAutoConfiguration.java index 57341b29b9..ff941e7ba4 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientAutoConfiguration.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientAutoConfiguration.java @@ -29,18 +29,14 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -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.ConditionalOnBlockingDiscoveryEnabled; -import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled; import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled; import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration; import org.springframework.cloud.kubernetes.client.KubernetesClientAutoConfiguration; import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.PodUtils; -import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnKubernetesDiscoveryEnabled; +import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnSpringCloudKubernetesBlockingDiscovery; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryClientHealthIndicatorInitializer; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryPropertiesAutoConfiguration; @@ -54,10 +50,7 @@ * @author wind57 */ @Configuration(proxyBeanMethods = false) -@ConditionalOnDiscoveryEnabled -@ConditionalOnKubernetesDiscoveryEnabled -@ConditionalOnBlockingDiscoveryEnabled -@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) +@ConditionalOnSpringCloudKubernetesBlockingDiscovery @AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class }) @AutoConfigureAfter({ KubernetesClientAutoConfiguration.class, KubernetesDiscoveryPropertiesAutoConfiguration.class, KubernetesClientInformerAutoConfiguration.class, diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/ConditionalOnSpringCloudKubernetesBlockingDiscovery.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/ConditionalOnSpringCloudKubernetesBlockingDiscovery.java new file mode 100644 index 0000000000..72f4988bce --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/ConditionalOnSpringCloudKubernetesBlockingDiscovery.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.commons.discovery; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform; +import org.springframework.boot.cloud.CloudPlatform; +import org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled; +import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled; + +/** + * Provides common conditionals to be used for blocking discovery. + * + * @author wind57 + */ +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@ConditionalOnDiscoveryEnabled +@ConditionalOnKubernetesDiscoveryEnabled +@ConditionalOnBlockingDiscoveryEnabled +@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) +public @interface ConditionalOnSpringCloudKubernetesBlockingDiscovery { + +} diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java index 397c6cbf0d..d59f06504e 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientBlockingAutoConfiguration.java @@ -19,17 +19,13 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.cloud.CloudPlatform; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled; -import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled; import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled; import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicatorProperties; -import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnKubernetesDiscoveryEnabled; +import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnSpringCloudKubernetesBlockingDiscovery; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; @@ -39,12 +35,9 @@ /** * @author wind57 */ -//@Configuration(proxyBeanMethods = false) -//@ConditionalOnDiscoveryEnabled -//@ConditionalOnKubernetesDiscoveryEnabled -//@ConditionalOnBlockingDiscoveryEnabled -//@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) - dadasdsa replace with single annotation in all 3 places and place it in commond + +@Configuration(proxyBeanMethods = false) +@ConditionalOnSpringCloudKubernetesBlockingDiscovery @EnableConfigurationProperties({ DiscoveryClientHealthIndicatorProperties.class, KubernetesDiscoveryClientProperties.class }) class KubernetesDiscoveryClientBlockingAutoConfiguration { diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientAutoConfiguration.java index 27d7297da3..ab842468bf 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientAutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientAutoConfiguration.java @@ -23,16 +23,12 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -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.ConditionalOnBlockingDiscoveryEnabled; -import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled; import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled; import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration; import org.springframework.cloud.kubernetes.commons.PodUtils; -import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnKubernetesDiscoveryEnabled; +import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnSpringCloudKubernetesBlockingDiscovery; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryClientHealthIndicatorInitializer; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryPropertiesAutoConfiguration; @@ -51,10 +47,7 @@ * @author Tim Ysewyn */ @Configuration(proxyBeanMethods = false) -@ConditionalOnDiscoveryEnabled -@ConditionalOnKubernetesDiscoveryEnabled -@ConditionalOnBlockingDiscoveryEnabled -@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) +@ConditionalOnSpringCloudKubernetesBlockingDiscovery @AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class }) @AutoConfigureAfter({ Fabric8AutoConfiguration.class, KubernetesDiscoveryPropertiesAutoConfiguration.class }) public class KubernetesDiscoveryClientAutoConfiguration { From 92c66eed1c160f381f25557b743c6e26bb4e3f37 Mon Sep 17 00:00:00 2001 From: wind57 Date: Sat, 18 Nov 2023 21:38:34 +0200 Subject: [PATCH 53/53] common annotation for all reactive discovery implementations --- ...ctiveDiscoveryClientAutoConfiguration.java | 11 +---- ...pringCloudKubernetesReactiveDiscovery.java | 46 +++++++++++++++++++ ...coveryClientReactiveAutoConfiguration.java | 11 +---- ...ctiveDiscoveryClientAutoConfiguration.java | 11 +---- 4 files changed, 52 insertions(+), 27 deletions(-) create mode 100644 spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/ConditionalOnSpringCloudKubernetesReactiveDiscovery.java diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClientAutoConfiguration.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClientAutoConfiguration.java index 62f7393912..62f91935fe 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClientAutoConfiguration.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClientAutoConfiguration.java @@ -28,12 +28,8 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -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.ConditionalOnDiscoveryEnabled; import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled; -import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled; import org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration; import org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration; import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; @@ -48,7 +44,7 @@ import org.springframework.cloud.kubernetes.client.discovery.KubernetesInformerDiscoveryClient; import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.PodUtils; -import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnKubernetesDiscoveryEnabled; +import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnSpringCloudKubernetesReactiveDiscovery; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryClientHealthIndicatorInitializer; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryPropertiesAutoConfiguration; @@ -65,10 +61,7 @@ */ @Configuration(proxyBeanMethods = false) -@ConditionalOnDiscoveryEnabled -@ConditionalOnKubernetesDiscoveryEnabled -@ConditionalOnReactiveDiscoveryEnabled -@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) +@ConditionalOnSpringCloudKubernetesReactiveDiscovery @AutoConfigureBefore({ SimpleReactiveDiscoveryClientAutoConfiguration.class, ReactiveCommonsClientAutoConfiguration.class }) @AutoConfigureAfter({ ReactiveCompositeDiscoveryClientAutoConfiguration.class, diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/ConditionalOnSpringCloudKubernetesReactiveDiscovery.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/ConditionalOnSpringCloudKubernetesReactiveDiscovery.java new file mode 100644 index 0000000000..0d39906a30 --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/ConditionalOnSpringCloudKubernetesReactiveDiscovery.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.commons.discovery; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform; +import org.springframework.boot.cloud.CloudPlatform; +import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled; +import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled; + +/** + * Provides common conditionals to be used for reactive discovery. + * + * @author wind57 + */ +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@ConditionalOnDiscoveryEnabled +@ConditionalOnKubernetesDiscoveryEnabled +@ConditionalOnReactiveDiscoveryEnabled +@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) +public @interface ConditionalOnSpringCloudKubernetesReactiveDiscovery { + +} diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java index 4be0e1a89e..d80eaa4a28 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientReactiveAutoConfiguration.java @@ -17,17 +17,13 @@ package org.springframework.cloud.kubernetes.discovery; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.cloud.CloudPlatform; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled; import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled; -import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled; import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicatorProperties; import org.springframework.cloud.client.discovery.health.reactive.ReactiveDiscoveryClientHealthIndicator; -import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnKubernetesDiscoveryEnabled; +import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnSpringCloudKubernetesReactiveDiscovery; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -37,10 +33,7 @@ * @author wind57 */ @Configuration(proxyBeanMethods = false) -@ConditionalOnDiscoveryEnabled -@ConditionalOnKubernetesDiscoveryEnabled -@ConditionalOnReactiveDiscoveryEnabled -@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) +@ConditionalOnSpringCloudKubernetesReactiveDiscovery @EnableConfigurationProperties({ DiscoveryClientHealthIndicatorProperties.class, KubernetesDiscoveryClientProperties.class }) class KubernetesDiscoveryClientReactiveAutoConfiguration { diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/reactive/KubernetesReactiveDiscoveryClientAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/reactive/KubernetesReactiveDiscoveryClientAutoConfiguration.java index 948d37bf85..b0935aad92 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/reactive/KubernetesReactiveDiscoveryClientAutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/reactive/KubernetesReactiveDiscoveryClientAutoConfiguration.java @@ -22,19 +22,15 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -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.ConditionalOnDiscoveryEnabled; import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled; -import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled; import org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration; import org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration; 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.PodUtils; -import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnKubernetesDiscoveryEnabled; +import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnSpringCloudKubernetesReactiveDiscovery; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryClientHealthIndicatorInitializer; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryPropertiesAutoConfiguration; @@ -53,10 +49,7 @@ * @author Tim Ysewyn */ @Configuration(proxyBeanMethods = false) -@ConditionalOnDiscoveryEnabled -@ConditionalOnKubernetesDiscoveryEnabled -@ConditionalOnReactiveDiscoveryEnabled -@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) +@ConditionalOnSpringCloudKubernetesReactiveDiscovery @AutoConfigureBefore({ SimpleReactiveDiscoveryClientAutoConfiguration.class, ReactiveCommonsClientAutoConfiguration.class }) @AutoConfigureAfter({ ReactiveCompositeDiscoveryClientAutoConfiguration.class,