Fix #341 - allow defining a primary port name when multiple ports are defined for a service (#342)

This commit is contained in:
Jakub Kubryński
2019-02-28 16:53:53 +01:00
committed by Ryan Baxter
parent e5d40686ca
commit fda256fc7e
3 changed files with 74 additions and 8 deletions

View File

@@ -153,8 +153,8 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
if (endpointAddress.getTargetRef() != null) {
instanceId = endpointAddress.getTargetRef().getUid();
}
final EndpointPort endpointPort = s.getPorts().stream().findFirst()
.orElseThrow(IllegalStateException::new);
EndpointPort endpointPort = findEndpointPort(s);
instances.add(new KubernetesServiceInstance(instanceId, serviceId,
endpointAddress, endpointPort, endpointMetadata,
this.isServicePortSecureResolver
@@ -170,6 +170,27 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
return instances;
}
private EndpointPort findEndpointPort(EndpointSubset s) {
List<EndpointPort> ports = s.getPorts();
EndpointPort endpointPort;
if (ports.size() == 1) {
endpointPort = ports.get(0);
}
else {
Predicate<EndpointPort> portPredicate;
if (!StringUtils.isEmpty(properties.getPrimaryPortName())) {
portPredicate = port -> properties.getPrimaryPortName()
.equalsIgnoreCase(port.getName());
}
else {
portPredicate = port -> true;
}
endpointPort = ports.stream().filter(portPredicate).findAny()
.orElseThrow(IllegalStateException::new);
}
return endpointPort;
}
private List<EndpointSubset> getSubsetsFromEndpoints(Endpoints endpoints) {
if (endpoints == null) {
return new ArrayList<>();

View File

@@ -60,6 +60,12 @@ public class KubernetesDiscoveryProperties {
*/
private Map<String, String> serviceLabels = new HashMap<>();
/**
* If set then the port with a given name is used as primary when multiple ports are
* defined for a service.
*/
private String primaryPortName;
private Metadata metadata = new Metadata();
public boolean isEnabled() {
@@ -102,6 +108,14 @@ public class KubernetesDiscoveryProperties {
this.serviceLabels = serviceLabels;
}
public String getPrimaryPortName() {
return primaryPortName;
}
public void setPrimaryPortName(String primaryPortName) {
this.primaryPortName = primaryPortName;
}
public Metadata getMetadata() {
return this.metadata;
}

View File

@@ -57,12 +57,10 @@ public class KubernetesDiscoveryClientTest {
@Test
public void getInstancesShouldBeAbleToHandleEndpointsSingleAddress() {
mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/endpoint")
.andReturn(200,
new EndpointsBuilder().withNewMetadata().withName("endpoint")
.endMetadata().addNewSubset().addNewAddress()
.withIp("ip1").withNewTargetRef().withUid("uid").endTargetRef().endAddress()
.addNewPort("http", 80, "TCP")
.endSubset().build())
.andReturn(200, new EndpointsBuilder().withNewMetadata()
.withName("endpoint").endMetadata().addNewSubset().addNewAddress()
.withIp("ip1").withNewTargetRef().withUid("uid").endTargetRef()
.endAddress().addNewPort("http", 80, "TCP").endSubset().build())
.once();
mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint")
@@ -86,6 +84,39 @@ public class KubernetesDiscoveryClientTest {
.filteredOn(s -> s.getInstanceId().equals("uid")).hasSize(1);
}
@Test
public void getInstancesShouldBeAbleToHandleEndpointsSingleAddressAndMultiplePorts() {
mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/endpoint")
.andReturn(200, new EndpointsBuilder().withNewMetadata()
.withName("endpoint").endMetadata().addNewSubset().addNewAddress()
.withIp("ip1").withNewTargetRef().withUid("uid").endTargetRef()
.endAddress().addNewPort("mgmt", 9000, "TCP")
.addNewPort("http", 80, "TCP").endSubset().build())
.once();
mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint")
.andReturn(200, new ServiceBuilder().withNewMetadata()
.withName("endpoint").withLabels(new HashMap<String, String>() {
{
put("l", "v");
}
}).endMetadata().build())
.once();
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
properties.setPrimaryPortName("http");
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient,
properties, KubernetesClient::services,
new DefaultIsServicePortSecureResolver(properties));
final List<ServiceInstance> instances = discoveryClient.getInstances("endpoint");
assertThat(instances).hasSize(1)
.filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1)
.filteredOn(s -> s.getInstanceId().equals("uid")).hasSize(1)
.filteredOn(s -> 80 == s.getPort()).hasSize(1);
}
@Test
public void getInstancesShouldBeAbleToHandleEndpointsMultipleAddresses() {
mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/endpoint")