Skip to content

Commit dd52a85

Browse files
committed
started tests
Signed-off-by: wind57 <[email protected]>
1 parent 58ea298 commit dd52a85

File tree

1 file changed

+160
-0
lines changed
  • spring-cloud-kubernetes-fabric8-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/it/mode/cached

1 file changed

+160
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.mode.cached;
2+
3+
import com.github.tomakehurst.wiremock.WireMockServer;
4+
import com.github.tomakehurst.wiremock.client.WireMock;
5+
import io.fabric8.kubernetes.api.model.Service;
6+
import io.fabric8.kubernetes.client.Config;
7+
import io.fabric8.kubernetes.client.utils.Serialization;
8+
import org.assertj.core.api.Assertions;
9+
import org.junit.jupiter.api.AfterAll;
10+
import org.junit.jupiter.api.BeforeAll;
11+
import org.junit.jupiter.api.Test;
12+
import org.junit.jupiter.api.extension.ExtendWith;
13+
import org.mockito.MockedStatic;
14+
import org.mockito.Mockito;
15+
16+
import org.springframework.beans.factory.annotation.Autowired;
17+
import org.springframework.boot.test.context.SpringBootTest;
18+
import org.springframework.boot.test.system.CapturedOutput;
19+
import org.springframework.boot.test.system.OutputCaptureExtension;
20+
import org.springframework.cloud.client.ServiceInstance;
21+
import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
22+
import org.springframework.cloud.kubernetes.commons.loadbalancer.KubernetesServiceInstanceMapper;
23+
import org.springframework.cloud.kubernetes.fabric8.loadbalancer.Fabric8ServicesListSupplier;
24+
import org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.Util;
25+
import org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.mode.App;
26+
import org.springframework.cloud.kubernetes.fabric8.loadbalancer.it.mode.LoadBalancerConfiguration;
27+
import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier;
28+
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
29+
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
30+
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
31+
import org.springframework.http.HttpMethod;
32+
import org.springframework.web.reactive.function.client.WebClient;
33+
34+
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
35+
36+
/**
37+
* @author wind57
38+
*/
39+
@SpringBootTest(
40+
properties = { "spring.cloud.kubernetes.loadbalancer.mode=SERVICE", "spring.main.cloud-platform=KUBERNETES",
41+
"spring.cloud.kubernetes.discovery.all-namespaces=false",
42+
"spring.cloud.kubernetes.client.namespace=a" },
43+
classes = { LoadBalancerConfiguration.class, App.class })
44+
@ExtendWith(OutputCaptureExtension.class)
45+
class CachedServicesTest {
46+
47+
private static final String MY_SERVICE_URL = "http://my-service";
48+
49+
private static final int SERVICE_A_PORT = 8888;
50+
51+
private static final int SERVICE_B_PORT = 8889;
52+
53+
private static WireMockServer wireMockServer;
54+
55+
private static WireMockServer serviceAMockServer;
56+
57+
@SuppressWarnings("rawtypes")
58+
private static final MockedStatic<KubernetesServiceInstanceMapper> MOCKED_STATIC = Mockito
59+
.mockStatic(KubernetesServiceInstanceMapper.class);
60+
61+
@Autowired
62+
private WebClient.Builder builder;
63+
64+
@Autowired
65+
private LoadBalancerClientFactory loadBalancerClientFactory;
66+
67+
@BeforeAll
68+
static void beforeAll() {
69+
70+
wireMockServer = new WireMockServer(options().dynamicPort());
71+
wireMockServer.start();
72+
WireMock.configureFor("localhost", wireMockServer.port());
73+
74+
serviceAMockServer = new WireMockServer(SERVICE_A_PORT);
75+
serviceAMockServer.start();
76+
WireMock.configureFor("localhost", SERVICE_A_PORT);
77+
78+
// we mock host creation so that it becomes something like : localhost:8888
79+
// then wiremock can catch this request, and we can assert for the result
80+
MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("my-service", "a", "cluster.local"))
81+
.thenReturn("localhost");
82+
83+
MOCKED_STATIC.when(() -> KubernetesServiceInstanceMapper.createHost("my-service", "b", "cluster.local"))
84+
.thenReturn("localhost");
85+
86+
// Configure the kubernetes master url to point to the mock server
87+
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, "http://localhost:" + wireMockServer.port());
88+
System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true");
89+
System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false");
90+
System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
91+
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
92+
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
93+
}
94+
95+
@AfterAll
96+
static void afterAll() {
97+
wireMockServer.stop();
98+
serviceAMockServer.stop();
99+
MOCKED_STATIC.close();
100+
}
101+
102+
/**
103+
* <pre>
104+
* TODO
105+
* - my-service is present in 'a' namespace
106+
* - my-service is present in 'b' namespace
107+
* - we enable search in namespace 'a'
108+
* - load balancer mode is 'SERVICE'
109+
*
110+
* - as such, only my-service in namespace a is load balanced
111+
* - we also assert the type of ServiceInstanceListSupplier corresponding to the SERVICE mode.
112+
* </pre>
113+
*/
114+
@Test
115+
void test(CapturedOutput output) {
116+
117+
Service serviceA = Util.service("a", "my-service", SERVICE_A_PORT);
118+
Service serviceB = Util.service("b", "my-service", SERVICE_B_PORT);
119+
120+
String serviceAJson = Serialization.asJson(serviceA);
121+
String serviceBJson = Serialization.asJson(serviceB);
122+
123+
wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/a/services/my-service"))
124+
.willReturn(WireMock.aResponse().withBody(serviceAJson).withStatus(200)));
125+
126+
wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/api/v1/namespaces/b/services/my-service"))
127+
.willReturn(WireMock.aResponse().withBody(serviceBJson).withStatus(200)));
128+
129+
serviceAMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/"))
130+
.willReturn(WireMock.aResponse().withBody("service-a-reached").withStatus(200)));
131+
132+
String serviceAResult = builder.baseUrl(MY_SERVICE_URL)
133+
.build()
134+
.method(HttpMethod.GET)
135+
.retrieve()
136+
.bodyToMono(String.class)
137+
.block();
138+
Assertions.assertThat(serviceAResult).isEqualTo("service-a-reached");
139+
140+
ReactiveLoadBalancer<ServiceInstance> reactiveLoadBalancer = loadBalancerClientFactory.getInstance("service-a");
141+
142+
CachingServiceInstanceListSupplier supplier = (CachingServiceInstanceListSupplier) loadBalancerClientFactory
143+
.getProvider("my-service", ServiceInstanceListSupplier.class)
144+
.getIfAvailable();
145+
Assertions.assertThat(supplier.getDelegate().getClass()).isSameAs(Fabric8ServicesListSupplier.class);
146+
147+
Assertions.assertThat(output.getOut()).contains("serviceID : my-service");
148+
Assertions.assertThat(output.getOut()).contains("discovering services in namespace : a");
149+
150+
// was called in namespace 'a'
151+
wireMockServer.verify(WireMock.exactly(1),
152+
WireMock.getRequestedFor(WireMock.urlEqualTo("/api/v1/namespaces/a/services/my-service")));
153+
154+
// was not called in namespace 'b'
155+
wireMockServer.verify(WireMock.exactly(0),
156+
WireMock.getRequestedFor(WireMock.urlEqualTo("/api/v1/namespaces/b/services/my-service")));
157+
158+
}
159+
160+
}

0 commit comments

Comments
 (0)