Skip to content

Commit

Permalink
Reload functionality clean-up part 4 (#1036)
Browse files Browse the repository at this point in the history
  • Loading branch information
wind57 authored Jul 7, 2022
1 parent 2ed17de commit 797af02
Show file tree
Hide file tree
Showing 46 changed files with 1,812 additions and 311 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
import org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration;
Expand All @@ -42,113 +41,106 @@
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.ConditionalOnKubernetesReloadEnabled;
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;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.scheduling.TaskScheduler;

/**
* @author Ryan Baxter
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnKubernetesAndConfigEnabled
@ConditionalOnClass(EndpointAutoConfiguration.class)
@ConditionalOnKubernetesReloadEnabled
@ConditionalOnClass({ EndpointAutoConfiguration.class, RestartEndpoint.class, ContextRefresher.class })
@AutoConfigureAfter({ InfoEndpointAutoConfiguration.class, RefreshEndpointAutoConfiguration.class,
RefreshAutoConfiguration.class })
@Import(ConfigReloadAutoConfiguration.class)
@EnableConfigurationProperties(ConfigReloadProperties.class)
@Import(ConfigReloadAutoConfiguration.class)
public class KubernetesClientConfigReloadAutoConfiguration {

/**
* Configuration reload must be enabled explicitly.
* Polling configMap ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
* @param configMapPropertySourceLocator configMap property source locator
* @return a bean that listen to configuration changes and fire a reload.
*/
@ConditionalOnProperty("spring.cloud.kubernetes.reload.enabled")
@ConditionalOnClass({ RestartEndpoint.class, ContextRefresher.class })
protected static class ConfigReloadAutoConfigurationBeans {

/**
* Polling configMap ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
* @param configMapPropertySourceLocator configMap property source locator
* @return a bean that listen to configuration changes and fire a reload.
*/
@Bean
@ConditionalOnBean(KubernetesClientConfigMapPropertySourceLocator.class)
@Conditional(PollingReloadDetectionMode.class)
public ConfigurationChangeDetector configMapPropertyChangePollingWatcher(ConfigReloadProperties properties,
ConfigurationUpdateStrategy strategy,
KubernetesClientConfigMapPropertySourceLocator configMapPropertySourceLocator,
AbstractEnvironment environment, TaskSchedulerWrapper taskScheduler) {

return new PollingConfigMapChangeDetector(environment, properties, strategy,
KubernetesClientConfigMapPropertySource.class, configMapPropertySourceLocator,
taskScheduler.getTaskScheduler());
}
@Bean
@ConditionalOnBean(KubernetesClientConfigMapPropertySourceLocator.class)
@Conditional(PollingReloadDetectionMode.class)
public ConfigurationChangeDetector configMapPropertyChangePollingWatcher(ConfigReloadProperties properties,
ConfigurationUpdateStrategy strategy,
KubernetesClientConfigMapPropertySourceLocator configMapPropertySourceLocator,
AbstractEnvironment environment, TaskSchedulerWrapper<TaskScheduler> taskScheduler) {

/**
* Polling secrets ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
* @param secretsPropertySourceLocator secrets property source locator
* @return a bean that listen to configuration changes and fire a reload.
*/
@Bean
@ConditionalOnBean(KubernetesClientSecretsPropertySourceLocator.class)
@Conditional(PollingReloadDetectionMode.class)
public ConfigurationChangeDetector secretsPropertyChangePollingWatcher(ConfigReloadProperties properties,
ConfigurationUpdateStrategy strategy,
KubernetesClientSecretsPropertySourceLocator secretsPropertySourceLocator,
AbstractEnvironment environment, TaskSchedulerWrapper taskScheduler) {
return new PollingConfigMapChangeDetector(environment, properties, strategy,
KubernetesClientConfigMapPropertySource.class, configMapPropertySourceLocator,
taskScheduler.getTaskScheduler());
}

return new PollingSecretsChangeDetector(environment, properties, strategy,
KubernetesClientSecretsPropertySource.class, secretsPropertySourceLocator,
taskScheduler.getTaskScheduler());
}
/**
* Polling secrets ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
* @param secretsPropertySourceLocator secrets property source locator
* @return a bean that listen to configuration changes and fire a reload.
*/
@Bean
@ConditionalOnBean(KubernetesClientSecretsPropertySourceLocator.class)
@Conditional(PollingReloadDetectionMode.class)
public ConfigurationChangeDetector secretsPropertyChangePollingWatcher(ConfigReloadProperties properties,
ConfigurationUpdateStrategy strategy,
KubernetesClientSecretsPropertySourceLocator secretsPropertySourceLocator, AbstractEnvironment environment,
TaskSchedulerWrapper<TaskScheduler> taskScheduler) {

/**
* Event Based configMap ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
* @param configMapPropertySourceLocator configMap property source locator
* @return a bean that listen to configMap change events and fire a reload.
*/
@Bean
@ConditionalOnBean(KubernetesClientConfigMapPropertySourceLocator.class)
@Conditional(EventReloadDetectionMode.class)
public ConfigurationChangeDetector configMapPropertyChangeEventWatcher(ConfigReloadProperties properties,
ConfigurationUpdateStrategy strategy,
KubernetesClientConfigMapPropertySourceLocator configMapPropertySourceLocator,
AbstractEnvironment environment, CoreV1Api coreV1Api,
KubernetesNamespaceProvider kubernetesNamespaceProvider) {
return new PollingSecretsChangeDetector(environment, properties, strategy,
KubernetesClientSecretsPropertySource.class, secretsPropertySourceLocator,
taskScheduler.getTaskScheduler());
}

return new KubernetesClientEventBasedConfigMapChangeDetector(coreV1Api, environment, properties, strategy,
configMapPropertySourceLocator, kubernetesNamespaceProvider);
}
/**
* Event Based configMap ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
* @param configMapPropertySourceLocator configMap property source locator
* @return a bean that listen to configMap change events and fire a reload.
*/
@Bean
@ConditionalOnBean(KubernetesClientConfigMapPropertySourceLocator.class)
@Conditional(EventReloadDetectionMode.class)
public ConfigurationChangeDetector configMapPropertyChangeEventWatcher(ConfigReloadProperties properties,
ConfigurationUpdateStrategy strategy,
KubernetesClientConfigMapPropertySourceLocator configMapPropertySourceLocator,
AbstractEnvironment environment, CoreV1Api coreV1Api,
KubernetesNamespaceProvider kubernetesNamespaceProvider) {

/**
* Event Based secrets ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
* @param secretsPropertySourceLocator secrets property source locator
* @return a bean that listen to secrets change events and fire a reload.
*/
@Bean
@ConditionalOnBean(KubernetesClientSecretsPropertySourceLocator.class)
@Conditional(EventReloadDetectionMode.class)
public ConfigurationChangeDetector secretsPropertyChangeEventWatcher(ConfigReloadProperties properties,
ConfigurationUpdateStrategy strategy,
KubernetesClientSecretsPropertySourceLocator secretsPropertySourceLocator,
AbstractEnvironment environment, CoreV1Api coreV1Api,
KubernetesNamespaceProvider kubernetesNamespaceProvider) {
return new KubernetesClientEventBasedConfigMapChangeDetector(coreV1Api, environment, properties, strategy,
configMapPropertySourceLocator, kubernetesNamespaceProvider);
}

return new KubernetesClientEventBasedSecretsChangeDetector(coreV1Api, environment, properties, strategy,
secretsPropertySourceLocator, kubernetesNamespaceProvider);
}
/**
* Event Based secrets ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
* @param secretsPropertySourceLocator secrets property source locator
* @return a bean that listen to secrets change events and fire a reload.
*/
@Bean
@ConditionalOnBean(KubernetesClientSecretsPropertySourceLocator.class)
@Conditional(EventReloadDetectionMode.class)
public ConfigurationChangeDetector secretsPropertyChangeEventWatcher(ConfigReloadProperties properties,
ConfigurationUpdateStrategy strategy,
KubernetesClientSecretsPropertySourceLocator secretsPropertySourceLocator, AbstractEnvironment environment,
CoreV1Api coreV1Api, KubernetesNamespaceProvider kubernetesNamespaceProvider) {

return new KubernetesClientEventBasedSecretsChangeDetector(coreV1Api, environment, properties, strategy,
secretsPropertySourceLocator, kubernetesNamespaceProvider);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,9 @@
import io.kubernetes.client.util.CallGeneratorParams;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySource;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator;
import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationChangeDetector;
Expand All @@ -44,17 +41,15 @@
*/
public class KubernetesClientEventBasedConfigMapChangeDetector extends ConfigurationChangeDetector {

private static final Log LOG = LogFactory.getLog(KubernetesClientEventBasedConfigMapChangeDetector.class);

private CoreV1Api coreV1Api = null;
private final CoreV1Api coreV1Api;

private final KubernetesClientConfigMapPropertySourceLocator propertySourceLocator;

private final SharedInformerFactory factory;

private KubernetesClientProperties kubernetesClientProperties;
private final String namespace;

private KubernetesNamespaceProvider kubernetesNamespaceProvider;
private final boolean monitorConfigMaps;

public KubernetesClientEventBasedConfigMapChangeDetector(CoreV1Api coreV1Api, ConfigurableEnvironment environment,
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
Expand All @@ -71,38 +66,33 @@ public KubernetesClientEventBasedConfigMapChangeDetector(CoreV1Api coreV1Api, Co
// 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.kubernetesNamespaceProvider = kubernetesNamespaceProvider;
}

private String getNamespace() {
return kubernetesNamespaceProvider != null ? kubernetesNamespaceProvider.getNamespace()
: kubernetesClientProperties.getNamespace();
this.namespace = kubernetesNamespaceProvider.getNamespace();
this.monitorConfigMaps = properties.isMonitoringConfigMaps();
}

@PostConstruct
public void watch() {
if (coreV1Api != null && this.properties.isMonitoringConfigMaps()) {
if (coreV1Api != null && monitorConfigMaps) {
SharedIndexInformer<V1ConfigMap> configMapInformer = factory.sharedIndexInformerFor(
(CallGeneratorParams params) -> coreV1Api.listNamespacedConfigMapCall(getNamespace(), null, null,
null, null, null, null, params.resourceVersion, null, params.timeoutSeconds, params.watch,
null),
(CallGeneratorParams params) -> coreV1Api.listNamespacedConfigMapCall(namespace, null, null, null,
null, null, null, params.resourceVersion, null, params.timeoutSeconds, params.watch, null),
V1ConfigMap.class, V1ConfigMapList.class);
configMapInformer.addEventHandler(new ResourceEventHandler<V1ConfigMap>() {
configMapInformer.addEventHandler(new ResourceEventHandler<>() {
@Override
public void onAdd(V1ConfigMap obj) {
LOG.info("CongifMap " + obj.getMetadata().getName() + " was added.");
log.info("ConfigMap " + obj.getMetadata().getName() + " was added.");
onEvent(obj);
}

@Override
public void onUpdate(V1ConfigMap oldObj, V1ConfigMap newObj) {
LOG.info("ConfigMap " + newObj.getMetadata().getName() + " was added.");
log.info("ConfigMap " + newObj.getMetadata().getName() + " was added.");
onEvent(newObj);
}

@Override
public void onDelete(V1ConfigMap obj, boolean deletedFinalStateUnknown) {
LOG.info("ConfigMap " + obj.getMetadata() + " was deleted.");
log.info("ConfigMap " + obj.getMetadata() + " was deleted.");
onEvent(obj);
}
});
Expand All @@ -116,15 +106,15 @@ public void unwatch() {
}

private void onEvent(V1ConfigMap configMap) {
this.log.debug(String.format("onEvent configMap: %s", configMap.toString()));
log.debug("onEvent configMap: " + configMap.toString());
boolean changed = changed(locateMapPropertySources(this.propertySourceLocator, this.environment),
findPropertySources(KubernetesClientConfigMapPropertySource.class));
if (changed) {
LOG.info("Configuration change detected, reloading properties.");
log.info("Configuration change detected, reloading properties.");
reloadProperties();
}
else {
LOG.warn("Configuration change was not detected.");
log.warn("Configuration change was not detected.");
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,9 @@
import io.kubernetes.client.openapi.models.V1SecretList;
import io.kubernetes.client.util.CallGeneratorParams;
import jakarta.annotation.PostConstruct;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySource;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator;
import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationChangeDetector;
Expand All @@ -43,17 +40,15 @@
*/
public class KubernetesClientEventBasedSecretsChangeDetector extends ConfigurationChangeDetector {

private static final Log LOG = LogFactory.getLog(KubernetesClientEventBasedSecretsChangeDetector.class);

private CoreV1Api coreV1Api;
private final CoreV1Api coreV1Api;

private final KubernetesClientSecretsPropertySourceLocator propertySourceLocator;

private final SharedInformerFactory factory;

private KubernetesClientProperties kubernetesClientProperties;
private final String namespace;

private KubernetesNamespaceProvider kubernetesNamespaceProvider;
private final boolean monitorSecrets;

public KubernetesClientEventBasedSecretsChangeDetector(CoreV1Api coreV1Api, ConfigurableEnvironment environment,
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
Expand All @@ -70,37 +65,33 @@ public KubernetesClientEventBasedSecretsChangeDetector(CoreV1Api coreV1Api, Conf
// See https://github.com/spring-cloud/spring-cloud-kubernetes/issues/885
this.factory = new SharedInformerFactory(createApiClientForInformerClient());
this.coreV1Api = coreV1Api;
this.kubernetesNamespaceProvider = kubernetesNamespaceProvider;
}

private String getNamespace() {
return kubernetesNamespaceProvider != null ? kubernetesNamespaceProvider.getNamespace()
: kubernetesClientProperties.getNamespace();
this.namespace = kubernetesNamespaceProvider.getNamespace();
this.monitorSecrets = properties.isMonitoringSecrets();
}

@PostConstruct
public void watch() {
if (coreV1Api != null && this.properties.isMonitoringSecrets()) {
if (coreV1Api != null && monitorSecrets) {
SharedIndexInformer<V1Secret> configMapInformer = factory.sharedIndexInformerFor(
(CallGeneratorParams params) -> coreV1Api.listNamespacedSecretCall(getNamespace(), null, null, null,
(CallGeneratorParams params) -> coreV1Api.listNamespacedSecretCall(namespace, null, null, null,
null, null, null, params.resourceVersion, null, params.timeoutSeconds, params.watch, null),
V1Secret.class, V1SecretList.class);
configMapInformer.addEventHandler(new ResourceEventHandler<V1Secret>() {
configMapInformer.addEventHandler(new ResourceEventHandler<>() {
@Override
public void onAdd(V1Secret obj) {
LOG.info("Secret " + obj.getMetadata().getName() + " was added.");
log.info("Secret " + obj.getMetadata().getName() + " was added.");
onEvent(obj);
}

@Override
public void onUpdate(V1Secret oldObj, V1Secret newObj) {
LOG.info("Secret " + newObj.getMetadata().getName() + " was added.");
log.info("Secret " + newObj.getMetadata().getName() + " was added.");
onEvent(newObj);
}

@Override
public void onDelete(V1Secret obj, boolean deletedFinalStateUnknown) {
LOG.info("Secret " + obj.getMetadata() + " was deleted.");
log.info("Secret " + obj.getMetadata() + " was deleted.");
onEvent(obj);
}
});
Expand All @@ -109,11 +100,11 @@ public void onDelete(V1Secret obj, boolean deletedFinalStateUnknown) {
}

private void onEvent(V1Secret secret) {
this.log.debug(String.format("onEvent configMap: %s", secret.toString()));
log.debug("onEvent configMap: " + secret.toString());
boolean changed = changed(locateMapPropertySources(this.propertySourceLocator, this.environment),
findPropertySources(KubernetesClientSecretsPropertySource.class));
if (changed) {
this.log.info("Detected change in secrets");
log.info("Detected change in secrets");
reloadProperties();
}
}
Expand Down
Loading

0 comments on commit 797af02

Please sign in to comment.