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 51d07512..b7a7723c 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 @@ -44,6 +44,7 @@ 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.NAMESPACE_METADATA_KEY; import static org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClientUtils.endpointsPort; +import static org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClientUtils.serviceMetadata; import static org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClientUtils.subsetsFromEndpoints; /** @@ -143,7 +144,7 @@ public class KubernetesDiscoveryClient implements DiscoveryClient { List instances = new ArrayList<>(); if (!subsets.isEmpty()) { final Service service = this.client.services().inNamespace(namespace).withName(serviceId).get(); - final Map serviceMetadata = this.getServiceMetadata(service); + final Map serviceMetadata = serviceMetadata(serviceId, service, properties); KubernetesDiscoveryProperties.Metadata metadataProps = this.properties.metadata(); for (EndpointSubset s : subsets) { @@ -192,29 +193,6 @@ public class KubernetesDiscoveryClient implements DiscoveryClient { return instances; } - private Map getServiceMetadata(Service service) { - final Map serviceMetadata = new HashMap<>(); - KubernetesDiscoveryProperties.Metadata metadataProps = this.properties.metadata(); - if (metadataProps.addLabels()) { - Map labelMetadata = keysWithPrefix(service.getMetadata().getLabels(), - metadataProps.labelsPrefix()); - if (log.isDebugEnabled()) { - log.debug("Adding label metadata: " + labelMetadata); - } - serviceMetadata.putAll(labelMetadata); - } - if (metadataProps.addAnnotations()) { - Map annotationMetadata = keysWithPrefix(service.getMetadata().getAnnotations(), - metadataProps.annotationsPrefix()); - if (log.isDebugEnabled()) { - log.debug("Adding annotation metadata: " + annotationMetadata); - } - serviceMetadata.putAll(annotationMetadata); - } - - return serviceMetadata; - } - @Override public List getServices() { return adapter.apply(client).stream().map(s -> s.getMetadata().getName()).toList(); diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientUtils.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientUtils.java index e3494e33..73870207 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientUtils.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesDiscoveryClientUtils.java @@ -16,6 +16,7 @@ package org.springframework.cloud.kubernetes.fabric8.discovery; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -32,6 +33,7 @@ import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscover import org.springframework.core.log.LogAccessor; import org.springframework.util.StringUtils; +import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.keysWithPrefix; 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; @@ -119,6 +121,26 @@ final class KubernetesDiscoveryClientUtils { return primaryPortName; } + static Map serviceMetadata(String serviceId, Service service, + KubernetesDiscoveryProperties properties) { + 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); + } + + return serviceMetadata; + } + private static Optional fromMap(Map existingPorts, String key, String message) { Integer fromPrimaryPortName = existingPorts.get(key); if (fromPrimaryPortName == null) { 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 e80ebf7f..dcccde37 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,6 +19,7 @@ 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.EndpointPortBuilder; import io.fabric8.kubernetes.api.model.EndpointSubset; @@ -324,4 +325,169 @@ 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 = ""; + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(addLabels, + labelsPrefix, addAnnotations, annotationsPrefix, false, ""); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, + true, "", Set.of(), Map.of(), "", metadata, 0, false); + Service service = new ServiceBuilder().build(); + + Map result = KubernetesDiscoveryClientUtils.serviceMetadata("my-service", service, properties); + Assertions.assertEquals(result.size(), 0); + } + + /** + *
+	 *     - 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 = ""; + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(addLabels, + labelsPrefix, addAnnotations, annotationsPrefix, false, ""); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, + true, "", Set.of(), Map.of(), "", metadata, 0, false); + Service service = new ServiceBuilder() + .withMetadata(new ObjectMetaBuilder().withLabels(Map.of("a", "b")).build()).build(); + + Map result = KubernetesDiscoveryClientUtils.serviceMetadata("my-service", service, properties); + Assertions.assertEquals(result.size(), 1); + Assertions.assertEquals(result, Map.of("a", "b")); + Assertions.assertTrue(output.getOut().contains("Adding labels metadata: {a=b} 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 = ""; + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(addLabels, + labelsPrefix, addAnnotations, annotationsPrefix, false, ""); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, + true, "", Set.of(), Map.of(), "", metadata, 0, false); + Service service = new ServiceBuilder() + .withMetadata(new ObjectMetaBuilder().withLabels(Map.of("a", "b", "c", "d")).build()).build(); + + Map result = KubernetesDiscoveryClientUtils.serviceMetadata("my-service", service, properties); + Assertions.assertEquals(result.size(), 2); + Assertions.assertEquals(result, Map.of("prefix-a", "b", "prefix-c", "d")); + // so that result is deterministic in assertion + String labels = result.toString(); + Assertions.assertTrue( + output.getOut().contains("Adding labels metadata: " + labels + " 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 = ""; + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(addLabels, + labelsPrefix, addAnnotations, annotationsPrefix, false, ""); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, + true, "", Set.of(), Map.of(), "", metadata, 0, false); + Service service = new ServiceBuilder().withMetadata( + new ObjectMetaBuilder().withAnnotations(Map.of("aa", "bb")).withLabels(Map.of("a", "b")).build()) + .build(); + + Map result = KubernetesDiscoveryClientUtils.serviceMetadata("my-service", service, properties); + Assertions.assertEquals(result.size(), 1); + Assertions.assertEquals(result, Map.of("aa", "bb")); + 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 testServiceMetadataAddAnnotationsWithPrefixPrefix(CapturedOutput output) { + boolean addLabels = false; + String labelsPrefix = ""; + boolean addAnnotations = true; + String annotationsPrefix = "prefix-"; + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(addLabels, + labelsPrefix, addAnnotations, annotationsPrefix, false, ""); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, + true, "", Set.of(), Map.of(), "", metadata, 0, false); + Service service = new ServiceBuilder().withMetadata(new ObjectMetaBuilder() + .withAnnotations(Map.of("aa", "bb", "cc", "dd")).withLabels(Map.of("a", "b")).build()).build(); + + Map result = KubernetesDiscoveryClientUtils.serviceMetadata("my-service", service, properties); + Assertions.assertEquals(result.size(), 2); + Assertions.assertEquals(result, Map.of("prefix-aa", "bb", "prefix-cc", "dd")); + // so that result is deterministic in assertion + String annotations = result.toString(); + 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-"; + KubernetesDiscoveryProperties.Metadata metadata = new KubernetesDiscoveryProperties.Metadata(addLabels, + labelsPrefix, addAnnotations, annotationsPrefix, false, ""); + KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60L, + true, "", Set.of(), Map.of(), "", metadata, 0, false); + Service service = new ServiceBuilder().withMetadata(new ObjectMetaBuilder() + .withAnnotations(Map.of("aa", "bb", "cc", "dd")).withLabels(Map.of("a", "b", "c", "d")).build()) + .build(); + + Map result = KubernetesDiscoveryClientUtils.serviceMetadata("my-service", service, properties); + Assertions.assertEquals(result.size(), 4); + Assertions.assertEquals(result, + Map.of("annotation-aa", "bb", "annotation-cc", "dd", "label-a", "b", "label-c", "d")); + // 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")); + } + }