fix 1207 for kubernetes native client (#1208)
This commit is contained in:
@@ -65,6 +65,11 @@
|
||||
<artifactId>reactor-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-kubernetes-test-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.tomakehurst</groupId>
|
||||
<artifactId>wiremock-jre8-standalone</artifactId>
|
||||
|
||||
@@ -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.
|
||||
|
||||
}
|
||||
@@ -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<V1Service> serviceLister,
|
||||
Lister<V1Endpoints> endpointsLister, SharedInformer<V1Service> serviceInformer,
|
||||
SharedInformer<V1Endpoints> 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.
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
@@ -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<V1Service> serviceLister, Lister<V1Endpoints> endpointsLister,
|
||||
SharedInformer<V1Service> serviceInformer, SharedInformer<V1Endpoints> 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<V1Service> serviceLister,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
|
||||
<logger name="org.testcontainers" level="INFO"/>
|
||||
<logger name="com.github.dockerjava" level="WARN"/>
|
||||
<logger name="io.fabric8.kubernetes.client" level="ERROR"/>
|
||||
</configuration>
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user