Don't configure reload beans unless the properties are set (#1200)

This commit is contained in:
erabii
2023-01-17 00:40:37 +00:00
committed by GitHub
parent 8260df5c8e
commit 5f4b9ca997
25 changed files with 931 additions and 145 deletions

View File

@@ -23,7 +23,8 @@ import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfi
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
import org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration;
import org.springframework.cloud.commons.util.TaskSchedulerWrapper;
@@ -34,14 +35,16 @@ import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfig
import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySource;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.config.ConditionalOnKubernetesAndConfigEnabled;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadAutoConfiguration;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadPropertiesAutoConfiguration;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationChangeDetector;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.commons.config.reload.PollingConfigMapChangeDetector;
import org.springframework.cloud.kubernetes.commons.config.reload.PollingSecretsChangeDetector;
import org.springframework.cloud.kubernetes.commons.config.reload.condition.ConditionalOnConfigMapsReloadEnabled;
import org.springframework.cloud.kubernetes.commons.config.reload.condition.ConditionalOnKubernetesReloadEnabled;
import org.springframework.cloud.kubernetes.commons.config.reload.condition.ConditionalOnSecretsReloadEnabled;
import org.springframework.cloud.kubernetes.commons.config.reload.condition.EventReloadDetectionMode;
import org.springframework.cloud.kubernetes.commons.config.reload.condition.PollingReloadDetectionMode;
import org.springframework.context.annotation.Bean;
@@ -55,12 +58,11 @@ import org.springframework.scheduling.TaskScheduler;
* @author Ryan Baxter
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnKubernetesAndConfigEnabled
@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES)
@ConditionalOnKubernetesReloadEnabled
@ConditionalOnClass({ EndpointAutoConfiguration.class, RestartEndpoint.class, ContextRefresher.class })
@AutoConfigureAfter({ InfoEndpointAutoConfiguration.class, RefreshEndpointAutoConfiguration.class,
RefreshAutoConfiguration.class })
@EnableConfigurationProperties(ConfigReloadProperties.class)
RefreshAutoConfiguration.class, ConfigReloadPropertiesAutoConfiguration.class })
@Import(ConfigReloadAutoConfiguration.class)
public class KubernetesClientConfigReloadAutoConfiguration {
@@ -72,6 +74,7 @@ public class KubernetesClientConfigReloadAutoConfiguration {
* @return a bean that listen to configuration changes and fire a reload.
*/
@Bean
@ConditionalOnConfigMapsReloadEnabled
@ConditionalOnBean(KubernetesClientConfigMapPropertySourceLocator.class)
@Conditional(PollingReloadDetectionMode.class)
public ConfigurationChangeDetector configMapPropertyChangePollingWatcher(ConfigReloadProperties properties,
@@ -92,6 +95,7 @@ public class KubernetesClientConfigReloadAutoConfiguration {
* @return a bean that listen to configuration changes and fire a reload.
*/
@Bean
@ConditionalOnSecretsReloadEnabled
@ConditionalOnBean(KubernetesClientSecretsPropertySourceLocator.class)
@Conditional(PollingReloadDetectionMode.class)
public ConfigurationChangeDetector secretsPropertyChangePollingWatcher(ConfigReloadProperties properties,
@@ -112,6 +116,7 @@ public class KubernetesClientConfigReloadAutoConfiguration {
* @return a bean that listen to configMap change events and fire a reload.
*/
@Bean
@ConditionalOnConfigMapsReloadEnabled
@ConditionalOnBean(KubernetesClientConfigMapPropertySourceLocator.class)
@Conditional(EventReloadDetectionMode.class)
public ConfigurationChangeDetector configMapPropertyChangeEventWatcher(ConfigReloadProperties properties,
@@ -132,6 +137,7 @@ public class KubernetesClientConfigReloadAutoConfiguration {
* @return a bean that listen to secrets change events and fire a reload.
*/
@Bean
@ConditionalOnSecretsReloadEnabled
@ConditionalOnBean(KubernetesClientSecretsPropertySourceLocator.class)
@Conditional(EventReloadDetectionMode.class)
public ConfigurationChangeDetector secretsPropertyChangeEventWatcher(ConfigReloadProperties properties,

View File

@@ -57,8 +57,6 @@ public class KubernetesClientEventBasedConfigMapChangeDetector extends Configura
private final KubernetesClientConfigMapPropertySourceLocator propertySourceLocator;
private final boolean monitorConfigMaps;
private final SharedInformerFactory factory;
private final List<SharedIndexInformer<V1ConfigMap>> informers = new ArrayList<>();
@@ -103,41 +101,38 @@ public class KubernetesClientEventBasedConfigMapChangeDetector extends Configura
// certificate authorities for the cluster. This results in SSL errors.
// See https://github.com/spring-cloud/spring-cloud-kubernetes/issues/885
this.factory = new SharedInformerFactory(createApiClientForInformerClient());
this.monitorConfigMaps = properties.monitoringConfigMaps();
this.enableReloadFiltering = properties.enableReloadFiltering();
namespaces = namespaces(kubernetesNamespaceProvider, properties, "configmap");
}
@PostConstruct
void inform() {
if (monitorConfigMaps) {
LOG.info(() -> "Kubernetes event-based configMap change detector activated");
LOG.info(() -> "Kubernetes event-based configMap change detector activated");
namespaces.forEach(namespace -> {
SharedIndexInformer<V1ConfigMap> informer;
String filter = null;
namespaces.forEach(namespace -> {
SharedIndexInformer<V1ConfigMap> informer;
String filter = null;
if (enableReloadFiltering) {
filter = ConfigReloadProperties.RELOAD_LABEL_FILTER + "=true";
LOG.debug(() -> "added configmap informer for namespace : " + namespace + " with enabled filter");
}
else {
LOG.debug(() -> "added configmap informer for namespace : " + namespace);
}
if (enableReloadFiltering) {
filter = ConfigReloadProperties.RELOAD_LABEL_FILTER + "=true";
LOG.debug(() -> "added configmap informer for namespace : " + namespace + " with enabled filter");
}
else {
LOG.debug(() -> "added configmap informer for namespace : " + namespace);
}
String filterOnInformerLabel = filter;
informer = factory
.sharedIndexInformerFor(
(CallGeneratorParams params) -> coreV1Api.listNamespacedConfigMapCall(namespace, null,
null, null, null, filterOnInformerLabel, null, params.resourceVersion, null,
params.timeoutSeconds, params.watch, null),
V1ConfigMap.class, V1ConfigMapList.class);
informer.addEventHandler(handler);
informers.add(informer);
});
String filterOnInformerLabel = filter;
informer = factory
.sharedIndexInformerFor(
(CallGeneratorParams params) -> coreV1Api.listNamespacedConfigMapCall(namespace, null, null,
null, null, filterOnInformerLabel, null, params.resourceVersion, null,
params.timeoutSeconds, params.watch, null),
V1ConfigMap.class, V1ConfigMapList.class);
informer.addEventHandler(handler);
informers.add(informer);
});
factory.startAllRegisteredInformers();
}
factory.startAllRegisteredInformers();
}
@PreDestroy

View File

@@ -57,8 +57,6 @@ public class KubernetesClientEventBasedSecretsChangeDetector extends Configurati
private final KubernetesClientSecretsPropertySourceLocator propertySourceLocator;
private final boolean monitorSecrets;
private final SharedInformerFactory factory;
private final List<SharedIndexInformer<V1Secret>> informers = new ArrayList<>();
@@ -103,40 +101,37 @@ public class KubernetesClientEventBasedSecretsChangeDetector extends Configurati
// certificate authorities for the cluster. This results in SSL errors.
// See https://github.com/spring-cloud/spring-cloud-kubernetes/issues/885
this.factory = new SharedInformerFactory(createApiClientForInformerClient());
this.monitorSecrets = properties.monitoringSecrets();
this.enableReloadFiltering = properties.enableReloadFiltering();
namespaces = namespaces(kubernetesNamespaceProvider, properties, "secret");
}
@PostConstruct
void inform() {
if (monitorSecrets) {
LOG.info(() -> "Kubernetes event-based secrets change detector activated");
LOG.info(() -> "Kubernetes event-based secrets change detector activated");
namespaces.forEach(namespace -> {
SharedIndexInformer<V1Secret> informer;
String filter = null;
namespaces.forEach(namespace -> {
SharedIndexInformer<V1Secret> informer;
String filter = null;
if (enableReloadFiltering) {
filter = ConfigReloadProperties.RELOAD_LABEL_FILTER + "=true";
LOG.debug(() -> "added secret informer for namespace : " + namespace + " with enabled filter");
}
else {
LOG.debug(() -> "added secret informer for namespace : " + namespace);
}
if (enableReloadFiltering) {
filter = ConfigReloadProperties.RELOAD_LABEL_FILTER + "=true";
LOG.debug(() -> "added secret informer for namespace : " + namespace + " with enabled filter");
}
else {
LOG.debug(() -> "added secret informer for namespace : " + namespace);
}
String filterOnInformerLabel = filter;
informer = factory.sharedIndexInformerFor(
(CallGeneratorParams params) -> coreV1Api.listNamespacedSecretCall(namespace, null, null, null,
null, filterOnInformerLabel, null, params.resourceVersion, null, params.timeoutSeconds,
params.watch, null),
V1Secret.class, V1SecretList.class);
informer.addEventHandler(handler);
informers.add(informer);
});
String filterOnInformerLabel = filter;
informer = factory.sharedIndexInformerFor(
(CallGeneratorParams params) -> coreV1Api.listNamespacedSecretCall(namespace, null, null, null,
null, filterOnInformerLabel, null, params.resourceVersion, null, params.timeoutSeconds,
params.watch, null),
V1Secret.class, V1SecretList.class);
informer.addEventHandler(handler);
informers.add(informer);
});
factory.startAllRegisteredInformers();
}
factory.startAllRegisteredInformers();
}
@PreDestroy

View File

@@ -18,7 +18,9 @@ package org.springframework.cloud.kubernetes.client.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
@@ -30,6 +32,7 @@ import io.kubernetes.client.openapi.models.V1ConfigMapList;
import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder;
import io.kubernetes.client.util.ClientBuilder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -46,9 +49,15 @@ import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
import org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration;
import org.springframework.cloud.kubernetes.client.KubernetesClientAutoConfiguration;
import org.springframework.cloud.kubernetes.client.config.reload.KubernetesClientConfigReloadAutoConfiguration;
import org.springframework.cloud.kubernetes.client.config.reload.KubernetesClientEventBasedConfigMapChangeDetector;
import org.springframework.cloud.kubernetes.client.config.reload.KubernetesClientEventBasedSecretsChangeDetector;
import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
import org.springframework.cloud.kubernetes.commons.config.KubernetesBootstrapConfiguration;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadAutoConfiguration;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadPropertiesAutoConfiguration;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationChangeDetector;
import org.springframework.cloud.kubernetes.commons.config.reload.PollingConfigMapChangeDetector;
import org.springframework.cloud.kubernetes.commons.config.reload.PollingSecretsChangeDetector;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -77,7 +86,7 @@ public class KubernetesClientConfigReloadAutoConfigurationTest {
context = new SpringApplicationBuilder(PropertyPlaceholderAutoConfiguration.class, LocalTestConfig.class,
ConfigReloadAutoConfiguration.class, RefreshAutoConfiguration.class, EndpointAutoConfiguration.class,
InfoEndpointAutoConfiguration.class, RefreshEndpointAutoConfiguration.class,
ConfigurationPropertiesBindingPostProcessor.class,
ConfigurationPropertiesBindingPostProcessor.class, ConfigReloadPropertiesAutoConfiguration.class,
ConfigurationPropertiesRebinderAutoConfiguration.class, KubernetesClientBootstrapConfiguration.class,
KubernetesBootstrapConfiguration.class, KubernetesClientConfigReloadAutoConfiguration.class)
.web(org.springframework.boot.WebApplicationType.NONE).properties(envArray).run();
@@ -111,7 +120,7 @@ public class KubernetesClientConfigReloadAutoConfigurationTest {
// 1. watchers
@Test
void kubernetesWatchersWhenKubernetesDisabled() throws Exception {
void kubernetesWatchersWhenKubernetesDisabled() {
setup();
assertThat(context.containsBean("configMapPropertySourceLocator")).isFalse();
assertThat(context.containsBean("secretsPropertySourceLocator")).isFalse();
@@ -122,7 +131,7 @@ public class KubernetesClientConfigReloadAutoConfigurationTest {
}
@Test
void kubernetesWatchersWhenConfigDisabled() throws Exception {
void kubernetesWatchersWhenConfigDisabled() {
setup("spring.cloud.kubernetes.config.enabled=false");
assertThat(context.containsBean("configMapPropertyChangePollingWatcher")).isFalse();
assertThat(context.containsBean("secretsPropertyChangePollingWatcher")).isFalse();
@@ -131,7 +140,7 @@ public class KubernetesClientConfigReloadAutoConfigurationTest {
}
@Test
void kubernetesWatchersWhenReloadDisabled() throws Exception {
void kubernetesWatchersWhenReloadDisabled() {
setup("spring.cloud.kubernetes.reload.enabled=false");
assertThat(context.containsBean("configMapPropertyChangePollingWatcher")).isFalse();
assertThat(context.containsBean("secretsPropertyChangePollingWatcher")).isFalse();
@@ -140,7 +149,7 @@ public class KubernetesClientConfigReloadAutoConfigurationTest {
}
@Test
void kubernetesReloadEnabledButSecretAndConfigDisabled() throws Exception {
void kubernetesReloadEnabledButSecretAndConfigDisabled() {
setup("spring.cloud.kubernetes.reload.enabled=true", "spring.cloud.kubernetes.config.enabled=false",
"spring.cloud.kubernetes.secrets.enabled=false");
assertThat(context.containsBean("configMapPropertyChangePollingWatcher")).isFalse();
@@ -149,46 +158,314 @@ public class KubernetesClientConfigReloadAutoConfigurationTest {
assertThat(context.containsBean("secretsPropertyChangeEventWatcher")).isFalse();
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is true by default
*
* - config map event watcher is picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void kubernetesReloadEnabledWithPolling() throws Exception {
setup("spring.cloud.kubernetes.reload.enabled=true", "spring.cloud.kubernetes.reload.mode=polling",
"spring.main.cloud-platform=KUBERNETES");
assertThat(context.containsBean("configMapPropertySourceLocator")).isTrue();
assertThat(context.containsBean("secretsPropertySourceLocator")).isTrue();
assertThat(context.containsBean("configMapPropertyChangePollingWatcher")).isTrue();
assertThat(context.containsBean("secretsPropertyChangePollingWatcher")).isTrue();
assertThat(context.containsBean("configMapPropertyChangeEventWatcher")).isFalse();
assertThat(context.containsBean("secretsPropertyChangeEventWatcher")).isFalse();
void reloadEventEnabledMonitoringConfigMapsEnabledByDefault() {
setup("spring.cloud.kubernetes.reload.enabled=true", "spring.main.cloud-platform=KUBERNETES");
Map<String, ConfigurationChangeDetector> map = context.getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 1);
Assertions.assertTrue(map.values().iterator().next().getClass()
.isAssignableFrom(KubernetesClientEventBasedConfigMapChangeDetector.class));
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is true by default
*
* - config map event watcher is picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void kubernetesReloadEnabledWithEvent() throws Exception {
void reloadEventEnabledMonitoringConfigMapsEnabled() {
setup("spring.cloud.kubernetes.reload.enabled=true", "spring.cloud.kubernetes.reload.mode=event",
"spring.main.cloud-platform=KUBERNETES");
assertThat(context.containsBean("configMapPropertyChangePollingWatcher")).isFalse();
assertThat(context.containsBean("secretsPropertyChangePollingWatcher")).isFalse();
assertThat(context.containsBean("configMapPropertyChangeEventWatcher")).isTrue();
assertThat(context.containsBean("secretsPropertyChangeEventWatcher")).isTrue();
Map<String, ConfigurationChangeDetector> map = context.getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 1);
Assertions.assertTrue(map.values().iterator().next().getClass()
.isAssignableFrom(KubernetesClientEventBasedConfigMapChangeDetector.class));
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is false
*
* - config map event watcher is not picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadEventEnabledMonitoringConfigMapsDisabled() {
setup("spring.cloud.kubernetes.reload.enabled=true", "spring.cloud.kubernetes.reload.mode=event",
"spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.reload.monitoring-configMaps=false");
Map<String, ConfigurationChangeDetector> map = context.getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 0);
}
/**
* <pre>
* - reload mode is enabled (via poll reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is false
*
* - config map event watcher is not picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadPollingEnabledMonitoringConfigMapsDisabledMonitoringSecretsDisabled() {
setup("spring.cloud.kubernetes.reload.enabled=true", "spring.cloud.kubernetes.reload.mode=polling",
"spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.reload.monitoring-configMaps=false");
Map<String, ConfigurationChangeDetector> map = context.getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 0);
}
/**
* <pre>
* - reload mode is enabled (via poll reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is true by default
*
* - config map event watcher is not picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - config map polling watcher is not picked up
* </pre>
*/
@Test
void reloadPollingEnabledMonitoringConfigMapsEnabled() {
setup("spring.cloud.kubernetes.reload.enabled=true", "spring.cloud.kubernetes.reload.mode=polling",
"spring.main.cloud-platform=KUBERNETES");
Map<String, ConfigurationChangeDetector> map = context.getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 1);
Assertions.assertTrue(
map.values().iterator().next().getClass().isAssignableFrom(PollingConfigMapChangeDetector.class));
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-secrets is true
* - spring.cloud.kubernetes.reload.monitoring-configMaps is false
*
* - config map event watcher is not picked up
* - config map polling watcher is not picked up
* - secrets event watcher is picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadEventEnabledMonitoringConfigMapsDisabledMonitoringSecretsEnabled() {
setup("spring.cloud.kubernetes.reload.enabled=true", "spring.main.cloud-platform=KUBERNETES",
"spring.cloud.kubernetes.reload.monitoring-secrets=true",
"spring.cloud.kubernetes.reload.monitoring-configMaps=false",
"spring.cloud.kubernetes.reload.mode=event");
Map<String, ConfigurationChangeDetector> map = context.getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 1);
Assertions.assertTrue(map.values().iterator().next().getClass()
.isAssignableFrom(KubernetesClientEventBasedSecretsChangeDetector.class));
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-secrets is true
* - spring.cloud.kubernetes.reload.monitoring-configMaps is false
*
* - config map event watcher is not picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is picked up
* </pre>
*/
@Test
void reloadPollingEnabledMonitoringConfigMapsDisabledMonitoringSecretsEnabled() {
setup("spring.cloud.kubernetes.reload.enabled=true", "spring.main.cloud-platform=KUBERNETES",
"spring.cloud.kubernetes.reload.monitoring-secrets=true",
"spring.cloud.kubernetes.reload.monitoring-configMaps=false",
"spring.cloud.kubernetes.reload.mode=polling");
Map<String, ConfigurationChangeDetector> map = context.getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 1);
Assertions.assertTrue(
map.values().iterator().next().getClass().isAssignableFrom(PollingSecretsChangeDetector.class));
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-secrets is true
* - spring.cloud.kubernetes.reload.monitoring-configMaps is true
*
* - config map event watcher is picked up
* - config map polling watcher is not picked up
* - secrets event watcher is picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadEventEnabledMonitoringConfigMapsEnabledMonitoringSecretsEnabled() {
setup("spring.cloud.kubernetes.reload.enabled=true", "spring.main.cloud-platform=KUBERNETES",
"spring.cloud.kubernetes.reload.monitoring-secrets=true",
"spring.cloud.kubernetes.reload.monitoring-configMaps=true",
"spring.cloud.kubernetes.reload.mode=event");
Map<String, ConfigurationChangeDetector> map = context.getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 2);
List<ConfigurationChangeDetector> result = map.values().stream()
.sorted(Comparator.comparing(x -> x.getClass().getName())).toList();
Assertions.assertEquals(result.get(0).getClass(), KubernetesClientEventBasedConfigMapChangeDetector.class);
Assertions.assertEquals(result.get(1).getClass(), KubernetesClientEventBasedSecretsChangeDetector.class);
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-secrets is true
* - spring.cloud.kubernetes.reload.monitoring-configMaps is true
*
* - config map event watcher is not picked up
* - config map polling watcher is picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is picked up
* </pre>
*/
@Test
void reloadPollingEnabledMonitoringConfigMapsEnabledMonitoringSecretsEnabled() {
setup("spring.cloud.kubernetes.reload.enabled=true", "spring.main.cloud-platform=KUBERNETES",
"spring.cloud.kubernetes.reload.monitoring-secrets=true",
"spring.cloud.kubernetes.reload.monitoring-configMaps=true",
"spring.cloud.kubernetes.reload.mode=polling");
Map<String, ConfigurationChangeDetector> map = context.getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 2);
List<ConfigurationChangeDetector> result = map.values().stream()
.sorted(Comparator.comparing(x -> x.getClass().getName())).toList();
Assertions.assertEquals(result.get(0).getClass(), PollingConfigMapChangeDetector.class);
Assertions.assertEquals(result.get(1).getClass(), PollingSecretsChangeDetector.class);
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is false
* - spring.cloud.kubernetes.reload.monitoring-secrets is false
*
* - config map event watcher is not picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadEventEnabledMonitoringConfigMapsDisabledMonitoringSecretsDisabled() {
setup("spring.cloud.kubernetes.reload.enabled=true", "spring.cloud.kubernetes.reload.mode=event",
"spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.reload.monitoring-configMaps=false",
"spring.cloud.kubernetes.reload.monitoring-secrets=false");
Map<String, ConfigurationChangeDetector> map = context.getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 0);
}
/**
* <pre>
* - reload mode is enabled (via poll reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is false
* - spring.cloud.kubernetes.reload.monitoring-secrets is false
*
* - config map event watcher is not picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadPollingEnabledMonitorConfigMapsDisabledMonitoringSecretsDisabled() {
setup("spring.cloud.kubernetes.reload.enabled=true", "spring.cloud.kubernetes.reload.mode=polling",
"spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.reload.monitoring-configMaps=false",
"spring.cloud.kubernetes.reload.monitoring-secrets=false");
Map<String, ConfigurationChangeDetector> map = context.getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 0);
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is true
* - spring.cloud.kubernetes.reload.monitoring-secrets is false
*
* - config map event watcher is picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadEventEnabledMonitoringConfigMapsEnabledMonitoringSecretsDisabled() {
setup("spring.cloud.kubernetes.reload.enabled=true", "spring.cloud.kubernetes.reload.mode=event",
"spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.reload.monitoring-configMaps=true",
"spring.cloud.kubernetes.reload.monitoring-secrets=false");
Map<String, ConfigurationChangeDetector> map = context.getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 1);
List<ConfigurationChangeDetector> result = map.values().stream()
.sorted(Comparator.comparing(x -> x.getClass().getName())).toList();
Assertions.assertEquals(result.get(0).getClass(), KubernetesClientEventBasedConfigMapChangeDetector.class);
}
/**
* <pre>
* - reload mode is enabled (via polling reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is true
* - spring.cloud.kubernetes.reload.monitoring-secrets is false
*
* - config map event watcher is not picked up
* - config map polling watcher is picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadPollingEnabledMonitoringConfigMapsEnabledMonitoringSecretsDisabled() {
setup("spring.cloud.kubernetes.reload.enabled=true", "spring.cloud.kubernetes.reload.mode=polling",
"spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.reload.monitoring-configMaps=true",
"spring.cloud.kubernetes.reload.monitoring-secrets=false");
Map<String, ConfigurationChangeDetector> map = context.getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 1);
List<ConfigurationChangeDetector> result = map.values().stream()
.sorted(Comparator.comparing(x -> x.getClass().getName())).toList();
Assertions.assertEquals(result.get(0).getClass(), PollingConfigMapChangeDetector.class);
}
// 2. config and secrets property source locators
@Test
void kubernetesConfigAndSecretEnabledByDefault() throws Exception {
void kubernetesConfigAndSecretEnabledByDefault() {
setup("spring.main.cloud-platform=KUBERNETES");
assertThat(context.containsBean("configMapPropertySourceLocator")).isTrue();
assertThat(context.containsBean("secretsPropertySourceLocator")).isTrue();
}
@Test
void kubernetesConfigEnabledButSecretDisabled() throws Exception {
void kubernetesConfigEnabledButSecretDisabled() {
setup("spring.cloud.kubernetes.secrets.enabled=false", "spring.main.cloud-platform=KUBERNETES");
assertThat(context.containsBean("configMapPropertySourceLocator")).isTrue();
assertThat(context.containsBean("secretsPropertySourceLocator")).isFalse();
}
@Test
void kubernetesSecretsEnabledButConfigDisabled() throws Exception {
void kubernetesSecretsEnabledButConfigDisabled() {
setup("spring.cloud.kubernetes.config.enabled=false", "spring.main.cloud-platform=KUBERNETES");
assertThat(context.containsBean("configMapPropertySourceLocator")).isFalse();
assertThat(context.containsBean("secretsPropertySourceLocator")).isTrue();

View File

@@ -0,0 +1,30 @@
/*
* 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.config.reload;
import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
/**
* @author wind57
*/
@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES)
@EnableConfigurationProperties(ConfigReloadProperties.class)
public class ConfigReloadPropertiesAutoConfiguration {
}

View File

@@ -0,0 +1,42 @@
/*
* 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.config.reload.condition;
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.ConditionalOnProperty;
/**
* Provides a more succinct conditional for:
* <code>spring.cloud.kubernetes.reload.monitoring-configMaps</code>.
*
* @author wind57
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@ConditionalOnProperty(name = "spring.cloud.kubernetes.reload.monitoring-configMaps", havingValue = "true",
matchIfMissing = true)
public @interface ConditionalOnConfigMapsReloadEnabled {
}

View File

@@ -0,0 +1,41 @@
/*
* 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.config.reload.condition;
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.ConditionalOnProperty;
/**
* Provides a more succinct conditional for:
* <code>spring.cloud.kubernetes.reload.monitoring-secrets</code>.
*
* @author wind57
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@ConditionalOnProperty(name = "spring.cloud.kubernetes.reload.monitoring-secrets", havingValue = "true")
public @interface ConditionalOnSecretsReloadEnabled {
}

View File

@@ -1,2 +1,3 @@
org.springframework.cloud.kubernetes.commons.KubernetesCommonsAutoConfiguration
org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadAutoConfiguration
org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadPropertiesAutoConfiguration

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2022 the original author or authors.
* 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.
@@ -23,21 +23,24 @@ import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfi
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
import org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration;
import org.springframework.cloud.commons.util.TaskSchedulerWrapper;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.cloud.context.restart.RestartEndpoint;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.config.ConditionalOnKubernetesAndConfigEnabled;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadAutoConfiguration;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadPropertiesAutoConfiguration;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationChangeDetector;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.commons.config.reload.PollingConfigMapChangeDetector;
import org.springframework.cloud.kubernetes.commons.config.reload.PollingSecretsChangeDetector;
import org.springframework.cloud.kubernetes.commons.config.reload.condition.ConditionalOnConfigMapsReloadEnabled;
import org.springframework.cloud.kubernetes.commons.config.reload.condition.ConditionalOnKubernetesReloadEnabled;
import org.springframework.cloud.kubernetes.commons.config.reload.condition.ConditionalOnSecretsReloadEnabled;
import org.springframework.cloud.kubernetes.commons.config.reload.condition.EventReloadDetectionMode;
import org.springframework.cloud.kubernetes.commons.config.reload.condition.PollingReloadDetectionMode;
import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySource;
@@ -58,12 +61,11 @@ import org.springframework.scheduling.TaskScheduler;
* @author Kris Iyer
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnKubernetesAndConfigEnabled
@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES)
@ConditionalOnKubernetesReloadEnabled
@ConditionalOnClass({ EndpointAutoConfiguration.class, RestartEndpoint.class, ContextRefresher.class })
@AutoConfigureAfter({ InfoEndpointAutoConfiguration.class, RefreshEndpointAutoConfiguration.class,
RefreshAutoConfiguration.class })
@EnableConfigurationProperties(ConfigReloadProperties.class)
RefreshAutoConfiguration.class, ConfigReloadPropertiesAutoConfiguration.class })
@Import(ConfigReloadAutoConfiguration.class)
public class Fabric8ConfigReloadAutoConfiguration {
@@ -75,6 +77,7 @@ public class Fabric8ConfigReloadAutoConfiguration {
* @return a bean that listen to configuration changes and fire a reload.
*/
@Bean
@ConditionalOnConfigMapsReloadEnabled
@ConditionalOnBean(Fabric8ConfigMapPropertySourceLocator.class)
@Conditional(PollingReloadDetectionMode.class)
public ConfigurationChangeDetector configMapPropertyChangePollingWatcher(ConfigReloadProperties properties,
@@ -95,6 +98,7 @@ public class Fabric8ConfigReloadAutoConfiguration {
* @return a bean that listen to configuration changes and fire a reload.
*/
@Bean
@ConditionalOnSecretsReloadEnabled
@ConditionalOnBean(Fabric8SecretsPropertySourceLocator.class)
@Conditional(PollingReloadDetectionMode.class)
public ConfigurationChangeDetector secretsPropertyChangePollingWatcher(ConfigReloadProperties properties,
@@ -114,6 +118,7 @@ public class Fabric8ConfigReloadAutoConfiguration {
* @return a bean that listen to configMap change events and fire a reload.
*/
@Bean
@ConditionalOnConfigMapsReloadEnabled
@ConditionalOnBean(Fabric8ConfigMapPropertySourceLocator.class)
@Conditional(EventReloadDetectionMode.class)
public ConfigurationChangeDetector configMapPropertyChangeEventWatcher(ConfigReloadProperties properties,
@@ -133,6 +138,7 @@ public class Fabric8ConfigReloadAutoConfiguration {
* @return a bean that listen to secrets change events and fire a reload.
*/
@Bean
@ConditionalOnSecretsReloadEnabled
@ConditionalOnBean(Fabric8SecretsPropertySourceLocator.class)
@Conditional(EventReloadDetectionMode.class)
public ConfigurationChangeDetector secretsPropertyChangeEventWatcher(ConfigReloadProperties properties,

View File

@@ -58,8 +58,6 @@ public class Fabric8EventBasedConfigMapChangeDetector extends ConfigurationChang
private final KubernetesClient kubernetesClient;
private final boolean monitoringConfigMaps;
private final List<SharedIndexInformer<ConfigMap>> informers = new ArrayList<>();
private final Set<String> namespaces;
@@ -74,31 +72,28 @@ public class Fabric8EventBasedConfigMapChangeDetector extends ConfigurationChang
this.kubernetesClient = kubernetesClient;
this.fabric8ConfigMapPropertySourceLocator = fabric8ConfigMapPropertySourceLocator;
this.enableReloadFiltering = properties.enableReloadFiltering();
monitoringConfigMaps = properties.monitoringConfigMaps();
namespaces = namespaces(kubernetesClient, namespaceProvider, properties, "configmap");
}
@PostConstruct
private void inform() {
if (monitoringConfigMaps) {
LOG.info("Kubernetes event-based configMap change detector activated");
LOG.info("Kubernetes event-based configMap change detector activated");
namespaces.forEach(namespace -> {
SharedIndexInformer<ConfigMap> informer;
if (enableReloadFiltering) {
informer = kubernetesClient.configMaps().inNamespace(namespace)
.withLabels(Map.of(ConfigReloadProperties.RELOAD_LABEL_FILTER, "true")).inform();
LOG.debug("added configmap informer for namespace : " + namespace + " with enabled filter");
}
else {
informer = kubernetesClient.configMaps().inNamespace(namespace).inform();
LOG.debug("added configmap informer for namespace : " + namespace);
}
namespaces.forEach(namespace -> {
SharedIndexInformer<ConfigMap> informer;
if (enableReloadFiltering) {
informer = kubernetesClient.configMaps().inNamespace(namespace)
.withLabels(Map.of(ConfigReloadProperties.RELOAD_LABEL_FILTER, "true")).inform();
LOG.debug("added configmap informer for namespace : " + namespace + " with enabled filter");
}
else {
informer = kubernetesClient.configMaps().inNamespace(namespace).inform();
LOG.debug("added configmap informer for namespace : " + namespace);
}
informer.addEventHandler(new ConfigMapInformerAwareEventHandler(informer));
informers.add(informer);
});
}
informer.addEventHandler(new ConfigMapInformerAwareEventHandler(informer));
informers.add(informer);
});
}
@PreDestroy

View File

@@ -58,8 +58,6 @@ public class Fabric8EventBasedSecretsChangeDetector extends ConfigurationChangeD
private final KubernetesClient kubernetesClient;
private final boolean monitorSecrets;
private final List<SharedIndexInformer<Secret>> informers = new ArrayList<>();
private final Set<String> namespaces;
@@ -74,7 +72,6 @@ public class Fabric8EventBasedSecretsChangeDetector extends ConfigurationChangeD
this.kubernetesClient = kubernetesClient;
this.fabric8SecretsPropertySourceLocator = fabric8SecretsPropertySourceLocator;
this.enableReloadFiltering = properties.enableReloadFiltering();
monitorSecrets = properties.monitoringSecrets();
namespaces = namespaces(kubernetesClient, namespaceProvider, properties, "secrets");
}
@@ -88,25 +85,23 @@ public class Fabric8EventBasedSecretsChangeDetector extends ConfigurationChangeD
@PostConstruct
private void inform() {
if (monitorSecrets) {
LOG.info("Kubernetes event-based secrets change detector activated");
LOG.info("Kubernetes event-based secrets change detector activated");
namespaces.forEach(namespace -> {
SharedIndexInformer<Secret> informer;
if (enableReloadFiltering) {
informer = kubernetesClient.secrets().inNamespace(namespace)
.withLabels(Map.of(ConfigReloadProperties.RELOAD_LABEL_FILTER, "true")).inform();
LOG.debug("added secret informer for namespace : " + namespace + " with enabled filter");
}
else {
informer = kubernetesClient.secrets().inNamespace(namespace).inform();
LOG.debug("added secret informer for namespace : " + namespace);
}
namespaces.forEach(namespace -> {
SharedIndexInformer<Secret> informer;
if (enableReloadFiltering) {
informer = kubernetesClient.secrets().inNamespace(namespace)
.withLabels(Map.of(ConfigReloadProperties.RELOAD_LABEL_FILTER, "true")).inform();
LOG.debug("added secret informer for namespace : " + namespace + " with enabled filter");
}
else {
informer = kubernetesClient.secrets().inNamespace(namespace).inform();
LOG.debug("added secret informer for namespace : " + namespace);
}
informer.addEventHandler(new SecretInformerAwareEventHandler(informer));
informers.add(informer);
});
}
informer.addEventHandler(new SecretInformerAwareEventHandler(informer));
informers.add(informer);
});
}
protected void onEvent(Secret secret) {

View File

@@ -21,10 +21,12 @@ import java.util.stream.Stream;
import org.junit.jupiter.api.AfterEach;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
import org.springframework.cloud.bootstrap.BootstrapConfiguration;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadPropertiesAutoConfiguration;
import org.springframework.cloud.kubernetes.fabric8.config.reload.Fabric8ConfigReloadAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
@@ -44,8 +46,8 @@ public class KubernetesConfigTestBase {
protected void setup(Class<?> mockClientConfiguration, String... env) {
String[] properties = Stream.concat(Arrays.stream(commonProperties), Arrays.stream(env)).toArray(String[]::new);
context = new SpringApplicationBuilder(PropertyPlaceholderAutoConfiguration.class, mockClientConfiguration,
BootstrapConfiguration.class, Fabric8ConfigReloadAutoConfiguration.class,
RefreshAutoConfiguration.class).web(org.springframework.boot.WebApplicationType.NONE)
BootstrapConfiguration.class, Fabric8ConfigReloadAutoConfiguration.class, ConfigReloadPropertiesAutoConfiguration.class,
RefreshAutoConfiguration.class).web(WebApplicationType.NONE)
.properties(properties).run();
}

View File

@@ -16,18 +16,25 @@
package org.springframework.cloud.kubernetes.fabric8.config.reload;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationChangeDetector;
import org.springframework.cloud.kubernetes.commons.config.reload.PollingConfigMapChangeDetector;
import org.springframework.cloud.kubernetes.commons.config.reload.PollingSecretsChangeDetector;
import org.springframework.cloud.kubernetes.fabric8.config.KubernetesConfigTestBase;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -41,7 +48,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* detector and update strategy beans won't be available.
**/
@EnableKubernetesMockClient(crud = true, https = false)
public class ConfigReloadAutoConfigurationTest extends KubernetesConfigTestBase {
class ConfigReloadAutoConfigurationTest extends KubernetesConfigTestBase {
private static final String APPLICATION_NAME = "application";
@@ -53,7 +60,7 @@ public class ConfigReloadAutoConfigurationTest extends KubernetesConfigTestBase
private static KubernetesClient mockClient;
@BeforeAll
public static void setUpBeforeClass() {
static void setUpBeforeClass() {
// Configure the kubernetes master url to point to the mock server
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.getConfiguration().getMasterUrl());
@@ -76,44 +83,330 @@ public class ConfigReloadAutoConfigurationTest extends KubernetesConfigTestBase
}
@BeforeEach
public void beforeEach() {
void beforeEach() {
commonProperties = new String[] { "spring.cloud.bootstrap.enabled=true" };
}
@Test
public void kubernetesConfigReloadDisabled() {
void kubernetesConfigReloadDisabled() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.reload.enabled=false");
assertThat(this.getContext().containsBean("configurationChangeDetector")).isFalse();
assertThat(this.getContext().containsBean("configurationUpdateStrategy")).isFalse();
}
@Test
public void kubernetesConfigReloadWhenKubernetesConfigDisabled() {
void kubernetesConfigReloadWhenKubernetesConfigDisabled() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.config.enabled=false");
assertThat(this.getContext().containsBean("configurationChangeDetector")).isFalse();
assertThat(this.getContext().containsBean("configurationUpdateStrategy")).isFalse();
}
@Test
public void kubernetesConfigReloadWhenKubernetesDisabled() {
void kubernetesConfigReloadWhenKubernetesDisabled() {
setup(KubernetesClientTestConfiguration.class);
assertThat(this.getContext().containsBean("configurationChangeDetector")).isFalse();
assertThat(this.getContext().containsBean("configurationUpdateStrategy")).isFalse();
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is true by default
*
* - config map event watcher is picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
public void kubernetesReloadEnabled() {
setup(KubernetesClientTestConfiguration.class, "spring.main.cloud-platform=KUBERNETES",
"spring.cloud.kubernetes.config.enabled=true", "spring.cloud.kubernetes.secrets.enabled=true",
"spring.cloud.kubernetes.reload.enabled=true");
assertThat(this.getContext().containsBean("configMapPropertySourceLocator")).isTrue();
assertThat(this.getContext().containsBean("secretsPropertySourceLocator")).isTrue();
assertThat(this.getContext().containsBean("configMapPropertyChangeEventWatcher")).isTrue();
assertThat(this.getContext().containsBean("secretsPropertyChangeEventWatcher")).isTrue();
void reloadEventEnabledMonitoringConfigMapsEnabledByDefault() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.reload.enabled=true",
"spring.main.cloud-platform=KUBERNETES");
Map<String, ConfigurationChangeDetector> map = getContext().getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 1);
Assertions.assertTrue(map.values().iterator().next().getClass()
.isAssignableFrom(Fabric8EventBasedConfigMapChangeDetector.class));
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is true by default
*
* - config map event watcher is picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadEventEnabledMonitoringConfigMapsEnabled() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.reload.enabled=true",
"spring.cloud.kubernetes.reload.mode=event", "spring.main.cloud-platform=KUBERNETES");
Map<String, ConfigurationChangeDetector> map = getContext().getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 1);
Assertions.assertTrue(map.values().iterator().next().getClass()
.isAssignableFrom(Fabric8EventBasedConfigMapChangeDetector.class));
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is false
*
* - config map event watcher is not picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadEventEnabledMonitoringConfigMapsDisabled() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.reload.enabled=true",
"spring.cloud.kubernetes.reload.mode=event", "spring.main.cloud-platform=KUBERNETES",
"spring.cloud.kubernetes.reload.monitoring-configMaps=false");
Map<String, ConfigurationChangeDetector> map = getContext().getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 0);
}
/**
* <pre>
* - reload mode is enabled (via poll reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is false
*
* - config map event watcher is not picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadPollingEnabledMonitoringConfigMapsDisabledMonitoringSecretsDisabled() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.reload.enabled=true",
"spring.cloud.kubernetes.reload.mode=polling", "spring.main.cloud-platform=KUBERNETES",
"spring.cloud.kubernetes.reload.monitoring-configMaps=false");
Map<String, ConfigurationChangeDetector> map = getContext().getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 0);
}
/**
* <pre>
* - reload mode is enabled (via poll reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is true by default
*
* - config map event watcher is not picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - config map polling watcher is not picked up
* </pre>
*/
@Test
void reloadPollingEnabledMonitoringConfigMapsEnabled() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.reload.enabled=true",
"spring.cloud.kubernetes.reload.mode=polling", "spring.main.cloud-platform=KUBERNETES");
Map<String, ConfigurationChangeDetector> map = getContext().getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 1);
Assertions.assertTrue(
map.values().iterator().next().getClass().isAssignableFrom(PollingConfigMapChangeDetector.class));
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-secrets is true
* - spring.cloud.kubernetes.reload.monitoring-configMaps is false
*
* - config map event watcher is not picked up
* - config map polling watcher is not picked up
* - secrets event watcher is picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadEventEnabledMonitoringConfigMapsDisabledMonitoringSecretsEnabled() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.reload.enabled=true",
"spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.reload.monitoring-secrets=true",
"spring.cloud.kubernetes.reload.monitoring-configMaps=false",
"spring.cloud.kubernetes.reload.mode=event");
Map<String, ConfigurationChangeDetector> map = getContext().getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 1);
Assertions.assertTrue(map.values().iterator().next().getClass()
.isAssignableFrom(Fabric8EventBasedSecretsChangeDetector.class));
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-secrets is true
* - spring.cloud.kubernetes.reload.monitoring-configMaps is false
*
* - config map event watcher is not picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is picked up
* </pre>
*/
@Test
void reloadPollingEnabledMonitoringConfigMapsDisabledMonitoringSecretsEnabled() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.reload.enabled=true",
"spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.reload.monitoring-secrets=true",
"spring.cloud.kubernetes.reload.monitoring-configMaps=false",
"spring.cloud.kubernetes.reload.mode=polling");
Map<String, ConfigurationChangeDetector> map = getContext().getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 1);
Assertions.assertTrue(
map.values().iterator().next().getClass().isAssignableFrom(PollingSecretsChangeDetector.class));
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-secrets is true
* - spring.cloud.kubernetes.reload.monitoring-configMaps is true
*
* - config map event watcher is picked up
* - config map polling watcher is not picked up
* - secrets event watcher is picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadEventEnabledMonitoringConfigMapsEnabledMonitoringSecretsEnabled() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.reload.enabled=true",
"spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.reload.monitoring-secrets=true",
"spring.cloud.kubernetes.reload.monitoring-configMaps=true",
"spring.cloud.kubernetes.reload.mode=event");
Map<String, ConfigurationChangeDetector> map = getContext().getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 2);
List<ConfigurationChangeDetector> result = map.values().stream()
.sorted(Comparator.comparing(x -> x.getClass().getName())).toList();
Assertions.assertEquals(result.get(0).getClass(), Fabric8EventBasedConfigMapChangeDetector.class);
Assertions.assertEquals(result.get(1).getClass(), Fabric8EventBasedSecretsChangeDetector.class);
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-secrets is true
* - spring.cloud.kubernetes.reload.monitoring-configMaps is true
*
* - config map event watcher is not picked up
* - config map polling watcher is picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is picked up
* </pre>
*/
@Test
void reloadPollingEnabledMonitoringConfigMapsEnabledMonitoringSecretsEnabled() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.reload.enabled=true",
"spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.reload.monitoring-secrets=true",
"spring.cloud.kubernetes.reload.monitoring-configMaps=true",
"spring.cloud.kubernetes.reload.mode=polling");
Map<String, ConfigurationChangeDetector> map = getContext().getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 2);
List<ConfigurationChangeDetector> result = map.values().stream()
.sorted(Comparator.comparing(x -> x.getClass().getName())).toList();
Assertions.assertEquals(result.get(0).getClass(), PollingConfigMapChangeDetector.class);
Assertions.assertEquals(result.get(1).getClass(), PollingSecretsChangeDetector.class);
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is false
* - spring.cloud.kubernetes.reload.monitoring-secrets is false
*
* - config map event watcher is not picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadEventEnabledMonitoringConfigMapsDisabledMonitoringSecretsDisabled() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.reload.enabled=true",
"spring.cloud.kubernetes.reload.mode=event", "spring.main.cloud-platform=KUBERNETES",
"spring.cloud.kubernetes.reload.monitoring-configMaps=false",
"spring.cloud.kubernetes.reload.monitoring-secrets=false");
Map<String, ConfigurationChangeDetector> map = getContext().getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 0);
}
/**
* <pre>
* - reload mode is enabled (via poll reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is false
* - spring.cloud.kubernetes.reload.monitoring-secrets is false
*
* - config map event watcher is not picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadPollingEnabledMonitorConfigMapsDisabledMonitoringSecretsDisabled() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.reload.enabled=true",
"spring.cloud.kubernetes.reload.mode=polling", "spring.main.cloud-platform=KUBERNETES",
"spring.cloud.kubernetes.reload.monitoring-configMaps=false",
"spring.cloud.kubernetes.reload.monitoring-secrets=false");
Map<String, ConfigurationChangeDetector> map = getContext().getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 0);
}
/**
* <pre>
* - reload mode is enabled (via event reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is true
* - spring.cloud.kubernetes.reload.monitoring-secrets is false
*
* - config map event watcher is picked up
* - config map polling watcher is not picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadEventEnabledMonitoringConfigMapsEnabledMonitoringSecretsDisabled() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.reload.enabled=true",
"spring.cloud.kubernetes.reload.mode=event", "spring.main.cloud-platform=KUBERNETES",
"spring.cloud.kubernetes.reload.monitoring-configMaps=true",
"spring.cloud.kubernetes.reload.monitoring-secrets=false");
Map<String, ConfigurationChangeDetector> map = getContext().getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 1);
List<ConfigurationChangeDetector> result = map.values().stream()
.sorted(Comparator.comparing(x -> x.getClass().getName())).toList();
Assertions.assertEquals(result.get(0).getClass(), Fabric8EventBasedConfigMapChangeDetector.class);
}
/**
* <pre>
* - reload mode is enabled (via polling reload)
* - spring.cloud.kubernetes.reload.monitoring-configMaps is true
* - spring.cloud.kubernetes.reload.monitoring-secrets is false
*
* - config map event watcher is not picked up
* - config map polling watcher is picked up
* - secrets event watcher is not picked up
* - secrets polling watcher is not picked up
* </pre>
*/
@Test
void reloadPollingEnabledMonitoringConfigMapsEnabledMonitoringSecretsDisabled() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.reload.enabled=true",
"spring.cloud.kubernetes.reload.mode=polling", "spring.main.cloud-platform=KUBERNETES",
"spring.cloud.kubernetes.reload.monitoring-configMaps=true",
"spring.cloud.kubernetes.reload.monitoring-secrets=false");
Map<String, ConfigurationChangeDetector> map = getContext().getBeansOfType(ConfigurationChangeDetector.class);
Assertions.assertEquals(map.size(), 1);
List<ConfigurationChangeDetector> result = map.values().stream()
.sorted(Comparator.comparing(x -> x.getClass().getName())).toList();
Assertions.assertEquals(result.get(0).getClass(), PollingConfigMapChangeDetector.class);
}
@Test
public void kubernetesReloadEnabledButSecretDisabled() {
void kubernetesReloadEnabledButSecretDisabled() {
setup(KubernetesClientTestConfiguration.class, "spring.main.cloud-platform=KUBERNETES",
"spring.cloud.kubernetes.config.enabled=true", "spring.cloud.kubernetes.secrets.enabled=false",
"spring.cloud.kubernetes.reload.enabled=true");
@@ -124,7 +417,7 @@ public class ConfigReloadAutoConfigurationTest extends KubernetesConfigTestBase
}
@Test
public void kubernetesReloadEnabledButSecretAndConfigDisabled() {
void kubernetesReloadEnabledButSecretAndConfigDisabled() {
setup(KubernetesClientTestConfiguration.class, "spring.cloud.kubernetes.config.enabled=false",
"spring.cloud.kubernetes.secrets.enabled=false", "spring.cloud.kubernetes.reload.enabled=true");
assertThat(this.getContext().containsBean("configMapPropertySourceLocator")).isFalse();

View File

@@ -94,6 +94,8 @@ class ConfigMapEventReloadIT {
@Test
void testInformFromOneNamespaceEventNotTriggered() throws Exception {
manifests("one", Phase.CREATE);
assertLogStatement(true, "added configmap informer for namespace");
assertLogStatement(false, "added secret informer for namespace");
WebClient webClient = builder().baseUrl("localhost/left").build();
String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
@@ -136,6 +138,8 @@ class ConfigMapEventReloadIT {
@Test
void testInformFromOneNamespaceEventTriggered() throws Exception {
manifests("two", Phase.CREATE);
assertLogStatement(true, "added configmap informer for namespace");
assertLogStatement(false, "added secret informer for namespace");
// read the value from the right-configmap
WebClient webClient = builder().baseUrl("localhost/right").build();
@@ -176,6 +180,10 @@ class ConfigMapEventReloadIT {
@Test
void testInform() throws Exception {
manifests("three", Phase.CREATE);
// wait a little for the logs to be available
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(10));
assertLogStatement(true, "added configmap informer for namespace");
assertLogStatement(false, "added secret informer for namespace");
// read the initial value from the right-configmap
WebClient rightWebClient = builder().baseUrl("localhost/right").build();
@@ -270,6 +278,23 @@ class ConfigMapEventReloadIT {
}
/**
* assert that only config map logs are present, not secrets.
*/
private void assertLogStatement(boolean contains, String log) throws Exception {
String appPodName = K3S
.execInContainer("kubectl", "get", "pods", "-l",
"app=spring-cloud-kubernetes-client-configmap-event-reload", "-o=name", "--no-headers")
.getStdout();
String allLogs = K3S.execInContainer("kubectl", "logs", appPodName.trim()).getStdout();
if (contains) {
Assertions.assertTrue(allLogs.contains(log));
}
else {
Assertions.assertFalse(allLogs.contains(log));
}
}
private WebClient.Builder builder() {
return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
}
@@ -278,7 +303,6 @@ class ConfigMapEventReloadIT {
return Retry.fixedDelay(120, Duration.ofSeconds(1)).filter(Objects::nonNull);
}
@SuppressWarnings({ "unchecked", "raw" })
private static void replaceConfigMap(V1ConfigMap configMap, String name) throws ApiException {
api.replaceNamespacedConfigMap(name, "right", configMap, null, null, null, null);
}

View File

@@ -29,3 +29,5 @@ spec:
env:
- name: SPRING_PROFILES_ACTIVE
value: one
- name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_CONFIG_RELOAD
value: DEBUG

View File

@@ -29,3 +29,5 @@ spec:
env:
- name: SPRING_PROFILES_ACTIVE
value: three
- name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_CONFIG_RELOAD
value: DEBUG

View File

@@ -29,3 +29,5 @@ spec:
env:
- name: SPRING_PROFILES_ACTIVE
value: two
- name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_CONFIG_RELOAD
value: DEBUG

View File

@@ -14,6 +14,7 @@ spring:
strategy: shutdown
mode: event
monitoring-secrets: true
monitoring-configMaps: false
secrets:
enabled: true
enable-api: true

View File

@@ -27,6 +27,7 @@ import io.kubernetes.client.openapi.models.V1Secret;
import io.kubernetes.client.openapi.models.V1Service;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.testcontainers.k3s.K3sContainer;
@@ -83,6 +84,8 @@ class SecretsEventReloadIT {
@Test
void testSecretReload() throws Exception {
configK8sClientIt(Phase.CREATE);
assertLogStatement(false, "added configmap informer for namespace");
assertLogStatement(true, "added secret informer for namespace");
testSecretEventReload();
}
@@ -122,6 +125,23 @@ class SecretsEventReloadIT {
}
}
/**
* assert that only config map logs are present, not secrets.
*/
private void assertLogStatement(boolean contains, String log) throws Exception {
String appPodName = K3S
.execInContainer("kubectl", "get", "pods", "-l",
"app=spring-cloud-kubernetes-client-secrets-event-reload", "-o=name", "--no-headers")
.getStdout();
String allLogs = K3S.execInContainer("kubectl", "logs", appPodName.trim()).getStdout();
if (contains) {
Assertions.assertTrue(allLogs.contains(log));
}
else {
Assertions.assertFalse(allLogs.contains(log));
}
}
private WebClient.Builder builder() {
return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
}

View File

@@ -26,3 +26,6 @@ spec:
path: /actuator/health/liveness
ports:
- containerPort: 8080
env:
- name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_CONFIG_RELOAD
value: DEBUG

View File

@@ -100,6 +100,8 @@ class ConfigMapEventReloadIT {
@Test
void testInformFromOneNamespaceEventNotTriggered() {
manifests("one", Phase.CREATE);
assertLogStatement(true, "added configmap informer for namespace");
assertLogStatement(false, "added secret informer for namespace");
WebClient webClient = builder().baseUrl("localhost/left").build();
String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
@@ -142,6 +144,8 @@ class ConfigMapEventReloadIT {
@Test
void testInformFromOneNamespaceEventTriggered() {
manifests("two", Phase.CREATE);
assertLogStatement(true, "added configmap informer for namespace");
assertLogStatement(false, "added secret informer for namespace");
// read the value from the right-configmap
WebClient webClient = builder().baseUrl("localhost/right").build();
@@ -181,6 +185,8 @@ class ConfigMapEventReloadIT {
@Test
void testInform() {
manifests("three", Phase.CREATE);
assertLogStatement(true, "added configmap informer for namespace");
assertLogStatement(false, "added secret informer for namespace");
// read the initial value from the right-configmap
WebClient rightWebClient = builder().baseUrl("localhost/right").build();
@@ -282,6 +288,24 @@ class ConfigMapEventReloadIT {
}
private void assertLogStatement(boolean contains, String log) {
try {
String appPodName = K3S.execInContainer("kubectl", "get", "pods", "-l",
"app=spring-cloud-kubernetes-fabric8-client-configmap-event-reload", "-o=name", "--no-headers")
.getStdout();
String allLogs = K3S.execInContainer("kubectl", "logs", appPodName.trim()).getStdout();
if (contains) {
Assertions.assertTrue(allLogs.contains(log));
}
else {
Assertions.assertFalse(allLogs.contains(log));
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private WebClient.Builder builder() {
return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
}

View File

@@ -26,3 +26,6 @@ spec:
path: /actuator/health/liveness
ports:
- containerPort: 8080
env:
- name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_FABRIC8_CONFIG_RELOAD
value: DEBUG

View File

@@ -14,6 +14,7 @@ spring:
monitoring-secrets: true
strategy: shutdown
mode: event
monitoring-configMaps: false
secrets:
enabled: true
enable-api: true

View File

@@ -82,6 +82,8 @@ class SecretsEventsReloadIT {
@Test
void test() {
assertLogStatement(false, "added configmap informer for namespace");
assertLogStatement(true, "added secret informer for namespace");
WebClient webClient = builder().baseUrl("localhost/key").build();
String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
.block();
@@ -127,6 +129,27 @@ class SecretsEventsReloadIT {
}
/**
* assert that only config map logs are present, not secrets.
*/
private void assertLogStatement(boolean contains, String log) {
try {
String appPodName = K3S.execInContainer("kubectl", "get", "pods", "-l",
"app=spring-cloud-kubernetes-fabric8-client-secrets-event-reload", "-o=name", "--no-headers")
.getStdout();
String allLogs = K3S.execInContainer("kubectl", "logs", appPodName.trim()).getStdout();
if (contains) {
Assertions.assertTrue(allLogs.contains(log));
}
else {
Assertions.assertFalse(allLogs.contains(log));
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private WebClient.Builder builder() {
return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
}

View File

@@ -26,3 +26,6 @@ spec:
path: /actuator/health/liveness
ports:
- containerPort: 8080
env:
- name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_FABRIC8_CONFIG_RELOAD
value: DEBUG