Skip to content

Commit fda256f

Browse files
jkubrynskiRyan Baxter
authored and
Ryan Baxter
committed
Fix spring-cloud#341 - allow defining a primary port name when multiple ports are defined for a service (spring-cloud#342)
1 parent e5d4068 commit fda256f

File tree

3 files changed

+74
-8
lines changed

3 files changed

+74
-8
lines changed

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

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,8 @@ public List<ServiceInstance> getInstances(String serviceId) {
153153
if (endpointAddress.getTargetRef() != null) {
154154
instanceId = endpointAddress.getTargetRef().getUid();
155155
}
156-
final EndpointPort endpointPort = s.getPorts().stream().findFirst()
157-
.orElseThrow(IllegalStateException::new);
156+
157+
EndpointPort endpointPort = findEndpointPort(s);
158158
instances.add(new KubernetesServiceInstance(instanceId, serviceId,
159159
endpointAddress, endpointPort, endpointMetadata,
160160
this.isServicePortSecureResolver
@@ -170,6 +170,27 @@ public List<ServiceInstance> getInstances(String serviceId) {
170170
return instances;
171171
}
172172

173+
private EndpointPort findEndpointPort(EndpointSubset s) {
174+
List<EndpointPort> ports = s.getPorts();
175+
EndpointPort endpointPort;
176+
if (ports.size() == 1) {
177+
endpointPort = ports.get(0);
178+
}
179+
else {
180+
Predicate<EndpointPort> portPredicate;
181+
if (!StringUtils.isEmpty(properties.getPrimaryPortName())) {
182+
portPredicate = port -> properties.getPrimaryPortName()
183+
.equalsIgnoreCase(port.getName());
184+
}
185+
else {
186+
portPredicate = port -> true;
187+
}
188+
endpointPort = ports.stream().filter(portPredicate).findAny()
189+
.orElseThrow(IllegalStateException::new);
190+
}
191+
return endpointPort;
192+
}
193+
173194
private List<EndpointSubset> getSubsetsFromEndpoints(Endpoints endpoints) {
174195
if (endpoints == null) {
175196
return new ArrayList<>();

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ public class KubernetesDiscoveryProperties {
6060
*/
6161
private Map<String, String> serviceLabels = new HashMap<>();
6262

63+
/**
64+
* If set then the port with a given name is used as primary when multiple ports are
65+
* defined for a service.
66+
*/
67+
private String primaryPortName;
68+
6369
private Metadata metadata = new Metadata();
6470

6571
public boolean isEnabled() {
@@ -102,6 +108,14 @@ public void setServiceLabels(Map<String, String> serviceLabels) {
102108
this.serviceLabels = serviceLabels;
103109
}
104110

111+
public String getPrimaryPortName() {
112+
return primaryPortName;
113+
}
114+
115+
public void setPrimaryPortName(String primaryPortName) {
116+
this.primaryPortName = primaryPortName;
117+
}
118+
105119
public Metadata getMetadata() {
106120
return this.metadata;
107121
}

spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTest.java

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,10 @@ public void setup() {
5757
@Test
5858
public void getInstancesShouldBeAbleToHandleEndpointsSingleAddress() {
5959
mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/endpoint")
60-
.andReturn(200,
61-
new EndpointsBuilder().withNewMetadata().withName("endpoint")
62-
.endMetadata().addNewSubset().addNewAddress()
63-
.withIp("ip1").withNewTargetRef().withUid("uid").endTargetRef().endAddress()
64-
.addNewPort("http", 80, "TCP")
65-
.endSubset().build())
60+
.andReturn(200, new EndpointsBuilder().withNewMetadata()
61+
.withName("endpoint").endMetadata().addNewSubset().addNewAddress()
62+
.withIp("ip1").withNewTargetRef().withUid("uid").endTargetRef()
63+
.endAddress().addNewPort("http", 80, "TCP").endSubset().build())
6664
.once();
6765

6866
mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint")
@@ -86,6 +84,39 @@ public void getInstancesShouldBeAbleToHandleEndpointsSingleAddress() {
8684
.filteredOn(s -> s.getInstanceId().equals("uid")).hasSize(1);
8785
}
8886

87+
@Test
88+
public void getInstancesShouldBeAbleToHandleEndpointsSingleAddressAndMultiplePorts() {
89+
mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/endpoint")
90+
.andReturn(200, new EndpointsBuilder().withNewMetadata()
91+
.withName("endpoint").endMetadata().addNewSubset().addNewAddress()
92+
.withIp("ip1").withNewTargetRef().withUid("uid").endTargetRef()
93+
.endAddress().addNewPort("mgmt", 9000, "TCP")
94+
.addNewPort("http", 80, "TCP").endSubset().build())
95+
.once();
96+
97+
mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint")
98+
.andReturn(200, new ServiceBuilder().withNewMetadata()
99+
.withName("endpoint").withLabels(new HashMap<String, String>() {
100+
{
101+
put("l", "v");
102+
}
103+
}).endMetadata().build())
104+
.once();
105+
106+
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
107+
properties.setPrimaryPortName("http");
108+
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient,
109+
properties, KubernetesClient::services,
110+
new DefaultIsServicePortSecureResolver(properties));
111+
112+
final List<ServiceInstance> instances = discoveryClient.getInstances("endpoint");
113+
114+
assertThat(instances).hasSize(1)
115+
.filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1)
116+
.filteredOn(s -> s.getInstanceId().equals("uid")).hasSize(1)
117+
.filteredOn(s -> 80 == s.getPort()).hasSize(1);
118+
}
119+
89120
@Test
90121
public void getInstancesShouldBeAbleToHandleEndpointsMultipleAddresses() {
91122
mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/endpoint")

0 commit comments

Comments
 (0)