From 68436f7dcab3687f67752972316eaaaf17f7d999 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Mon, 4 Oct 2021 19:22:16 -0400 Subject: [PATCH 1/2] Cherry pick c48fdfd121902eca45cc74d7da1b96c1cd4bf496 --- ...netesDiscoveryClientAutoConfiguration.java | 15 ++++-- .../KubernetesInformerDiscoveryClient.java | 30 ++++++++++-- ...oudKubernetesInformerFactoryProcessor.java | 15 +++--- ...ubernetesInformerDiscoveryClientTests.java | 49 +++++++++++++++++++ 4 files changed, 92 insertions(+), 17 deletions(-) diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientAutoConfiguration.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientAutoConfiguration.java index 826e7e23..263e1d73 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientAutoConfiguration.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientAutoConfiguration.java @@ -48,6 +48,7 @@ import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscover import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; @Configuration(proxyBeanMethods = false) @ConditionalOnKubernetesDiscoveryEnabled @@ -80,11 +81,15 @@ public class KubernetesDiscoveryClientAutoConfiguration { @Bean @ConditionalOnMissingBean public SpringCloudKubernetesInformerFactoryProcessor discoveryInformerConfigurer( - KubernetesNamespaceProvider kubernetesNamespaceProvider, - KubernetesDiscoveryProperties kubernetesDiscoveryProperties, ApiClient apiClient, - CatalogSharedInformerFactory sharedInformerFactory) { - return new SpringCloudKubernetesInformerFactoryProcessor(kubernetesDiscoveryProperties, - kubernetesNamespaceProvider, apiClient, sharedInformerFactory); + KubernetesNamespaceProvider kubernetesNamespaceProvider, ApiClient apiClient, + CatalogSharedInformerFactory sharedInformerFactory, Environment environment) { + // Injecting KubernetesDiscoveryProperties here would cause it to be + // initialize too early + // Instead get the all-namespaces property value from the Environment directly + boolean allNamespaces = environment.getProperty("spring.cloud.kubernetes.discovery.all-namespaces", + Boolean.class, false); + return new SpringCloudKubernetesInformerFactoryProcessor(kubernetesNamespaceProvider, apiClient, + sharedInformerFactory, allNamespaces); } @Bean 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 23c4afbc..112f8a4f 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 @@ -102,7 +102,7 @@ public class KubernetesInformerDiscoveryClient implements DiscoveryClient, Initi V1Service service = properties.isAllNamespaces() ? this.serviceLister.list().stream() .filter(svc -> serviceId.equals(svc.getMetadata().getName())).findFirst().orElse(null) : this.serviceLister.namespace(this.namespace).get(serviceId); - if (service == null) { + if (service == null || !matchServiceLabels(service)) { // no such service present in the cluster return new ArrayList<>(); } @@ -205,8 +205,8 @@ public class KubernetesInformerDiscoveryClient implements DiscoveryClient, Initi public List getServices() { List services = this.properties.isAllNamespaces() ? this.serviceLister.list() : this.serviceLister.namespace(this.namespace).list(); - return services.stream().filter(s -> s.getMetadata() != null) // safeguard - .map(s -> s.getMetadata().getName()).collect(Collectors.toList()); + return services.stream().filter(this::matchServiceLabels).map(s -> s.getMetadata().getName()) + .collect(Collectors.toList()); } @Override @@ -230,4 +230,28 @@ public class KubernetesInformerDiscoveryClient implements DiscoveryClient, Initi + " services) , discovery client is now available"); } + private boolean matchServiceLabels(V1Service service) { + if (log.isDebugEnabled()) { + log.debug("Kubernetes Service Label Properties:"); + if (this.properties.getServiceLabels() != null) { + this.properties.getServiceLabels().forEach((key, value) -> log.debug(key + ":" + value)); + } + log.debug("Service " + service.getMetadata().getName() + " labels:"); + if (service.getMetadata() != null && service.getMetadata().getLabels() != null) { + service.getMetadata().getLabels().forEach((key, value) -> log.debug(key + ":" + value)); + } + } + // safeguard + if (service.getMetadata() == null) { + return false; + } + if (properties.getServiceLabels() == null || properties.getServiceLabels().isEmpty()) { + return true; + } + return properties.getServiceLabels().keySet().stream() + .allMatch(k -> service.getMetadata().getLabels() != null + && service.getMetadata().getLabels().containsKey(k) + && service.getMetadata().getLabels().get(k).equals(properties.getServiceLabels().get(k))); + } + } diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/SpringCloudKubernetesInformerFactoryProcessor.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/SpringCloudKubernetesInformerFactoryProcessor.java index c3a5ecf3..ef4d574c 100644 --- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/SpringCloudKubernetesInformerFactoryProcessor.java +++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/SpringCloudKubernetesInformerFactoryProcessor.java @@ -38,7 +38,6 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; -import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.core.ResolvableType; /** @@ -54,26 +53,24 @@ class SpringCloudKubernetesInformerFactoryProcessor extends KubernetesInformerFa private final SharedInformerFactory sharedInformerFactory; - private final KubernetesDiscoveryProperties kubernetesDiscoveryProperties; + private final boolean allNamespaces; private final KubernetesNamespaceProvider kubernetesNamespaceProvider; @Autowired - SpringCloudKubernetesInformerFactoryProcessor(KubernetesDiscoveryProperties kubernetesDiscoveryProperties, - KubernetesNamespaceProvider kubernetesNamespaceProvider, ApiClient apiClient, - SharedInformerFactory sharedInformerFactory) { + SpringCloudKubernetesInformerFactoryProcessor(KubernetesNamespaceProvider kubernetesNamespaceProvider, + ApiClient apiClient, SharedInformerFactory sharedInformerFactory, boolean allNamespaces) { super(); this.apiClient = apiClient; this.sharedInformerFactory = sharedInformerFactory; this.kubernetesNamespaceProvider = kubernetesNamespaceProvider; - this.kubernetesDiscoveryProperties = kubernetesDiscoveryProperties; + this.allNamespaces = allNamespaces; } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - String namespace = kubernetesDiscoveryProperties.isAllNamespaces() ? Namespaces.NAMESPACE_ALL - : kubernetesNamespaceProvider.getNamespace() == null ? Namespaces.NAMESPACE_DEFAULT - : kubernetesNamespaceProvider.getNamespace(); + String namespace = allNamespaces ? Namespaces.NAMESPACE_ALL : kubernetesNamespaceProvider.getNamespace() == null + ? Namespaces.NAMESPACE_DEFAULT : kubernetesNamespaceProvider.getNamespace(); this.apiClient.setHttpClient(this.apiClient.getHttpClient().newBuilder().readTimeout(Duration.ZERO).build()); 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 c6adf384..a46dca61 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 @@ -17,6 +17,7 @@ package org.springframework.cloud.kubernetes.client.discovery; import java.util.HashMap; +import java.util.Map; import io.kubernetes.client.informer.SharedInformerFactory; import io.kubernetes.client.informer.cache.Cache; @@ -59,6 +60,11 @@ public class KubernetesInformerDiscoveryClientTests { .metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace2")) .spec(new V1ServiceSpec().loadBalancerIP("1.1.1.1")).status(new V1ServiceStatus()); + private static final V1Service testService3 = new V1Service() + .metadata(new V1ObjectMeta().name("test-svc-3").namespace("namespace1").putLabelsItem("spring", "true") + .putLabelsItem("k8s", "true")) + .spec(new V1ServiceSpec().loadBalancerIP("1.1.1.1")).status(new V1ServiceStatus()); + private static final V1Endpoints testEndpoints1 = new V1Endpoints() .metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1")) .addSubsetsItem(new V1EndpointSubset().addPortsItem(new V1EndpointPort().port(8080)) @@ -91,6 +97,11 @@ public class KubernetesInformerDiscoveryClientTests { .addPortsItem(new V1EndpointPort().name("tcp2").port(443)) .addAddressesItem(new V1EndpointAddress().ip("1.1.1.1"))); + private static final V1Endpoints testEndpoints3 = new V1Endpoints() + .metadata(new V1ObjectMeta().name("test-svc-3").namespace("namespace1")) + .addSubsetsItem(new V1EndpointSubset().addPortsItem(new V1EndpointPort().port(8080)) + .addAddressesItem(new V1EndpointAddress().ip("2.2.2.2"))); + @Test public void testDiscoveryGetServicesAllNamespaceShouldWork() { Lister serviceLister = setupServiceLister(testService1, testService2); @@ -106,6 +117,44 @@ public class KubernetesInformerDiscoveryClientTests { verify(kubernetesDiscoveryProperties, times(1)).isAllNamespaces(); } + @Test + public void testDiscoveryWithServiceLabels() { + Lister serviceLister = setupServiceLister(testService1, testService2, testService3); + + Map labels = new HashMap<>(); + labels.put("k8s", "true"); + labels.put("spring", "true"); + + when(kubernetesDiscoveryProperties.getServiceLabels()).thenReturn(labels); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("", + sharedInformerFactory, serviceLister, null, null, null, kubernetesDiscoveryProperties); + + assertThat(discoveryClient.getServices().toArray()).containsOnly(testService3.getMetadata().getName()); + + verify(kubernetesDiscoveryProperties, times(1)).isAllNamespaces(); + } + + @Test + public void testDiscoveryInstancesWithServiceLabels() { + Lister serviceLister = setupServiceLister(testService1, testService2, testService3); + Lister endpointsLister = setupEndpointsLister(testEndpoints1, testEndpoints3); + + Map labels = new HashMap<>(); + labels.put("k8s", "true"); + labels.put("spring", "true"); + + when(kubernetesDiscoveryProperties.isAllNamespaces()).thenReturn(true); + when(kubernetesDiscoveryProperties.getServiceLabels()).thenReturn(labels); + + KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("", + sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties); + + assertThat(discoveryClient.getInstances("test-svc-1").toArray()).isEmpty(); + assertThat(discoveryClient.getInstances("test-svc-3").toArray()) + .containsOnly(new KubernetesServiceInstance("", "test-svc-3", "2.2.2.2", 8080, new HashMap<>(), false)); + } + @Test public void testDiscoveryGetServicesOneNamespaceShouldWork() { Lister serviceLister = setupServiceLister(testService1, testService2); From 32a8ae83dd1938a056f2689dc3fffea58972ab08 Mon Sep 17 00:00:00 2001 From: erabii Date: Thu, 21 Oct 2021 11:40:50 -0400 Subject: [PATCH 2/2] fix issue 870 (all the details are there in the comments) (#872) * fix * trigger build * trigger build --- spring-cloud-kubernetes-commons/pom.xml | 1 + spring-cloud-kubernetes-fabric8-autoconfig/pom.xml | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/spring-cloud-kubernetes-commons/pom.xml b/spring-cloud-kubernetes-commons/pom.xml index 04f1b5b1..e42958fb 100644 --- a/spring-cloud-kubernetes-commons/pom.xml +++ b/spring-cloud-kubernetes-commons/pom.xml @@ -51,6 +51,7 @@ org.springframework.boot spring-boot-starter-logging + true org.springframework.boot diff --git a/spring-cloud-kubernetes-fabric8-autoconfig/pom.xml b/spring-cloud-kubernetes-fabric8-autoconfig/pom.xml index c88efdc7..d1811ab3 100644 --- a/spring-cloud-kubernetes-fabric8-autoconfig/pom.xml +++ b/spring-cloud-kubernetes-fabric8-autoconfig/pom.xml @@ -66,6 +66,13 @@ org.springframework.boot spring-boot-starter-json + + + + org.springframework.boot + spring-boot-starter-logging + +