Don't configure reload beans unless the properties are set (#1200)
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -29,3 +29,5 @@ spec:
|
||||
env:
|
||||
- name: SPRING_PROFILES_ACTIVE
|
||||
value: one
|
||||
- name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_CONFIG_RELOAD
|
||||
value: DEBUG
|
||||
|
||||
@@ -29,3 +29,5 @@ spec:
|
||||
env:
|
||||
- name: SPRING_PROFILES_ACTIVE
|
||||
value: three
|
||||
- name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_CONFIG_RELOAD
|
||||
value: DEBUG
|
||||
|
||||
@@ -29,3 +29,5 @@ spec:
|
||||
env:
|
||||
- name: SPRING_PROFILES_ACTIVE
|
||||
value: two
|
||||
- name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_CONFIG_RELOAD
|
||||
value: DEBUG
|
||||
|
||||
@@ -14,6 +14,7 @@ spring:
|
||||
strategy: shutdown
|
||||
mode: event
|
||||
monitoring-secrets: true
|
||||
monitoring-configMaps: false
|
||||
secrets:
|
||||
enabled: true
|
||||
enable-api: true
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -14,6 +14,7 @@ spring:
|
||||
monitoring-secrets: true
|
||||
strategy: shutdown
|
||||
mode: event
|
||||
monitoring-configMaps: false
|
||||
secrets:
|
||||
enabled: true
|
||||
enable-api: true
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user