Move config-watcher to use k8s java client (#1055)

* Move config-watcher to use k8s java client
This commit is contained in:
Ryan Baxter
2022-08-01 12:23:08 -04:00
committed by GitHub
parent 91cea9feb0
commit 85a31ca39a
15 changed files with 245 additions and 223 deletions

View File

@@ -64,19 +64,19 @@ public class KubernetesClientEventBasedConfigMapChangeDetector extends Configura
@Override
public void onAdd(V1ConfigMap obj) {
log.debug("ConfigMap " + obj.getMetadata().getName() + " was added.");
log.debug(() -> "ConfigMap " + obj.getMetadata().getName() + " was added.");
onEvent(obj);
}
@Override
public void onUpdate(V1ConfigMap oldObj, V1ConfigMap newObj) {
log.debug("ConfigMap " + newObj.getMetadata().getName() + " was updated.");
log.debug(() -> "ConfigMap " + newObj.getMetadata().getName() + " was updated.");
onEvent(newObj);
}
@Override
public void onDelete(V1ConfigMap obj, boolean deletedFinalStateUnknown) {
log.debug("ConfigMap " + obj.getMetadata() + " was deleted.");
log.debug(() -> "ConfigMap " + obj.getMetadata() + " was deleted.");
onEvent(obj);
}
};
@@ -104,7 +104,7 @@ public class KubernetesClientEventBasedConfigMapChangeDetector extends Configura
@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;
@@ -112,10 +112,10 @@ public class KubernetesClientEventBasedConfigMapChangeDetector extends Configura
if (enableReloadFiltering) {
filter = ConfigReloadProperties.RELOAD_LABEL_FILTER + "=true";
log.debug("added configmap informer for namespace : " + namespace + " with enabled filter");
log.debug(() -> "added configmap informer for namespace : " + namespace + " with enabled filter");
}
else {
log.debug("added configmap informer for namespace : " + namespace);
log.debug(() -> "added configmap informer for namespace : " + namespace);
}
String filterOnInformerLabel = filter;
@@ -139,16 +139,16 @@ public class KubernetesClientEventBasedConfigMapChangeDetector extends Configura
factory.stopAllRegisteredInformers();
}
private void onEvent(V1ConfigMap configMap) {
log.debug("onEvent configMap: " + configMap.toString());
protected void onEvent(V1ConfigMap configMap) {
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.");
}
}

View File

