Skip to content

Commit 0078ee1

Browse files
authored
Merge pull request #2053 from wind57/major-changes-in-fabric8-discovery-implementation
major refactor of fabric8 discovery implementation
2 parents c1a53a7 + 39f5c31 commit 0078ee1

File tree

52 files changed

+870
-1083
lines changed

Some content is hidden

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

52 files changed

+870
-1083
lines changed

docs/modules/ROOT/pages/discovery-client.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ milliseconds (by default it is `30000`). For the http discovery server this must
236236
----
237237

238238
The heartbeat event will contain the target references (and their namespaces of the addresses of all endpoints
239-
(for the exact details of what will get returned you can take a look inside `KubernetesCatalogWatch`). This is an implementation detail, and listeners of the heartbeat event
239+
(for the exact details of what will get returned you can take a look inside `Fabric8CatalogWatch`). This is an implementation detail, and listeners of the heartbeat event
240240
should not rely on the details. Instead, they should see if there are differences between two subsequent heartbeats via `equals` method. We will take care to return a correct implementation that adheres to the equals contract.
241241
The endpoints will be queried in either :
242242
- `all-namespaces` (enabled via `spring.cloud.kubernetes.discovery.all-namespaces=true`)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright 2019-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.commons.discovery;
18+
19+
import java.net.URI;
20+
import java.util.Map;
21+
22+
import org.springframework.cloud.client.ServiceInstance;
23+
24+
/**
25+
* Type of {@link org.springframework.cloud.client.ServiceInstance} when
26+
* "spec.type=ExternalName".
27+
*
28+
* @author wind57
29+
*/
30+
public record KubernetesExternalNameServiceInstance(String serviceId, String host, String instanceId,
31+
Map<String, String> metadata) implements ServiceInstance {
32+
33+
@Override
34+
public String getServiceId() {
35+
return serviceId;
36+
}
37+
38+
@Override
39+
public String getHost() {
40+
return host;
41+
}
42+
43+
@Override
44+
public int getPort() {
45+
return -1;
46+
}
47+
48+
@Override
49+
public boolean isSecure() {
50+
return false;
51+
}
52+
53+
@Override
54+
public URI getUri() {
55+
return URI.create(host);
56+
}
57+
58+
@Override
59+
public Map<String, String> getMetadata() {
60+
return metadata;
61+
}
62+
63+
public String getInstanceId() {
64+
return instanceId;
65+
}
66+
67+
public String type() {
68+
return "ExternalName";
69+
}
70+
71+
}
Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.springframework.cloud.kubernetes.commons.discovery.EndpointNameAndNamespace;
3232
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties;
3333
import org.springframework.context.ApplicationEventPublisher;
34-
import org.springframework.context.ApplicationEventPublisherAware;
3534
import org.springframework.core.log.LogAccessor;
3635
import org.springframework.scheduling.annotation.Scheduled;
3736

@@ -43,32 +42,28 @@
4342
/**
4443
* @author Oleg Vyukov
4544
*/
46-
public class KubernetesCatalogWatch implements ApplicationEventPublisherAware {
45+
final class Fabric8CatalogWatch {
4746

4847
private static final String DISCOVERY_GROUP_VERSION = DISCOVERY_GROUP + "/" + DISCOVERY_VERSION;
4948

50-
private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(KubernetesCatalogWatch.class));
49+
private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(Fabric8CatalogWatch.class));
5150

5251
private final Fabric8CatalogWatchContext context;
5352

5453
private Function<Fabric8CatalogWatchContext, List<EndpointNameAndNamespace>> stateGenerator;
5554

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

58-
private ApplicationEventPublisher publisher;
57+
private final ApplicationEventPublisher publisher;
5958

60-
public KubernetesCatalogWatch(KubernetesClient kubernetesClient, KubernetesDiscoveryProperties properties,
61-
KubernetesNamespaceProvider namespaceProvider) {
59+
Fabric8CatalogWatch(KubernetesClient kubernetesClient, KubernetesDiscoveryProperties properties,
60+
KubernetesNamespaceProvider namespaceProvider, ApplicationEventPublisher publisher) {
6261
context = new Fabric8CatalogWatchContext(kubernetesClient, properties, namespaceProvider);
63-
}
64-
65-
@Override
66-
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
6762
this.publisher = publisher;
6863
}
6964

7065
@Scheduled(fixedDelayString = "${" + CATALOG_WATCH_PROPERTY_WITH_DEFAULT_VALUE + "}")
71-
public void catalogServicesWatch() {
66+
void catalogServicesWatch() {
7267
try {
7368

7469
List<EndpointNameAndNamespace> currentState = stateGenerator.apply(context);
@@ -97,7 +92,7 @@ Function<Fabric8CatalogWatchContext, List<EndpointNameAndNamespace>> stateGenera
9792
if (context.properties().useEndpointSlices()) {
9893
// can't use try with resources here as it will close the client
9994
KubernetesClient client = context.kubernetesClient();
100-
// this emulates : 'kubectl api-resources | grep -i EndpointSlice'
95+
// this emulates: 'kubectl api-resources | grep -i EndpointSlice'
10196
boolean found = client.getApiGroups()
10297
.getGroups()
10398
.stream()
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties;
2626
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryPropertiesAutoConfiguration;
2727
import org.springframework.cloud.kubernetes.fabric8.Fabric8AutoConfiguration;
28+
import org.springframework.context.ApplicationEventPublisher;
2829
import org.springframework.context.annotation.Bean;
2930
import org.springframework.context.annotation.Configuration;
3031
import org.springframework.core.env.Environment;
@@ -37,13 +38,13 @@
3738
@Configuration(proxyBeanMethods = false)
3839
@ConditionalOnKubernetesCatalogWatcherEnabled
3940
@AutoConfigureAfter({ Fabric8AutoConfiguration.class, KubernetesDiscoveryPropertiesAutoConfiguration.class })
40-
public class KubernetesCatalogWatchAutoConfiguration {
41+
final class Fabric8CatalogWatchAutoConfiguration {
4142

4243
@Bean
4344
@ConditionalOnMissingBean
44-
public KubernetesCatalogWatch kubernetesCatalogWatch(KubernetesClient client,
45-
KubernetesDiscoveryProperties properties, Environment environment) {
46-
return new KubernetesCatalogWatch(client, properties, new KubernetesNamespaceProvider(environment));
45+
Fabric8CatalogWatch fabric8CatalogWatch(KubernetesClient client, KubernetesDiscoveryProperties properties,
46+
Environment environment, ApplicationEventPublisher publisher) {
47+
return new Fabric8CatalogWatch(client, properties, new KubernetesNamespaceProvider(environment), publisher);
4748
}
4849

4950
}

spring-cloud-kubernetes-fabric8-discovery/src/main/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerBootstrapper.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import io.fabric8.kubernetes.client.Config;
2222
import io.fabric8.kubernetes.client.KubernetesClient;
23+
import jakarta.annotation.Nonnull;
2324

2425
import org.springframework.boot.bootstrap.BootstrapRegistry;
2526
import org.springframework.cloud.config.client.ConfigServerConfigDataLocationResolver.PropertyResolver;
@@ -37,7 +38,7 @@
3738
class Fabric8ConfigServerBootstrapper extends KubernetesConfigServerBootstrapper {
3839

3940
@Override
40-
public void initialize(BootstrapRegistry registry) {
41+
public void initialize(@Nonnull BootstrapRegistry registry) {
4142
if (hasConfigServerInstanceProvider()) {
4243
return;
4344
}
@@ -61,8 +62,8 @@ public void initialize(BootstrapRegistry registry) {
6162
if (!getDiscoveryEnabled(context)) {
6263
return (id) -> Collections.emptyList();
6364
}
64-
if (context.isRegistered(KubernetesDiscoveryClient.class)) {
65-
KubernetesDiscoveryClient client = context.get(KubernetesDiscoveryClient.class);
65+
if (context.isRegistered(Fabric8DiscoveryClient.class)) {
66+
Fabric8DiscoveryClient client = context.get(Fabric8DiscoveryClient.class);
6667
return client::getInstances;
6768
}
6869
else {
@@ -72,12 +73,11 @@ public void initialize(BootstrapRegistry registry) {
7273
.kubernetesClientConfig(context.get(KubernetesClientProperties.class));
7374
KubernetesClient kubernetesClient = fabric8AutoConfiguration.kubernetesClient(config);
7475
KubernetesDiscoveryProperties discoveryProperties = context.get(KubernetesDiscoveryProperties.class);
75-
KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(kubernetesClient,
76-
discoveryProperties,
77-
KubernetesClientServicesFunctionProvider.servicesFunction(discoveryProperties,
78-
new KubernetesNamespaceProvider(propertyResolver
79-
.get(KubernetesNamespaceProvider.NAMESPACE_PROPERTY, String.class, null))),
80-
null, new ServicePortSecureResolver(discoveryProperties));
76+
Fabric8DiscoveryClient discoveryClient = new Fabric8DiscoveryClient(kubernetesClient,
77+
discoveryProperties, new ServicePortSecureResolver(discoveryProperties),
78+
new KubernetesNamespaceProvider(propertyResolver
79+
.get(KubernetesNamespaceProvider.NAMESPACE_PROPERTY, String.class, null)),
80+
new Fabric8DiscoveryClientSpelAutoConfiguration().predicate(discoveryProperties));
8181
return discoveryClient::getInstances;
8282
}
8383
});
Lines changed: 29 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,19 @@
3636
import org.springframework.cloud.kubernetes.commons.discovery.ServiceMetadata;
3737
import org.springframework.cloud.kubernetes.commons.discovery.ServicePortNameAndNumber;
3838
import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver;
39-
import org.springframework.context.EnvironmentAware;
40-
import org.springframework.core.env.Environment;
4139
import org.springframework.core.log.LogAccessor;
4240

4341
import static org.springframework.cloud.kubernetes.commons.discovery.DiscoveryClientUtils.endpointsPort;
4442
import static org.springframework.cloud.kubernetes.commons.discovery.DiscoveryClientUtils.serviceInstance;
4543
import static org.springframework.cloud.kubernetes.commons.discovery.DiscoveryClientUtils.serviceInstanceMetadata;
4644
import static org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryConstants.EXTERNAL_NAME;
4745
import static org.springframework.cloud.kubernetes.fabric8.Fabric8Utils.serviceMetadata;
46+
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.addresses;
47+
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.endpointSubsetsPortData;
48+
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.endpoints;
49+
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8DiscoveryClientUtils.services;
4850
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8InstanceIdHostPodNameSupplier.externalName;
4951
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8InstanceIdHostPodNameSupplier.nonExternalName;
50-
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8KubernetesDiscoveryClientUtils.addresses;
51-
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8KubernetesDiscoveryClientUtils.endpointSubsetsPortData;
52-
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8KubernetesDiscoveryClientUtils.endpoints;
53-
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8KubernetesDiscoveryClientUtils.services;
5452
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8PodLabelsAndAnnotationsSupplier.externalName;
5553
import static org.springframework.cloud.kubernetes.fabric8.discovery.Fabric8PodLabelsAndAnnotationsSupplier.nonExternalName;
5654

@@ -60,40 +58,29 @@
6058
* @author Ioannis Canellos
6159
* @author Tim Ysewyn
6260
*/
63-
public class KubernetesDiscoveryClient implements DiscoveryClient, EnvironmentAware {
61+
final class Fabric8DiscoveryClient implements DiscoveryClient {
6462

65-
private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(KubernetesDiscoveryClient.class));
63+
private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(Fabric8DiscoveryClient.class));
6664

6765
private final KubernetesDiscoveryProperties properties;
6866

69-
private final KubernetesClientServicesFunction kubernetesClientServicesFunction;
70-
7167
private final ServicePortSecureResolver servicePortSecureResolver;
7268

73-
private final Fabric8DiscoveryServicesAdapter adapter;
74-
7569
private final KubernetesClient client;
7670

77-
private KubernetesNamespaceProvider namespaceProvider;
71+
private final KubernetesNamespaceProvider namespaceProvider;
7872

79-
public KubernetesDiscoveryClient(KubernetesClient client,
80-
KubernetesDiscoveryProperties kubernetesDiscoveryProperties,
81-
KubernetesClientServicesFunction kubernetesClientServicesFunction) {
73+
private final Predicate<Service> predicate;
8274

83-
this(client, kubernetesDiscoveryProperties, kubernetesClientServicesFunction, null,
84-
new ServicePortSecureResolver(kubernetesDiscoveryProperties));
85-
}
86-
87-
KubernetesDiscoveryClient(KubernetesClient client, KubernetesDiscoveryProperties kubernetesDiscoveryProperties,
88-
KubernetesClientServicesFunction kubernetesClientServicesFunction, Predicate<Service> filter,
89-
ServicePortSecureResolver servicePortSecureResolver) {
75+
Fabric8DiscoveryClient(KubernetesClient client, KubernetesDiscoveryProperties kubernetesDiscoveryProperties,
76+
ServicePortSecureResolver servicePortSecureResolver, KubernetesNamespaceProvider namespaceProvider,
77+
Predicate<Service> predicate) {
9078

9179
this.client = client;
9280
this.properties = kubernetesDiscoveryProperties;
9381
this.servicePortSecureResolver = servicePortSecureResolver;
94-
this.kubernetesClientServicesFunction = kubernetesClientServicesFunction;
95-
this.adapter = new Fabric8DiscoveryServicesAdapter(kubernetesClientServicesFunction,
96-
kubernetesDiscoveryProperties, filter);
82+
this.namespaceProvider = namespaceProvider;
83+
this.predicate = predicate;
9784
}
9885

9986
@Override
@@ -105,7 +92,8 @@ public String description() {
10592
public List<ServiceInstance> getInstances(String serviceId) {
10693
Objects.requireNonNull(serviceId);
10794

108-
List<Endpoints> allEndpoints = getEndPointsList(serviceId).stream().toList();
95+
List<Endpoints> allEndpoints = endpoints(properties, client, namespaceProvider, "fabric8-discovery", serviceId,
96+
predicate);
10997

11098
List<ServiceInstance> instances = new ArrayList<>();
11199
for (Endpoints endpoints : allEndpoints) {
@@ -135,8 +123,20 @@ public List<ServiceInstance> getInstances(String serviceId) {
135123
return instances;
136124
}
137125

138-
public List<Endpoints> getEndPointsList(String serviceId) {
139-
return endpoints(properties, client, namespaceProvider, "fabric8-discovery", serviceId, adapter.filter());
126+
@Override
127+
public List<String> getServices() {
128+
List<String> services = services(properties, client, namespaceProvider, predicate, null, "fabric8 discovery")
129+
.stream()
130+
.map(service -> service.getMetadata().getName())
131+
.distinct()
132+
.toList();
133+
LOG.debug(() -> "will return services : " + services);
134+
return services;
135+
}
136+
137+
@Override
138+
public int getOrder() {
139+
return properties.order();
140140
}
141141

142142
private List<ServiceInstance> serviceInstances(Endpoints endpoints, String serviceId) {
@@ -176,31 +176,4 @@ private List<ServiceInstance> serviceInstances(Endpoints endpoints, String servi
176176
return instances;
177177
}
178178

179-
@Override
180-
public List<String> getServices() {
181-
List<String> services = adapter.apply(client).stream().map(s -> s.getMetadata().getName()).distinct().toList();
182-
LOG.debug(() -> "will return services : " + services);
183-
return services;
184-
}
185-
186-
@Deprecated(forRemoval = true)
187-
public List<String> getServices(Predicate<Service> filter) {
188-
return new Fabric8DiscoveryServicesAdapter(kubernetesClientServicesFunction, properties, filter).apply(client)
189-
.stream()
190-
.map(s -> s.getMetadata().getName())
191-
.distinct()
192-
.toList();
193-
}
194-
195-
@Override
196-
public int getOrder() {
197-
return properties.order();
198-
}
199-
200-
@Deprecated(forRemoval = true)
201-
@Override
202-
public final void setEnvironment(Environment environment) {
203-
namespaceProvider = new KubernetesNamespaceProvider(environment);
204-
}
205-
206179
}

0 commit comments

Comments
 (0)