Skip to content

Commit debd44c

Browse files
authored
Merge pull request #2058 from wind57/major-changes-in-k8s-client-discovery-implementation
Major changes in k8s client discovery implementation
2 parents 4ad2fe5 + a921c4a commit debd44c

File tree

64 files changed

+754
-692
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+754
-692
lines changed

spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/ConditionalOnSelectiveNamespacesMissing.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
*
3434
* @author wind57
3535
*/
36-
public final class ConditionalOnSelectiveNamespacesMissing implements ConfigurationCondition {
36+
final class ConditionalOnSelectiveNamespacesMissing implements ConfigurationCondition {
3737

3838
private static final LogAccessor LOG = new LogAccessor(
3939
LogFactory.getLog(ConditionalOnSelectiveNamespacesMissing.class));

spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/ConditionalOnSelectiveNamespacesPresent.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
*
3434
* @author wind57
3535
*/
36-
public final class ConditionalOnSelectiveNamespacesPresent implements ConfigurationCondition {
36+
final class ConditionalOnSelectiveNamespacesPresent implements ConfigurationCondition {
3737

3838
private static final LogAccessor LOG = new LogAccessor(
3939
LogFactory.getLog(ConditionalOnSelectiveNamespacesPresent.class));
Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.cloud.kubernetes.client.discovery.catalog;
17+
package org.springframework.cloud.kubernetes.client.discovery;
1818

1919
import java.util.List;
2020
import java.util.function.Function;
@@ -32,7 +32,6 @@
3232
import org.springframework.cloud.kubernetes.commons.discovery.EndpointNameAndNamespace;
3333
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties;
3434
import org.springframework.context.ApplicationEventPublisher;
35-
import org.springframework.context.ApplicationEventPublisherAware;
3635
import org.springframework.core.log.LogAccessor;
3736
import org.springframework.scheduling.annotation.Scheduled;
3837

@@ -46,25 +45,21 @@
4645
*
4746
* @author wind57
4847
*/
49-
class KubernetesCatalogWatch implements ApplicationEventPublisherAware {
48+
final class KubernetesClientCatalogWatch {
5049

51-
private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(KubernetesCatalogWatch.class));
50+
private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(KubernetesClientCatalogWatch.class));
5251

53-
private final KubernetesCatalogWatchContext context;
52+
private final KubernetesClientCatalogWatchContext context;
5453

55-
private Function<KubernetesCatalogWatchContext, List<EndpointNameAndNamespace>> stateGenerator;
54+
private Function<KubernetesClientCatalogWatchContext, List<EndpointNameAndNamespace>> stateGenerator;
5655

5756
private volatile List<EndpointNameAndNamespace> catalogEndpointsState = null;
5857

59-
private ApplicationEventPublisher publisher;
58+
private final ApplicationEventPublisher publisher;
6059

61-
KubernetesCatalogWatch(CoreV1Api coreV1Api, ApiClient apiClient, KubernetesDiscoveryProperties properties,
62-
KubernetesNamespaceProvider namespaceProvider) {
63-
context = new KubernetesCatalogWatchContext(coreV1Api, apiClient, properties, namespaceProvider);
64-
}
65-
66-
@Override
67-
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
60+
KubernetesClientCatalogWatch(CoreV1Api coreV1Api, ApiClient apiClient, KubernetesDiscoveryProperties properties,
61+
KubernetesNamespaceProvider namespaceProvider, ApplicationEventPublisher publisher) {
62+
context = new KubernetesClientCatalogWatchContext(coreV1Api, apiClient, properties, namespaceProvider);
6863
this.publisher = publisher;
6964
}
7065

@@ -91,9 +86,9 @@ void postConstruct() {
9186
stateGenerator = stateGenerator();
9287
}
9388

94-
Function<KubernetesCatalogWatchContext, List<EndpointNameAndNamespace>> stateGenerator() {
89+
Function<KubernetesClientCatalogWatchContext, List<EndpointNameAndNamespace>> stateGenerator() {
9590

96-
Function<KubernetesCatalogWatchContext, List<EndpointNameAndNamespace>> localStateGenerator;
91+
Function<KubernetesClientCatalogWatchContext, List<EndpointNameAndNamespace>> localStateGenerator;
9792

9893
if (context.properties().useEndpointSlices()) {
9994
// this emulates : 'kubectl api-resources | grep -i EndpointSlice'
@@ -108,7 +103,7 @@ Function<KubernetesCatalogWatchContext, List<EndpointNameAndNamespace>> stateGen
108103
throw new IllegalArgumentException("EndpointSlices are not supported on the cluster");
109104
}
110105
else {
111-
localStateGenerator = new KubernetesEndpointSlicesCatalogWatch();
106+
localStateGenerator = new KubernetesClientEndpointSlicesCatalogWatch();
112107
}
113108
}
114109
catch (ApiException e) {
@@ -117,7 +112,7 @@ Function<KubernetesCatalogWatchContext, List<EndpointNameAndNamespace>> stateGen
117112

118113
}
119114
else {
120-
localStateGenerator = new KubernetesEndpointsCatalogWatch();
115+
localStateGenerator = new KubernetesClientEndpointsCatalogWatch();
121116
}
122117

123118
LOG.debug(() -> "stateGenerator is of type: " + localStateGenerator.getClass().getSimpleName());
Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.cloud.kubernetes.client.discovery.catalog;
17+
package org.springframework.cloud.kubernetes.client.discovery;
1818

1919
import io.kubernetes.client.openapi.ApiClient;
2020
import io.kubernetes.client.openapi.apis.CoreV1Api;
@@ -26,6 +26,7 @@
2626
import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnKubernetesCatalogWatcherEnabled;
2727
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties;
2828
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryPropertiesAutoConfiguration;
29+
import org.springframework.context.ApplicationEventPublisher;
2930
import org.springframework.context.annotation.Bean;
3031
import org.springframework.context.annotation.Configuration;
3132
import org.springframework.core.env.Environment;
@@ -38,14 +39,14 @@
3839
@Configuration(proxyBeanMethods = false)
3940
@ConditionalOnKubernetesCatalogWatcherEnabled
4041
@AutoConfigureAfter({ KubernetesClientAutoConfiguration.class, KubernetesDiscoveryPropertiesAutoConfiguration.class })
41-
class KubernetesCatalogWatchAutoConfiguration {
42+
final class KubernetesClientCatalogWatchAutoConfiguration {
4243

4344
@Bean
4445
@ConditionalOnMissingBean
45-
KubernetesCatalogWatch kubernetesCatalogWatch(CoreV1Api coreV1Api, ApiClient apiClient,
46-
KubernetesDiscoveryProperties properties, Environment environment) {
47-
return new KubernetesCatalogWatch(coreV1Api, apiClient, properties,
48-
new KubernetesNamespaceProvider(environment));
46+
KubernetesClientCatalogWatch kubernetesClientCatalogWatch(CoreV1Api coreV1Api, ApiClient apiClient,
47+
KubernetesDiscoveryProperties properties, Environment environment, ApplicationEventPublisher publisher) {
48+
return new KubernetesClientCatalogWatch(coreV1Api, apiClient, properties,
49+
new KubernetesNamespaceProvider(environment), publisher);
4950
}
5051

5152
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.cloud.kubernetes.client.discovery.catalog;
17+
package org.springframework.cloud.kubernetes.client.discovery;
1818

1919
import java.util.Comparator;
2020
import java.util.List;
@@ -37,8 +37,8 @@
3737
*
3838
* @author wind57
3939
*/
40-
record KubernetesCatalogWatchContext(CoreV1Api coreV1Api, ApiClient apiClient, KubernetesDiscoveryProperties properties,
41-
KubernetesNamespaceProvider namespaceProvider) {
40+
record KubernetesClientCatalogWatchContext(CoreV1Api coreV1Api, ApiClient apiClient,
41+
KubernetesDiscoveryProperties properties, KubernetesNamespaceProvider namespaceProvider) {
4242

4343
static List<EndpointNameAndNamespace> state(Stream<V1ObjectReference> references) {
4444
return references.filter(Objects::nonNull)

spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesClientConfigServerBootstrapper.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.util.Collections;
2020
import java.util.List;
21+
import java.util.function.Predicate;
2122

2223
import io.kubernetes.client.informer.SharedIndexInformer;
2324
import io.kubernetes.client.informer.SharedInformerFactory;
@@ -50,7 +51,7 @@
5051
/**
5152
* @author Ryan Baxter
5253
*/
53-
class KubernetesClientConfigServerBootstrapper extends KubernetesConfigServerBootstrapper {
54+
final class KubernetesClientConfigServerBootstrapper extends KubernetesConfigServerBootstrapper {
5455

5556
private static final Log LOG = LogFactory.getLog(KubernetesClientConfigServerBootstrapper.class);
5657

@@ -70,8 +71,9 @@ public void initialize(BootstrapRegistry registry) {
7071
if (!getDiscoveryEnabled(context)) {
7172
return (id) -> Collections.emptyList();
7273
}
73-
if (context.isRegistered(KubernetesInformerDiscoveryClient.class)) {
74-
KubernetesInformerDiscoveryClient client = context.get(KubernetesInformerDiscoveryClient.class);
74+
if (context.isRegistered(KubernetesClientInformerDiscoveryClient.class)) {
75+
KubernetesClientInformerDiscoveryClient client = context
76+
.get(KubernetesClientInformerDiscoveryClient.class);
7577
return client::getInstances;
7678
}
7779
else {
@@ -97,10 +99,11 @@ public void initialize(BootstrapRegistry registry) {
9799
SharedIndexInformer<V1Endpoints> endpointsSharedIndexInformer = sharedInformerFactory
98100
.sharedIndexInformerFor(endpointsApi, V1Endpoints.class, 0L, namespace);
99101
Lister<V1Endpoints> endpointsLister = new Lister<>(endpointsSharedIndexInformer.getIndexer());
100-
KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(
102+
Predicate<V1Service> predicate = x -> true;
103+
KubernetesClientInformerDiscoveryClient discoveryClient = new KubernetesClientInformerDiscoveryClient(
101104
List.of(sharedInformerFactory), List.of(serviceLister), List.of(endpointsLister),
102105
List.of(serviceSharedIndexInformer), List.of(endpointsSharedIndexInformer), discoveryProperties,
103-
new CoreV1Api(apiClient));
106+
new CoreV1Api(apiClient), predicate);
104107
try {
105108
discoveryClient.afterPropertiesSet();
106109
return discoveryClient::getInstances;
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
@Configuration(proxyBeanMethods = false)
2525
@ConditionalOnProperty("spring.cloud.config.discovery.enabled")
26-
@Import({ KubernetesClientAutoConfiguration.class, KubernetesInformerDiscoveryClientAutoConfiguration.class })
27-
public class KubernetesDiscoveryClientConfigClientBootstrapConfiguration {
26+
@Import({ KubernetesClientAutoConfiguration.class, KubernetesClientInformerDiscoveryClientAutoConfiguration.class })
27+
final class KubernetesClientDiscoveryClientConfigClientBootstrapConfiguration {
2828

2929
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright 2012-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.kubernetes.client.discovery;
18+
19+
import java.util.Optional;
20+
import java.util.function.Predicate;
21+
22+
import io.kubernetes.client.openapi.models.V1Service;
23+
24+
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
25+
import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform;
26+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
27+
import org.springframework.boot.cloud.CloudPlatform;
28+
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
29+
import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnBlockingOrReactiveDiscoveryEnabled;
30+
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties;
31+
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryPropertiesAutoConfiguration;
32+
import org.springframework.context.annotation.Bean;
33+
import org.springframework.context.annotation.Configuration;
34+
import org.springframework.expression.Expression;
35+
import org.springframework.expression.spel.standard.SpelExpressionParser;
36+
import org.springframework.expression.spel.support.SimpleEvaluationContext;
37+
38+
/**
39+
* @author wind57
40+
*/
41+
@Configuration(proxyBeanMethods = false)
42+
@ConditionalOnDiscoveryEnabled
43+
@ConditionalOnBlockingOrReactiveDiscoveryEnabled
44+
@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES)
45+
@AutoConfigureAfter(KubernetesDiscoveryPropertiesAutoConfiguration.class)
46+
final class KubernetesClientDiscoveryClientSpelAutoConfiguration {
47+
48+
@Bean
49+
@ConditionalOnMissingBean
50+
Predicate<V1Service> predicate(KubernetesDiscoveryProperties properties) {
51+
SpelExpressionParser parser = new SpelExpressionParser();
52+
SimpleEvaluationContext evaluationContext = SimpleEvaluationContext.forReadOnlyDataBinding()
53+
.withInstanceMethods()
54+
.build();
55+
56+
String spelExpression = properties.filter();
57+
Predicate<V1Service> predicate;
58+
if (spelExpression == null || spelExpression.isEmpty()) {
59+
predicate = service -> true;
60+
}
61+
else {
62+
Expression filterExpr = parser.parseExpression(spelExpression);
63+
predicate = service -> {
64+
Boolean include = filterExpr.getValue(evaluationContext, service, Boolean.class);
65+
return Optional.ofNullable(include).orElse(false);
66+
};
67+
}
68+
return predicate;
69+
}
70+
71+
}
Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.util.List;
2222
import java.util.Map;
2323
import java.util.Optional;
24-
import java.util.function.Predicate;
2524
import java.util.function.Supplier;
2625
import java.util.stream.Collectors;
2726

@@ -39,9 +38,6 @@
3938
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties;
4039
import org.springframework.cloud.kubernetes.commons.discovery.ServiceMetadata;
4140
import org.springframework.core.log.LogAccessor;
42-
import org.springframework.expression.Expression;
43-
import org.springframework.expression.spel.standard.SpelExpressionParser;
44-
import org.springframework.expression.spel.support.SimpleEvaluationContext;
4541
import org.springframework.util.CollectionUtils;
4642

4743
import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryConstants.UNSET_PORT_NAME;
@@ -50,17 +46,12 @@
5046
/**
5147
* @author wind57
5248
*/
53-
final class KubernetesDiscoveryClientUtils {
49+
final class KubernetesClientDiscoveryClientUtils {
5450

55-
private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(KubernetesDiscoveryClientUtils.class));
51+
private static final LogAccessor LOG = new LogAccessor(
52+
LogFactory.getLog(KubernetesClientDiscoveryClientUtils.class));
5653

57-
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
58-
59-
private static final SimpleEvaluationContext EVALUATION_CONTEXT = SimpleEvaluationContext.forReadOnlyDataBinding()
60-
.withInstanceMethods()
61-
.build();
62-
63-
private KubernetesDiscoveryClientUtils() {
54+
private KubernetesClientDiscoveryClientUtils() {
6455

6556
}
6657

@@ -89,24 +80,6 @@ static boolean matchesServiceLabels(V1Service service, KubernetesDiscoveryProper
8980

9081
}
9182

92-
static Predicate<V1Service> filter(KubernetesDiscoveryProperties properties) {
93-
String spelExpression = properties.filter();
94-
Predicate<V1Service> predicate;
95-
if (spelExpression == null || spelExpression.isEmpty()) {
96-
LOG.debug(() -> "filter not defined, returning always true predicate");
97-
predicate = service -> true;
98-
}
99-
else {
100-
Expression filterExpr = PARSER.parseExpression(spelExpression);
101-
predicate = service -> {
102-
Boolean include = filterExpr.getValue(EVALUATION_CONTEXT, service, Boolean.class);
103-
return Optional.ofNullable(include).orElse(false);
104-
};
105-
LOG.debug(() -> "returning predicate based on filter expression: " + spelExpression);
106-
}
107-
return predicate;
108-
}
109-
11083
static void postConstruct(List<SharedInformerFactory> sharedInformerFactories,
11184
KubernetesDiscoveryProperties properties, Supplier<Boolean> informersReadyFunc,
11285
List<Lister<V1Service>> serviceListers) {
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.cloud.kubernetes.client.discovery.catalog;
17+
package org.springframework.cloud.kubernetes.client.discovery;
1818

1919
import java.util.ArrayList;
2020
import java.util.Collections;
@@ -35,21 +35,21 @@
3535
import org.springframework.cloud.kubernetes.commons.discovery.EndpointNameAndNamespace;
3636
import org.springframework.core.log.LogAccessor;
3737

38-
import static org.springframework.cloud.kubernetes.client.discovery.catalog.KubernetesCatalogWatchContext.labelSelector;
38+
import static org.springframework.cloud.kubernetes.client.discovery.KubernetesClientCatalogWatchContext.labelSelector;
3939

4040
/**
4141
* Implementation that is based on EndpointSlice V1.
4242
*
4343
* @author wind57
4444
*/
45-
final class KubernetesEndpointSlicesCatalogWatch
46-
implements Function<KubernetesCatalogWatchContext, List<EndpointNameAndNamespace>> {
45+
final class KubernetesClientEndpointSlicesCatalogWatch
46+
implements Function<KubernetesClientCatalogWatchContext, List<EndpointNameAndNamespace>> {
4747

4848
private static final LogAccessor LOG = new LogAccessor(
49-
LogFactory.getLog(KubernetesEndpointSlicesCatalogWatch.class));
49+
LogFactory.getLog(KubernetesClientEndpointSlicesCatalogWatch.class));
5050

5151
@Override
52-
public List<EndpointNameAndNamespace> apply(KubernetesCatalogWatchContext context) {
52+
public List<EndpointNameAndNamespace> apply(KubernetesClientCatalogWatchContext context) {
5353

5454
List<V1EndpointSlice> endpointSlices;
5555
DiscoveryV1Api api = new DiscoveryV1Api(context.apiClient());
@@ -85,7 +85,7 @@ List<EndpointNameAndNamespace> generateState(List<V1EndpointSlice> endpointSlice
8585
.flatMap(List::stream)
8686
.map(V1Endpoint::getTargetRef);
8787

88-
return KubernetesCatalogWatchContext.state(references);
88+
return KubernetesClientCatalogWatchContext.state(references);
8989
}
9090

9191
private List<V1EndpointSlice> endpointSlices(DiscoveryV1Api api, Map<String, String> labels) {

0 commit comments

Comments
 (0)