@@ -64,19 +64,19 @@ public class KubernetesClientEventBasedSecretsChangeDetector extends Configurati
@Override
public void onAdd(V1Secret obj) {
log.debug("Secret " + obj.getMetadata().getName() + " was added.");
log.debug(() -> "Secret " + obj.getMetadata().getName() + " was added.");
onEvent(obj);
}
@Override
public void onUpdate(V1Secret oldObj, V1Secret newObj) {
log.debug("Secret " + newObj.getMetadata().getName() + " was updated.");
log.debug(() -> "Secret " + newObj.getMetadata().getName() + " was updated.");
onEvent(newObj);
}
@Override
public void onDelete(V1Secret obj, boolean deletedFinalStateUnknown) {
log.debug("Secret " + obj.getMetadata() + " was deleted.");
log.debug(() -> "Secret " + obj.getMetadata() + " was deleted.");
onEvent(obj);
}
};
@@ -104,7 +104,7 @@ public class KubernetesClientEventBasedSecretsChangeDetector extends Configurati
@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;
@@ -112,10 +112,10 @@ public class KubernetesClientEventBasedSecretsChangeDetector extends Configurati
if (enableReloadFiltering) {
filter = ConfigReloadProperties.RELOAD_LABEL_FILTER + "=true";
log.debug("added secret informer for namespace : " + namespace + " with enabled filter");
log.debug(() -> "added secret informer for namespace : " + namespace + " with enabled filter");
}
else {
log.debug("added secret informer for namespace : " + namespace);
log.debug(() -> "added secret informer for namespace : " + namespace);
}
String filterOnInformerLabel = filter;
@@ -138,12 +138,12 @@ public class KubernetesClientEventBasedSecretsChangeDetector extends Configurati
factory.stopAllRegisteredInformers();
}
private void onEvent(V1Secret secret) {
log.debug("onEvent secret: " + secret.toString());
protected void onEvent(V1Secret secret) {
log.debug(() -> "onEvent secret: " + secret.toString());
boolean changed = changed(locateMapPropertySources(this.propertySourceLocator, this.environment),
findPropertySources(KubernetesClientSecretsPropertySource.class));
if (changed) {
log.info("Detected change in secrets");
log.info(() -> "Detected change in secrets");
reloadProperties();
}
}

View File

@@ -22,7 +22,6 @@ import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.bootstrap.config.BootstrapPropertySource;
@@ -32,6 +31,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.log.LogAccessor;
/**
* This is the superclass of all beans that can listen to changes in the configuration and
@@ -41,7 +41,7 @@ import org.springframework.core.env.PropertySource;
*/
public abstract class ConfigurationChangeDetector {
protected Log log = LogFactory.getLog(getClass());
protected LogAccessor log = new LogAccessor(LogFactory.getLog(this.getClass()));
protected ConfigurableEnvironment environment;
@@ -57,21 +57,21 @@ public abstract class ConfigurationChangeDetector {
}
public void reloadProperties() {
log.info("Reloading using strategy: " + this.strategy.name());
log.info(() -> "Reloading using strategy: " + this.strategy.name());
strategy.reloadProcedure().run();
}
public boolean changed(List<? extends MapPropertySource> left, List<? extends MapPropertySource> right) {
if (left.size() != right.size()) {
log.warn("The current number of ConfigMap PropertySources does not match "
log.warn(() -> "The current number of ConfigMap PropertySources does not match "
+ "the ones loaded from the Kubernetes - No reload will take place");
if (log.isDebugEnabled()) {
log.debug("left size: " + left.size());
left.forEach(item -> log.debug(item));
left.forEach(item -> log.debug(item.toString()));
log.debug("right size: " + right.size());
right.forEach(item -> log.debug(item));
right.forEach(item -> log.debug(item.toString()));
}
return false;
}
@@ -94,8 +94,8 @@ public abstract class ConfigurationChangeDetector {
List<PropertySource<?>> sources = environment.getPropertySources().stream()
.collect(Collectors.toCollection(ArrayList::new));
log.debug("environment: " + environment);
log.debug("environment sources: " + sources);
log.debug(() -> "environment: " + environment);
log.debug(() -> "environment sources: " + sources);
while (!sources.isEmpty()) {
PropertySource<?> source = sources.remove(0);
@@ -140,11 +140,11 @@ public abstract class ConfigurationChangeDetector {
result.addAll(list);
}
else {
log.debug("Found property source that cannot be handled: " + propertySource.getClass());
log.debug(() -> "Found property source that cannot be handled: " + propertySource.getClass());
}
log.debug("environment: " + environment);
log.debug("sources: " + result);
log.debug(() -> "environment: " + environment);
log.debug(() -> "sources: " + result);
return result;
}

View File

@@ -21,15 +21,7 @@
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8-all</artifactId>
<artifactId>spring-cloud-starter-kubernetes-client-all</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>

View File

@@ -16,19 +16,20 @@
package org.springframework.cloud.kubernetes.configuration.watcher;
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1ConfigMap;
import reactor.core.publisher.Mono;
import org.springframework.cloud.bus.BusProperties;
import org.springframework.cloud.bus.event.PathDestinationFactory;
import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
@@ -42,19 +43,19 @@ public class BusEventBasedConfigMapWatcherChangeDetector extends ConfigMapWatche
private final BusProperties busProperties;
public BusEventBasedConfigMapWatcherChangeDetector(AbstractEnvironment environment,
ConfigReloadProperties properties, KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator, BusProperties busProperties,
public BusEventBasedConfigMapWatcherChangeDetector(CoreV1Api coreV1Api, ConfigurableEnvironment environment,
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
KubernetesClientConfigMapPropertySourceLocator propertySourceLocator,
KubernetesNamespaceProvider kubernetesNamespaceProvider, BusProperties busProperties,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadPoolTaskExecutor) {
super(environment, properties, kubernetesClient, strategy, fabric8ConfigMapPropertySourceLocator,
super(coreV1Api, environment, properties, strategy, propertySourceLocator, kubernetesNamespaceProvider,
k8SConfigurationProperties, threadPoolTaskExecutor);
this.busProperties = busProperties;
}
@Override
protected Mono<Void> triggerRefresh(ConfigMap configMap) {
protected Mono<Void> triggerRefresh(V1ConfigMap configMap) {
this.applicationEventPublisher.publishEvent(new RefreshRemoteApplicationEvent(configMap, busProperties.getId(),
new PathDestinationFactory().getDestination(configMap.getMetadata().getName())));
return Mono.empty();

View File

@@ -16,19 +16,20 @@
package org.springframework.cloud.kubernetes.configuration.watcher;
import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1Secret;
import reactor.core.publisher.Mono;
import org.springframework.cloud.bus.BusProperties;
import org.springframework.cloud.bus.event.PathDestinationFactory;
import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
@@ -42,19 +43,19 @@ public class BusEventBasedSecretsWatcherChangeDetector extends SecretsWatcherCha
private final BusProperties busProperties;
public BusEventBasedSecretsWatcherChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator, BusProperties busProperties,
public BusEventBasedSecretsWatcherChangeDetector(CoreV1Api coreV1Api, ConfigurableEnvironment environment,
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
KubernetesClientSecretsPropertySourceLocator propertySourceLocator,
KubernetesNamespaceProvider kubernetesNamespaceProvider, BusProperties busProperties,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadPoolTaskExecutor) {
super(environment, properties, kubernetesClient, strategy, fabric8SecretsPropertySourceLocator,
super(coreV1Api, environment, properties, strategy, propertySourceLocator, kubernetesNamespaceProvider,
k8SConfigurationProperties, threadPoolTaskExecutor);
this.busProperties = busProperties;
}
@Override
protected Mono<Void> triggerRefresh(Secret secret) {
protected Mono<Void> triggerRefresh(V1Secret secret) {
this.applicationEventPublisher.publishEvent(new RefreshRemoteApplicationEvent(secret, busProperties.getId(),
new PathDestinationFactory().getDestination(secret.getMetadata().getName())));
return Mono.empty();

View File

@@ -20,25 +20,25 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1ConfigMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Mono;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator;
import org.springframework.cloud.kubernetes.client.config.reload.KubernetesClientEventBasedConfigMapChangeDetector;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
import org.springframework.cloud.kubernetes.fabric8.config.reload.Fabric8EventBasedConfigMapChangeDetector;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
* @author Ryan Baxter
* @author Kris Iyer
*/
public abstract class ConfigMapWatcherChangeDetector extends Fabric8EventBasedConfigMapChangeDetector {
public abstract class ConfigMapWatcherChangeDetector extends KubernetesClientEventBasedConfigMapChangeDetector {
protected Log log = LogFactory.getLog(getClass());
@@ -46,20 +46,21 @@ public abstract class ConfigMapWatcherChangeDetector extends Fabric8EventBasedCo
protected ConfigurationWatcherConfigurationProperties k8SConfigurationProperties;
public ConfigMapWatcherChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator,
public ConfigMapWatcherChangeDetector(CoreV1Api coreV1Api, ConfigurableEnvironment environment,
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
KubernetesClientConfigMapPropertySourceLocator propertySourceLocator,
KubernetesNamespaceProvider kubernetesNamespaceProvider,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadPoolTaskExecutor) {
super(environment, properties, kubernetesClient, strategy, fabric8ConfigMapPropertySourceLocator,
new KubernetesNamespaceProvider(environment));
super(coreV1Api, environment, properties, strategy, propertySourceLocator, kubernetesNamespaceProvider);
this.executorService = Executors.newScheduledThreadPool(k8SConfigurationProperties.getThreadPoolSize(),
threadPoolTaskExecutor);
this.k8SConfigurationProperties = k8SConfigurationProperties;
}
@Override
protected void onEvent(ConfigMap configMap) {
protected void onEvent(V1ConfigMap configMap) {
if (isSpringCloudKubernetesConfig(configMap)) {
if (log.isDebugEnabled()) {
log.debug("Scheduling remote refresh event to be published for ConfigMap "
@@ -77,7 +78,7 @@ public abstract class ConfigMapWatcherChangeDetector extends Fabric8EventBasedCo
}
}
protected boolean isSpringCloudKubernetesConfig(ConfigMap configMap) {
protected boolean isSpringCloudKubernetesConfig(V1ConfigMap configMap) {
if (configMap.getMetadata() == null || configMap.getMetadata().getLabels() == null) {
return false;
}
@@ -85,6 +86,6 @@ public abstract class ConfigMapWatcherChangeDetector extends Fabric8EventBasedCo
configMap.getMetadata().getLabels().getOrDefault(k8SConfigurationProperties.getConfigLabel(), "false"));
}
protected abstract Mono<Void> triggerRefresh(ConfigMap configMap);
protected abstract Mono<Void> triggerRefresh(V1ConfigMap configMap);
}

View File

@@ -16,7 +16,7 @@
package org.springframework.cloud.kubernetes.configuration.watcher;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import org.springframework.boot.actuate.autoconfigure.amqp.RabbitHealthContributorAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@@ -24,11 +24,12 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.bus.BusProperties;
import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator;
import org.springframework.cloud.kubernetes.client.discovery.reactive.KubernetesInformerReactiveDiscoveryClient;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator;
import org.springframework.cloud.kubernetes.fabric8.discovery.reactive.KubernetesReactiveDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -53,31 +54,30 @@ public class ConfigurationWatcherAutoConfiguration {
@Bean
@ConditionalOnMissingBean(ConfigMapWatcherChangeDetector.class)
@ConditionalOnBean(Fabric8ConfigMapPropertySourceLocator.class)
@ConditionalOnBean(KubernetesClientConfigMapPropertySourceLocator.class)
public ConfigMapWatcherChangeDetector httpBasedConfigMapWatchChangeDetector(AbstractEnvironment environment,
KubernetesClient kubernetesClient,
Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator,
Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator, ConfigReloadProperties properties,
ConfigurationUpdateStrategy strategy,
CoreV1Api coreV1Api, KubernetesClientConfigMapPropertySourceLocator configMapPropertySourceLocator,
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadFactory, WebClient webClient,
KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient) {
return new HttpBasedConfigMapWatchChangeDetector(environment, properties, kubernetesClient, strategy,
fabric8ConfigMapPropertySourceLocator, k8SConfigurationProperties, threadFactory, webClient,
KubernetesNamespaceProvider namespaceProvider, ThreadPoolTaskExecutor threadFactory, WebClient webClient,
KubernetesInformerReactiveDiscoveryClient kubernetesReactiveDiscoveryClient) {
return new HttpBasedConfigMapWatchChangeDetector(coreV1Api, environment, properties, strategy,
configMapPropertySourceLocator, namespaceProvider, k8SConfigurationProperties, threadFactory, webClient,
kubernetesReactiveDiscoveryClient);
}
@Bean
@ConditionalOnMissingBean(SecretsWatcherChangeDetector.class)
@ConditionalOnBean(Fabric8SecretsPropertySourceLocator.class)
@ConditionalOnMissingBean
@ConditionalOnBean(KubernetesClientSecretsPropertySourceLocator.class)
public SecretsWatcherChangeDetector httpBasedSecretsWatchChangeDetector(AbstractEnvironment environment,
KubernetesClient kubernetesClient, Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator,
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
CoreV1Api coreV1Api, KubernetesClientSecretsPropertySourceLocator secretsPropertySourceLocator,
KubernetesNamespaceProvider namespaceProvider, ConfigReloadProperties properties,
ConfigurationUpdateStrategy strategy,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadFactory, WebClient webClient,
KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient) {
return new HttpBasedSecretsWatchChangeDetector(environment, properties, kubernetesClient, strategy,
fabric8SecretsPropertySourceLocator, k8SConfigurationProperties, threadFactory, webClient,
KubernetesInformerReactiveDiscoveryClient kubernetesReactiveDiscoveryClient) {
return new HttpBasedSecretsWatchChangeDetector(coreV1Api, environment, properties, strategy,
secretsPropertySourceLocator, namespaceProvider, k8SConfigurationProperties, threadFactory, webClient,
kubernetesReactiveDiscoveryClient);
}
@@ -88,28 +88,32 @@ public class ConfigurationWatcherAutoConfiguration {
@Bean
@ConditionalOnMissingBean(ConfigMapWatcherChangeDetector.class)
@ConditionalOnBean(Fabric8ConfigMapPropertySourceLocator.class)
@ConditionalOnBean(KubernetesClientConfigMapPropertySourceLocator.class)
public ConfigMapWatcherChangeDetector busConfigMapChangeWatcher(BusProperties busProperties,
AbstractEnvironment environment, KubernetesClient kubernetesClient,
Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator,
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
AbstractEnvironment environment, CoreV1Api coreV1Api,
KubernetesClientConfigMapPropertySourceLocator configMapPropertySourceLocator,
KubernetesNamespaceProvider kubernetesNamespaceProvider, ConfigReloadProperties properties,
ConfigurationUpdateStrategy strategy,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadFactory) {
return new BusEventBasedConfigMapWatcherChangeDetector(environment, properties, kubernetesClient, strategy,
fabric8ConfigMapPropertySourceLocator, busProperties, k8SConfigurationProperties, threadFactory);
return new BusEventBasedConfigMapWatcherChangeDetector(coreV1Api, environment, properties, strategy,
configMapPropertySourceLocator, kubernetesNamespaceProvider, busProperties,
k8SConfigurationProperties, threadFactory);
}
@Bean
@ConditionalOnMissingBean(SecretsWatcherChangeDetector.class)
@ConditionalOnBean(Fabric8SecretsPropertySourceLocator.class)
@ConditionalOnBean(KubernetesClientSecretsPropertySourceLocator.class)
public SecretsWatcherChangeDetector busSecretsChangeWatcher(BusProperties busProperties,
AbstractEnvironment environment, KubernetesClient kubernetesClient,
Fabric8SecretsPropertySourceLocator secretsPropertySourceLocator, ConfigReloadProperties properties,
AbstractEnvironment environment, CoreV1Api coreV1Api,
KubernetesClientSecretsPropertySourceLocator secretsPropertySourceLocator,
ConfigReloadProperties properties, KubernetesNamespaceProvider kubernetesNamespaceProvider,
ConfigurationUpdateStrategy strategy,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadFactory) {
return new BusEventBasedSecretsWatcherChangeDetector(environment, properties, kubernetesClient, strategy,
secretsPropertySourceLocator, busProperties, k8SConfigurationProperties, threadFactory);
return new BusEventBasedSecretsWatcherChangeDetector(coreV1Api, environment, properties, strategy,
secretsPropertySourceLocator, kubernetesNamespaceProvider, busProperties,
k8SConfigurationProperties, threadFactory);
}
}
@@ -121,28 +125,31 @@ public class ConfigurationWatcherAutoConfiguration {
@Bean
@ConditionalOnMissingBean(ConfigMapWatcherChangeDetector.class)
@ConditionalOnBean(Fabric8ConfigMapPropertySourceLocator.class)
@ConditionalOnBean(KubernetesClientConfigMapPropertySourceLocator.class)
public ConfigMapWatcherChangeDetector busConfigMapChangeWatcher(BusProperties busProperties,
AbstractEnvironment environment, KubernetesClient kubernetesClient,
Fabric8ConfigMapPropertySourceLocator configMapPropertySourceLocator, ConfigReloadProperties properties,
AbstractEnvironment environment, CoreV1Api coreV1Api,
KubernetesClientConfigMapPropertySourceLocator configMapPropertySourceLocator,
ConfigReloadProperties properties, KubernetesNamespaceProvider namespaceProvider,
ConfigurationUpdateStrategy strategy,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadFactory) {
return new BusEventBasedConfigMapWatcherChangeDetector(environment, properties, kubernetesClient, strategy,
configMapPropertySourceLocator, busProperties, k8SConfigurationProperties, threadFactory);
return new BusEventBasedConfigMapWatcherChangeDetector(coreV1Api, environment, properties, strategy,
configMapPropertySourceLocator, namespaceProvider, busProperties, k8SConfigurationProperties,
threadFactory);
}
@Bean
@ConditionalOnMissingBean(SecretsWatcherChangeDetector.class)
@ConditionalOnBean(Fabric8SecretsPropertySourceLocator.class)
@ConditionalOnBean(KubernetesClientSecretsPropertySourceLocator.class)
public SecretsWatcherChangeDetector busSecretsChangeWatcher(BusProperties busProperties,
AbstractEnvironment environment, KubernetesClient kubernetesClient,
Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator,
AbstractEnvironment environment, CoreV1Api coreV1Api,
KubernetesClientSecretsPropertySourceLocator secretsPropertySourceLocator,
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadFactory) {
return new BusEventBasedSecretsWatcherChangeDetector(environment, properties, kubernetesClient, strategy,
fabric8SecretsPropertySourceLocator, busProperties, k8SConfigurationProperties, threadFactory);
ThreadPoolTaskExecutor threadFactory, KubernetesNamespaceProvider namespaceProvider) {
return new BusEventBasedSecretsWatcherChangeDetector(coreV1Api, environment, properties, strategy,
secretsPropertySourceLocator, namespaceProvider, busProperties, k8SConfigurationProperties,
threadFactory);
}
}

View File

@@ -18,20 +18,21 @@ package org.springframework.cloud.kubernetes.configuration.watcher;
import java.net.URI;
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1ConfigMap;
import io.kubernetes.client.openapi.models.V1ObjectMeta;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator;
import org.springframework.cloud.kubernetes.client.discovery.reactive.KubernetesInformerReactiveDiscoveryClient;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
import org.springframework.cloud.kubernetes.fabric8.discovery.reactive.KubernetesReactiveDiscoveryClient;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.StringUtils;
@@ -53,15 +54,16 @@ public class HttpBasedConfigMapWatchChangeDetector extends ConfigMapWatcherChang
private WebClient webClient;
private KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient;
private KubernetesInformerReactiveDiscoveryClient kubernetesReactiveDiscoveryClient;
public HttpBasedConfigMapWatchChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator,
public HttpBasedConfigMapWatchChangeDetector(CoreV1Api coreV1Api, ConfigurableEnvironment environment,
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
KubernetesClientConfigMapPropertySourceLocator propertySourceLocator,
KubernetesNamespaceProvider kubernetesNamespaceProvider,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadPoolTaskExecutor, WebClient webClient,
KubernetesReactiveDiscoveryClient k8sReactiveDiscoveryClient) {
super(environment, properties, kubernetesClient, strategy, fabric8ConfigMapPropertySourceLocator,
KubernetesInformerReactiveDiscoveryClient k8sReactiveDiscoveryClient) {
super(coreV1Api, environment, properties, strategy, propertySourceLocator, kubernetesNamespaceProvider,
k8SConfigurationProperties, threadPoolTaskExecutor);
this.webClient = webClient;
this.kubernetesReactiveDiscoveryClient = k8sReactiveDiscoveryClient;
@@ -110,7 +112,7 @@ public class HttpBasedConfigMapWatchChangeDetector extends ConfigMapWatcherChang
return actuatorUriBuilder.build().toUri();
}
protected Flux<ResponseEntity<Void>> refresh(ObjectMeta objectMeta) {
protected Flux<ResponseEntity<Void>> refresh(V1ObjectMeta objectMeta) {
return kubernetesReactiveDiscoveryClient.getInstances(objectMeta.getName()).flatMap(si -> {
URI actuatorUri = getActuatorUri(si);
@@ -131,7 +133,7 @@ public class HttpBasedConfigMapWatchChangeDetector extends ConfigMapWatcherChang
}
@Override
protected Mono<Void> triggerRefresh(ConfigMap configMap) {
protected Mono<Void> triggerRefresh(V1ConfigMap configMap) {
return refresh(configMap.getMetadata()).then();
}

View File

@@ -18,18 +18,19 @@ package org.springframework.cloud.kubernetes.configuration.watcher;
import java.net.URI;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1ObjectMeta;
import io.kubernetes.client.openapi.models.V1Secret;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator;
import org.springframework.cloud.kubernetes.client.discovery.reactive.KubernetesInformerReactiveDiscoveryClient;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator;
import org.springframework.cloud.kubernetes.fabric8.discovery.reactive.KubernetesReactiveDiscoveryClient;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.StringUtils;
@@ -49,22 +50,23 @@ public class HttpBasedSecretsWatchChangeDetector extends SecretsWatcherChangeDet
private WebClient webClient;
private KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient;
private KubernetesInformerReactiveDiscoveryClient kubernetesReactiveDiscoveryClient;
public HttpBasedSecretsWatchChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator,
public HttpBasedSecretsWatchChangeDetector(CoreV1Api coreV1Api, ConfigurableEnvironment environment,
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
KubernetesClientSecretsPropertySourceLocator propertySourceLocator,
KubernetesNamespaceProvider kubernetesNamespaceProvider,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadPoolTaskExecutor, WebClient webClient,
KubernetesReactiveDiscoveryClient k8sReactiveDiscoveryClient) {
super(environment, properties, kubernetesClient, strategy, fabric8SecretsPropertySourceLocator,
KubernetesInformerReactiveDiscoveryClient k8sReactiveDiscoveryClient) {
super(coreV1Api, environment, properties, strategy, propertySourceLocator, kubernetesNamespaceProvider,
k8SConfigurationProperties, threadPoolTaskExecutor);
this.webClient = webClient;
this.kubernetesReactiveDiscoveryClient = k8sReactiveDiscoveryClient;
}
@Override
protected Mono<Void> triggerRefresh(Secret secret) {
protected Mono<Void> triggerRefresh(V1Secret secret) {
return refresh(secret.getMetadata()).then();
}
@@ -111,7 +113,7 @@ public class HttpBasedSecretsWatchChangeDetector extends SecretsWatcherChangeDet
return actuatorUriBuilder.build().toUri();
}
protected Flux<ResponseEntity<Void>> refresh(ObjectMeta objectMeta) {
protected Flux<ResponseEntity<Void>> refresh(V1ObjectMeta objectMeta) {
return kubernetesReactiveDiscoveryClient.getInstances(objectMeta.getName()).flatMap(si -> {
URI actuatorUri = getActuatorUri(si);

View File

@@ -20,25 +20,25 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1Secret;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Mono;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator;
import org.springframework.cloud.kubernetes.client.config.reload.KubernetesClientEventBasedSecretsChangeDetector;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator;
import org.springframework.cloud.kubernetes.fabric8.config.reload.Fabric8EventBasedSecretsChangeDetector;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
* @author Ryan Baxter
* @author Kris Iyer
*/
public abstract class SecretsWatcherChangeDetector extends Fabric8EventBasedSecretsChangeDetector {
public abstract class SecretsWatcherChangeDetector extends KubernetesClientEventBasedSecretsChangeDetector {
protected Log log = LogFactory.getLog(getClass());
@@ -46,19 +46,19 @@ public abstract class SecretsWatcherChangeDetector extends Fabric8EventBasedSecr
protected ConfigurationWatcherConfigurationProperties k8SConfigurationProperties;
public SecretsWatcherChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator,
public SecretsWatcherChangeDetector(CoreV1Api coreV1Api, ConfigurableEnvironment environment,
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
KubernetesClientSecretsPropertySourceLocator propertySourceLocator,
KubernetesNamespaceProvider kubernetesNamespaceProvider,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadPoolTaskExecutor) {
super(environment, properties, kubernetesClient, strategy, fabric8SecretsPropertySourceLocator,
new KubernetesNamespaceProvider(environment));
super(coreV1Api, environment, properties, strategy, propertySourceLocator, kubernetesNamespaceProvider);
this.executorService = Executors.newScheduledThreadPool(k8SConfigurationProperties.getThreadPoolSize(),
threadPoolTaskExecutor);
this.k8SConfigurationProperties = k8SConfigurationProperties;
}
protected boolean isSpringCloudKubernetesSecret(Secret secret) {
protected boolean isSpringCloudKubernetesSecret(V1Secret secret) {
if (secret.getMetadata() == null || secret.getMetadata().getLabels() == null) {
return false;
}
@@ -66,10 +66,10 @@ public abstract class SecretsWatcherChangeDetector extends Fabric8EventBasedSecr
secret.getMetadata().getLabels().getOrDefault(k8SConfigurationProperties.getSecretLabel(), "false"));
}
protected abstract Mono<Void> triggerRefresh(Secret secret);
protected abstract Mono<Void> triggerRefresh(V1Secret secret);
@Override
protected void onEvent(Secret secret) {
protected void onEvent(V1Secret secret) {
if (isSpringCloudKubernetesSecret(secret)) {
if (log.isDebugEnabled()) {
log.debug("Scheduling remote refresh event to be published for Secret " + secret.getMetadata().getName()

View File

@@ -18,9 +18,9 @@ package org.springframework.cloud.kubernetes.configuration.watcher;
import java.util.Set;
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1ConfigMap;
import io.kubernetes.client.openapi.models.V1ObjectMeta;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -30,15 +30,17 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.bus.BusProperties;
import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import static org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider.NAMESPACE_PROPERTY;
/**
* @author Ryan Baxter
@@ -53,10 +55,10 @@ class BusEventBasedConfigMapWatcherChangeDetectorTests {
});
@Mock
private KubernetesClient client;
private CoreV1Api coreV1Api;
@Mock
private Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator;
private KubernetesClientConfigMapPropertySourceLocator configMapPropertySourceLocator;
@Mock
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@@ -71,21 +73,23 @@ class BusEventBasedConfigMapWatcherChangeDetectorTests {
@BeforeEach
void setup() {
MockEnvironment mockEnvironment = new MockEnvironment();
mockEnvironment.setProperty(NAMESPACE_PROPERTY, "default");
ConfigReloadProperties configReloadProperties = new ConfigReloadProperties();
configReloadProperties.setNamespaces(Set.of("default"));
ConfigurationWatcherConfigurationProperties configurationWatcherConfigurationProperties = new ConfigurationWatcherConfigurationProperties();
busProperties = new BusProperties();
changeDetector = new BusEventBasedConfigMapWatcherChangeDetector(mockEnvironment, configReloadProperties,
client, UPDATE_STRATEGY, fabric8ConfigMapPropertySourceLocator, busProperties,
changeDetector = new BusEventBasedConfigMapWatcherChangeDetector(coreV1Api, mockEnvironment,
configReloadProperties, UPDATE_STRATEGY, configMapPropertySourceLocator,
new KubernetesNamespaceProvider(mockEnvironment), busProperties,
configurationWatcherConfigurationProperties, threadPoolTaskExecutor);
changeDetector.setApplicationEventPublisher(applicationEventPublisher);
}
@Test
void triggerRefreshWithConfigMap() {
ObjectMeta objectMeta = new ObjectMeta();
V1ObjectMeta objectMeta = new V1ObjectMeta();
objectMeta.setName("foo");
ConfigMap configMap = new ConfigMap();
V1ConfigMap configMap = new V1ConfigMap();
configMap.setMetadata(objectMeta);
changeDetector.triggerRefresh(configMap);
ArgumentCaptor<RefreshRemoteApplicationEvent> argumentCaptor = ArgumentCaptor

View File

@@ -18,9 +18,9 @@ package org.springframework.cloud.kubernetes.configuration.watcher;
import java.util.Set;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1ObjectMeta;
import io.kubernetes.client.openapi.models.V1Secret;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -30,15 +30,17 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.bus.BusProperties;
import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import static org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider.NAMESPACE_PROPERTY;
/**
* @author Ryan Baxter
@@ -53,10 +55,10 @@ class BusEventBasedSecretsWatcherChangeDetectorTests {
});
@Mock
private KubernetesClient client;
private CoreV1Api coreV1Api;
@Mock
private Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator;
private KubernetesClientSecretsPropertySourceLocator secretsPropertySourceLocator;
@Mock
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@@ -71,21 +73,23 @@ class BusEventBasedSecretsWatcherChangeDetectorTests {
@BeforeEach
void setup() {
MockEnvironment mockEnvironment = new MockEnvironment();
mockEnvironment.setProperty(NAMESPACE_PROPERTY, "default");
ConfigReloadProperties configReloadProperties = new ConfigReloadProperties();
configReloadProperties.setNamespaces(Set.of("default"));
ConfigurationWatcherConfigurationProperties configurationWatcherConfigurationProperties = new ConfigurationWatcherConfigurationProperties();
busProperties = new BusProperties();
changeDetector = new BusEventBasedSecretsWatcherChangeDetector(mockEnvironment, configReloadProperties, client,
UPDATE_STRATEGY, fabric8SecretsPropertySourceLocator, busProperties,
changeDetector = new BusEventBasedSecretsWatcherChangeDetector(coreV1Api, mockEnvironment,
configReloadProperties, UPDATE_STRATEGY, secretsPropertySourceLocator,
new KubernetesNamespaceProvider(mockEnvironment), busProperties,
configurationWatcherConfigurationProperties, threadPoolTaskExecutor);
changeDetector.setApplicationEventPublisher(applicationEventPublisher);
}
@Test
void triggerRefreshWithSecret() {
ObjectMeta objectMeta = new ObjectMeta();
V1ObjectMeta objectMeta = new V1ObjectMeta();
objectMeta.setName("foo");
Secret secret = new Secret();
V1Secret secret = new V1Secret();
secret.setMetadata(objectMeta);
changeDetector.triggerRefresh(secret);
ArgumentCaptor<RefreshRemoteApplicationEvent> argumentCaptor = ArgumentCaptor

View File

@@ -21,11 +21,11 @@ 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.EndpointAddress;
import io.fabric8.kubernetes.api.model.EndpointPort;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1ConfigMap;
import io.kubernetes.client.openapi.models.V1EndpointAddress;
import io.kubernetes.client.openapi.models.V1EndpointPort;
import io.kubernetes.client.openapi.models.V1ObjectMeta;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@@ -35,17 +35,19 @@ import org.mockito.junit.MockitoJUnitRunner;
import reactor.core.publisher.Flux;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator;
import org.springframework.cloud.kubernetes.client.discovery.reactive.KubernetesInformerReactiveDiscoveryClient;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesServiceInstance;
import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
import org.springframework.cloud.kubernetes.fabric8.discovery.reactive.KubernetesReactiveDiscoveryClient;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.reactive.function.client.WebClient;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import static org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider.NAMESPACE_PROPERTY;
/**
* @author Ryan Baxter
@@ -60,19 +62,19 @@ public class HttpBasedConfigMapWatchChangeDetectorTests {
// public WireMockRule wireMockRule = new WireMockRule(0);
@Mock
private KubernetesClient client;
private CoreV1Api coreV1Api;
@Mock
private ConfigurationUpdateStrategy updateStrategy;
@Mock
private Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator;
private KubernetesClientConfigMapPropertySourceLocator configMapPropertySourceLocator;
@Mock
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Mock
private KubernetesReactiveDiscoveryClient reactiveDiscoveryClient;
private KubernetesInformerReactiveDiscoveryClient reactiveDiscoveryClient;
private HttpBasedConfigMapWatchChangeDetector changeDetector;
@@ -80,10 +82,10 @@ public class HttpBasedConfigMapWatchChangeDetectorTests {
@Before
public void setup() {
EndpointAddress fooEndpointAddress = new EndpointAddress();
V1EndpointAddress fooEndpointAddress = new V1EndpointAddress();
fooEndpointAddress.setIp("127.0.0.1");
fooEndpointAddress.setHostname("localhost");
EndpointPort fooEndpointPort = new EndpointPort();
V1EndpointPort fooEndpointPort = new V1EndpointPort();
// fooEndpointPort.setPort(wireMockRule.port());
List<ServiceInstance> instances = new ArrayList<>();
KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance("foo", "foo",
@@ -91,18 +93,20 @@ public class HttpBasedConfigMapWatchChangeDetectorTests {
instances.add(fooServiceInstance);
when(reactiveDiscoveryClient.getInstances(eq("foo"))).thenReturn(Flux.fromIterable(instances));
MockEnvironment mockEnvironment = new MockEnvironment();
mockEnvironment.setProperty(NAMESPACE_PROPERTY, "default");
ConfigReloadProperties configReloadProperties = new ConfigReloadProperties();
configurationWatcherConfigurationProperties = new ConfigurationWatcherConfigurationProperties();
WebClient webClient = WebClient.builder().build();
changeDetector = new HttpBasedConfigMapWatchChangeDetector(mockEnvironment, configReloadProperties, client,
updateStrategy, fabric8ConfigMapPropertySourceLocator, configurationWatcherConfigurationProperties,
threadPoolTaskExecutor, webClient, reactiveDiscoveryClient);
changeDetector = new HttpBasedConfigMapWatchChangeDetector(coreV1Api, mockEnvironment, configReloadProperties,
updateStrategy, configMapPropertySourceLocator, new KubernetesNamespaceProvider(mockEnvironment),
configurationWatcherConfigurationProperties, threadPoolTaskExecutor, webClient,
reactiveDiscoveryClient);
}
@Test
public void triggerConfigMapRefresh() {
ConfigMap configMap = new ConfigMap();
ObjectMeta objectMeta = new ObjectMeta();
V1ConfigMap configMap = new V1ConfigMap();
V1ObjectMeta objectMeta = new V1ObjectMeta();
objectMeta.setName("foo");
configMap.setMetadata(objectMeta);
// WireMock.configureFor("localhost", wireMockRule.port());
@@ -114,8 +118,8 @@ public class HttpBasedConfigMapWatchChangeDetectorTests {
@Test
public void triggerConfigMapRefreshWithPropertiesBasedActuatorPath() throws InterruptedException {
configurationWatcherConfigurationProperties.setActuatorPath("/my/custom/actuator");
ConfigMap configMap = new ConfigMap();
ObjectMeta objectMeta = new ObjectMeta();
V1ConfigMap configMap = new V1ConfigMap();
V1ObjectMeta objectMeta = new V1ObjectMeta();
objectMeta.setName("foo");
configMap.setMetadata(objectMeta);
// WireMock.configureFor("localhost", wireMockRule.port());
@@ -129,18 +133,18 @@ public class HttpBasedConfigMapWatchChangeDetectorTests {
Map<String, String> metadata = new HashMap<>();
// metadata.put(ANNOTATION_KEY, "http://:" + wireMockRule.port() +
// "/my/custom/actuator");
EndpointAddress fooEndpointAddress = new EndpointAddress();
V1EndpointAddress fooEndpointAddress = new V1EndpointAddress();
fooEndpointAddress.setIp("127.0.0.1");
fooEndpointAddress.setHostname("localhost");
EndpointPort fooEndpointPort = new EndpointPort();
V1EndpointPort fooEndpointPort = new V1EndpointPort();
// fooEndpointPort.setPort(wireMockRule.port());
List<ServiceInstance> instances = new ArrayList<>();
KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance("foo", "foo",
fooEndpointAddress.getIp(), fooEndpointPort.getPort(), metadata, false);
instances.add(fooServiceInstance);
when(reactiveDiscoveryClient.getInstances(eq("foo"))).thenReturn(Flux.fromIterable(instances));
ConfigMap configMap = new ConfigMap();
ObjectMeta objectMeta = new ObjectMeta();
V1ConfigMap configMap = new V1ConfigMap();
V1ObjectMeta objectMeta = new V1ObjectMeta();
objectMeta.setName("foo");
configMap.setMetadata(objectMeta);
// stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh")).willReturn(aResponse().withStatus(200)));

View File

@@ -21,11 +21,11 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.fabric8.kubernetes.api.model.EndpointAddress;
import io.fabric8.kubernetes.api.model.EndpointPort;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1EndpointAddress;
import io.kubernetes.client.openapi.models.V1EndpointPort;
import io.kubernetes.client.openapi.models.V1ObjectMeta;
import io.kubernetes.client.openapi.models.V1Secret;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@@ -35,17 +35,19 @@ import org.mockito.junit.MockitoJUnitRunner;
import reactor.core.publisher.Flux;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator;
import org.springframework.cloud.kubernetes.client.discovery.reactive.KubernetesInformerReactiveDiscoveryClient;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesServiceInstance;
import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator;
import org.springframework.cloud.kubernetes.fabric8.discovery.reactive.KubernetesReactiveDiscoveryClient;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.reactive.function.client.WebClient;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import static org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider.NAMESPACE_PROPERTY;
/**
* @author Ryan Baxter
@@ -60,19 +62,19 @@ public class HttpBasedSecretsWatchChangeDetectorTests {
// public WireMockRule wireMockRule = new WireMockRule(0);
@Mock
private KubernetesClient client;
private CoreV1Api coreV1Api;
@Mock
private ConfigurationUpdateStrategy updateStrategy;
@Mock
private Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator;
private KubernetesClientSecretsPropertySourceLocator secretsPropertySourceLocator;
@Mock
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Mock
private KubernetesReactiveDiscoveryClient reactiveDiscoveryClient;
private KubernetesInformerReactiveDiscoveryClient reactiveDiscoveryClient;
private HttpBasedSecretsWatchChangeDetector changeDetector;
@@ -80,10 +82,10 @@ public class HttpBasedSecretsWatchChangeDetectorTests {
@Before
public void setup() {
EndpointAddress fooEndpointAddress = new EndpointAddress();
V1EndpointAddress fooEndpointAddress = new V1EndpointAddress();
fooEndpointAddress.setIp("127.0.0.1");
fooEndpointAddress.setHostname("localhost");
EndpointPort fooEndpointPort = new EndpointPort();
V1EndpointPort fooEndpointPort = new V1EndpointPort();
// fooEndpointPort.setPort(wireMockRule.port());
List<ServiceInstance> instances = new ArrayList<>();
KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance("foo", "foo",
@@ -91,18 +93,20 @@ public class HttpBasedSecretsWatchChangeDetectorTests {
instances.add(fooServiceInstance);
when(reactiveDiscoveryClient.getInstances(eq("foo"))).thenReturn(Flux.fromIterable(instances));
MockEnvironment mockEnvironment = new MockEnvironment();
mockEnvironment.setProperty(NAMESPACE_PROPERTY, "default");
ConfigReloadProperties configReloadProperties = new ConfigReloadProperties();
configurationWatcherConfigurationProperties = new ConfigurationWatcherConfigurationProperties();
WebClient webClient = WebClient.builder().build();
changeDetector = new HttpBasedSecretsWatchChangeDetector(mockEnvironment, configReloadProperties, client,
updateStrategy, fabric8SecretsPropertySourceLocator, configurationWatcherConfigurationProperties,
threadPoolTaskExecutor, webClient, reactiveDiscoveryClient);
changeDetector = new HttpBasedSecretsWatchChangeDetector(coreV1Api, mockEnvironment, configReloadProperties,
updateStrategy, secretsPropertySourceLocator, new KubernetesNamespaceProvider(mockEnvironment),
configurationWatcherConfigurationProperties, threadPoolTaskExecutor, webClient,
reactiveDiscoveryClient);
}
@Test
public void triggerSecretRefresh() throws InterruptedException {
Secret secret = new Secret();
ObjectMeta objectMeta = new ObjectMeta();
V1Secret secret = new V1Secret();
V1ObjectMeta objectMeta = new V1ObjectMeta();
objectMeta.setName("foo");
secret.setMetadata(objectMeta);
// WireMock.configureFor("localhost", wireMockRule.port());
@@ -114,8 +118,8 @@ public class HttpBasedSecretsWatchChangeDetectorTests {
@Test
public void triggerSecretRefreshWithPropertiesBasedActuatorPath() throws InterruptedException {
configurationWatcherConfigurationProperties.setActuatorPath("/my/custom/actuator");
Secret secret = new Secret();
ObjectMeta objectMeta = new ObjectMeta();
V1Secret secret = new V1Secret();
V1ObjectMeta objectMeta = new V1ObjectMeta();
objectMeta.setName("foo");
secret.setMetadata(objectMeta);
// WireMock.configureFor("localhost", wireMockRule.port());
@@ -129,18 +133,18 @@ public class HttpBasedSecretsWatchChangeDetectorTests {
Map<String, String> metadata = new HashMap<>();
// metadata.put(ANNOTATION_KEY, "http://:" + wireMockRule.port() +
// "/my/custom/actuator");
EndpointAddress fooEndpointAddress = new EndpointAddress();
V1EndpointAddress fooEndpointAddress = new V1EndpointAddress();
fooEndpointAddress.setIp("127.0.0.1");
fooEndpointAddress.setHostname("localhost");
EndpointPort fooEndpointPort = new EndpointPort();
V1EndpointPort fooEndpointPort = new V1EndpointPort();
// fooEndpointPort.setPort(wireMockRule.port());
List<ServiceInstance> instances = new ArrayList<>();
KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance("foo", "foo",
fooEndpointAddress.getIp(), fooEndpointPort.getPort(), metadata, false);
instances.add(fooServiceInstance);
when(reactiveDiscoveryClient.getInstances(eq("foo"))).thenReturn(Flux.fromIterable(instances));
Secret secret = new Secret();
ObjectMeta objectMeta = new ObjectMeta();
V1Secret secret = new V1Secret();
V1ObjectMeta objectMeta = new V1ObjectMeta();
objectMeta.setName("foo");
secret.setMetadata(objectMeta);
// stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh")).willReturn(aResponse().withStatus(200)));