diff --git a/spring-cloud-kubernetes-loadbalancer/pom.xml b/spring-cloud-kubernetes-loadbalancer/pom.xml
index 42515da1..d564c118 100644
--- a/spring-cloud-kubernetes-loadbalancer/pom.xml
+++ b/spring-cloud-kubernetes-loadbalancer/pom.xml
@@ -41,5 +41,10 @@
spring-boot-starter-test
test
+
+ io.fabric8
+ kubernetes-server-mock
+ test
+
diff --git a/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesClientConfiguration.java b/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesClientConfiguration.java
index dddc13f4..c16c9fe8 100644
--- a/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesClientConfiguration.java
+++ b/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesClientConfiguration.java
@@ -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);
}
}
diff --git a/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstance.java b/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstance.java
index f1315277..8967e072 100644
--- a/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstance.java
+++ b/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstance.java
@@ -40,6 +40,9 @@ public class KubernetesServiceInstance implements ServiceInstance {
private Map metadata;
+ KubernetesServiceInstance() {
+ }
+
KubernetesServiceInstance(String serviceId, String instanceId, int port,
boolean secure, String host, URI uri, Map metadata) {
this.serviceId = serviceId;
diff --git a/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServicesListSupplier.java b/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServicesListSupplier.java
index 51fe8fbc..29d61bfa 100644
--- a/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServicesListSupplier.java
+++ b/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServicesListSupplier.java
@@ -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> get() {
List 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 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);
}
diff --git a/spring-cloud-kubernetes-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstanceMapperTest.java b/spring-cloud-kubernetes-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstanceMapperTest.java
index a696fcfa..2d5d5fc2 100644
--- a/spring-cloud-kubernetes-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstanceMapperTest.java
+++ b/spring-cloud-kubernetes-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstanceMapperTest.java
@@ -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 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 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 ports, Map 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 ports,
+ Map 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 labels) {
- ServicePort servicePort = new ServicePortBuilder()
- .withPort(port)
- .withName(portName)
- .build();
+ private Service buildService(String name, String uid, int port, String portName,
+ Map labels) {
+ ServicePort servicePort = new ServicePortBuilder().withPort(port)
+ .withName(portName).build();
return buildService(name, uid, Collections.singletonList(servicePort), labels);
}
diff --git a/spring-cloud-kubernetes-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceListSupplierTest.java b/spring-cloud-kubernetes-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceListSupplierTest.java
new file mode 100644
index 00000000..542fe17a
--- /dev/null
+++ b/spring-cloud-kubernetes-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceListSupplierTest.java
@@ -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> serviceOperation;
+
+ @Mock
+ NonNamespaceOperation> namespaceOperation;
+
+ @Mock
+ ServiceResource serviceResource;
+
+ @Mock
+ FilterWatchListMultiDeletable> 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 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 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();
+ }
+
+}