diff --git a/spring-cloud-kubernetes-client-discovery/pom.xml b/spring-cloud-kubernetes-client-discovery/pom.xml
index d57c9477..6b12953e 100644
--- a/spring-cloud-kubernetes-client-discovery/pom.xml
+++ b/spring-cloud-kubernetes-client-discovery/pom.xml
@@ -65,6 +65,11 @@
reactor-test
test
+
+ org.springframework.cloud
+ spring-cloud-kubernetes-test-support
+ test
+
com.github.tomakehurst
wiremock-jre8-standalone
diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/CatalogSharedInformerFactory.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/CatalogSharedInformerFactory.java
new file mode 100644
index 00000000..2e1477bb
--- /dev/null
+++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/CatalogSharedInformerFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019-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.client.discovery;
+
+import io.kubernetes.client.informer.SharedInformerFactory;
+import io.kubernetes.client.openapi.models.V1Endpoints;
+import io.kubernetes.client.openapi.models.V1EndpointsList;
+import io.kubernetes.client.openapi.models.V1Service;
+import io.kubernetes.client.openapi.models.V1ServiceList;
+import io.kubernetes.client.spring.extended.controller.annotation.GroupVersionResource;
+import io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformer;
+import io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformers;
+
+@KubernetesInformers({
+ @KubernetesInformer(apiTypeClass = V1Service.class, apiListTypeClass = V1ServiceList.class,
+ groupVersionResource = @GroupVersionResource(apiGroup = "", apiVersion = "v1",
+ resourcePlural = "services")),
+ @KubernetesInformer(apiTypeClass = V1Endpoints.class, apiListTypeClass = V1EndpointsList.class,
+ groupVersionResource = @GroupVersionResource(apiGroup = "", apiVersion = "v1",
+ resourcePlural = "endpoints")) })
+public class CatalogSharedInformerFactory extends SharedInformerFactory {
+
+ // TODO: optimization to ease memory pressure from continuous list&watch.
+
+}
diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientAutoConfiguration.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientAutoConfiguration.java
deleted file mode 100644
index cf277934..00000000
--- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientAutoConfiguration.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2013-2019 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.client.discovery;
-
-import io.kubernetes.client.informer.SharedInformer;
-import io.kubernetes.client.informer.SharedInformerFactory;
-import io.kubernetes.client.informer.cache.Lister;
-import io.kubernetes.client.openapi.ApiClient;
-import io.kubernetes.client.openapi.models.V1Endpoints;
-import io.kubernetes.client.openapi.models.V1EndpointsList;
-import io.kubernetes.client.openapi.models.V1Service;
-import io.kubernetes.client.openapi.models.V1ServiceList;
-import io.kubernetes.client.spring.extended.controller.annotation.GroupVersionResource;
-import io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformer;
-import io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformers;
-import io.kubernetes.client.spring.extended.controller.config.KubernetesInformerAutoConfiguration;
-
-import org.springframework.boot.actuate.health.HealthIndicator;
-import org.springframework.boot.autoconfigure.AutoConfigureAfter;
-import org.springframework.boot.autoconfigure.AutoConfigureBefore;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.cloud.CloudPlatform;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.cloud.client.CommonsClientAutoConfiguration;
-import org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled;
-import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
-import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled;
-import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration;
-import org.springframework.cloud.kubernetes.client.KubernetesClientAutoConfiguration;
-import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
-import org.springframework.cloud.kubernetes.commons.PodUtils;
-import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnKubernetesDiscoveryEnabled;
-import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryClientHealthIndicatorInitializer;
-import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties;
-import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.env.Environment;
-
-@Configuration(proxyBeanMethods = false)
-@ConditionalOnKubernetesDiscoveryEnabled
-@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES)
-@AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class,
- // So that CatalogSharedInformerFactory can be processed in prior to the default
- // factory
- KubernetesInformerAutoConfiguration.class })
-@AutoConfigureAfter({ KubernetesClientAutoConfiguration.class })
-@EnableConfigurationProperties(KubernetesDiscoveryProperties.class)
-public class KubernetesDiscoveryClientAutoConfiguration {
-
- @ConditionalOnClass({ HealthIndicator.class })
- @ConditionalOnDiscoveryEnabled
- @ConditionalOnDiscoveryHealthIndicatorEnabled
- @Configuration
- public static class KubernetesDiscoveryClientHealthIndicatorConfiguration {
-
- @Bean
- public KubernetesDiscoveryClientHealthIndicatorInitializer indicatorInitializer(
- ApplicationEventPublisher applicationEventPublisher, PodUtils podUtils) {
- return new KubernetesDiscoveryClientHealthIndicatorInitializer(podUtils, applicationEventPublisher);
- }
-
- }
-
- @Configuration(proxyBeanMethods = false)
- @ConditionalOnBlockingDiscoveryEnabled
- public static class KubernetesInformerDiscoveryConfiguration {
-
- @Bean
- @ConditionalOnMissingBean
- public SpringCloudKubernetesInformerFactoryProcessor discoveryInformerConfigurer(
- KubernetesNamespaceProvider kubernetesNamespaceProvider, ApiClient apiClient,
- CatalogSharedInformerFactory sharedInformerFactory, Environment environment) {
- // Injecting KubernetesDiscoveryProperties here would cause it to be
- // initialize too early
- // Instead get the all-namespaces property value from the Environment directly
- boolean allNamespaces = environment.getProperty("spring.cloud.kubernetes.discovery.all-namespaces",
- Boolean.class, false);
- return new SpringCloudKubernetesInformerFactoryProcessor(kubernetesNamespaceProvider, apiClient,
- sharedInformerFactory, allNamespaces);
- }
-
- @Bean
- @ConditionalOnMissingBean
- public CatalogSharedInformerFactory catalogSharedInformerFactory(ApiClient apiClient) {
- return new CatalogSharedInformerFactory();
- }
-
- @Bean
- @ConditionalOnMissingBean
- public KubernetesInformerDiscoveryClient kubernetesInformerDiscoveryClient(
- KubernetesNamespaceProvider kubernetesNamespaceProvider,
- CatalogSharedInformerFactory sharedInformerFactory, Lister serviceLister,
- Lister endpointsLister, SharedInformer serviceInformer,
- SharedInformer endpointsInformer, KubernetesDiscoveryProperties properties) {
- return new KubernetesInformerDiscoveryClient(kubernetesNamespaceProvider.getNamespace(),
- sharedInformerFactory, serviceLister, endpointsLister, serviceInformer, endpointsInformer,
- properties);
- }
-
- @KubernetesInformers({
- @KubernetesInformer(apiTypeClass = V1Service.class, apiListTypeClass = V1ServiceList.class,
- groupVersionResource = @GroupVersionResource(apiGroup = "", apiVersion = "v1",
- resourcePlural = "services")),
- @KubernetesInformer(apiTypeClass = V1Endpoints.class, apiListTypeClass = V1EndpointsList.class,
- groupVersionResource = @GroupVersionResource(apiGroup = "", apiVersion = "v1",
- resourcePlural = "endpoints")) })
- class CatalogSharedInformerFactory extends SharedInformerFactory {
-
- // TODO: optimization to ease memory pressure from continuous list&watch.
-
- }
-
- }
-
-}
diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfiguration.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfiguration.java
index 656750b7..954c1c14 100644
--- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfiguration.java
+++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfiguration.java
@@ -23,7 +23,7 @@ import org.springframework.context.annotation.Import;
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty("spring.cloud.config.discovery.enabled")
-@Import({ KubernetesClientAutoConfiguration.class, KubernetesDiscoveryClientAutoConfiguration.class })
+@Import({ KubernetesClientAutoConfiguration.class, KubernetesInformerDiscoveryClientAutoConfiguration.class })
public class KubernetesDiscoveryClientConfigClientBootstrapConfiguration {
}
diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryPropertiesAutoConfiguration.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryPropertiesAutoConfiguration.java
new file mode 100644
index 00000000..3c9f6f85
--- /dev/null
+++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryPropertiesAutoConfiguration.java
@@ -0,0 +1,28 @@
+/*
+ * 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.client.discovery;
+
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties;
+
+/**
+ * @author wind57
+ */
+@EnableConfigurationProperties(KubernetesDiscoveryProperties.class)
+public class KubernetesDiscoveryPropertiesAutoConfiguration {
+
+}
diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientAutoConfiguration.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientAutoConfiguration.java
new file mode 100644
index 00000000..150c247c
--- /dev/null
+++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientAutoConfiguration.java
@@ -0,0 +1,103 @@
+/*
+ * 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.client.discovery;
+
+import io.kubernetes.client.informer.SharedInformer;
+import io.kubernetes.client.informer.cache.Lister;
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.openapi.models.V1Endpoints;
+import io.kubernetes.client.openapi.models.V1Service;
+import io.kubernetes.client.spring.extended.controller.config.KubernetesInformerAutoConfiguration;
+
+import org.springframework.boot.actuate.health.HealthIndicator;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.cloud.CloudPlatform;
+import org.springframework.cloud.client.CommonsClientAutoConfiguration;
+import org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled;
+import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
+import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled;
+import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration;
+import org.springframework.cloud.kubernetes.client.KubernetesClientAutoConfiguration;
+import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
+import org.springframework.cloud.kubernetes.commons.PodUtils;
+import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnKubernetesDiscoveryEnabled;
+import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryClientHealthIndicatorInitializer;
+import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+
+/**
+ * @author wind57
+ */
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnDiscoveryEnabled
+@ConditionalOnKubernetesDiscoveryEnabled
+@ConditionalOnBlockingDiscoveryEnabled
+@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES)
+@AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class,
+ // So that CatalogSharedInformerFactory can be processed prior to the default
+ // factory
+ KubernetesInformerAutoConfiguration.class })
+@AutoConfigureAfter({ KubernetesClientAutoConfiguration.class, KubernetesDiscoveryPropertiesAutoConfiguration.class })
+public class KubernetesInformerDiscoveryClientAutoConfiguration {
+
+ @Bean
+ @ConditionalOnClass({ HealthIndicator.class })
+ @ConditionalOnDiscoveryHealthIndicatorEnabled
+ public KubernetesDiscoveryClientHealthIndicatorInitializer indicatorInitializer(
+ ApplicationEventPublisher applicationEventPublisher, PodUtils> podUtils) {
+ return new KubernetesDiscoveryClientHealthIndicatorInitializer(podUtils, applicationEventPublisher);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public KubernetesInformerDiscoveryClient kubernetesInformerDiscoveryClient(
+ KubernetesNamespaceProvider kubernetesNamespaceProvider, CatalogSharedInformerFactory sharedInformerFactory,
+ Lister serviceLister, Lister endpointsLister,
+ SharedInformer serviceInformer, SharedInformer endpointsInformer,
+ KubernetesDiscoveryProperties properties) {
+ return new KubernetesInformerDiscoveryClient(kubernetesNamespaceProvider.getNamespace(), sharedInformerFactory,
+ serviceLister, endpointsLister, serviceInformer, endpointsInformer, properties);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public CatalogSharedInformerFactory catalogSharedInformerFactory() {
+ return new CatalogSharedInformerFactory();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public SpringCloudKubernetesInformerFactoryProcessor discoveryInformerConfigurer(
+ KubernetesNamespaceProvider kubernetesNamespaceProvider, ApiClient apiClient,
+ CatalogSharedInformerFactory sharedInformerFactory, Environment environment) {
+ // Injecting KubernetesDiscoveryProperties here would cause it to be
+ // initialized too early.
+ // Instead, get the all-namespaces property value from the Environment directly
+ boolean allNamespaces = environment.getProperty("spring.cloud.kubernetes.discovery.all-namespaces",
+ Boolean.class, false);
+ return new SpringCloudKubernetesInformerFactoryProcessor(kubernetesNamespaceProvider, apiClient,
+ sharedInformerFactory, allNamespaces);
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/SpringCloudKubernetesInformerFactoryProcessor.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/SpringCloudKubernetesInformerFactoryProcessor.java
index ef4d574c..def53df5 100644
--- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/SpringCloudKubernetesInformerFactoryProcessor.java
+++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/SpringCloudKubernetesInformerFactoryProcessor.java
@@ -43,7 +43,7 @@ import org.springframework.core.ResolvableType;
/**
* @author Ryan Baxter
*/
-class SpringCloudKubernetesInformerFactoryProcessor extends KubernetesInformerFactoryProcessor {
+public class SpringCloudKubernetesInformerFactoryProcessor extends KubernetesInformerFactoryProcessor {
private static final Logger log = LoggerFactory.getLogger(SpringCloudKubernetesInformerFactoryProcessor.class);
@@ -58,7 +58,7 @@ class SpringCloudKubernetesInformerFactoryProcessor extends KubernetesInformerFa
private final KubernetesNamespaceProvider kubernetesNamespaceProvider;
@Autowired
- SpringCloudKubernetesInformerFactoryProcessor(KubernetesNamespaceProvider kubernetesNamespaceProvider,
+ public SpringCloudKubernetesInformerFactoryProcessor(KubernetesNamespaceProvider kubernetesNamespaceProvider,
ApiClient apiClient, SharedInformerFactory sharedInformerFactory, boolean allNamespaces) {
super();
this.apiClient = apiClient;
diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/catalog/KubernetesCatalogWatchAutoConfiguration.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/catalog/KubernetesCatalogWatchAutoConfiguration.java
index 52210ba1..1e4e6152 100644
--- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/catalog/KubernetesCatalogWatchAutoConfiguration.java
+++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/catalog/KubernetesCatalogWatchAutoConfiguration.java
@@ -25,6 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
import org.springframework.cloud.kubernetes.client.KubernetesClientAutoConfiguration;
+import org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryPropertiesAutoConfiguration;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnKubernetesCatalogEnabled;
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties;
@@ -39,13 +40,13 @@ import org.springframework.core.env.Environment;
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnDiscoveryEnabled
+@ConditionalOnKubernetesCatalogEnabled
@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES)
-@AutoConfigureAfter({ KubernetesClientAutoConfiguration.class })
+@AutoConfigureAfter({ KubernetesClientAutoConfiguration.class, KubernetesDiscoveryPropertiesAutoConfiguration.class })
class KubernetesCatalogWatchAutoConfiguration {
@Bean
@ConditionalOnMissingBean
- @ConditionalOnKubernetesCatalogEnabled
KubernetesCatalogWatch kubernetesCatalogWatch(CoreV1Api coreV1Api, ApiClient apiClient,
KubernetesDiscoveryProperties properties, Environment environment) {
return new KubernetesCatalogWatch(coreV1Api, apiClient, properties,
diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClient.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClient.java
index 83262c00..a02be9a4 100644
--- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClient.java
+++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClient.java
@@ -36,7 +36,7 @@ import org.springframework.util.Assert;
*/
public class KubernetesInformerReactiveDiscoveryClient implements ReactiveDiscoveryClient {
- private KubernetesInformerDiscoveryClient kubernetesDiscoveryClient;
+ private final KubernetesInformerDiscoveryClient kubernetesDiscoveryClient;
public KubernetesInformerReactiveDiscoveryClient(KubernetesNamespaceProvider kubernetesNamespaceProvider,
SharedInformerFactory sharedInformerFactory, Lister serviceLister,
diff --git a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClientAutoConfiguration.java b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClientAutoConfiguration.java
index 08538f41..9f8d03c8 100644
--- a/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClientAutoConfiguration.java
+++ b/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClientAutoConfiguration.java
@@ -19,13 +19,9 @@ package org.springframework.cloud.kubernetes.client.discovery.reactive;
import io.kubernetes.client.informer.SharedInformer;
import io.kubernetes.client.informer.SharedInformerFactory;
import io.kubernetes.client.informer.cache.Lister;
+import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.models.V1Endpoints;
-import io.kubernetes.client.openapi.models.V1EndpointsList;
import io.kubernetes.client.openapi.models.V1Service;
-import io.kubernetes.client.openapi.models.V1ServiceList;
-import io.kubernetes.client.spring.extended.controller.annotation.GroupVersionResource;
-import io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformer;
-import io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformers;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
@@ -43,12 +39,15 @@ import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIn
import org.springframework.cloud.client.discovery.health.reactive.ReactiveDiscoveryClientHealthIndicator;
import org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryClientAutoConfiguration;
import org.springframework.cloud.kubernetes.client.KubernetesClientPodUtils;
-import org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryClientAutoConfiguration;
+import org.springframework.cloud.kubernetes.client.discovery.CatalogSharedInformerFactory;
+import org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryPropertiesAutoConfiguration;
+import org.springframework.cloud.kubernetes.client.discovery.SpringCloudKubernetesInformerFactoryProcessor;
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnKubernetesDiscoveryEnabled;
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
/**
* @author Ryan Baxter
@@ -56,15 +55,28 @@ import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@ConditionalOnDiscoveryEnabled
+@ConditionalOnKubernetesDiscoveryEnabled
@ConditionalOnReactiveDiscoveryEnabled
@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES)
-@ConditionalOnKubernetesDiscoveryEnabled
@AutoConfigureBefore({ SimpleReactiveDiscoveryClientAutoConfiguration.class,
ReactiveCommonsClientAutoConfiguration.class })
@AutoConfigureAfter({ ReactiveCompositeDiscoveryClientAutoConfiguration.class,
- KubernetesDiscoveryClientAutoConfiguration.class })
+ KubernetesDiscoveryPropertiesAutoConfiguration.class })
public class KubernetesInformerReactiveDiscoveryClientAutoConfiguration {
+ @Bean
+ @ConditionalOnClass(name = "org.springframework.boot.actuate.health.ReactiveHealthIndicator")
+ @ConditionalOnDiscoveryHealthIndicatorEnabled
+ public ReactiveDiscoveryClientHealthIndicator kubernetesReactiveDiscoveryClientHealthIndicator(
+ KubernetesInformerReactiveDiscoveryClient client, DiscoveryClientHealthIndicatorProperties properties,
+ KubernetesClientPodUtils podUtils) {
+ ReactiveDiscoveryClientHealthIndicator healthIndicator = new ReactiveDiscoveryClientHealthIndicator(client,
+ properties);
+ InstanceRegisteredEvent> event = new InstanceRegisteredEvent<>(podUtils.currentPod(), null);
+ healthIndicator.onApplicationEvent(event);
+ return healthIndicator;
+ }
+
@Bean
@ConditionalOnMissingBean
public KubernetesInformerReactiveDiscoveryClient kubernetesReactiveDiscoveryClient(
@@ -77,29 +89,23 @@ public class KubernetesInformerReactiveDiscoveryClientAutoConfiguration {
}
@Bean
- @ConditionalOnClass(name = "org.springframework.boot.actuate.health.ReactiveHealthIndicator")
- @ConditionalOnDiscoveryHealthIndicatorEnabled
- public ReactiveDiscoveryClientHealthIndicator kubernetesReactiveDiscoveryClientHealthIndicator(
- KubernetesInformerReactiveDiscoveryClient client, DiscoveryClientHealthIndicatorProperties properties,
- KubernetesClientPodUtils podUtils) {
- ReactiveDiscoveryClientHealthIndicator healthIndicator = new ReactiveDiscoveryClientHealthIndicator(client,
- properties);
- InstanceRegisteredEvent event = new InstanceRegisteredEvent(podUtils.currentPod(), null);
- healthIndicator.onApplicationEvent(event);
- return healthIndicator;
+ @ConditionalOnMissingBean
+ public CatalogSharedInformerFactory catalogSharedInformerFactory() {
+ return new CatalogSharedInformerFactory();
}
- @KubernetesInformers({
- @KubernetesInformer(apiTypeClass = V1Service.class, apiListTypeClass = V1ServiceList.class,
- groupVersionResource = @GroupVersionResource(apiGroup = "", apiVersion = "v1",
- resourcePlural = "services")),
- @KubernetesInformer(apiTypeClass = V1Endpoints.class, apiListTypeClass = V1EndpointsList.class,
- groupVersionResource = @GroupVersionResource(apiGroup = "", apiVersion = "v1",
- resourcePlural = "endpoints")) })
- class CatalogSharedInformerFactory extends SharedInformerFactory {
-
- // TODO: optimization to ease memory pressure from continuous list&watch.
-
+ @Bean
+ @ConditionalOnMissingBean
+ public SpringCloudKubernetesInformerFactoryProcessor discoveryInformerConfigurer(
+ KubernetesNamespaceProvider kubernetesNamespaceProvider, ApiClient apiClient,
+ CatalogSharedInformerFactory sharedInformerFactory, Environment environment) {
+ // Injecting KubernetesDiscoveryProperties here would cause it to be
+ // initialized too early.
+ // Instead, get the all-namespaces property value from the Environment directly
+ boolean allNamespaces = environment.getProperty("spring.cloud.kubernetes.discovery.all-namespaces",
+ Boolean.class, false);
+ return new SpringCloudKubernetesInformerFactoryProcessor(kubernetesNamespaceProvider, apiClient,
+ sharedInformerFactory, allNamespaces);
}
}
diff --git a/spring-cloud-kubernetes-client-discovery/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-kubernetes-client-discovery/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index 608352b9..f058c16f 100644
--- a/spring-cloud-kubernetes-client-discovery/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/spring-cloud-kubernetes-client-discovery/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1,3 +1,4 @@
org.springframework.cloud.kubernetes.client.discovery.catalog.KubernetesCatalogWatchAutoConfiguration
-org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryClientAutoConfiguration
+org.springframework.cloud.kubernetes.client.discovery.KubernetesInformerDiscoveryClientAutoConfiguration
+org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryPropertiesAutoConfiguration
org.springframework.cloud.kubernetes.client.discovery.reactive.KubernetesInformerReactiveDiscoveryClientAutoConfiguration
diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests.java
index 3c506e43..3228927e 100644
--- a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests.java
+++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests.java
@@ -50,7 +50,7 @@ import static org.mockito.Mockito.when;
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty("spring.cloud.config.discovery.enabled")
-@Import({ KubernetesClientAutoConfiguration.class, KubernetesDiscoveryClientAutoConfiguration.class })
+@Import({ KubernetesClientAutoConfiguration.class, KubernetesInformerDiscoveryClientAutoConfiguration.class })
public class KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests {
private AnnotationConfigApplicationContext context;
@@ -83,13 +83,13 @@ public class KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests {
TestPropertyValues.of(env).applyTo(parent);
parent.register(UtilAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
EnvironmentKnobbler.class, KubernetesCommonsAutoConfiguration.class,
- KubernetesClientAutoConfiguration.class, KubernetesDiscoveryClientAutoConfiguration.class,
+ KubernetesClientAutoConfiguration.class, KubernetesInformerDiscoveryClientAutoConfiguration.class,
DiscoveryClientConfigServiceBootstrapConfiguration.class, ConfigClientProperties.class);
parent.refresh();
this.context = new AnnotationConfigApplicationContext();
this.context.setParent(parent);
this.context.register(PropertyPlaceholderAutoConfiguration.class, KubernetesCommonsAutoConfiguration.class,
- KubernetesDiscoveryClientAutoConfiguration.class);
+ KubernetesInformerDiscoveryClientAutoConfiguration.class);
this.context.refresh();
}
diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientAutoConfigurationApplicationContextTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientAutoConfigurationApplicationContextTests.java
new file mode 100644
index 00000000..7aca7cf9
--- /dev/null
+++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClientAutoConfigurationApplicationContextTests.java
@@ -0,0 +1,220 @@
+/*
+ * 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.client.discovery;
+
+import java.io.StringReader;
+
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.util.Config;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Test;
+import org.testcontainers.k3s.K3sContainer;
+
+import org.springframework.boot.actuate.health.HealthIndicator;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.FilteredClassLoader;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.cloud.kubernetes.client.KubernetesClientAutoConfiguration;
+import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryClientHealthIndicatorInitializer;
+import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Test various conditionals for
+ * {@link KubernetesInformerDiscoveryClientAutoConfiguration}
+ *
+ * @author wind57
+ */
+class KubernetesInformerDiscoveryClientAutoConfigurationApplicationContextTests {
+
+ private ApplicationContextRunner applicationContextRunner;
+
+ private static K3sContainer container;
+
+ @AfterAll
+ static void afterAll() {
+ container.stop();
+ }
+
+ @Test
+ void discoveryEnabledDefault() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false");
+ applicationContextRunner.run(context -> {
+ assertThat(context).hasSingleBean(KubernetesDiscoveryClientHealthIndicatorInitializer.class);
+ assertThat(context).hasSingleBean(KubernetesInformerDiscoveryClient.class);
+ assertThat(context).hasSingleBean(CatalogSharedInformerFactory.class);
+ assertThat(context).hasSingleBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void discoveryEnabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.enabled=true");
+ applicationContextRunner.run(context -> {
+ assertThat(context).hasSingleBean(KubernetesDiscoveryClientHealthIndicatorInitializer.class);
+ assertThat(context).hasSingleBean(KubernetesInformerDiscoveryClient.class);
+ assertThat(context).hasSingleBean(CatalogSharedInformerFactory.class);
+ assertThat(context).hasSingleBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void discoveryDisabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.enabled=false");
+ applicationContextRunner.run(context -> {
+ assertThat(context).doesNotHaveBean(KubernetesDiscoveryClientHealthIndicatorInitializer.class);
+ assertThat(context).doesNotHaveBean(KubernetesInformerDiscoveryClient.class);
+ assertThat(context).doesNotHaveBean(CatalogSharedInformerFactory.class);
+ assertThat(context).doesNotHaveBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void kubernetesDiscoveryEnabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.kubernetes.discovery.enabled=true");
+ applicationContextRunner.run(context -> {
+ assertThat(context).hasSingleBean(KubernetesDiscoveryClientHealthIndicatorInitializer.class);
+ assertThat(context).hasSingleBean(KubernetesInformerDiscoveryClient.class);
+ assertThat(context).hasSingleBean(CatalogSharedInformerFactory.class);
+ assertThat(context).hasSingleBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void kubernetesDiscoveryDisabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.kubernetes.discovery.enabled=false");
+ applicationContextRunner.run(context -> {
+ assertThat(context).doesNotHaveBean(KubernetesDiscoveryClientHealthIndicatorInitializer.class);
+ assertThat(context).doesNotHaveBean(KubernetesInformerDiscoveryClient.class);
+ assertThat(context).doesNotHaveBean(CatalogSharedInformerFactory.class);
+ assertThat(context).doesNotHaveBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void kubernetesDiscoveryBlockingEnabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.blocking.enabled=true");
+ applicationContextRunner.run(context -> {
+ assertThat(context).hasSingleBean(KubernetesDiscoveryClientHealthIndicatorInitializer.class);
+ assertThat(context).hasSingleBean(KubernetesInformerDiscoveryClient.class);
+ assertThat(context).hasSingleBean(CatalogSharedInformerFactory.class);
+ assertThat(context).hasSingleBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void kubernetesDiscoveryBlockingDisabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.blocking.enabled=false");
+ applicationContextRunner.run(context -> {
+ assertThat(context).doesNotHaveBean(KubernetesDiscoveryClientHealthIndicatorInitializer.class);
+ assertThat(context).doesNotHaveBean(KubernetesInformerDiscoveryClient.class);
+ assertThat(context).doesNotHaveBean(CatalogSharedInformerFactory.class);
+ assertThat(context).doesNotHaveBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void kubernetesDiscoveryHealthIndicatorEnabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.client.health-indicator.enabled=true");
+ applicationContextRunner.run(context -> {
+ assertThat(context).hasSingleBean(KubernetesDiscoveryClientHealthIndicatorInitializer.class);
+ assertThat(context).hasSingleBean(KubernetesInformerDiscoveryClient.class);
+ assertThat(context).hasSingleBean(CatalogSharedInformerFactory.class);
+ assertThat(context).hasSingleBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void kubernetesDiscoveryHealthIndicatorDisabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.client.health-indicator.enabled=false");
+ applicationContextRunner.run(context -> {
+ assertThat(context).doesNotHaveBean(KubernetesDiscoveryClientHealthIndicatorInitializer.class);
+ assertThat(context).hasSingleBean(KubernetesInformerDiscoveryClient.class);
+ assertThat(context).hasSingleBean(CatalogSharedInformerFactory.class);
+ assertThat(context).hasSingleBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void kubernetesDiscoveryHealthIndicatorEnabledHealthIndicatorMissing() {
+ setupWithFilteredClassLoader(HealthIndicator.class, "spring.main.cloud-platform=KUBERNETES",
+ "spring.cloud.config.enabled=false", "spring.cloud.discovery.client.health-indicator.enabled=true");
+ applicationContextRunner.run(context -> {
+ assertThat(context).doesNotHaveBean(KubernetesDiscoveryClientHealthIndicatorInitializer.class);
+ assertThat(context).hasSingleBean(KubernetesInformerDiscoveryClient.class);
+ assertThat(context).hasSingleBean(CatalogSharedInformerFactory.class);
+ assertThat(context).hasSingleBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ /**
+ * reactive is disabled and should not impact blocking in any way
+ */
+ @Test
+ void reactiveDisabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.reactive.enabled=false");
+ applicationContextRunner.run(context -> {
+ assertThat(context).hasSingleBean(KubernetesDiscoveryClientHealthIndicatorInitializer.class);
+ assertThat(context).hasSingleBean(KubernetesInformerDiscoveryClient.class);
+ assertThat(context).hasSingleBean(CatalogSharedInformerFactory.class);
+ assertThat(context).hasSingleBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ private void setup(String... properties) {
+ applicationContextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(KubernetesInformerDiscoveryClientAutoConfiguration.class,
+ KubernetesClientAutoConfiguration.class, KubernetesDiscoveryPropertiesAutoConfiguration.class))
+ .withUserConfiguration(ApiClientConfig.class).withPropertyValues(properties);
+ }
+
+ private void setupWithFilteredClassLoader(Class> cls, String... properties) {
+ applicationContextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(KubernetesInformerDiscoveryClientAutoConfiguration.class,
+ KubernetesClientAutoConfiguration.class, KubernetesDiscoveryPropertiesAutoConfiguration.class))
+ .withClassLoader(new FilteredClassLoader(cls)).withUserConfiguration(ApiClientConfig.class)
+ .withPropertyValues(properties);
+ }
+
+ @Configuration
+ static class ApiClientConfig {
+
+ @Bean
+ @Primary
+ ApiClient apiClient() throws Exception {
+ container = Commons.container();
+ container.start();
+
+ return Config.fromConfig(new StringReader(container.getKubeConfigYaml()));
+ }
+
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/catalog/KubernetesCatalogWatchAutoConfigurationApplicationContextTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/catalog/KubernetesCatalogWatchAutoConfigurationApplicationContextTests.java
new file mode 100644
index 00000000..8f9af495
--- /dev/null
+++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/catalog/KubernetesCatalogWatchAutoConfigurationApplicationContextTests.java
@@ -0,0 +1,111 @@
+/*
+ * 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.client.discovery.catalog;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.cloud.kubernetes.client.KubernetesClientAutoConfiguration;
+import org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryPropertiesAutoConfiguration;
+import org.springframework.cloud.kubernetes.client.discovery.KubernetesInformerDiscoveryClient;
+import org.springframework.cloud.kubernetes.client.discovery.reactive.KubernetesInformerReactiveDiscoveryClient;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Test various conditionals for {@link KubernetesCatalogWatch}
+ *
+ * @author wind57
+ */
+class KubernetesCatalogWatchAutoConfigurationApplicationContextTests {
+
+ private ApplicationContextRunner applicationContextRunner;
+
+ @Test
+ void discoveryEnabledDefault() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false");
+ applicationContextRunner.run(context -> assertThat(context).hasSingleBean(KubernetesCatalogWatch.class));
+ }
+
+ @Test
+ void discoveryEnabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.enabled=true");
+ applicationContextRunner.run(context -> assertThat(context).hasSingleBean(KubernetesCatalogWatch.class));
+ }
+
+ @Test
+ void discoveryDisabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.enabled=false");
+ applicationContextRunner.run(context -> assertThat(context).doesNotHaveBean(KubernetesCatalogWatch.class));
+ }
+
+ @Test
+ void kubernetesDiscoveryEnabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.kubernetes.discovery.enabled=true");
+ applicationContextRunner.run(context -> assertThat(context).hasSingleBean(KubernetesCatalogWatch.class));
+ }
+
+ // disabling discovery has no impact on the catalog watch.
+ @Test
+ void kubernetesDiscoveryDisabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.kubernetes.discovery.enabled=false");
+ applicationContextRunner.run(context -> assertThat(context).hasSingleBean(KubernetesCatalogWatch.class));
+ }
+
+ /**
+ * both blocking and reactive configs are disabled, should not influence catalog
+ * watcher in any way.
+ */
+ @Test
+ void disableBlockingAndReactive() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.blocking.enabled=false", "spring.cloud.discovery.reactive.enabled=false");
+ applicationContextRunner.run(context -> {
+ assertThat(context).hasSingleBean(KubernetesCatalogWatch.class);
+ assertThat(context).doesNotHaveBean(KubernetesInformerReactiveDiscoveryClient.class);
+ assertThat(context).doesNotHaveBean(KubernetesInformerDiscoveryClient.class);
+ });
+ }
+
+ /**
+ * both blocking and reactive configs are disabled, should not influence catalog
+ * watcher in any way.
+ */
+ @Test
+ void disableKubernetesDiscovery() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.kubernetes.discovery.enabled=false");
+ applicationContextRunner.run(context -> {
+ assertThat(context).hasSingleBean(KubernetesCatalogWatch.class);
+ assertThat(context).doesNotHaveBean(KubernetesInformerReactiveDiscoveryClient.class);
+ assertThat(context).doesNotHaveBean(KubernetesInformerDiscoveryClient.class);
+ });
+ }
+
+ private void setup(String... properties) {
+ applicationContextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(KubernetesCatalogWatchAutoConfiguration.class,
+ KubernetesClientAutoConfiguration.class, KubernetesDiscoveryPropertiesAutoConfiguration.class))
+ .withPropertyValues(properties);
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClientAutoConfigurationApplicationContextTests.java b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClientAutoConfigurationApplicationContextTests.java
new file mode 100644
index 00000000..08105ecc
--- /dev/null
+++ b/spring-cloud-kubernetes-client-discovery/src/test/java/org/springframework/cloud/kubernetes/client/discovery/reactive/KubernetesInformerReactiveDiscoveryClientAutoConfigurationApplicationContextTests.java
@@ -0,0 +1,194 @@
+/*
+ * 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.client.discovery.reactive;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.FilteredClassLoader;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.cloud.client.discovery.health.reactive.ReactiveDiscoveryClientHealthIndicator;
+import org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryClientAutoConfiguration;
+import org.springframework.cloud.commons.util.UtilAutoConfiguration;
+import org.springframework.cloud.kubernetes.client.KubernetesClientAutoConfiguration;
+import org.springframework.cloud.kubernetes.client.discovery.CatalogSharedInformerFactory;
+import org.springframework.cloud.kubernetes.client.discovery.KubernetesDiscoveryPropertiesAutoConfiguration;
+import org.springframework.cloud.kubernetes.client.discovery.SpringCloudKubernetesInformerFactoryProcessor;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Test various conditionals for
+ * {@link KubernetesInformerReactiveDiscoveryClientAutoConfiguration}
+ *
+ * @author wind57
+ */
+class KubernetesInformerReactiveDiscoveryClientAutoConfigurationApplicationContextTests {
+
+ private ApplicationContextRunner applicationContextRunner;
+
+ @Test
+ void discoveryEnabledDefault() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false");
+ applicationContextRunner.run(context -> {
+ // simple from commons and ours
+ assertThat(context).getBeans(ReactiveDiscoveryClientHealthIndicator.class).size().isEqualTo(2);
+ assertThat(context).hasSingleBean(KubernetesInformerReactiveDiscoveryClient.class);
+ assertThat(context).hasSingleBean(CatalogSharedInformerFactory.class);
+ assertThat(context).hasSingleBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void discoveryEnabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.enabled=true");
+ applicationContextRunner.run(context -> {
+ // simple from commons and ours
+ assertThat(context).getBeans(ReactiveDiscoveryClientHealthIndicator.class).size().isEqualTo(2);
+ assertThat(context).hasSingleBean(KubernetesInformerReactiveDiscoveryClient.class);
+ assertThat(context).hasSingleBean(CatalogSharedInformerFactory.class);
+ assertThat(context).hasSingleBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void discoveryDisabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.enabled=false");
+ applicationContextRunner.run(context -> {
+ // simple from commons and ours
+ assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class);
+ assertThat(context).doesNotHaveBean(KubernetesInformerReactiveDiscoveryClient.class);
+ assertThat(context).doesNotHaveBean(CatalogSharedInformerFactory.class);
+ assertThat(context).doesNotHaveBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void kubernetesDiscoveryEnabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.kubernetes.discovery.enabled=true");
+ applicationContextRunner.run(context -> {
+ // simple from commons and ours
+ assertThat(context).getBeans(ReactiveDiscoveryClientHealthIndicator.class).size().isEqualTo(2);
+ assertThat(context).hasSingleBean(KubernetesInformerReactiveDiscoveryClient.class);
+ assertThat(context).hasSingleBean(CatalogSharedInformerFactory.class);
+ assertThat(context).hasSingleBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void kubernetesDiscoveryDisabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.kubernetes.discovery.enabled=false");
+ applicationContextRunner.run(context -> {
+ // only ours as the "simple" one from commons is not picked-up
+ assertThat(context).hasSingleBean(ReactiveDiscoveryClientHealthIndicator.class);
+ assertThat(context).doesNotHaveBean(KubernetesInformerReactiveDiscoveryClient.class);
+ assertThat(context).doesNotHaveBean(CatalogSharedInformerFactory.class);
+ assertThat(context).doesNotHaveBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void kubernetesReactiveDiscoveryEnabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.reactive.enabled=true");
+ applicationContextRunner.run(context -> {
+ // simple from commons and ours
+ assertThat(context).getBeans(ReactiveDiscoveryClientHealthIndicator.class).size().isEqualTo(2);
+ assertThat(context).hasSingleBean(KubernetesInformerReactiveDiscoveryClient.class);
+ assertThat(context).hasSingleBean(CatalogSharedInformerFactory.class);
+ assertThat(context).hasSingleBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void kubernetesReactiveDiscoveryDisabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.reactive.enabled=false");
+ applicationContextRunner.run(context -> {
+ assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class);
+ assertThat(context).doesNotHaveBean(KubernetesInformerReactiveDiscoveryClient.class);
+ assertThat(context).doesNotHaveBean(CatalogSharedInformerFactory.class);
+ assertThat(context).doesNotHaveBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ /**
+ * blocking is disabled, and it should not impact reactive in any way.
+ */
+ @Test
+ void blockingDisabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.blocking.enabled=false");
+ applicationContextRunner.run(context -> {
+ // simple from commons and ours
+ assertThat(context).getBeans(ReactiveDiscoveryClientHealthIndicator.class).size().isEqualTo(2);
+ assertThat(context).hasSingleBean(KubernetesInformerReactiveDiscoveryClient.class);
+ assertThat(context).hasSingleBean(CatalogSharedInformerFactory.class);
+ assertThat(context).hasSingleBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void healthDisabled() {
+ setup("spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.client.health-indicator.enabled=false");
+ applicationContextRunner.run(context -> {
+ // simple from commons
+ assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class);
+ assertThat(context).hasSingleBean(KubernetesInformerReactiveDiscoveryClient.class);
+ assertThat(context).hasSingleBean(CatalogSharedInformerFactory.class);
+ assertThat(context).hasSingleBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ @Test
+ void healthEnabledClassNotPresent() {
+ setupWithFilteredClassLoader("org.springframework.boot.actuate.health.ReactiveHealthIndicator",
+ "spring.main.cloud-platform=KUBERNETES", "spring.cloud.config.enabled=false",
+ "spring.cloud.discovery.client.health-indicator.enabled=false");
+ applicationContextRunner.run(context -> {
+ // simple from commons
+ assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class);
+ assertThat(context).hasSingleBean(KubernetesInformerReactiveDiscoveryClient.class);
+ assertThat(context).hasSingleBean(CatalogSharedInformerFactory.class);
+ assertThat(context).hasSingleBean(SpringCloudKubernetesInformerFactoryProcessor.class);
+ });
+ }
+
+ private void setup(String... properties) {
+ applicationContextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(
+ KubernetesInformerReactiveDiscoveryClientAutoConfiguration.class,
+ KubernetesClientAutoConfiguration.class, SimpleReactiveDiscoveryClientAutoConfiguration.class,
+ UtilAutoConfiguration.class, KubernetesDiscoveryPropertiesAutoConfiguration.class))
+ .withPropertyValues(properties);
+ }
+
+ private void setupWithFilteredClassLoader(String name, String... properties) {
+ applicationContextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(
+ KubernetesInformerReactiveDiscoveryClientAutoConfiguration.class,
+ KubernetesClientAutoConfiguration.class, SimpleReactiveDiscoveryClientAutoConfiguration.class,
+ UtilAutoConfiguration.class, KubernetesDiscoveryPropertiesAutoConfiguration.class))
+ .withClassLoader(new FilteredClassLoader(name)).withPropertyValues(properties);
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-discovery/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-client-discovery/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..ee243343
--- /dev/null
+++ b/spring-cloud-kubernetes-client-discovery/src/test/resources/logback-test.xml
@@ -0,0 +1,15 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesCatalogWatchAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesCatalogWatchAutoConfiguration.java
index d4f56566..58334dea 100644
--- a/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesCatalogWatchAutoConfiguration.java
+++ b/spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/KubernetesCatalogWatchAutoConfiguration.java
@@ -38,13 +38,13 @@ import org.springframework.core.env.Environment;
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnDiscoveryEnabled
+@ConditionalOnKubernetesCatalogEnabled
@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES)
@AutoConfigureAfter({ Fabric8AutoConfiguration.class })
public class KubernetesCatalogWatchAutoConfiguration {
@Bean
@ConditionalOnMissingBean
- @ConditionalOnKubernetesCatalogEnabled
public KubernetesCatalogWatch kubernetesCatalogWatch(KubernetesClient client,
KubernetesDiscoveryProperties properties, Environment environment) {
return new KubernetesCatalogWatch(client, properties, new KubernetesNamespaceProvider(environment));