From de8f93858640712d47b30cc7a836e2b17c2339cf Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Fri, 26 Mar 2021 15:59:44 -0400 Subject: [PATCH 1/3] Initialize discovery client properly Fixes #517 --- ...overyClientHealthIndicatorInitializer.java | 50 +++++++++++++++++++ ...CatalogServicesWatchConfigurationTest.java | 10 ++++ ...lientAutoConfigurationPropertiesTests.java | 10 ++++ .../src/main/resources/application.yaml | 8 +++ .../cloud/kubernetes/it/ServicesIT.java | 8 +++ .../src/main/resources/application.yaml | 8 +++ 6 files changed, 94 insertions(+) create mode 100644 spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientHealthIndicatorInitializer.java create mode 100644 spring-cloud-kubernetes-integration-tests/discovery/discovery-client/src/main/resources/application.yaml create mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/main/resources/application.yaml diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientHealthIndicatorInitializer.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientHealthIndicatorInitializer.java new file mode 100644 index 00000000..6577a3e8 --- /dev/null +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientHealthIndicatorInitializer.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013-2021 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.cloud.client.discovery.event.InstanceRegisteredEvent; +import org.springframework.cloud.kubernetes.PodUtils; +import org.springframework.context.ApplicationEventPublisher; + +/** + * @author Ryan Baxter + */ +public class KubernetesDiscoveryClientHealthIndicatorInitializer + implements InitializingBean { + + private PodUtils podUtils; + + private ApplicationEventPublisher applicationEventPublisher; + + public KubernetesDiscoveryClientHealthIndicatorInitializer(PodUtils podUtils, + ApplicationEventPublisher applicationEventPublisher) { + this.podUtils = podUtils; + this.applicationEventPublisher = applicationEventPublisher; + } + + public void initialize() { + this.applicationEventPublisher + .publishEvent(new InstanceRegisteredEvent<>(podUtils.currentPod(), null)); + } + + @Override + public void afterPropertiesSet() { + this.initialize(); + } + +} diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogServicesWatchConfigurationTest.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogServicesWatchConfigurationTest.java index 20fa5725..26b3ff8b 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogServicesWatchConfigurationTest.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogServicesWatchConfigurationTest.java @@ -16,6 +16,7 @@ package org.springframework.cloud.kubernetes.discovery; +import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.client.KubernetesClient; import org.junit.After; import org.junit.Test; @@ -23,12 +24,14 @@ import org.junit.Test; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.cloud.kubernetes.PodUtils; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * @author Oleg Vyukov @@ -86,6 +89,13 @@ public class KubernetesCatalogServicesWatchConfigurationTest { return mock(KubernetesClient.class); } + @Bean + PodUtils podUtils() { + PodUtils podPodUtils = mock(PodUtils.class); + when(podPodUtils.currentPod()).thenReturn(() -> mock(Pod.class)); + return podPodUtils; + } + } } diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationPropertiesTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationPropertiesTests.java index c3732d60..04f7c02b 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationPropertiesTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationPropertiesTests.java @@ -16,18 +16,21 @@ package org.springframework.cloud.kubernetes.discovery; +import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.client.KubernetesClient; import org.junit.After; import org.junit.Test; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.cloud.kubernetes.PodUtils; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * @author Ryan Dawson @@ -90,6 +93,13 @@ public class KubernetesDiscoveryClientAutoConfigurationPropertiesTests { return mock(KubernetesClient.class); } + @Bean + PodUtils podUtils() { + PodUtils podPodUtils = mock(PodUtils.class); + when(podPodUtils.currentPod()).thenReturn(() -> mock(Pod.class)); + return podPodUtils; + } + } } diff --git a/spring-cloud-kubernetes-integration-tests/discovery/discovery-client/src/main/resources/application.yaml b/spring-cloud-kubernetes-integration-tests/discovery/discovery-client/src/main/resources/application.yaml new file mode 100644 index 00000000..cd402822 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/discovery/discovery-client/src/main/resources/application.yaml @@ -0,0 +1,8 @@ +management: + endpoint: + health: + show-details: always + endpoints: + web: + exposure: + include: "*" diff --git a/spring-cloud-kubernetes-integration-tests/discovery/tests/src/test/java/org/springframework/cloud/kubernetes/it/ServicesIT.java b/spring-cloud-kubernetes-integration-tests/discovery/tests/src/test/java/org/springframework/cloud/kubernetes/it/ServicesIT.java index 2523c081..4ebe1ee2 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/tests/src/test/java/org/springframework/cloud/kubernetes/it/ServicesIT.java +++ b/spring-cloud-kubernetes-integration-tests/discovery/tests/src/test/java/org/springframework/cloud/kubernetes/it/ServicesIT.java @@ -25,6 +25,7 @@ import org.junit.runner.RunWith; import static io.restassured.RestAssured.given; import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.core.Is.is; @RequiresKubernetes @RunWith(Arquillian.class) @@ -57,4 +58,11 @@ public class ServicesIT { .body("serviceId", hasItems("discovery-service-a")); } + @Test + public void testHealthEndpoint() { + given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)) + .contentType("application/json").get("actuator/health").then() + .statusCode(200).body("components.discoveryComposite.status", is("UP")); + } + } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/main/resources/application.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/main/resources/application.yaml new file mode 100644 index 00000000..cd402822 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/main/resources/application.yaml @@ -0,0 +1,8 @@ +management: + endpoint: + health: + show-details: always + endpoints: + web: + exposure: + include: "*" From afc528335c04b6e65ce52c75e31d33161a034ad7 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Fri, 26 Mar 2021 16:47:59 -0400 Subject: [PATCH 2/3] Missing health initializer bean --- ...netesDiscoveryClientAutoConfiguration.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) 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 c6a4b774..4ed91133 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 @@ -18,17 +18,22 @@ package org.springframework.cloud.kubernetes.discovery; import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.boot.actuate.health.HealthIndicator; 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.ConditionalOnMissingBean; 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.ConditionalOnKubernetesEnabled; import org.springframework.cloud.kubernetes.KubernetesAutoConfiguration; +import org.springframework.cloud.kubernetes.PodUtils; import org.springframework.cloud.kubernetes.registry.KubernetesRegistration; import org.springframework.cloud.kubernetes.registry.KubernetesServiceRegistry; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -92,6 +97,21 @@ public class KubernetesDiscoveryClientAutoConfiguration { return new KubernetesDiscoveryProperties(); } + @ConditionalOnClass({ HealthIndicator.class }) + @ConditionalOnDiscoveryEnabled + @ConditionalOnDiscoveryHealthIndicatorEnabled + @Configuration + public static class KubernetesDiscoveryClientHealthIndicatorConfiguration { + + @Bean + public KubernetesDiscoveryClientHealthIndicatorInitializer indicatorInitializer( + ApplicationEventPublisher applicationEventPublisher, PodUtils podUtils) { + return new KubernetesDiscoveryClientHealthIndicatorInitializer(podUtils, + applicationEventPublisher); + } + + } + @Configuration(proxyBeanMethods = false) @ConditionalOnBlockingDiscoveryEnabled @ConditionalOnKubernetesDiscoveryEnabled From 79bcd2eaa50ad03ffc05bb417849a47f6e2ea706 Mon Sep 17 00:00:00 2001 From: Paul Jeffrey Date: Wed, 7 Apr 2021 13:52:57 -0600 Subject: [PATCH 3/3] Issue-753 Adds debug logging of property source information (#760) Co-authored-by: Paul Jeffrey --- .../reload/ConfigurationChangeDetector.java | 18 ++++++++++++++++++ .../EventBasedConfigurationChangeDetector.java | 6 ++++++ 2 files changed, 24 insertions(+) diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationChangeDetector.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationChangeDetector.java index 12034a49..3512e2e0 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationChangeDetector.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationChangeDetector.java @@ -102,6 +102,15 @@ public abstract class ConfigurationChangeDetector { this.log.warn( "The current number of ConfigMap PropertySources does not match " + "the ones loaded from the Kubernetes - No reload will take place"); + + if (log.isDebugEnabled()) { + this.log.debug(String.format("source 1: %d", l1.size())); + l1.forEach(item -> log.debug(item)); + + this.log.debug(String.format("source 2: %d", l2.size())); + l2.forEach(item -> log.debug(item)); + } + return false; } @@ -142,6 +151,11 @@ public abstract class ConfigurationChangeDetector { LinkedList> sources = toLinkedList( this.environment.getPropertySources()); + + this.log.debug("findPropertySources"); + this.log.debug(String.format("environment: %s", this.environment)); + this.log.debug(String.format("environment sources: %s", sources)); + while (!sources.isEmpty()) { PropertySource source = sources.pop(); if (source instanceof CompositePropertySource) { @@ -197,6 +211,10 @@ public abstract class ConfigurationChangeDetector { + propertySource.getClass()); } + this.log.debug("locateMapPropertySources"); + this.log.debug(String.format("environment: %s", environment)); + this.log.debug(String.format("sources: %s", result)); + return result; } diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigurationChangeDetector.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigurationChangeDetector.java index 6d7c0eba..8981985f 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigurationChangeDetector.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigurationChangeDetector.java @@ -141,6 +141,9 @@ public class EventBasedConfigurationChangeDetector extends ConfigurationChangeDe } private void onEvent(ConfigMap configMap) { + + this.log.debug(String.format("onEvent configMap: %s", configMap.toString())); + boolean changed = changed( locateMapPropertySources(this.configMapPropertySourceLocator, this.environment), @@ -152,6 +155,9 @@ public class EventBasedConfigurationChangeDetector extends ConfigurationChangeDe } private void onEvent(Secret secret) { + + this.log.debug(String.format("onEvent configMap: %s", secret.toString())); + boolean changed = changed( locateMapPropertySources(this.secretsPropertySourceLocator, this.environment),