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
new file mode 100644
index 00000000..140c05fb
--- /dev/null
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/discovery/DiscoveryClientUtils.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2019-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.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.core.log.LogAccessor;
+
+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;
+
+/**
+ * @author wind57
+ */
+public final class DiscoveryClientUtils {
+
+ private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(DiscoveryClientUtils.class));
+
+ private DiscoveryClientUtils() {
+ throw new AssertionError("no instance provided");
+ }
+
+ /**
+ * This adds the following metadata.
+ * - labels (if requested)
+ * - annotations (if requested)
+ * - ports (if requested)
+ * - namespace
+ * - service type
+ *
+ */
+ public static Map serviceMetadata(String serviceId, Map serviceLabels,
+ Map serviceAnnotations, Map portsData,
+ KubernetesDiscoveryProperties properties, String namespace, String serviceType) {
+ Map serviceMetadata = new HashMap<>();
+ KubernetesDiscoveryProperties.Metadata metadataProps = properties.metadata();
+ if (metadataProps.addLabels()) {
+ Map labelMetadata = keysWithPrefix(serviceLabels, metadataProps.labelsPrefix());
+ LOG.debug(() -> "Adding labels metadata: " + labelMetadata + " for serviceId: " + serviceId);
+ serviceMetadata.putAll(labelMetadata);
+ }
+ if (metadataProps.addAnnotations()) {
+ Map annotationMetadata = keysWithPrefix(serviceAnnotations,
+ metadataProps.annotationsPrefix());
+ LOG.debug(() -> "Adding annotations metadata: " + annotationMetadata + " for serviceId: " + serviceId);
+ serviceMetadata.putAll(annotationMetadata);
+ }
+
+ if (metadataProps.addPorts()) {
+ Map portMetadata = keysWithPrefix(portsData, properties.metadata().portsPrefix());
+ if (!portMetadata.isEmpty()) {
+ LOG.debug(() -> "Adding port metadata: " + portMetadata + " for serviceId : " + serviceId);
+ }
+ serviceMetadata.putAll(portMetadata);
+ }
+
+ serviceMetadata.put(NAMESPACE_METADATA_KEY, namespace);
+ serviceMetadata.put(SERVICE_TYPE, serviceType);
+ return serviceMetadata;
+ }
+
+}
diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/discovery/DiscoveryClientUtilsTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/discovery/DiscoveryClientUtilsTests.java
new file mode 100644
index 00000000..cf6d923a
--- /dev/null
+++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/discovery/DiscoveryClientUtilsTests.java
@@ -0,0 +1,356 @@
+/*
+ * 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.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+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;
+
+/**
+ * @author wind57
+ */
+@ExtendWith(OutputCaptureExtension.class)
+class DiscoveryClientUtilsTests {
+
+ /**
+ *
+ * - 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 = "";
+ String namespace = "default";
+
+ Map serviceLabels = Map.of();
+ Map serviceAnnotations = Map.of();
+ Map portsData = Map.of();
+
+ 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);
+
+ Map result = DiscoveryClientUtils.serviceMetadata("my-service", serviceLabels,
+ serviceAnnotations, portsData, properties, namespace, "ClusterIP");
+ Assertions.assertEquals(result.size(), 2);
+ Assertions.assertEquals(result, Map.of("k8s_namespace", "default", "type", "ClusterIP"));
+ }
+
+ /**
+ *
+ * - labels are not added, though they are not empty
+ * - annotations are not added, though they are not empty
+ *
+ */
+ @Test
+ void testServiceMetadataNotEmptyNotTaken() {
+ boolean addLabels = false;
+ String labelsPrefix = "";
+ boolean addAnnotations = false;
+ String annotationsPrefix = "";
+ boolean addPorts = false;
+ String portsPrefix = "";
+ String namespace = "default";
+
+ Map serviceLabels = Map.of("a", "1");
+ Map serviceAnnotations = Map.of("b", "2");
+ Map portsData = Map.of("c", "3");
+
+ 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);
+
+ Map result = DiscoveryClientUtils.serviceMetadata("my-service", serviceLabels,
+ serviceAnnotations, portsData, properties, namespace, "ClusterIP");
+ 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 = "";
+ String namespace = "default";
+
+ Map serviceLabels = Map.of("a", "b");
+ Map serviceAnnotations = Map.of("c", "2");
+ Map portsData = Map.of("d", "3");
+
+ 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);
+
+ Map result = DiscoveryClientUtils.serviceMetadata("my-service", serviceLabels,
+ serviceAnnotations, portsData, properties, namespace, "ClusterIP");
+
+ 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 = "";
+ String namespace = "default";
+
+ Map serviceLabels = Map.of("a", "b", "c", "d");
+ Map serviceAnnotations = Map.of("c", "2");
+ Map portsData = Map.of("d", "3");
+
+ 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);
+
+ Map result = DiscoveryClientUtils.serviceMetadata("my-service", serviceLabels,
+ serviceAnnotations, portsData, properties, namespace, "ClusterIP");
+
+ 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 = "";
+ String namespace = "default";
+
+ Map serviceLabels = Map.of("a", "b");
+ Map serviceAnnotations = Map.of("aa", "bb");
+ Map portsData = Map.of("d", "3");
+
+ 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);
+
+ Map result = DiscoveryClientUtils.serviceMetadata("my-service", serviceLabels,
+ serviceAnnotations, portsData, properties, namespace, "ClusterIP");
+
+ 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 = "";
+ String namespace = "default";
+
+ Map serviceLabels = Map.of("a", "b");
+ Map serviceAnnotations = Map.of("aa", "bb", "cc", "dd");
+ Map portsData = Map.of("d", "3");
+
+ 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);
+
+ Map result = DiscoveryClientUtils.serviceMetadata("my-service", serviceLabels,
+ serviceAnnotations, portsData, properties, namespace, "ClusterIP");
+
+ 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 = "";
+ String namespace = "default";
+
+ Map serviceLabels = Map.of("a", "b", "c", "d");
+ Map serviceAnnotations = Map.of("aa", "bb", "cc", "dd");
+ Map portsData = Map.of("d", "3");
+
+ 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);
+
+ Map result = DiscoveryClientUtils.serviceMetadata("my-service", serviceLabels,
+ serviceAnnotations, portsData, properties, namespace, "ClusterIP");
+
+ 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"));
+ }
+
+ /**
+ *
+ * - ports without prefix are added
+ *
+ */
+ @Test
+ void testServiceMetadataAddPortsWithoutPrefix(CapturedOutput output) {
+ boolean addLabels = false;
+ String labelsPrefix = "";
+ boolean addAnnotations = false;
+ String annotationsPrefix = "prefix-";
+ boolean addPorts = true;
+ String portsPrefix = "";
+ String namespace = "default";
+
+ Map serviceLabels = Map.of("a", "b");
+ Map serviceAnnotations = Map.of("aa", "bb", "cc", "dd");
+ Map portsData = Map.of("https", "8080");
+
+ 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);
+
+ Map result = DiscoveryClientUtils.serviceMetadata("my-service", serviceLabels,
+ serviceAnnotations, portsData, properties, namespace, "ClusterIP");
+
+ Assertions.assertEquals(result.size(), 3);
+ Assertions.assertEquals(result, Map.of("https", "8080", "k8s_namespace", "default", "type", "ClusterIP"));
+ Assertions
+ .assertTrue(output.getOut().contains("Adding port metadata: {https=8080} for serviceId : my-service"));
+ }
+
+ /**
+ *
+ * - ports without prefix are added
+ *
+ */
+ @Test
+ void testServiceMetadataAddPortsWithPrefix(CapturedOutput output) {
+ boolean addLabels = false;
+ String labelsPrefix = "";
+ boolean addAnnotations = false;
+ String annotationsPrefix = "prefix-";
+ boolean addPorts = true;
+ String portsPrefix = "prefix-";
+ String namespace = "default";
+
+ Map serviceLabels = Map.of("a", "b");
+ Map serviceAnnotations = Map.of("aa", "bb", "cc", "dd");
+ Map portsData = Map.of("http", "8081", "https", "8080");
+
+ 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);
+
+ Map result = DiscoveryClientUtils.serviceMetadata("my-service", serviceLabels,
+ serviceAnnotations, portsData, properties, namespace, "ClusterIP");
+
+ Assertions.assertEquals(result.size(), 4);
+ Assertions.assertEquals(result,
+ Map.of("prefix-https", "8080", "prefix-http", "8081", "k8s_namespace", "default", "type", "ClusterIP"));
+ Assertions.assertTrue(output.getOut()
+ .contains("Adding port metadata: {prefix-http=8081, prefix-https=8080} 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-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 591eb8fa..4df970d2 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
@@ -52,12 +52,9 @@ import org.springframework.core.log.LogAccessor;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
-import static java.util.stream.Collectors.toMap;
-import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.keysWithPrefix;
import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryConstants.EXTERNAL_NAME;
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.NAMESPACE_METADATA_KEY;
import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryConstants.PRIMARY_PORT_NAME_LABEL_KEY;
import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryConstants.SERVICE_TYPE;
import static org.springframework.cloud.kubernetes.fabric8.discovery.ServicePortSecureResolver.Input;
@@ -152,49 +149,6 @@ final class Fabric8KubernetesDiscoveryClientUtils {
return primaryPortName;
}
- /**
- * This adds the following metadata.
- * - labels (if requested)
- * - annotations (if requested)
- * - ports (if requested)
- * - namespace
- * - service type
- *
- */
- static Map serviceMetadata(String serviceId, Service service,
- KubernetesDiscoveryProperties properties, List endpointSubsets, String namespace) {
- 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);
- }
-
- if (metadataProps.addPorts()) {
- Map ports = endpointSubsets.stream()
- .flatMap(endpointSubset -> endpointSubset.getPorts().stream())
- .filter(port -> StringUtils.hasText(port.getName()))
- .collect(toMap(EndpointPort::getName, port -> Integer.toString(port.getPort())));
- Map portMetadata = keysWithPrefix(ports, properties.metadata().portsPrefix());
- if (!portMetadata.isEmpty()) {
- LOG.debug(() -> "Adding port metadata: " + portMetadata + " for serviceId : " + serviceId);
- }
- serviceMetadata.putAll(portMetadata);
- }
-
- serviceMetadata.put(NAMESPACE_METADATA_KEY, namespace);
- serviceMetadata.put(SERVICE_TYPE, service.getSpec().getType());
- return serviceMetadata;
- }
-
static List endpoints(KubernetesDiscoveryProperties properties, KubernetesClient client,
KubernetesNamespaceProvider namespaceProvider, String target, @Nullable String serviceName,
Predicate filter) {
@@ -376,6 +330,12 @@ final class Fabric8KubernetesDiscoveryClientUtils {
return Map.of();
}
+ static Map portsData(List endpointSubsets) {
+ return endpointSubsets.stream().flatMap(endpointSubset -> endpointSubset.getPorts().stream())
+ .filter(port -> StringUtils.hasText(port.getName()))
+ .collect(Collectors.toMap(EndpointPort::getName, port -> Integer.toString(port.getPort())));
+ }
+
/**
* serviceName can be null, in which case, such a filter will not be applied.
*/
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 031cdc6f..149d0679 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
@@ -25,6 +25,7 @@ import java.util.function.Predicate;
import io.fabric8.kubernetes.api.model.EndpointAddress;
import io.fabric8.kubernetes.api.model.EndpointSubset;
import io.fabric8.kubernetes.api.model.Endpoints;
+import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.commons.logging.LogFactory;
@@ -32,6 +33,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
+import org.springframework.cloud.kubernetes.commons.discovery.DiscoveryClientUtils;
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
@@ -41,8 +43,8 @@ import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesD
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8KubernetesDiscoveryClientUtils.addresses;
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8KubernetesDiscoveryClientUtils.endpoints;
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8KubernetesDiscoveryClientUtils.endpointsPort;
+import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8KubernetesDiscoveryClientUtils.portsData;
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8KubernetesDiscoveryClientUtils.serviceInstance;
-import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8KubernetesDiscoveryClientUtils.serviceMetadata;
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8KubernetesDiscoveryClientUtils.services;
/**
@@ -119,11 +121,14 @@ public class KubernetesDiscoveryClient implements DiscoveryClient, EnvironmentAw
s -> s.getSpec().getType().equals(EXTERNAL_NAME), Map.of("metadata.name", serviceId),
"fabric8-discovery");
for (Service service : services) {
- Map serviceMetadata = serviceMetadata(serviceId, service, properties, List.of(),
- service.getMetadata().getNamespace());
+ ObjectMeta serviceMetadata = service.getMetadata();
+ Map result = DiscoveryClientUtils.serviceMetadata(serviceId,
+ serviceMetadata.getLabels(), serviceMetadata.getAnnotations(), Map.of(), properties,
+ serviceMetadata.getNamespace(), service.getSpec().getType());
+
ServiceInstance externalNameServiceInstance = serviceInstance(null, service, null,
- new Fabric8ServicePortData(-1, null), serviceId, serviceMetadata,
- service.getMetadata().getNamespace(), properties, client);
+ new Fabric8ServicePortData(-1, null), serviceId, result, service.getMetadata().getNamespace(),
+ properties, client);
instances.add(externalNameServiceInstance);
}
}
@@ -147,14 +152,18 @@ public class KubernetesDiscoveryClient implements DiscoveryClient, EnvironmentAw
List instances = new ArrayList<>();
Service service = client.services().inNamespace(namespace).withName(serviceId).get();
- Map serviceMetadata = serviceMetadata(serviceId, service, properties, subsets, namespace);
+ ObjectMeta serviceMetadata = service.getMetadata();
+
+ Map result = DiscoveryClientUtils.serviceMetadata(serviceId, serviceMetadata.getLabels(),
+ serviceMetadata.getAnnotations(), portsData(subsets), properties, serviceMetadata.getNamespace(),
+ service.getSpec().getType());
for (EndpointSubset endpointSubset : subsets) {
Fabric8ServicePortData portData = endpointsPort(endpointSubset, serviceId, properties, service);
List addresses = addresses(endpointSubset, properties);
for (EndpointAddress endpointAddress : addresses) {
ServiceInstance serviceInstance = serviceInstance(servicePortSecureResolver, service, endpointAddress,
- portData, serviceId, serviceMetadata, namespace, properties, client);
+ portData, serviceId, result, namespace, properties, client);
instances.add(serviceInstance);
}
}
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 cce2a443..7199f1bb 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
@@ -20,6 +20,9 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+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.Service;
import io.fabric8.kubernetes.api.model.ServiceBuilder;
import io.fabric8.kubernetes.api.model.ServiceSpecBuilder;
@@ -280,6 +283,33 @@ class Fabric8KubernetesDiscoveryClientUtilsTests {
Assertions.assertEquals(result.get(0).getMetadata().getName(), "external-name-service");
}
+ @Test
+ void testPortsDataOne() {
+ List endpointSubsets = List.of(
+ new EndpointSubsetBuilder().withPorts(new EndpointPortBuilder().withPort(8081).withName("").build())
+ .build(),
+ new EndpointSubsetBuilder()
+ .withPorts(new EndpointPortBuilder().withPort(8080).withName("https").build()).build());
+
+ Map portsData = Fabric8KubernetesDiscoveryClientUtils.portsData(endpointSubsets);
+ Assertions.assertEquals(portsData.size(), 1);
+ Assertions.assertEquals(portsData.get("https"), "8080");
+ }
+
+ @Test
+ void testPortsDataTwo() {
+ List endpointSubsets = List.of(
+ new EndpointSubsetBuilder().withPorts(new EndpointPortBuilder().withPort(8081).withName("http").build())
+ .build(),
+ new EndpointSubsetBuilder()
+ .withPorts(new EndpointPortBuilder().withPort(8080).withName("https").build()).build());
+
+ Map portsData = Fabric8KubernetesDiscoveryClientUtils.portsData(endpointSubsets);
+ Assertions.assertEquals(portsData.size(), 2);
+ Assertions.assertEquals(portsData.get("https"), "8080");
+ Assertions.assertEquals(portsData.get("http"), "8081");
+ }
+
private void service(String name, String namespace, Map labels) {
Service service = new ServiceBuilder().withNewMetadata().withName(name).withLabels(labels)
.withNamespace(namespace).and().build();
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 366ca511..8a42ef27 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
@@ -19,7 +19,6 @@ package org.springframework.cloud.kubernetes.fabric8.discovery;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.stream.Collectors;
import io.fabric8.kubernetes.api.model.EndpointAddress;
import io.fabric8.kubernetes.api.model.EndpointAddressBuilder;
@@ -357,295 +356,6 @@ class KubernetesDiscoveryClientUtilsTests {
Assertions.assertTrue(output.getOut().contains("found primary-port-name via 'http' to match port : 8082"));
}
- /**
- *
- * - 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 = "";
-
- String namespace = "default";
-
- 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);
- Service service = new ServiceBuilder().withSpec(new ServiceSpecBuilder().withType("ClusterIP").build()).build();
-
- Map result = Fabric8KubernetesDiscoveryClientUtils.serviceMetadata("my-service", service,
- properties, List.of(), namespace);
- 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 = "";
-
- String namespace = "default";
-
- 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);
- Service service = new ServiceBuilder().withSpec(new ServiceSpecBuilder().withType("ClusterIP").build())
- .withMetadata(new ObjectMetaBuilder().withLabels(Map.of("a", "b")).build()).build();
-
- Map result = Fabric8KubernetesDiscoveryClientUtils.serviceMetadata("my-service", service,
- properties, List.of(), namespace);
- 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 = "";
-
- String namespace = "default";
-
- 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);
- Service service = new ServiceBuilder().withSpec(new ServiceSpecBuilder().withType("ClusterIP").build())
- .withMetadata(new ObjectMetaBuilder().withLabels(Map.of("a", "b", "c", "d")).build()).build();
-
- Map result = Fabric8KubernetesDiscoveryClientUtils.serviceMetadata("my-service", service,
- properties, List.of(), namespace);
- 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 = "";
-
- String namespace = "default";
-
- 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);
- Service service = new ServiceBuilder().withSpec(new ServiceSpecBuilder().withType("ClusterIP").build())
- .withMetadata(new ObjectMetaBuilder().withAnnotations(Map.of("aa", "bb")).withLabels(Map.of("a", "b"))
- .build())
- .build();
-
- Map result = Fabric8KubernetesDiscoveryClientUtils.serviceMetadata("my-service", service,
- properties, List.of(), namespace);
- 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 = "";
-
- String namespace = "default";
-
- 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);
- Service service = new ServiceBuilder().withSpec(new ServiceSpecBuilder().withType("ClusterIP").build())
- .withMetadata(new ObjectMetaBuilder().withAnnotations(Map.of("aa", "bb", "cc", "dd"))
- .withLabels(Map.of("a", "b")).build())
- .build();
-
- Map result = Fabric8KubernetesDiscoveryClientUtils.serviceMetadata("my-service", service,
- properties, List.of(), namespace);
- 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 = "";
-
- String namespace = "default";
-
- 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);
- Service service = new ServiceBuilder()
- .withSpec(new ServiceSpecBuilder().withType("ClusterIP").build()).withMetadata(new ObjectMetaBuilder()
- .withAnnotations(Map.of("aa", "bb", "cc", "dd")).withLabels(Map.of("a", "b", "c", "d")).build())
- .build();
-
- Map result = Fabric8KubernetesDiscoveryClientUtils.serviceMetadata("my-service", service,
- properties, List.of(), namespace);
- 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"));
- }
-
- /**
- *
- * - ports without prefix are added
- *
- */
- @Test
- void testServiceMetadataAddPortsWithoutPrefix(CapturedOutput output) {
- boolean addLabels = false;
- String labelsPrefix = "";
- boolean addAnnotations = false;
- String annotationsPrefix = "prefix-";
- boolean addPorts = true;
- String portsPrefix = "";
-
- String namespace = "default";
-
- 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);
- Service service = new ServiceBuilder().withSpec(new ServiceSpecBuilder().withType("ClusterIP").build())
- .withMetadata(new ObjectMetaBuilder().withAnnotations(Map.of("aa", "bb", "cc", "dd"))
- .withLabels(Map.of("a", "b")).build())
- .build();
-
- List endpointSubsets = List.of(
- new EndpointSubsetBuilder().withPorts(new EndpointPortBuilder().withPort(8081).withName("").build())
- .build(),
- new EndpointSubsetBuilder()
- .withPorts(new EndpointPortBuilder().withPort(8080).withName("https").build()).build());
-
- Map result = Fabric8KubernetesDiscoveryClientUtils.serviceMetadata("my-service", service,
- properties, endpointSubsets, namespace);
- Assertions.assertEquals(result.size(), 3);
- Assertions.assertEquals(result, Map.of("https", "8080", "k8s_namespace", "default", "type", "ClusterIP"));
- Assertions
- .assertTrue(output.getOut().contains("Adding port metadata: {https=8080} for serviceId : my-service"));
- }
-
- /**
- *
- * - ports without prefix are added
- *
- */
- @Test
- void testServiceMetadataAddPortsWithPrefix(CapturedOutput output) {
- boolean addLabels = false;
- String labelsPrefix = "";
- boolean addAnnotations = false;
- String annotationsPrefix = "prefix-";
- boolean addPorts = true;
- String portsPrefix = "prefix-";
-
- String namespace = "default";
-
- 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);
- Service service = new ServiceBuilder().withSpec(new ServiceSpecBuilder().withType("ClusterIP").build())
- .withMetadata(new ObjectMetaBuilder().withAnnotations(Map.of("aa", "bb", "cc", "dd"))
- .withLabels(Map.of("a", "b")).build())
- .build();
-
- List endpointSubsets = List.of(
- new EndpointSubsetBuilder().withPorts(new EndpointPortBuilder().withPort(8081).withName("http").build())
- .build(),
- new EndpointSubsetBuilder()
- .withPorts(new EndpointPortBuilder().withPort(8080).withName("https").build()).build());
-
- Map result = Fabric8KubernetesDiscoveryClientUtils.serviceMetadata("my-service", service,
- properties, endpointSubsets, namespace);
- Assertions.assertEquals(result.size(), 4);
- Assertions.assertEquals(result,
- Map.of("prefix-https", "8080", "prefix-http", "8081", "k8s_namespace", "default", "type", "ClusterIP"));
- Assertions.assertTrue(output.getOut()
- .contains("Adding port metadata: {prefix-http=8081, prefix-https=8080} for serviceId : my-service"));
- }
-
/**
*
* - ready addresses are empty
@@ -797,10 +507,4 @@ class KubernetesDiscoveryClientUtilsTests {
Assertions.assertNull(defaultInstance.getCluster());
}
- 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();
- }
-
}