Refactor loadbalancer it test (14) (#1443)
This commit is contained in:
@@ -23,31 +23,61 @@ import java.util.Objects;
|
||||
import io.kubernetes.client.openapi.models.V1Deployment;
|
||||
import io.kubernetes.client.openapi.models.V1Ingress;
|
||||
import io.kubernetes.client.openapi.models.V1Service;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
import org.testcontainers.k3s.K3sContainer;
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
import reactor.util.retry.Retry;
|
||||
import reactor.util.retry.RetryBackoffSpec;
|
||||
|
||||
import org.springframework.boot.test.json.BasicJsonTester;
|
||||
import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
|
||||
import org.springframework.cloud.kubernetes.integration.tests.commons.Phase;
|
||||
import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import static org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util.patchWithMerge;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
class LoadBalancerIT {
|
||||
|
||||
private static final BasicJsonTester BASIC_JSON_TESTER = new BasicJsonTester(LoadBalancerIT.class);
|
||||
|
||||
private static final String BODY_FOR_MERGE = """
|
||||
{
|
||||
"spec": {
|
||||
"template": {
|
||||
"spec": {
|
||||
"containers": [{
|
||||
"name": "spring-cloud-kubernetes-client-loadbalancer-it",
|
||||
"env": [
|
||||
{
|
||||
"name": "SPRING_CLOUD_KUBERNETES_LOADBALANCER_MODE",
|
||||
"value": "SERVICE"
|
||||
}
|
||||
]
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
private static final Map<String, String> POD_LABELS = Map.of("app",
|
||||
"spring-cloud-kubernetes-client-loadbalancer-it");
|
||||
|
||||
private static final String SERVICE_URL = "http://localhost:80/loadbalancer-it/service";
|
||||
|
||||
private static final String SPRING_CLOUD_K8S_LOADBALANCER_APP_NAME = "spring-cloud-kubernetes-client-loadbalancer-it";
|
||||
@@ -65,10 +95,12 @@ class LoadBalancerIT {
|
||||
Commons.loadSpringCloudKubernetesImage(SPRING_CLOUD_K8S_LOADBALANCER_APP_NAME, K3S);
|
||||
util = new Util(K3S);
|
||||
util.setUp(NAMESPACE);
|
||||
loadbalancerIt(Phase.CREATE);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void afterAll() throws Exception {
|
||||
loadbalancerIt(Phase.DELETE);
|
||||
Commons.cleanUp(SPRING_CLOUD_K8S_LOADBALANCER_APP_NAME, K3S);
|
||||
Commons.systemPrune();
|
||||
}
|
||||
@@ -84,17 +116,16 @@ class LoadBalancerIT {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLoadBalancerServiceMode() {
|
||||
loadbalancerIt(false, Phase.CREATE);
|
||||
@Order(1)
|
||||
void testLoadBalancerPodMode() {
|
||||
testLoadBalancer();
|
||||
loadbalancerIt(false, Phase.DELETE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLoadBalancerPodMode() {
|
||||
loadbalancerIt(true, Phase.CREATE);
|
||||
@Order(2)
|
||||
void testLoadBalancerServiceMode() {
|
||||
patchForServiceMode("spring-cloud-kubernetes-client-loadbalancer-it-deployment", NAMESPACE);
|
||||
testLoadBalancer();
|
||||
loadbalancerIt(true, Phase.DELETE);
|
||||
}
|
||||
|
||||
private void testLoadBalancer() {
|
||||
@@ -102,21 +133,15 @@ class LoadBalancerIT {
|
||||
WebClient.Builder builder = builder();
|
||||
WebClient serviceClient = builder.baseUrl(SERVICE_URL).build();
|
||||
|
||||
ResolvableType resolvableType = ResolvableType.forClassWithGenerics(Map.class, String.class, Object.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> result = (Map<String, Object>) serviceClient.method(HttpMethod.GET).retrieve()
|
||||
.bodyToMono(ParameterizedTypeReference.forType(resolvableType.getType())).retryWhen(retrySpec())
|
||||
.block();
|
||||
|
||||
Assertions.assertTrue(result.containsKey("mappings"));
|
||||
Assertions.assertTrue(result.containsKey("meta"));
|
||||
|
||||
String result = serviceClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).block();
|
||||
Assertions.assertThat(BASIC_JSON_TESTER.from(result)).extractingJsonPathArrayValue("$.mappings").isEmpty();
|
||||
Assertions.assertThat(BASIC_JSON_TESTER.from(result)).extractingJsonPathNumberValue("$.meta.total")
|
||||
.isEqualTo(0);
|
||||
}
|
||||
|
||||
private void loadbalancerIt(boolean podBased, Phase phase) {
|
||||
V1Deployment deployment = podBased
|
||||
? (V1Deployment) util.yaml("spring-cloud-kubernetes-client-loadbalancer-pod-it-deployment.yaml")
|
||||
: (V1Deployment) util.yaml("spring-cloud-kubernetes-client-loadbalancer-service-it-deployment.yaml");
|
||||
private static void loadbalancerIt(Phase phase) {
|
||||
V1Deployment deployment = (V1Deployment) util
|
||||
.yaml("spring-cloud-kubernetes-client-loadbalancer-pod-it-deployment.yaml");
|
||||
V1Service service = (V1Service) util.yaml("spring-cloud-kubernetes-client-loadbalancer-it-service.yaml");
|
||||
V1Ingress ingress = (V1Ingress) util.yaml("spring-cloud-kubernetes-client-loadbalancer-it-ingress.yaml");
|
||||
|
||||
@@ -136,4 +161,8 @@ class LoadBalancerIT {
|
||||
return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
|
||||
}
|
||||
|
||||
private static void patchForServiceMode(String deploymentName, String namespace) {
|
||||
patchWithMerge(deploymentName, namespace, BODY_FOR_MERGE, POD_LABELS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: spring-cloud-kubernetes-client-loadbalancer-it-deployment
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: spring-cloud-kubernetes-client-loadbalancer-it
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: spring-cloud-kubernetes-client-loadbalancer-it
|
||||
spec:
|
||||
serviceAccountName: spring-cloud-kubernetes-serviceaccount
|
||||
containers:
|
||||
- name: spring-cloud-kubernetes-client-loadbalancer-it
|
||||
env:
|
||||
- name: SPRING_CLOUD_KUBERNETES_LOADBALANCER_MODE
|
||||
value: SERVICE
|
||||
image: docker.io/springcloud/spring-cloud-kubernetes-client-loadbalancer-it
|
||||
imagePullPolicy: IfNotPresent
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
port: 8080
|
||||
path: /actuator/health/readiness
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
port: 8080
|
||||
path: /actuator/health/liveness
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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.discoveryclient.it;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
import reactor.util.retry.Retry;
|
||||
import reactor.util.retry.RetryBackoffSpec;
|
||||
|
||||
import org.springframework.boot.test.json.BasicJsonTester;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* @author mbialkowski1
|
||||
*/
|
||||
final class DiscoveryClientFilterNamespaceDelegate {
|
||||
|
||||
private static final BasicJsonTester BASIC_JSON_TESTER = new BasicJsonTester(
|
||||
DiscoveryClientFilterNamespaceDelegate.class);
|
||||
|
||||
static void testNamespaceDiscoveryClient() {
|
||||
testLoadBalancer();
|
||||
testHealth();
|
||||
}
|
||||
|
||||
private static void testLoadBalancer() {
|
||||
|
||||
WebClient.Builder builder = builder();
|
||||
WebClient serviceClient = builder.baseUrl("http://localhost:80/discoveryclient-it/services").build();
|
||||
String result = serviceClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
|
||||
.block();
|
||||
|
||||
Assertions.assertThat(BASIC_JSON_TESTER.from(result)).extractingJsonPathArrayValue("$")
|
||||
.contains("service-wiremock");
|
||||
|
||||
// ServiceInstance
|
||||
WebClient serviceInstanceClient = builder
|
||||
.baseUrl("http://localhost:80/discoveryclient-it/service/service-wiremock").build();
|
||||
String serviceInstances = serviceInstanceClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class)
|
||||
.retryWhen(retrySpec()).block();
|
||||
|
||||
Assertions.assertThat(BASIC_JSON_TESTER.from(serviceInstances)).extractingJsonPathStringValue("$.[0].serviceId")
|
||||
.isEqualTo("service-wiremock");
|
||||
|
||||
Assertions.assertThat(BASIC_JSON_TESTER.from(serviceInstances)).extractingJsonPathStringValue("$.[0].namespace")
|
||||
.isEqualTo("left");
|
||||
}
|
||||
|
||||
private static void testHealth() {
|
||||
WebClient.Builder builder = builder();
|
||||
WebClient serviceClient = builder.baseUrl("http://localhost:80/discoveryclient-it/actuator/health").build();
|
||||
|
||||
String health = serviceClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
|
||||
.block();
|
||||
|
||||
Assertions.assertThat(BASIC_JSON_TESTER.from(health))
|
||||
.extractingJsonPathStringValue("$.components.discoveryComposite.status").isEqualTo("UP");
|
||||
}
|
||||
|
||||
private static WebClient.Builder builder() {
|
||||
return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
|
||||
}
|
||||
|
||||
private static RetryBackoffSpec retrySpec() {
|
||||
return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,13 +17,15 @@
|
||||
package org.springframework.cloud.kubernetes.discoveryclient.it;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import io.kubernetes.client.openapi.apis.RbacAuthorizationV1Api;
|
||||
import io.kubernetes.client.openapi.models.V1ClusterRoleBinding;
|
||||
import io.kubernetes.client.openapi.models.V1Deployment;
|
||||
import io.kubernetes.client.openapi.models.V1Ingress;
|
||||
import io.kubernetes.client.openapi.models.V1Service;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -32,28 +34,81 @@ import reactor.netty.http.client.HttpClient;
|
||||
import reactor.util.retry.Retry;
|
||||
import reactor.util.retry.RetryBackoffSpec;
|
||||
|
||||
import org.springframework.boot.test.json.BasicJsonTester;
|
||||
import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
|
||||
import org.springframework.cloud.kubernetes.integration.tests.commons.Phase;
|
||||
import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.cloud.kubernetes.discoveryclient.it.DiscoveryClientFilterNamespaceDelegate.testNamespaceDiscoveryClient;
|
||||
import static org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util.patchWithReplace;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
class DiscoveryClientIT {
|
||||
|
||||
private static final String BODY_ONE = """
|
||||
{
|
||||
"spec": {
|
||||
"template": {
|
||||
"spec": {
|
||||
"containers": [{
|
||||
"name": "spring-cloud-kubernetes-discoveryclient-it",
|
||||
"image": "image_name_here",
|
||||
"env": [
|
||||
{
|
||||
"name": "SPRING_CLOUD_KUBERNETES_DISCOVERY_NAMESPACES_0",
|
||||
"value": "left"
|
||||
}
|
||||
]
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
private static final String BODY_TWO = """
|
||||
{
|
||||
"spec": {
|
||||
"template": {
|
||||
"spec": {
|
||||
"containers": [{
|
||||
"name": "spring-cloud-kubernetes-discoveryserver",
|
||||
"image": "image_name_here",
|
||||
"env": [
|
||||
{
|
||||
"name": "SPRING_CLOUD_KUBERNETES_DISCOVERY_ALL_NAMESPACES",
|
||||
"value": "TRUE"
|
||||
}
|
||||
]
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
private static final Map<String, String> POD_LABELS = Map.of("app", "spring-cloud-kubernetes-discoveryclient-it");
|
||||
|
||||
private static final Map<String, String> POD_LABELS_DISCOVERY = Map.of("app",
|
||||
"spring-cloud-kubernetes-discoveryserver");
|
||||
|
||||
private static final BasicJsonTester BASIC_JSON_TESTER = new BasicJsonTester(DiscoveryClientIT.class);
|
||||
|
||||
private static final String DISCOVERY_SERVER_APP_NAME = "spring-cloud-kubernetes-discoveryserver";
|
||||
|
||||
private static final String SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME = "spring-cloud-kubernetes-discoveryclient-it";
|
||||
|
||||
private static final String NAMESPACE = "default";
|
||||
|
||||
private static final String NAMESPACE_LEFT = "left";
|
||||
|
||||
private static final String NAMESPACE_RIGHT = "right";
|
||||
|
||||
private static final K3sContainer K3S = Commons.container();
|
||||
|
||||
private static Util util;
|
||||
@@ -67,8 +122,21 @@ class DiscoveryClientIT {
|
||||
|
||||
Commons.validateImage(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, K3S);
|
||||
Commons.loadSpringCloudKubernetesImage(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, K3S);
|
||||
|
||||
util = new Util(K3S);
|
||||
util.setUp(NAMESPACE);
|
||||
|
||||
util.createNamespace(NAMESPACE_LEFT);
|
||||
util.createNamespace(NAMESPACE_RIGHT);
|
||||
|
||||
RbacAuthorizationV1Api rbacApi = new RbacAuthorizationV1Api();
|
||||
V1ClusterRoleBinding clusterRole = (V1ClusterRoleBinding) util
|
||||
.yaml("namespace-filter/cluster-admin-serviceaccount-role.yaml");
|
||||
rbacApi.createClusterRoleBinding(clusterRole, null, null, null, null);
|
||||
|
||||
util.wiremock(NAMESPACE_LEFT, "/wiremock-" + NAMESPACE_LEFT, Phase.CREATE, false);
|
||||
util.wiremock(NAMESPACE_RIGHT, "/wiremock-" + NAMESPACE_RIGHT, Phase.CREATE, false);
|
||||
|
||||
discoveryServer(Phase.CREATE);
|
||||
|
||||
}
|
||||
@@ -78,6 +146,12 @@ class DiscoveryClientIT {
|
||||
Commons.cleanUp(DISCOVERY_SERVER_APP_NAME, K3S);
|
||||
Commons.cleanUp(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, K3S);
|
||||
|
||||
util.wiremock(NAMESPACE_LEFT, "/wiremock-" + NAMESPACE_LEFT, Phase.DELETE, false);
|
||||
util.wiremock(NAMESPACE_RIGHT, "/wiremock-" + NAMESPACE_RIGHT, Phase.DELETE, false);
|
||||
|
||||
util.deleteNamespace(NAMESPACE_LEFT);
|
||||
util.deleteNamespace(NAMESPACE_RIGHT);
|
||||
|
||||
discoveryServer(Phase.DELETE);
|
||||
discoveryIt(Phase.DELETE);
|
||||
Commons.systemPrune();
|
||||
@@ -88,34 +162,35 @@ class DiscoveryClientIT {
|
||||
discoveryIt(Phase.CREATE);
|
||||
testLoadBalancer();
|
||||
testHealth();
|
||||
|
||||
patchForNamespaceFilter(
|
||||
"docker.io/springcloud/spring-cloud-kubernetes-discoveryclient-it:" + Commons.pomVersion(),
|
||||
"spring-cloud-kubernetes-discoveryclient-it-deployment", NAMESPACE);
|
||||
patchForAllNamespaces("docker.io/springcloud/spring-cloud-kubernetes-discoveryserver:" + Commons.pomVersion(),
|
||||
"spring-cloud-kubernetes-discoveryserver-deployment", NAMESPACE);
|
||||
testNamespaceDiscoveryClient();
|
||||
}
|
||||
|
||||
private void testLoadBalancer() {
|
||||
WebClient.Builder builder = builder();
|
||||
WebClient serviceClient = builder.baseUrl("http://localhost:80/discoveryclient-it/services").build();
|
||||
|
||||
String[] result = serviceClient.method(HttpMethod.GET).retrieve().bodyToMono(String[].class)
|
||||
.retryWhen(retrySpec()).block();
|
||||
assertThat(Arrays.stream(result).anyMatch("spring-cloud-kubernetes-discoveryserver"::equalsIgnoreCase))
|
||||
.isTrue();
|
||||
String result = serviceClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
|
||||
.block();
|
||||
|
||||
Assertions.assertThat(BASIC_JSON_TESTER.from(result)).extractingJsonPathArrayValue("$")
|
||||
.contains("spring-cloud-kubernetes-discoveryserver");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
void testHealth() {
|
||||
WebClient.Builder builder = builder();
|
||||
WebClient serviceClient = builder.baseUrl("http://localhost:80/discoveryclient-it/actuator/health").build();
|
||||
|
||||
ResolvableType resolvableType = ResolvableType.forClassWithGenerics(Map.class, String.class, Object.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> health = (Map<String, Object>) serviceClient.method(HttpMethod.GET).retrieve()
|
||||
.bodyToMono(ParameterizedTypeReference.forType(resolvableType.getType())).retryWhen(retrySpec())
|
||||
String health = serviceClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
|
||||
.block();
|
||||
|
||||
Map<String, Object> components = (Map<String, Object>) health.get("components");
|
||||
|
||||
Map<String, Object> discoveryComposite = (Map<String, Object>) components.get("discoveryComposite");
|
||||
assertThat(discoveryComposite.get("status")).isEqualTo("UP");
|
||||
Assertions.assertThat(BASIC_JSON_TESTER.from(health))
|
||||
.extractingJsonPathStringValue("$.components.discoveryComposite.status").isEqualTo("UP");
|
||||
}
|
||||
|
||||
private static void discoveryIt(Phase phase) {
|
||||
@@ -154,4 +229,12 @@ class DiscoveryClientIT {
|
||||
return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
|
||||
}
|
||||
|
||||
static void patchForNamespaceFilter(String image, String deploymentName, String namespace) {
|
||||
patchWithReplace(image, deploymentName, namespace, BODY_ONE, POD_LABELS);
|
||||
}
|
||||
|
||||
static void patchForAllNamespaces(String image, String deploymentName, String namespace) {
|
||||
patchWithReplace(image, deploymentName, namespace, BODY_TWO, POD_LABELS_DISCOVERY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -420,9 +420,6 @@ public final class Util {
|
||||
.getItems().stream().noneMatch(x -> x.getMetadata().getName().equals(name)));
|
||||
}
|
||||
|
||||
/**
|
||||
* deploy wiremock without ingress.
|
||||
*/
|
||||
public void wiremock(String namespace, String path, Phase phase) {
|
||||
wiremock(namespace, path, phase, true);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user