#562 Adding all namespaces handling + tests
This commit is contained in:
@@ -41,5 +41,10 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<artifactId>kubernetes-server-mock</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.cloud.kubernetes.loadbalancer;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cloud.kubernetes.discovery.KubernetesDiscoveryProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
@@ -33,8 +34,10 @@ public class KubernetesClientConfiguration {
|
||||
@ConditionalOnProperty(name = "spring.cloud.kubernetes.loadbalancer.mode",
|
||||
havingValue = "SERVICE")
|
||||
KubernetesServicesListSupplier kubernetesServicesListSupplier(Environment environment,
|
||||
KubernetesClient kubernetesClient, KubernetesServiceInstanceMapper mapper) {
|
||||
return new KubernetesServicesListSupplier(environment, kubernetesClient, mapper);
|
||||
KubernetesClient kubernetesClient, KubernetesServiceInstanceMapper mapper,
|
||||
KubernetesDiscoveryProperties discoveryProperties) {
|
||||
return new KubernetesServicesListSupplier(environment, kubernetesClient, mapper,
|
||||
discoveryProperties);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,6 +40,9 @@ public class KubernetesServiceInstance implements ServiceInstance {
|
||||
|
||||
private Map<String, String> metadata;
|
||||
|
||||
KubernetesServiceInstance() {
|
||||
}
|
||||
|
||||
KubernetesServiceInstance(String serviceId, String instanceId, int port,
|
||||
boolean secure, String host, URI uri, Map<String, String> metadata) {
|
||||
this.serviceId = serviceId;
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.apache.commons.lang.StringUtils;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.kubernetes.discovery.KubernetesDiscoveryProperties;
|
||||
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
|
||||
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
|
||||
import org.springframework.core.env.Environment;
|
||||
@@ -38,12 +39,16 @@ public class KubernetesServicesListSupplier implements ServiceInstanceListSuppli
|
||||
|
||||
private KubernetesClient kubernetesClient;
|
||||
|
||||
private KubernetesDiscoveryProperties discoveryProperties;
|
||||
|
||||
private KubernetesServiceInstanceMapper mapper;
|
||||
|
||||
KubernetesServicesListSupplier(Environment environment,
|
||||
KubernetesClient kubernetesClient, KubernetesServiceInstanceMapper mapper) {
|
||||
KubernetesClient kubernetesClient, KubernetesServiceInstanceMapper mapper,
|
||||
KubernetesDiscoveryProperties discoveryProperties) {
|
||||
this.environment = environment;
|
||||
this.kubernetesClient = kubernetesClient;
|
||||
this.discoveryProperties = discoveryProperties;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@@ -55,13 +60,21 @@ public class KubernetesServicesListSupplier implements ServiceInstanceListSuppli
|
||||
@Override
|
||||
public Flux<List<ServiceInstance>> get() {
|
||||
List<ServiceInstance> result = new ArrayList<>();
|
||||
Service service = StringUtils.isNotBlank(this.kubernetesClient.getNamespace())
|
||||
? this.kubernetesClient
|
||||
.services().inNamespace(this.kubernetesClient.getNamespace())
|
||||
.withName(this.getServiceId()).get()
|
||||
: this.kubernetesClient.services().withName(this.getServiceId()).get();
|
||||
if (service != null) {
|
||||
result.add(mapper.map(service));
|
||||
if (discoveryProperties.isAllNamespaces()) {
|
||||
List<Service> services = this.kubernetesClient.services().inAnyNamespace()
|
||||
.withField("metadata.name", this.getServiceId()).list().getItems();
|
||||
services.forEach(service -> result.add(mapper.map(service)));
|
||||
}
|
||||
else {
|
||||
Service service = StringUtils.isNotBlank(this.kubernetesClient.getNamespace())
|
||||
? this.kubernetesClient.services()
|
||||
.inNamespace(this.kubernetesClient.getNamespace())
|
||||
.withName(this.getServiceId()).get()
|
||||
: this.kubernetesClient.services().withName(this.getServiceId())
|
||||
.get();
|
||||
if (service != null) {
|
||||
result.add(mapper.map(service));
|
||||
}
|
||||
}
|
||||
return Flux.just(result);
|
||||
}
|
||||
|
||||
@@ -34,13 +34,12 @@ import org.springframework.cloud.kubernetes.discovery.KubernetesDiscoveryPropert
|
||||
public class KubernetesServiceInstanceMapperTest {
|
||||
|
||||
@Test
|
||||
void testMapperSimple() {
|
||||
public void testMapperSimple() {
|
||||
KubernetesLoadBalancerProperties properties = new KubernetesLoadBalancerProperties();
|
||||
KubernetesDiscoveryProperties discoveryProperties =
|
||||
new KubernetesDiscoveryProperties();
|
||||
KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties();
|
||||
Service service = buildService("test", "abc", 8080, null, new HashMap<>());
|
||||
KubernetesServiceInstance instance =
|
||||
new KubernetesServiceInstanceMapper(properties, discoveryProperties).map(service);
|
||||
KubernetesServiceInstance instance = new KubernetesServiceInstanceMapper(
|
||||
properties, discoveryProperties).map(service);
|
||||
Assertions.assertNotNull(instance);
|
||||
Assertions.assertEquals("test", instance.getServiceId());
|
||||
Assertions.assertEquals("abc", instance.getInstanceId());
|
||||
@@ -50,20 +49,13 @@ public class KubernetesServiceInstanceMapperTest {
|
||||
void testMapperMultiplePorts() {
|
||||
KubernetesLoadBalancerProperties properties = new KubernetesLoadBalancerProperties();
|
||||
properties.setPortName("http");
|
||||
KubernetesDiscoveryProperties discoveryProperties =
|
||||
new KubernetesDiscoveryProperties();
|
||||
KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties();
|
||||
List<ServicePort> ports = new ArrayList<>();
|
||||
ports.add(new ServicePortBuilder()
|
||||
.withPort(8080)
|
||||
.withName("web")
|
||||
.build());
|
||||
ports.add(new ServicePortBuilder()
|
||||
.withPort(9000)
|
||||
.withName("http")
|
||||
.build());
|
||||
ports.add(new ServicePortBuilder().withPort(8080).withName("web").build());
|
||||
ports.add(new ServicePortBuilder().withPort(9000).withName("http").build());
|
||||
Service service = buildService("test", "abc", ports, new HashMap<>());
|
||||
KubernetesServiceInstance instance =
|
||||
new KubernetesServiceInstanceMapper(properties, discoveryProperties).map(service);
|
||||
KubernetesServiceInstance instance = new KubernetesServiceInstanceMapper(
|
||||
properties, discoveryProperties).map(service);
|
||||
Assertions.assertNotNull(instance);
|
||||
Assertions.assertEquals("test", instance.getServiceId());
|
||||
Assertions.assertEquals("abc", instance.getInstanceId());
|
||||
@@ -73,11 +65,10 @@ public class KubernetesServiceInstanceMapperTest {
|
||||
@Test
|
||||
void testMapperSecure() {
|
||||
KubernetesLoadBalancerProperties properties = new KubernetesLoadBalancerProperties();
|
||||
KubernetesDiscoveryProperties discoveryProperties =
|
||||
new KubernetesDiscoveryProperties();
|
||||
KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties();
|
||||
Service service = buildService("test", "abc", 443, null, new HashMap<>());
|
||||
KubernetesServiceInstance instance =
|
||||
new KubernetesServiceInstanceMapper(properties, discoveryProperties).map(service);
|
||||
KubernetesServiceInstance instance = new KubernetesServiceInstanceMapper(
|
||||
properties, discoveryProperties).map(service);
|
||||
Assertions.assertNotNull(instance);
|
||||
Assertions.assertEquals("test", instance.getServiceId());
|
||||
Assertions.assertEquals("abc", instance.getInstanceId());
|
||||
@@ -87,14 +78,13 @@ public class KubernetesServiceInstanceMapperTest {
|
||||
@Test
|
||||
void testMapperSecureWithLabels() {
|
||||
KubernetesLoadBalancerProperties properties = new KubernetesLoadBalancerProperties();
|
||||
KubernetesDiscoveryProperties discoveryProperties =
|
||||
new KubernetesDiscoveryProperties();
|
||||
KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties();
|
||||
HashMap<String, String> labels = new HashMap<>();
|
||||
labels.put("secured", "true");
|
||||
labels.put("label1", "123");
|
||||
Service service = buildService("test", "abc", 8080, null, labels);
|
||||
KubernetesServiceInstance instance =
|
||||
new KubernetesServiceInstanceMapper(properties, discoveryProperties).map(service);
|
||||
KubernetesServiceInstance instance = new KubernetesServiceInstanceMapper(
|
||||
properties, discoveryProperties).map(service);
|
||||
Assertions.assertNotNull(instance);
|
||||
Assertions.assertEquals("test", instance.getServiceId());
|
||||
Assertions.assertEquals("abc", instance.getInstanceId());
|
||||
@@ -102,26 +92,17 @@ public class KubernetesServiceInstanceMapperTest {
|
||||
Assertions.assertEquals(2, instance.getMetadata().keySet().size());
|
||||
}
|
||||
|
||||
|
||||
private Service buildService(String name, String uid, List<ServicePort> ports, Map<String, String> labels) {
|
||||
return new ServiceBuilder()
|
||||
.withNewMetadata()
|
||||
.withName(name)
|
||||
.withNewUid(uid)
|
||||
.addToLabels(labels)
|
||||
.addToAnnotations(new HashMap<>(0))
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.addAllToPorts(ports)
|
||||
.endSpec()
|
||||
.build();
|
||||
private Service buildService(String name, String uid, List<ServicePort> ports,
|
||||
Map<String, String> labels) {
|
||||
return new ServiceBuilder().withNewMetadata().withName(name).withNewUid(uid)
|
||||
.addToLabels(labels).addToAnnotations(new HashMap<>(0)).endMetadata()
|
||||
.withNewSpec().addAllToPorts(ports).endSpec().build();
|
||||
}
|
||||
|
||||
private Service buildService(String name, String uid, int port, String portName, Map<String, String> labels) {
|
||||
ServicePort servicePort = new ServicePortBuilder()
|
||||
.withPort(port)
|
||||
.withName(portName)
|
||||
.build();
|
||||
private Service buildService(String name, String uid, int port, String portName,
|
||||
Map<String, String> labels) {
|
||||
ServicePort servicePort = new ServicePortBuilder().withPort(port)
|
||||
.withName(portName).build();
|
||||
return buildService(name, uid, Collections.singletonList(servicePort), labels);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2013-2020 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.loadbalancer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.DoneableService;
|
||||
import io.fabric8.kubernetes.api.model.Service;
|
||||
import io.fabric8.kubernetes.api.model.ServiceBuilder;
|
||||
import io.fabric8.kubernetes.api.model.ServiceList;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.fabric8.kubernetes.client.Watch;
|
||||
import io.fabric8.kubernetes.client.Watcher;
|
||||
import io.fabric8.kubernetes.client.dsl.FilterWatchListMultiDeletable;
|
||||
import io.fabric8.kubernetes.client.dsl.MixedOperation;
|
||||
import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
|
||||
import io.fabric8.kubernetes.client.dsl.ServiceResource;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.kubernetes.discovery.KubernetesDiscoveryProperties;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class KubernetesServiceListSupplierTest {
|
||||
|
||||
@Mock
|
||||
Environment environment;
|
||||
|
||||
@Mock
|
||||
KubernetesServiceInstanceMapper mapper;
|
||||
|
||||
@Mock
|
||||
KubernetesClient client;
|
||||
|
||||
@Mock
|
||||
MixedOperation<Service, ServiceList, DoneableService, ServiceResource<Service, DoneableService>> serviceOperation;
|
||||
|
||||
@Mock
|
||||
NonNamespaceOperation<Service, ServiceList, DoneableService, ServiceResource<Service, DoneableService>> namespaceOperation;
|
||||
|
||||
@Mock
|
||||
ServiceResource<Service, DoneableService> serviceResource;
|
||||
|
||||
@Mock
|
||||
FilterWatchListMultiDeletable<Service, ServiceList, Boolean, Watch, Watcher<Service>> multiDeletable;
|
||||
|
||||
@Test
|
||||
void testPositiveMatch() {
|
||||
when(environment.getProperty("loadbalancer.client.name"))
|
||||
.thenReturn("test-service");
|
||||
when(mapper.map(any(Service.class))).thenReturn(new KubernetesServiceInstance());
|
||||
when(this.client.getNamespace()).thenReturn("test");
|
||||
when(this.client.services()).thenReturn(this.serviceOperation);
|
||||
when(this.serviceOperation.inNamespace("test")).thenReturn(namespaceOperation);
|
||||
when(this.namespaceOperation.withName("test-service"))
|
||||
.thenReturn(this.serviceResource);
|
||||
when(this.serviceResource.get()).thenReturn(buildService("test-service", 8080));
|
||||
KubernetesServicesListSupplier supplier = new KubernetesServicesListSupplier(
|
||||
environment, client, mapper, new KubernetesDiscoveryProperties());
|
||||
List<ServiceInstance> instances = supplier.get().blockFirst();
|
||||
assert instances != null;
|
||||
Assertions.assertEquals(1, instances.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPositiveMatchAllNamespaces() {
|
||||
when(environment.getProperty("loadbalancer.client.name"))
|
||||
.thenReturn("test-service");
|
||||
when(mapper.map(any(Service.class))).thenReturn(new KubernetesServiceInstance());
|
||||
when(this.client.services()).thenReturn(this.serviceOperation);
|
||||
when(this.serviceOperation.inAnyNamespace()).thenReturn(this.multiDeletable);
|
||||
when(this.multiDeletable.withField("metadata.name", "test-service"))
|
||||
.thenReturn(this.multiDeletable);
|
||||
ServiceList serviceList = new ServiceList();
|
||||
serviceList.getItems().add(buildService("test-service", 8080));
|
||||
when(this.multiDeletable.list()).thenReturn(serviceList);
|
||||
KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties();
|
||||
discoveryProperties.setAllNamespaces(true);
|
||||
KubernetesServicesListSupplier supplier = new KubernetesServicesListSupplier(
|
||||
environment, client, mapper, discoveryProperties);
|
||||
List<ServiceInstance> instances = supplier.get().blockFirst();
|
||||
assert instances != null;
|
||||
Assertions.assertEquals(1, instances.size());
|
||||
}
|
||||
|
||||
private Service buildService(String name, int port) {
|
||||
return new ServiceBuilder().withNewMetadata().withName(name).endMetadata()
|
||||
.withNewSpec().addNewPort().withPort(8080).endPort().endSpec().build();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user