loadBalancerClientFactory;
+
+ @BeforeAll
+ static void beforeAll() {
+
+ wireMockServer = new WireMockServer(options().dynamicPort());
+ wireMockServer.start();
+ WireMock.configureFor("localhost", wireMockServer.port());
+
+ serviceAMockServer = new WireMockServer(SERVICE_A_PORT);
+ serviceAMockServer.start();
+ WireMock.configureFor("localhost", SERVICE_A_PORT);
+
+ serviceBMockServer = new WireMockServer(SERVICE_B_PORT);
+ serviceBMockServer.start();
+ WireMock.configureFor("localhost", SERVICE_B_PORT);
+
+ serviceCMockServer = new WireMockServer(SERVICE_C_PORT);
+ serviceCMockServer.start();
+ WireMock.configureFor("localhost", SERVICE_C_PORT);
+
+ // we mock host creation so that it becomes something like : localhost:8888
+ // then wiremock can catch this request, and we can assert for the result
+ MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("my-service", "a", "cluster.local"))
+ .thenReturn("localhost");
+
+ MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("my-service", "b", "cluster.local"))
+ .thenReturn("localhost");
+
+ MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("my-service", "c", "cluster.local"))
+ .thenReturn("localhost");
+
+ // Configure the kubernetes master url to point to the mock server
+ System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, "http://localhost:" + wireMockServer.port());
+ System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true");
+ System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false");
+ System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
+ System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
+ System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
+ }
+
+ @AfterAll
+ static void afterAll() {
+ wireMockServer.stop();
+ serviceAMockServer.stop();
+ serviceBMockServer.stop();
+ serviceCMockServer.stop();
+ MOCKED_STATIC.close();
+ }
+
+ /**
+ *
+ * - my-service is present in 'a' namespace
+ * - my-service is present in 'b' namespace
+ * - my-service is present in 'c' namespace
+ * - we enable search in selective namespaces [a, b]
+ * - load balancer mode is 'POD'
+ *
+ * - as such, only service in namespace a and b are load balanced
+ * - we also assert the type of ServiceInstanceListSupplier corresponding to the POD mode.
+ *
+ */
+ @Test
+ void test() {
+
+ Service serviceA = Util.service("a", "my-service", SERVICE_A_PORT);
+ Service serviceB = Util.service("b", "my-service", SERVICE_B_PORT);
+ Service serviceC = Util.service("c", "my-service", SERVICE_C_PORT);
+
+ Endpoints endpointsA = Util.endpoints(SERVICE_A_PORT, "127.0.0.1", "a");
+ Endpoints endpointsB = Util.endpoints(SERVICE_B_PORT, "127.0.0.1", "b");
+ Endpoints endpointsC = Util.endpoints(SERVICE_C_PORT, "127.0.0.1", "c");
+
+ String serviceAJson = Serialization.asJson(serviceA);
+ String serviceBJson = Serialization.asJson(serviceB);
+ String serviceCJson = Serialization.asJson(serviceC);
+
+ String endpointsAListAsString = Serialization.asJson(new EndpointsListBuilder().withItems(endpointsA).build());
+ String endpointsBListAsString = Serialization.asJson(new EndpointsListBuilder().withItems(endpointsB).build());
+ String endpointsCListAsString = Serialization.asJson(new EndpointsListBuilder().withItems(endpointsC).build());
+
+ wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/a/services/my-service"))
+ .willReturn(WireMock.aResponse().withBody(serviceAJson).withStatus(200)));
+
+ wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/b/services/my-service"))
+ .willReturn(WireMock.aResponse().withBody(serviceBJson).withStatus(200)));
+
+ wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/c/services/my-service"))
+ .willReturn(WireMock.aResponse().withBody(serviceCJson).withStatus(200)));
+
+ wireMockServer.stubFor(WireMock
+ .get(WireMock.urlEqualTo("/api/v1/namespaces/a/endpoints?fieldSelector=metadata.name%3Dmy-service"))
+ .willReturn(WireMock.aResponse().withBody(endpointsAListAsString).withStatus(200)));
+
+ wireMockServer.stubFor(WireMock
+ .get(WireMock.urlEqualTo("/api/v1/namespaces/b/endpoints?fieldSelector=metadata.name%3Dmy-service"))
+ .willReturn(WireMock.aResponse().withBody(endpointsBListAsString).withStatus(200)));
+
+ wireMockServer.stubFor(WireMock
+ .get(WireMock.urlEqualTo("/api/v1/namespaces/c/endpoints?fieldSelector=metadata.name%3Dmy-service"))
+ .willReturn(WireMock.aResponse().withBody(endpointsCListAsString).withStatus(200)));
+
+ serviceAMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/"))
+ .willReturn(WireMock.aResponse().withBody("service-a-reached").withStatus(200)));
+
+ serviceBMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/"))
+ .willReturn(WireMock.aResponse().withBody("service-b-reached").withStatus(200)));
+
+ serviceCMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/"))
+ .willReturn(WireMock.aResponse().withBody("service-c-reached").withStatus(200)));
+
+ String firstCallResult = builder.baseUrl(MY_SERVICE_URL).build().method(HttpMethod.GET).retrieve()
+ .bodyToMono(String.class).block();
+
+ String secondCallResult = builder.baseUrl(MY_SERVICE_URL).build().method(HttpMethod.GET).retrieve()
+ .bodyToMono(String.class).block();
+
+ // since selective namespaces is a Set, we need to be careful with assertion order
+ if (firstCallResult.equals("service-a-reached")) {
+ Assertions.assertThat(secondCallResult).isEqualTo("service-b-reached");
+ }
+ else {
+ Assertions.assertThat(firstCallResult).isEqualTo("service-b-reached");
+ Assertions.assertThat(secondCallResult).isEqualTo("service-a-reached");
+ }
+
+ CachingServiceInstanceListSupplier supplier = (CachingServiceInstanceListSupplier) loadBalancerClientFactory
+ .getIfAvailable().getProvider("my-service", ServiceInstanceListSupplier.class).getIfAvailable();
+ Assertions.assertThat(supplier.getDelegate().getClass())
+ .isSameAs(DiscoveryClientServiceInstanceListSupplier.class);
+
+ wireMockServer.verify(WireMock.exactly(1),
+ WireMock.getRequestedFor(WireMock.urlEqualTo("/api/v1/namespaces/a/services/my-service")));
+
+ wireMockServer.verify(WireMock.exactly(1),
+ WireMock.getRequestedFor(WireMock.urlEqualTo("/api/v1/namespaces/b/services/my-service")));
+
+ // not triggered in namespace 'c' since that is not a selective namespace
+ wireMockServer.verify(WireMock.exactly(0),
+ WireMock.getRequestedFor(WireMock.urlEqualTo("/api/v1/namespaces/c/services/my-service")));
+
+ wireMockServer.verify(WireMock.exactly(1), WireMock.getRequestedFor(
+ WireMock.urlEqualTo("/api/v1/namespaces/a/endpoints?fieldSelector=metadata.name%3Dmy-service")));
+
+ wireMockServer.verify(WireMock.exactly(1), WireMock.getRequestedFor(
+ WireMock.urlEqualTo("/api/v1/namespaces/b/endpoints?fieldSelector=metadata.name%3Dmy-service")));
+
+ // not triggered in namespace 'c' since that is not a selective namespace
+ wireMockServer.verify(WireMock.exactly(0), WireMock.getRequestedFor(
+ WireMock.urlEqualTo("/api/v1/namespaces/c/endpoints?fieldSelector=metadata.name%3Dmy-service")));
+ }
+
+}
diff --git a/spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/PodModeSpecificNamespaceTest.java b/spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/mode/pod/SpecificNamespaceTest.java
similarity index 62%
rename from spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/PodModeSpecificNamespaceTest.java
rename to spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/mode/pod/SpecificNamespaceTest.java
index fc5692de8..53c84fc75 100644
--- a/spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/PodModeSpecificNamespaceTest.java
+++ b/spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/mode/pod/SpecificNamespaceTest.java
@@ -14,17 +14,12 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.fabric8.loadbalancer.it;
+package org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.mode.pod;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
-import io.fabric8.kubernetes.api.model.EndpointAddressBuilder;
-import io.fabric8.kubernetes.api.model.EndpointPortBuilder;
-import io.fabric8.kubernetes.api.model.EndpointSubsetBuilder;
import io.fabric8.kubernetes.api.model.Endpoints;
-import io.fabric8.kubernetes.api.model.EndpointsBuilder;
import io.fabric8.kubernetes.api.model.EndpointsListBuilder;
-import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.utils.Serialization;
@@ -37,34 +32,29 @@
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.context.TestConfiguration;
-import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.kubernetes.commons.loadbalancer.KubernetesServiceInstanceMapper;
+import org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.Util;
import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.DiscoveryClientServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
-import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.web.reactive.function.client.WebClient;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
-import static org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.PodModeSpecificNamespaceTest.Configuration;
-import static org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.PodModeSpecificNamespaceTest.LoadBalancerConfiguration;
+import static org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.Util.Configuration;
+import static org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.Util.LoadBalancerConfiguration;
/**
* @author wind57
*/
-@SpringBootTest(
- properties = { "spring.cloud.kubernetes.loadbalancer.mode=POD", "spring.main.cloud-platform=KUBERNETES",
+@SpringBootTest(properties = { "spring.cloud.kubernetes.loadbalancer.mode=POD", "spring.main.cloud-platform=KUBERNETES",
"spring.cloud.kubernetes.discovery.all-namespaces=false", "spring.cloud.kubernetes.client.namespace=a" },
- classes = { LoadBalancerConfiguration.class, Configuration.class })
-class PodModeSpecificNamespaceTest {
+ classes = { LoadBalancerConfiguration.class, Configuration.class })
+class SpecificNamespaceTest {
- private static final String SERVICE_A_URL = "http://service-a";
+ private static final String SERVICE_A_URL = "http://my-service";
private static final int SERVICE_A_PORT = 8888;
@@ -77,7 +67,7 @@ class PodModeSpecificNamespaceTest {
private static WireMockServer serviceBMockServer;
private static final MockedStatic MOCKED_STATIC = Mockito
- .mockStatic(KubernetesServiceInstanceMapper.class);
+ .mockStatic(KubernetesServiceInstanceMapper.class);
@Autowired
private WebClient.Builder builder;
@@ -102,11 +92,11 @@ static void beforeAll() {
// we mock host creation so that it becomes something like : localhost:8888
// then wiremock can catch this request, and we can assert for the result
- MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("service-a", "a", "cluster.local"))
- .thenReturn("localhost");
+ MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("my-service", "a", "cluster.local"))
+ .thenReturn("localhost");
- MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("service-b", "b", "cluster.local"))
- .thenReturn("localhost");
+ MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("my-service", "b", "cluster.local"))
+ .thenReturn("localhost");
// Configure the kubernetes master url to point to the mock server
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, "http://localhost:" + wireMockServer.port());
@@ -127,34 +117,23 @@ static void afterAll() {
/**
*
- * - service-a is present in 'a' namespace
- * - service-b is present in 'b' namespace
+ * - my-service is present in 'a' namespace
+ * - my-service is present in 'b' namespace
* - we enable search in namespace 'a'
* - load balancer mode is 'POD'
*
- * - as such, only service-a service is load balanced
+ * - as such, only my-service in namespace a is load balanced
* - we also assert the type of ServiceInstanceListSupplier corresponding to the POD mode.
*
*/
@Test
void test() {
- Service serviceA = Util.createService("a", "service-a", SERVICE_A_PORT);
- Service serviceB = Util.createService("b", "service-a", SERVICE_B_PORT);
+ Service serviceA = Util.service("a", "my-service", SERVICE_A_PORT);
+ Service serviceB = Util.service("b", "my-service", SERVICE_B_PORT);
- Endpoints endpointsA = new EndpointsBuilder()
- .withSubsets(new EndpointSubsetBuilder()
- .withPorts(new EndpointPortBuilder().withPort(SERVICE_A_PORT).build())
- .withAddresses(new EndpointAddressBuilder().withIp("127.0.0.1").build()).build())
- .withMetadata(new ObjectMetaBuilder().withName("no-port-name-service").withNamespace("a").build())
- .build();
-
- Endpoints endpointsB = new EndpointsBuilder()
- .withSubsets(new EndpointSubsetBuilder()
- .withPorts(new EndpointPortBuilder().withPort(SERVICE_B_PORT).build())
- .withAddresses(new EndpointAddressBuilder().withIp("127.0.0.1").build()).build())
- .withMetadata(new ObjectMetaBuilder().withName("no-port-name-service").withNamespace("b").build())
- .build();
+ Endpoints endpointsA = Util.endpoints(SERVICE_A_PORT, "127.0.0.1", "a");
+ Endpoints endpointsB = Util.endpoints(SERVICE_B_PORT, "127.0.0.1", "b");
String endpointsAListAsString = Serialization.asJson(new EndpointsListBuilder().withItems(endpointsA).build());
String endpointsBListAsString = Serialization.asJson(new EndpointsListBuilder().withItems(endpointsB).build());
@@ -162,55 +141,46 @@ void test() {
String serviceAString = Serialization.asJson(serviceA);
String serviceBString = Serialization.asJson(serviceB);
- wireMockServer
- .stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/a/endpoints?fieldSelector=metadata.name%3Dservice-a"))
+ wireMockServer.stubFor(WireMock
+ .get(WireMock.urlEqualTo("/api/v1/namespaces/a/endpoints?fieldSelector=metadata.name%3Dmy-service"))
.willReturn(WireMock.aResponse().withBody(endpointsAListAsString).withStatus(200)));
- wireMockServer
- .stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/b/endpoints?fieldSelector=metadata.name%3Dservice-b"))
+ wireMockServer.stubFor(WireMock
+ .get(WireMock.urlEqualTo("/api/v1/namespaces/b/endpoints?fieldSelector=metadata.name%3Dmy-service"))
.willReturn(WireMock.aResponse().withBody(endpointsBListAsString).withStatus(200)));
- wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/a/services/service-a"))
- .willReturn(WireMock.aResponse().withBody(serviceAString).withStatus(200)));
+ wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/a/services/my-service"))
+ .willReturn(WireMock.aResponse().withBody(serviceAString).withStatus(200)));
- wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/b/services/service-a"))
- .willReturn(WireMock.aResponse().withBody(serviceBString).withStatus(200)));
+ wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/b/services/my-service"))
+ .willReturn(WireMock.aResponse().withBody(serviceBString).withStatus(200)));
serviceAMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/"))
- .willReturn(WireMock.aResponse().withBody("service-a-reached").withStatus(200)));
+ .willReturn(WireMock.aResponse().withBody("service-a-reached").withStatus(200)));
serviceBMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/"))
- .willReturn(WireMock.aResponse().withBody("service-b-reached").withStatus(200)));
+ .willReturn(WireMock.aResponse().withBody("service-b-reached").withStatus(200)));
String serviceAResult = builder.baseUrl(SERVICE_A_URL).build().method(HttpMethod.GET).retrieve()
- .bodyToMono(String.class).block();
+ .bodyToMono(String.class).block();
Assertions.assertThat(serviceAResult).isEqualTo("service-a-reached");
CachingServiceInstanceListSupplier supplier = (CachingServiceInstanceListSupplier) loadBalancerClientFactory
- .getIfAvailable().getProvider("service-a", ServiceInstanceListSupplier.class).getIfAvailable();
+ .getIfAvailable().getProvider("my-service", ServiceInstanceListSupplier.class).getIfAvailable();
Assertions.assertThat(supplier.getDelegate().getClass())
- .isSameAs(DiscoveryClientServiceInstanceListSupplier.class);
- }
-
- @TestConfiguration
- static class LoadBalancerConfiguration {
+ .isSameAs(DiscoveryClientServiceInstanceListSupplier.class);
- @Bean
- @LoadBalanced
- WebClient.Builder client() {
- return WebClient.builder();
- }
+ wireMockServer.verify(WireMock.exactly(1), WireMock.getRequestedFor(
+ WireMock.urlEqualTo("/api/v1/namespaces/a/endpoints?fieldSelector=metadata.name%3Dmy-service")));
- }
-
- @SpringBootApplication
- static class Configuration {
+ wireMockServer.verify(WireMock.exactly(0), WireMock.getRequestedFor(
+ WireMock.urlEqualTo("/api/v1/namespaces/b/endpoints?fieldSelector=metadata.name%3Dmy-service")));
- public static void main(String[] args) {
- SpringApplication.run(ServiceModeAllNamespacesTest.Configuration.class);
- }
+ wireMockServer.verify(WireMock.exactly(1),
+ WireMock.getRequestedFor(WireMock.urlEqualTo("/api/v1/namespaces/a/services/my-service")));
+ wireMockServer.verify(WireMock.exactly(0),
+ WireMock.getRequestedFor(WireMock.urlEqualTo("/api/v1/namespaces/b/services/me-service")));
}
-
}
diff --git a/spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/ServiceModeAllNamespacesTest.java b/spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/mode/service/AllNamespacesTest.java
similarity index 79%
rename from spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/ServiceModeAllNamespacesTest.java
rename to spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/mode/service/AllNamespacesTest.java
index cf5750e65..77831735b 100644
--- a/spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/ServiceModeAllNamespacesTest.java
+++ b/spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/mode/service/AllNamespacesTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.fabric8.loadbalancer.it;
+package org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.mode.service;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
@@ -26,28 +26,27 @@
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.context.TestConfiguration;
-import org.springframework.cloud.client.loadbalancer.LoadBalanced;
+import org.springframework.boot.test.system.CapturedOutput;
+import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.cloud.kubernetes.commons.loadbalancer.KubernetesServiceInstanceMapper;
import org.springframework.cloud.kubernetes.fabric8.loadbalancer.Fabric8ServicesListSupplier;
+import org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.Util;
import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
-import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.web.reactive.function.client.WebClient;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
-import static org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.ServiceModeAllNamespacesTest.Configuration;
-import static org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.ServiceModeAllNamespacesTest.LoadBalancerConfiguration;
+import static org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.Util.Configuration;
+import static org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.Util.LoadBalancerConfiguration;
/**
* @author wind57
@@ -56,7 +55,8 @@
properties = { "spring.cloud.kubernetes.loadbalancer.mode=SERVICE", "spring.main.cloud-platform=KUBERNETES",
"spring.cloud.kubernetes.discovery.all-namespaces=true" },
classes = { LoadBalancerConfiguration.class, Configuration.class })
-class ServiceModeAllNamespacesTest {
+@ExtendWith(OutputCaptureExtension.class)
+class AllNamespacesTest {
private static final String SERVICE_A_URL = "http://service-a";
@@ -129,10 +129,10 @@ static void afterAll() {
*
*/
@Test
- void test() {
+ void test(CapturedOutput output) {
- Service serviceA = Util.createService("a", "service-a", SERVICE_A_PORT);
- Service serviceB = Util.createService("b", "service-b", SERVICE_B_PORT);
+ Service serviceA = Util.service("a", "service-a", SERVICE_A_PORT);
+ Service serviceB = Util.service("b", "service-b", SERVICE_B_PORT);
String serviceListAJson = Serialization.asJson(new ServiceListBuilder().withItems(serviceA).build());
String serviceListBJson = Serialization.asJson(new ServiceListBuilder().withItems(serviceB).build());
@@ -159,29 +159,23 @@ void test() {
.bodyToMono(String.class).block();
Assertions.assertThat(serviceBResult).isEqualTo("service-b-reached");
- CachingServiceInstanceListSupplier supplier = (CachingServiceInstanceListSupplier) loadBalancerClientFactory
+ CachingServiceInstanceListSupplier supplierA = (CachingServiceInstanceListSupplier) loadBalancerClientFactory
.getIfAvailable().getProvider("service-a", ServiceInstanceListSupplier.class).getIfAvailable();
- Assertions.assertThat(supplier.getDelegate().getClass()).isSameAs(Fabric8ServicesListSupplier.class);
- }
-
- @TestConfiguration
- static class LoadBalancerConfiguration {
+ Assertions.assertThat(supplierA.getDelegate().getClass()).isSameAs(Fabric8ServicesListSupplier.class);
- @Bean
- @LoadBalanced
- WebClient.Builder client() {
- return WebClient.builder();
- }
-
- }
+ CachingServiceInstanceListSupplier supplierB = (CachingServiceInstanceListSupplier) loadBalancerClientFactory
+ .getIfAvailable().getProvider("service-b", ServiceInstanceListSupplier.class).getIfAvailable();
+ Assertions.assertThat(supplierB.getDelegate().getClass()).isSameAs(Fabric8ServicesListSupplier.class);
- @SpringBootApplication
- static class Configuration {
+ Assertions.assertThat(output.getOut()).contains("serviceID : service-a");
+ Assertions.assertThat(output.getOut()).contains("serviceID : service-b");
+ Assertions.assertThat(output.getOut()).contains("discovering services in all namespaces");
- public static void main(String[] args) {
- SpringApplication.run(Configuration.class);
- }
+ wireMockServer.verify(WireMock.exactly(1), WireMock
+ .getRequestedFor(WireMock.urlEqualTo("/api/v1/services?fieldSelector=metadata.name%3Dservice-a")));
+ wireMockServer.verify(WireMock.exactly(1), WireMock
+ .getRequestedFor(WireMock.urlEqualTo("/api/v1/services?fieldSelector=metadata.name%3Dservice-b")));
}
}
diff --git a/spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/mode/service/SelectiveNamespacesTest.java b/spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/mode/service/SelectiveNamespacesTest.java
new file mode 100644
index 000000000..efeb89010
--- /dev/null
+++ b/spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/mode/service/SelectiveNamespacesTest.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2013-2024 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.fabric8.loadbalancer.it.mode.service;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import io.fabric8.kubernetes.api.model.Service;
+import io.fabric8.kubernetes.client.Config;
+import io.fabric8.kubernetes.client.utils.Serialization;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.system.CapturedOutput;
+import org.springframework.boot.test.system.OutputCaptureExtension;
+import org.springframework.cloud.kubernetes.commons.loadbalancer.KubernetesServiceInstanceMapper;
+import org.springframework.cloud.kubernetes.fabric8.loadbalancer.Fabric8ServicesListSupplier;
+import org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.Util;
+import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier;
+import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
+import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
+import org.springframework.http.HttpMethod;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
+import static org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.Util.Configuration;
+import static org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.Util.LoadBalancerConfiguration;
+
+/**
+ * @author wind57
+ */
+@SpringBootTest(properties = { "spring.cloud.kubernetes.loadbalancer.mode=SERVICE",
+ "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.discovery.all-namespaces=false",
+ "spring.cloud.kubernetes.discovery.namespaces.[0]=a", "spring.cloud.kubernetes.discovery.namespaces.[1]=b" },
+ classes = { LoadBalancerConfiguration.class, Configuration.class })
+@ExtendWith(OutputCaptureExtension.class)
+class SelectiveNamespacesTest {
+
+ private static final String MY_SERVICE_URL = "http://my-service";
+
+ private static final int SERVICE_A_PORT = 8887;
+
+ private static final int SERVICE_B_PORT = 8888;
+
+ private static final int SERVICE_C_PORT = 8889;
+
+ private static WireMockServer wireMockServer;
+
+ private static WireMockServer serviceAMockServer;
+
+ private static WireMockServer serviceBMockServer;
+
+ private static WireMockServer serviceCMockServer;
+
+ private static final MockedStatic MOCKED_STATIC = Mockito
+ .mockStatic(KubernetesServiceInstanceMapper.class);
+
+ @Autowired
+ private WebClient.Builder builder;
+
+ @Autowired
+ private ObjectProvider loadBalancerClientFactory;
+
+ @BeforeAll
+ static void beforeAll() {
+
+ wireMockServer = new WireMockServer(options().dynamicPort());
+ wireMockServer.start();
+ WireMock.configureFor("localhost", wireMockServer.port());
+
+ serviceAMockServer = new WireMockServer(SERVICE_A_PORT);
+ serviceAMockServer.start();
+ WireMock.configureFor("localhost", SERVICE_A_PORT);
+
+ serviceBMockServer = new WireMockServer(SERVICE_B_PORT);
+ serviceBMockServer.start();
+ WireMock.configureFor("localhost", SERVICE_B_PORT);
+
+ serviceCMockServer = new WireMockServer(SERVICE_C_PORT);
+ serviceCMockServer.start();
+ WireMock.configureFor("localhost", SERVICE_C_PORT);
+
+ // we mock host creation so that it becomes something like : localhost:8888
+ // then wiremock can catch this request, and we can assert for the result
+ MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("my-service", "a", "cluster.local"))
+ .thenReturn("localhost");
+
+ MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("my-service", "b", "cluster.local"))
+ .thenReturn("localhost");
+
+ MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("my-service", "c", "cluster.local"))
+ .thenReturn("localhost");
+
+ // Configure the kubernetes master url to point to the mock server
+ System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, "http://localhost:" + wireMockServer.port());
+ System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true");
+ System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false");
+ System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
+ System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
+ System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
+ }
+
+ @AfterAll
+ static void afterAll() {
+ wireMockServer.stop();
+ serviceAMockServer.stop();
+ serviceBMockServer.stop();
+ serviceCMockServer.stop();
+ MOCKED_STATIC.close();
+ }
+
+ /**
+ *
+ * - my-service is present in 'a' namespace
+ * - my-service is present in 'b' namespace
+ * - my-service is present in 'c' namespace
+ * - we enable search in selective namespaces [a, b]
+ * - load balancer mode is 'SERVICE'
+ *
+ * - as such, only service in namespace a and b are load balanced
+ * - we also assert the type of ServiceInstanceListSupplier corresponding to the SERVICE mode.
+ *
+ */
+ @Test
+ void test(CapturedOutput output) {
+
+ Service serviceA = Util.service("a", "my-service", SERVICE_A_PORT);
+ Service serviceB = Util.service("b", "my-service", SERVICE_B_PORT);
+ Service serviceC = Util.service("c", "my-service", SERVICE_C_PORT);
+
+ String serviceAJson = Serialization.asJson(serviceA);
+ String serviceBJson = Serialization.asJson(serviceB);
+ String serviceCJson = Serialization.asJson(serviceC);
+
+ wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/a/services/my-service"))
+ .willReturn(WireMock.aResponse().withBody(serviceAJson).withStatus(200)));
+
+ wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/b/services/my-service"))
+ .willReturn(WireMock.aResponse().withBody(serviceBJson).withStatus(200)));
+
+ wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/c/services/my-service"))
+ .willReturn(WireMock.aResponse().withBody(serviceCJson).withStatus(200)));
+
+ serviceAMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/"))
+ .willReturn(WireMock.aResponse().withBody("service-a-reached").withStatus(200)));
+
+ serviceBMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/"))
+ .willReturn(WireMock.aResponse().withBody("service-b-reached").withStatus(200)));
+
+ serviceCMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/"))
+ .willReturn(WireMock.aResponse().withBody("service-c-reached").withStatus(200)));
+
+ String firstCallResult = builder.baseUrl(MY_SERVICE_URL).build().method(HttpMethod.GET).retrieve()
+ .bodyToMono(String.class).block();
+
+ String secondCallResult = builder.baseUrl(MY_SERVICE_URL).build().method(HttpMethod.GET).retrieve()
+ .bodyToMono(String.class).block();
+
+ // since selective namespaces is a Set, we need to be careful with assertion order
+ if (firstCallResult.equals("service-a-reached")) {
+ Assertions.assertThat(secondCallResult).isEqualTo("service-b-reached");
+ }
+ else {
+ Assertions.assertThat(firstCallResult).isEqualTo("service-b-reached");
+ Assertions.assertThat(secondCallResult).isEqualTo("service-a-reached");
+ }
+
+ CachingServiceInstanceListSupplier supplier = (CachingServiceInstanceListSupplier) loadBalancerClientFactory
+ .getIfAvailable().getProvider("my-service", ServiceInstanceListSupplier.class).getIfAvailable();
+ Assertions.assertThat(supplier.getDelegate().getClass()).isSameAs(Fabric8ServicesListSupplier.class);
+
+ Assertions.assertThat(output.getOut()).contains("serviceID : my-service");
+ Assertions.assertThat(output.getOut()).contains("discovering services in selective namespaces : [a, b]");
+
+ wireMockServer.verify(WireMock.exactly(1),
+ WireMock.getRequestedFor(WireMock.urlEqualTo("/api/v1/namespaces/a/services/my-service")));
+
+ wireMockServer.verify(WireMock.exactly(1),
+ WireMock.getRequestedFor(WireMock.urlEqualTo("/api/v1/namespaces/b/services/my-service")));
+
+ // not triggered in namespace 'c' since that is not a selective namespace
+ wireMockServer.verify(WireMock.exactly(0),
+ WireMock.getRequestedFor(WireMock.urlEqualTo("/api/v1/namespaces/c/services/my-service")));
+ }
+
+}
diff --git a/spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/ServiceModeSpecificNamespaceTest.java b/spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/mode/service/SpecificNamespaceTest.java
similarity index 67%
rename from spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/ServiceModeSpecificNamespaceTest.java
rename to spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/mode/service/SpecificNamespaceTest.java
index 5369e6130..687a3cbb1 100644
--- a/spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/ServiceModeSpecificNamespaceTest.java
+++ b/spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/mode/service/SpecificNamespaceTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.fabric8.loadbalancer.it;
+package org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.mode.service;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
@@ -25,39 +25,40 @@
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.context.TestConfiguration;
-import org.springframework.cloud.client.loadbalancer.LoadBalanced;
+import org.springframework.boot.test.system.CapturedOutput;
+import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.cloud.kubernetes.commons.loadbalancer.KubernetesServiceInstanceMapper;
import org.springframework.cloud.kubernetes.fabric8.loadbalancer.Fabric8ServicesListSupplier;
+import org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.Util;
import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
-import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.web.reactive.function.client.WebClient;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
-import static org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.ServiceModeSpecificNamespaceTest.Configuration;
-import static org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.ServiceModeSpecificNamespaceTest.LoadBalancerConfiguration;
+import static org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.Util.Configuration;
+import static org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.Util.LoadBalancerConfiguration;
/**
* @author wind57
*/
@SpringBootTest(
- properties = { "spring.cloud.kubernetes.loadbalancer.mode=SERVICE", "spring.main.cloud-platform=KUBERNETES",
- "spring.cloud.kubernetes.discovery.all-namespaces=false", "spring.cloud.kubernetes.client.namespace=a" },
- classes = { LoadBalancerConfiguration.class, Configuration.class })
-class ServiceModeSpecificNamespaceTest {
+ properties = { "spring.cloud.kubernetes.loadbalancer.mode=SERVICE", "spring.main.cloud-platform=KUBERNETES",
+ "spring.cloud.kubernetes.discovery.all-namespaces=false",
+ "spring.cloud.kubernetes.client.namespace=a" },
+ classes = { LoadBalancerConfiguration.class, Configuration.class })
+@ExtendWith(OutputCaptureExtension.class)
+class SpecificNamespaceTest {
- private static final String SERVICE_A_URL = "http://service-a";
+ private static final String MY_SERVICE_URL = "http://my-service";
private static final int SERVICE_A_PORT = 8888;
@@ -70,7 +71,7 @@ class ServiceModeSpecificNamespaceTest {
private static WireMockServer serviceBMockServer;
private static final MockedStatic MOCKED_STATIC = Mockito
- .mockStatic(KubernetesServiceInstanceMapper.class);
+ .mockStatic(KubernetesServiceInstanceMapper.class);
@Autowired
private WebClient.Builder builder;
@@ -95,11 +96,11 @@ static void beforeAll() {
// we mock host creation so that it becomes something like : localhost:8888
// then wiremock can catch this request, and we can assert for the result
- MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("service-a", "a", "cluster.local"))
- .thenReturn("localhost");
+ MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("my-service", "a", "cluster.local"))
+ .thenReturn("localhost");
- MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("service-b", "b", "cluster.local"))
- .thenReturn("localhost");
+ MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("my-service", "b", "cluster.local"))
+ .thenReturn("localhost");
// Configure the kubernetes master url to point to the mock server
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, "http://localhost:" + wireMockServer.port());
@@ -120,64 +121,54 @@ static void afterAll() {
/**
*
- * - service-a is present in 'a' namespace
- * - service-a is present in 'b' namespace
+ * - my-service is present in 'a' namespace
+ * - my-service is present in 'b' namespace
* - we enable search in namespace 'a'
* - load balancer mode is 'SERVICE'
*
- * - as such, only service-a service is load balanced
+ * - as such, only my-service in namespace a is load balanced
* - we also assert the type of ServiceInstanceListSupplier corresponding to the SERVICE mode.
*
*/
@Test
- void test() {
+ void test(CapturedOutput output) {
- Service serviceA = Util.createService("a", "service-a", SERVICE_A_PORT);
- Service serviceB = Util.createService("b", "service-a", SERVICE_B_PORT);
+ Service serviceA = Util.service("a", "my-service", SERVICE_A_PORT);
+ Service serviceB = Util.service("b", "my-service", SERVICE_B_PORT);
String serviceAJson = Serialization.asJson(serviceA);
String serviceBJson = Serialization.asJson(serviceB);
- wireMockServer
- .stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/a/services/service-a"))
+ wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/a/services/my-service"))
.willReturn(WireMock.aResponse().withBody(serviceAJson).withStatus(200)));
- wireMockServer
- .stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/b/services/service-a"))
+ wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/b/services/my-service"))
.willReturn(WireMock.aResponse().withBody(serviceBJson).withStatus(200)));
serviceAMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/"))
- .willReturn(WireMock.aResponse().withBody("service-a-reached").withStatus(200)));
+ .willReturn(WireMock.aResponse().withBody("service-a-reached").withStatus(200)));
serviceBMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/"))
- .willReturn(WireMock.aResponse().withBody("service-b-reached").withStatus(200)));
+ .willReturn(WireMock.aResponse().withBody("service-b-reached").withStatus(200)));
- String serviceAResult = builder.baseUrl(SERVICE_A_URL).build().method(HttpMethod.GET).retrieve()
- .bodyToMono(String.class).block();
+ String serviceAResult = builder.baseUrl(MY_SERVICE_URL).build().method(HttpMethod.GET).retrieve()
+ .bodyToMono(String.class).block();
Assertions.assertThat(serviceAResult).isEqualTo("service-a-reached");
CachingServiceInstanceListSupplier supplier = (CachingServiceInstanceListSupplier) loadBalancerClientFactory
- .getIfAvailable().getProvider("service-a", ServiceInstanceListSupplier.class).getIfAvailable();
+ .getIfAvailable().getProvider("my-service", ServiceInstanceListSupplier.class).getIfAvailable();
Assertions.assertThat(supplier.getDelegate().getClass()).isSameAs(Fabric8ServicesListSupplier.class);
- }
-
- @TestConfiguration
- static class LoadBalancerConfiguration {
- @Bean
- @LoadBalanced
- WebClient.Builder client() {
- return WebClient.builder();
- }
-
- }
+ Assertions.assertThat(output.getOut()).contains("serviceID : my-service");
+ Assertions.assertThat(output.getOut()).contains("discovering services in namespace : a");
- @SpringBootApplication
- static class Configuration {
+ // was called in namespace 'a'
+ wireMockServer.verify(WireMock.exactly(1),
+ WireMock.getRequestedFor(WireMock.urlEqualTo("/api/v1/namespaces/a/services/my-service")));
- public static void main(String[] args) {
- SpringApplication.run(ServiceModeAllNamespacesTest.Configuration.class);
- }
+ // was not called in namespace 'b'
+ wireMockServer.verify(WireMock.exactly(0),
+ WireMock.getRequestedFor(WireMock.urlEqualTo("/api/v1/namespaces/b/services/my-service")));
}