-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix/740 #1067
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix/740 #1067
Changes from 13 commits
ee58343
a62e286
dcd124d
2a1fe94
c4ad7f4
43e0e50
7e47f4b
6543c2a
e7094de
b73cb51
2bd4b01
5af6a01
68ad890
776f262
7f1d2f3
6d2a755
657cc7a
97d65e8
94c2520
9d89ae5
4db3689
e48769a
fc47d6d
881e3e3
3a04a35
7ba8616
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -70,21 +70,21 @@ public class KubernetesClientEventBasedSecretsChangeDetector extends Configurati | |
| private final ResourceEventHandler<V1Secret> handler = new ResourceEventHandler<>() { | ||
|
|
||
| @Override | ||
| public void onAdd(V1Secret obj) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. renames only |
||
| LOG.debug(() -> "Secret " + obj.getMetadata().getName() + " was added."); | ||
| onEvent(obj); | ||
| public void onAdd(V1Secret secret) { | ||
| LOG.debug(() -> "Secret " + secret.getMetadata().getName() + " was added."); | ||
| onEvent(secret); | ||
| } | ||
|
|
||
| @Override | ||
| public void onUpdate(V1Secret oldObj, V1Secret newObj) { | ||
| LOG.debug(() -> "Secret " + newObj.getMetadata().getName() + " was updated."); | ||
| onEvent(newObj); | ||
| public void onUpdate(V1Secret oldSecret, V1Secret newSecret) { | ||
| LOG.debug(() -> "Secret " + newSecret.getMetadata().getName() + " was updated."); | ||
| onEvent(newSecret); | ||
| } | ||
|
|
||
| @Override | ||
| public void onDelete(V1Secret obj, boolean deletedFinalStateUnknown) { | ||
| LOG.debug(() -> "Secret " + obj.getMetadata() + " was deleted."); | ||
| onEvent(obj); | ||
| public void onDelete(V1Secret secret, boolean deletedFinalStateUnknown) { | ||
| LOG.debug(() -> "Secret " + secret.getMetadata().getName() + " was deleted."); | ||
| onEvent(secret); | ||
| } | ||
| }; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,8 +47,8 @@ final class BusEventBasedConfigMapWatcherChangeDetector extends ConfigMapWatcher | |
| } | ||
|
|
||
| @Override | ||
| public Mono<Void> triggerRefresh(KubernetesObject configMap) { | ||
| return busRefreshTrigger.triggerRefresh(configMap); | ||
| public Mono<Void> triggerRefresh(KubernetesObject configMap, String appName) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can have multiple apps based in a configMap/secret now |
||
| return busRefreshTrigger.triggerRefresh(configMap, appName); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,18 +16,25 @@ | |
|
|
||
| package org.springframework.cloud.kubernetes.configuration.watcher; | ||
|
|
||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the main changes are in this class. |
||
| import java.util.Arrays; | ||
| import java.util.Collections; | ||
| import java.util.Map; | ||
| import java.util.Optional; | ||
| import java.util.Set; | ||
| import java.util.concurrent.ScheduledExecutorService; | ||
| import java.util.concurrent.TimeUnit; | ||
| import java.util.function.Function; | ||
| import java.util.function.BiFunction; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| import io.kubernetes.client.common.KubernetesObject; | ||
| import io.kubernetes.client.openapi.models.V1ObjectMeta; | ||
| import org.apache.commons.logging.LogFactory; | ||
| import reactor.core.publisher.Mono; | ||
|
|
||
| import org.springframework.core.log.LogAccessor; | ||
|
|
||
| import static java.util.Collections.emptySet; | ||
|
|
||
| /** | ||
| * A common place where 'onEvent' code delegates to. | ||
| * | ||
|
|
@@ -40,37 +47,93 @@ final class WatcherUtil { | |
| private WatcherUtil() { | ||
| } | ||
|
|
||
| static void onEvent(KubernetesObject kubernetesObject, String label, long refreshDelay, | ||
| static void onEvent(KubernetesObject kubernetesObject, String label, String annotationName, long refreshDelay, | ||
| ScheduledExecutorService executorService, String type, | ||
| Function<KubernetesObject, Mono<Void>> triggerRefresh) { | ||
| BiFunction<KubernetesObject, String, Mono<Void>> triggerRefresh) { | ||
|
|
||
| String name = kubernetesObject.getMetadata().getName(); | ||
| boolean isSpringCloudKubernetes = isSpringCloudKubernetes(kubernetesObject, label); | ||
|
|
||
| if (isSpringCloudKubernetes) { | ||
|
|
||
| LOG.debug(() -> "Scheduling remote refresh event to be published for " + type + ": " + name | ||
| + " to be published in " + refreshDelay + " milliseconds"); | ||
| executorService.schedule(() -> { | ||
| try { | ||
| triggerRefresh.apply(kubernetesObject).subscribe(); | ||
| } | ||
| catch (Throwable t) { | ||
| LOG.warn(t, "Error when refreshing ConfigMap " + name); | ||
| } | ||
| }, refreshDelay, TimeUnit.MILLISECONDS); | ||
| Set<String> apps = apps(kubernetesObject, annotationName); | ||
|
|
||
| if (!apps.isEmpty()) { | ||
|
||
| LOG.info(() -> "will schedule remote refresh based on apps : " + apps); | ||
| apps.forEach(appName -> schedule(type, appName, refreshDelay, executorService, triggerRefresh, | ||
| kubernetesObject)); | ||
| } | ||
| else { | ||
| LOG.info(() -> "will schedule remote refresh based on name : " + name); | ||
| schedule(type, name, refreshDelay, executorService, triggerRefresh, kubernetesObject); | ||
| } | ||
|
|
||
| } | ||
| else { | ||
| LOG.debug(() -> "Not publishing event." + type + ": + name + does not contain the label " + label); | ||
| LOG.debug(() -> "Not publishing event." + type + ": " + name + " does not contain the label " + label); | ||
| } | ||
| } | ||
|
|
||
| private static boolean isSpringCloudKubernetes(KubernetesObject kubernetesObject, String label) { | ||
| static boolean isSpringCloudKubernetes(KubernetesObject kubernetesObject, String label) { | ||
| if (kubernetesObject.getMetadata() == null) { | ||
| return false; | ||
| } | ||
| return Boolean.parseBoolean(Optional.ofNullable(kubernetesObject.getMetadata().getLabels()) | ||
| .orElse(Collections.emptyMap()).getOrDefault(label, "false")); | ||
| return Boolean.parseBoolean(labels(kubernetesObject).getOrDefault(label, "false")); | ||
| } | ||
|
|
||
| static Set<String> apps(KubernetesObject kubernetesObject, String annotationName) { | ||
|
|
||
| Map<String, String> annotations = annotations(kubernetesObject); | ||
|
|
||
| if (annotations.isEmpty()) { | ||
| LOG.debug(() -> annotationName + " not present (empty data)"); | ||
| return emptySet(); | ||
| } | ||
|
|
||
| String appsValue = annotations.get(annotationName); | ||
|
|
||
| if (appsValue == null) { | ||
| LOG.debug(() -> annotationName + " not present (missing in annotations)"); | ||
| return emptySet(); | ||
| } | ||
|
|
||
| if (appsValue.isBlank()) { | ||
| LOG.debug(() -> appsValue + " not present (blanks only)"); | ||
| return emptySet(); | ||
| } | ||
|
|
||
| return Arrays.stream(appsValue.split(",")).map(String::trim).collect(Collectors.toSet()); | ||
| } | ||
|
|
||
| static Map<String, String> labels(KubernetesObject kubernetesObject) { | ||
| V1ObjectMeta metadata = kubernetesObject.getMetadata(); | ||
| if (metadata == null) { | ||
| return Map.of(); | ||
| } | ||
| return Optional.ofNullable(metadata.getLabels()).orElse(Map.of()); | ||
| } | ||
|
|
||
| static Map<String, String> annotations(KubernetesObject kubernetesObject) { | ||
| V1ObjectMeta metadata = kubernetesObject.getMetadata(); | ||
| if (metadata == null) { | ||
| return Map.of(); | ||
| } | ||
| return Optional.ofNullable(metadata.getAnnotations()).orElse(Collections.emptyMap()); | ||
| } | ||
|
|
||
| private static void schedule(String type, String appName, long refreshDelay, | ||
| ScheduledExecutorService executorService, BiFunction<KubernetesObject, String, Mono<Void>> triggerRefresh, | ||
| KubernetesObject kubernetesObject) { | ||
| LOG.debug(() -> "Scheduling remote refresh event to be published for " + type + ": with appName : " + appName | ||
| + " to be published in " + refreshDelay + " milliseconds"); | ||
| executorService.schedule(() -> { | ||
| try { | ||
| triggerRefresh.apply(kubernetesObject, appName).subscribe(); | ||
| } | ||
| catch (Throwable t) { | ||
| LOG.warn(t, "Error when refreshing appName " + appName); | ||
| } | ||
| }, refreshDelay, TimeUnit.MILLISECONDS); | ||
| } | ||
|
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just renames here - nothing else