From 66801c93d3df0346ad2187f9078f942db79be83f Mon Sep 17 00:00:00 2001 From: erabii Date: Wed, 4 Jan 2023 22:13:04 +0200 Subject: [PATCH] Simplify integration tests (#1181) --- .../action.yaml | 5 + .../KubernetesClientCatalogWatchIT.java | 150 +---- ...ernetesClientCatalogWatchNamespacesIT.java | 258 +++------ .../k8s/configmap.yaml | 9 - .../k8s/deployment-it.yaml | 29 - .../k8s/deployment-polling-it.yaml | 31 -- .../k8s/secret.yaml | 7 - .../k8s/service-it.yaml | 18 - .../skaffold.yaml | 33 -- .../config/it/ConfigMapAndSecretIT.java | 175 +++--- ...s-client-config-it-polling-deployment.yaml | 33 -- .../pom.xml | 5 - .../ConfigurationWatcherMultipleAppsIT.java | 303 ++-------- .../event/reload/ConfigMapEventReloadIT.java | 184 ++----- .../k8s/deployment-it.yaml | 26 - .../k8s/service-it.yaml | 18 - .../skaffold.yaml | 19 - ...rnetesClientLoadBalancerApplicationIt.java | 4 +- .../loadbalancer/it/LoadBalancerIT.java | 124 ++--- .../wiremock/wiremock-deployment.yaml | 27 - .../resources/wiremock/wiremock-ingress.yaml | 17 - .../resources/wiremock/wiremock-service.yaml | 14 - .../k8s/deployment-it.yaml | 26 - .../k8s/service-it.yaml | 18 - .../skaffold.yaml | 19 - .../it/ReactiveDiscoveryClientIT.java | 108 +--- .../pom.xml | 5 - .../ConfigurationWatcherMultipleAppIT.java | 261 ++------- .../rabbitmq/rabbitmq-controller.yaml | 29 - .../event/reload/SecretsEventReloadIT.java | 102 ++-- .../pom.xml | 5 - .../watcher/ActuatorRefreshIT.java | 114 ++-- .../watcher/ActuatorRefreshKafkaIT.java | 228 ++------ .../watcher/ActuatorRefreshRabbitMQIT.java | 187 ++----- .../resources/kafka/kafka-deployment.yaml | 54 -- .../test/resources/kafka/kafka-service.yaml | 16 - .../rabbitmq/rabbitmq-controller.yaml | 36 -- .../resources/rabbitmq/rabbitmq-service.yaml | 17 - .../zookeeper/zookeeper-deployment.yaml | 31 -- .../zookeeper/zookeeper-service.yaml | 16 - .../k8s/deployment-it.yaml | 26 - .../k8s/service-it.yaml | 18 - .../skaffold.yaml | 19 - .../core/k8s/it/ActuatorEndpointIT.java | 80 +-- .../k8s/deployment-it.yaml | 26 - .../k8s/service-it.yaml | 18 - .../it/DiscoveryClientFilterNamespaceIT.java | 274 +++------- .../discoveryclient/it/DiscoveryClientIT.java | 147 ++--- .../discovery-wiremock-deployment.yaml | 27 - .../wiremock/discovery-wiremock-ingress.yaml | 15 - .../wiremock/discovery-wiremock-service.yaml | 14 - .../catalog/watch/Fabric8CatalogWatchIT.java | 133 +---- .../Fabric8CatalogWatchWithNamespacesIT.java | 174 ++---- .../event/reload/ConfigMapEventReloadIT.java | 190 +++---- .../test/resources/{two => }/deployment.yaml | 3 - .../src/test/resources/one/deployment.yaml | 31 -- .../src/test/resources/three/deployment.yaml | 31 -- .../reload/ConfigMapPollingReloadIT.java | 107 +--- .../fabric8/configmap/Fabric8ConfigMapIT.java | 104 +--- .../fabric8/configmap/Fabric8DiscoveryIT.java | 132 +---- .../Fabric8DiscoveryNamespaceFilterIT.java | 175 ++---- .../wiremock/wiremock-deployment.yaml | 27 - .../resources/wiremock/wiremock-service.yaml | 14 - .../Fabric8ClientLoadbalancerApp.java | 2 +- .../it/Fabric8ClientLoadbalancerIT.java | 201 ++----- ...bric8-client-loadbalancer-deployment.yaml} | 3 - ...lient-loadbalancer-service-deployment.yaml | 31 -- .../wiremock/wiremock-deployment.yaml | 27 - .../resources/wiremock/wiremock-ingress.yaml | 17 - .../resources/wiremock/wiremock-service.yaml | 14 - .../event/reload/SecretsEventsReloadIT.java | 106 +--- .../kubernetes/fabric8/core/SimpleCoreIT.java | 83 +-- .../fabric8/istio/Fabric8IstioIT.java | 97 +--- .../integration/tests/commons/Commons.java | 28 +- .../tests/commons/Fabric8Utils.java | 297 ---------- .../integration/tests/commons/Phase.java | 34 ++ .../tests/commons/fabric8_client/Util.java | 400 ++++++++++++++ .../tests/commons/native_client/Util.java | 517 ++++++++++++++++++ .../main}/resources/busybox/deployment.yaml | 0 .../src/main}/resources/busybox/service.yaml | 0 .../resources/kafka/kafka-deployment.yaml | 0 .../main}/resources/kafka/kafka-service.yaml | 0 .../rabbitmq/rabbitmq-deployment.yaml | 24 + .../resources/rabbitmq/rabbitmq-service.yaml | 2 +- .../wiremock/wiremock-deployment.yaml | 10 +- .../resources/wiremock/wiremock-ingress.yaml | 2 +- .../wiremock/wiremock-root-path-ingress.yaml | 17 - .../resources/wiremock/wiremock-service.yaml | 6 +- .../zookeeper/zookeeper-deployment.yaml | 0 .../zookeeper/zookeeper-service.yaml | 0 90 files changed, 2045 insertions(+), 4419 deletions(-) delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/configmap.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/deployment-it.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/deployment-polling-it.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/secret.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/service-it.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/skaffold.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-polling-deployment.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/k8s/deployment-it.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/k8s/service-it.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/skaffold.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-deployment.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-ingress.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-service.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/k8s/deployment-it.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/k8s/service-it.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/skaffold.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/src/test/resources/rabbitmq/rabbitmq-controller.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka/kafka-deployment.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka/kafka-service.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq/rabbitmq-controller.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq/rabbitmq-service.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper/zookeeper-deployment.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper/zookeeper-service.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/k8s/deployment-it.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/k8s/service-it.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/skaffold.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/k8s/deployment-it.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/k8s/service-it.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/wiremock/discovery-wiremock-deployment.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/wiremock/discovery-wiremock-ingress.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/wiremock/discovery-wiremock-service.yaml rename spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/resources/{two => }/deployment.yaml (91%) delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/resources/one/deployment.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/resources/three/deployment.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/wiremock/wiremock-deployment.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/wiremock/wiremock-service.yaml rename spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/{spring-cloud-kubernetes-fabric8-client-loadbalancer-pod-deployment.yaml => spring-cloud-kubernetes-fabric8-client-loadbalancer-deployment.yaml} (90%) delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-service-deployment.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-deployment.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-ingress.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-service.yaml delete mode 100644 spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Fabric8Utils.java create mode 100644 spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Phase.java create mode 100644 spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/fabric8_client/Util.java create mode 100644 spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/native_client/Util.java rename {spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-catalog-watcher/src/test => spring-cloud-kubernetes-test-support/src/main}/resources/busybox/deployment.yaml (100%) rename {spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-catalog-watcher/src/test => spring-cloud-kubernetes-test-support/src/main}/resources/busybox/service.yaml (100%) rename {spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test => spring-cloud-kubernetes-test-support/src/main}/resources/kafka/kafka-deployment.yaml (100%) rename {spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test => spring-cloud-kubernetes-test-support/src/main}/resources/kafka/kafka-service.yaml (100%) create mode 100644 spring-cloud-kubernetes-test-support/src/main/resources/rabbitmq/rabbitmq-deployment.yaml rename {spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/src/test => spring-cloud-kubernetes-test-support/src/main}/resources/rabbitmq/rabbitmq-service.yaml (93%) delete mode 100644 spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-root-path-ingress.yaml rename {spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test => spring-cloud-kubernetes-test-support/src/main}/resources/zookeeper/zookeeper-deployment.yaml (100%) rename {spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test => spring-cloud-kubernetes-test-support/src/main}/resources/zookeeper/zookeeper-service.yaml (100%) diff --git a/.github/workflows/composites/fabric8-istio-integration-test/action.yaml b/.github/workflows/composites/fabric8-istio-integration-test/action.yaml index 5f410c33..a173905e 100644 --- a/.github/workflows/composites/fabric8-istio-integration-test/action.yaml +++ b/.github/workflows/composites/fabric8-istio-integration-test/action.yaml @@ -6,6 +6,11 @@ runs: - name: run fabric8 istio integration test shell: bash run: | + + cd spring-cloud-kubernetes-test-support + .././mvnw clean install + cd .. + docker load -i /tmp/docker/images/spring-cloud-kubernetes-fabric8-istio-it.tar cd spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/ ../.././mvnw clean install -Dskip.build.image=true diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/client/catalog/KubernetesClientCatalogWatchIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/client/catalog/KubernetesClientCatalogWatchIT.java index 07704366..3f3b654d 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/client/catalog/KubernetesClientCatalogWatchIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/client/catalog/KubernetesClientCatalogWatchIT.java @@ -20,13 +20,9 @@ import java.time.Duration; import java.util.List; import java.util.Objects; -import io.kubernetes.client.openapi.apis.AppsV1Api; -import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.apis.NetworkingV1Api; import io.kubernetes.client.openapi.models.V1Deployment; import io.kubernetes.client.openapi.models.V1Ingress; import io.kubernetes.client.openapi.models.V1Service; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -38,7 +34,8 @@ import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.commons.discovery.EndpointNameAndNamespace; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +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; @@ -46,7 +43,6 @@ import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; import static org.awaitility.Awaitility.await; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient; /** * @author wind57 @@ -59,47 +55,20 @@ class KubernetesClientCatalogWatchIT { private static final K3sContainer K3S = Commons.container(); - private static CoreV1Api api; - - private static AppsV1Api appsApi; - - private static NetworkingV1Api networkingApi; - - private static K8SUtils k8SUtils; - - private static String busyboxServiceName; - - private static String busyboxDeploymentName; - - private static String appDeploymentName; - - private static String appServiceName; - - private static String appIngressName; + private static Util util; @BeforeAll static void beforeAll() throws Exception { K3S.start(); - Commons.validateImage(APP_NAME, K3S); Commons.loadSpringCloudKubernetesImage(APP_NAME, K3S); - - createApiClient(K3S.getKubeConfigYaml()); - api = new CoreV1Api(); - appsApi = new AppsV1Api(); - networkingApi = new NetworkingV1Api(); - k8SUtils = new K8SUtils(api, appsApi); - k8SUtils.setUp(NAMESPACE); + util = new Util(K3S); + util.setUp(NAMESPACE); } @BeforeEach - void beforeEach() throws Exception { - deployBusyboxManifests(); - } - - @AfterEach - void afterEach() throws Exception { - deleteApp(); + void beforeEach() { + util.busybox(NAMESPACE, Phase.CREATE); } /** @@ -112,16 +81,18 @@ class KubernetesClientCatalogWatchIT { */ @Test void testCatalogWatchWithEndpoints() throws Exception { - deployApp(false); + app(false, Phase.CREATE); assertLogStatement("stateGenerator is of type: KubernetesEndpointsCatalogWatch"); test(); + app(false, Phase.DELETE); } @Test void testCatalogWatchWithEndpointSlices() throws Exception { - deployApp(true); + app(true, Phase.CREATE); assertLogStatement("stateGenerator is of type: KubernetesEndpointSlicesCatalogWatch"); test(); + app(true, Phase.DELETE); } /** @@ -140,8 +111,7 @@ class KubernetesClientCatalogWatchIT { * the test is the same for both endpoints and endpoint slices, the set-up for them is * different. */ - @SuppressWarnings("unchecked") - private void test() throws Exception { + private void test() { WebClient client = builder().baseUrl("localhost/result").build(); EndpointNameAndNamespace[] holder = new EndpointNameAndNamespace[2]; @@ -175,7 +145,7 @@ class KubernetesClientCatalogWatchIT { Assertions.assertEquals("default", resultOne.namespace()); Assertions.assertEquals("default", resultTwo.namespace()); - deleteBusyboxApp(); + util.busybox(NAMESPACE, Phase.DELETE); // what we get after delete EndpointNameAndNamespace[] afterDelete = new EndpointNameAndNamespace[1]; @@ -208,89 +178,19 @@ class KubernetesClientCatalogWatchIT { } - private void deployBusyboxManifests() throws Exception { + private static void app(boolean useEndpointSlices, Phase phase) { + V1Deployment deployment = useEndpointSlices + ? (V1Deployment) util.yaml("app/watcher-endpoint-slices-deployment.yaml") + : (V1Deployment) util.yaml("app/watcher-endpoints-deployment.yaml"); + V1Service service = (V1Service) util.yaml("app/watcher-service.yaml"); + V1Ingress ingress = (V1Ingress) util.yaml("app/watcher-ingress.yaml"); - V1Deployment busyboxDeployment = (V1Deployment) K8SUtils.readYamlFromClasspath(getBusyboxDeployment()); - - String[] image = K8SUtils.getImageFromDeployment(busyboxDeployment).split(":"); - Commons.pullImage(image[0], image[1], K3S); - Commons.loadImage(image[0], image[1], "busybox", K3S); - - appsApi.createNamespacedDeployment(NAMESPACE, busyboxDeployment, null, null, null, null); - busyboxDeploymentName = busyboxDeployment.getMetadata().getName(); - - V1Service busyboxService = (V1Service) K8SUtils.readYamlFromClasspath(getBusyboxService()); - busyboxServiceName = busyboxService.getMetadata().getName(); - api.createNamespacedService(NAMESPACE, busyboxService, null, null, null, null); - - k8SUtils.waitForDeployment(busyboxDeploymentName, NAMESPACE); - - } - - private static void deployApp(boolean useEndpointSlices) throws Exception { - - V1Deployment appDeployment = useEndpointSlices - ? (V1Deployment) K8SUtils.readYamlFromClasspath(getEndpointSlicesAppDeployment()) - : (V1Deployment) K8SUtils.readYamlFromClasspath(getEndpointsAppDeployment()); - - String version = K8SUtils.getPomVersion(); - String currentImage = appDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - appDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version); - - appsApi.createNamespacedDeployment(NAMESPACE, appDeployment, null, null, null, null); - appDeploymentName = appDeployment.getMetadata().getName(); - - V1Service appService = (V1Service) K8SUtils.readYamlFromClasspath(getAppService()); - appServiceName = appService.getMetadata().getName(); - api.createNamespacedService(NAMESPACE, appService, null, null, null, null); - - k8SUtils.waitForDeployment(appDeploymentName, NAMESPACE); - - V1Ingress appIngress = (V1Ingress) K8SUtils.readYamlFromClasspath(getAppIngress()); - appIngressName = appIngress.getMetadata().getName(); - networkingApi.createNamespacedIngress(NAMESPACE, appIngress, null, null, null, null); - k8SUtils.waitForIngress(appIngressName, NAMESPACE); - - } - - private void deleteBusyboxApp() throws Exception { - appsApi.deleteNamespacedDeployment(busyboxDeploymentName, NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedService(busyboxServiceName, NAMESPACE, null, null, null, null, null, null); - k8SUtils.waitForDeploymentToBeDeleted(busyboxDeploymentName, NAMESPACE); - } - - private void deleteApp() throws Exception { - appsApi.deleteNamespacedDeployment(appDeploymentName, NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedService(appServiceName, NAMESPACE, null, null, null, null, null, null); - networkingApi.deleteNamespacedIngress(appIngressName, NAMESPACE, null, null, null, null, null, null); - k8SUtils.waitForDeploymentToBeDeleted(busyboxDeploymentName, NAMESPACE); - } - - private static String getBusyboxService() { - return "busybox/service.yaml"; - } - - private static String getBusyboxDeployment() { - return "busybox/deployment.yaml"; - } - - /** - * deployment where support for endpoint slices is equal to false - */ - private static String getEndpointsAppDeployment() { - return "app/watcher-endpoints-deployment.yaml"; - } - - private static String getEndpointSlicesAppDeployment() { - return "app/watcher-endpoint-slices-deployment.yaml"; - } - - private static String getAppIngress() { - return "app/watcher-ingress.yaml"; - } - - private static String getAppService() { - return "app/watcher-service.yaml"; + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); + } + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); + } } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/client/catalog/KubernetesClientCatalogWatchNamespacesIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/client/catalog/KubernetesClientCatalogWatchNamespacesIT.java index 458bb2a5..37469aad 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/client/catalog/KubernetesClientCatalogWatchNamespacesIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/client/catalog/KubernetesClientCatalogWatchNamespacesIT.java @@ -18,18 +18,16 @@ package org.springframework.cloud.kubernetes.client.catalog; import java.time.Duration; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; import java.util.List; import java.util.Objects; import java.util.Set; -import io.kubernetes.client.openapi.apis.AppsV1Api; -import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.apis.NetworkingV1Api; import io.kubernetes.client.openapi.models.V1Deployment; import io.kubernetes.client.openapi.models.V1EnvVar; import io.kubernetes.client.openapi.models.V1EnvVarBuilder; import io.kubernetes.client.openapi.models.V1Ingress; -import io.kubernetes.client.openapi.models.V1NamespaceBuilder; import io.kubernetes.client.openapi.models.V1Service; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; @@ -43,7 +41,8 @@ import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.commons.discovery.EndpointNameAndNamespace; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +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; @@ -51,7 +50,6 @@ import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; import static org.awaitility.Awaitility.await; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient; public class KubernetesClientCatalogWatchNamespacesIT { @@ -65,58 +63,30 @@ public class KubernetesClientCatalogWatchNamespacesIT { private static final K3sContainer K3S = Commons.container(); - private static CoreV1Api api; - - private static AppsV1Api appsApi; - - private static NetworkingV1Api networkingApi; - - private static K8SUtils k8SUtils; - - private static String busyboxServiceNameA; - - private static String busyboxServiceNameB; - - private static String busyboxDeploymentNameA; - - private static String busyboxDeploymentNameB; - - private static String appDeploymentName; - - private static String appServiceName; - - private static String appIngressName; + private static Util util; @BeforeAll static void beforeAll() throws Exception { K3S.start(); - Commons.validateImage(APP_NAME, K3S); Commons.loadSpringCloudKubernetesImage(APP_NAME, K3S); - - createApiClient(K3S.getKubeConfigYaml()); - api = new CoreV1Api(); - appsApi = new AppsV1Api(); - networkingApi = new NetworkingV1Api(); - k8SUtils = new K8SUtils(api, appsApi); - k8SUtils.setUp(NAMESPACE_DEFAULT); + util = new Util(K3S); + util.setUp(NAMESPACE_DEFAULT); } @BeforeEach - void beforeEach() throws Exception { - api.createNamespace(new V1NamespaceBuilder().withNewMetadata().withName(NAMESPACE_A).and().build(), null, null, - null, null); - api.createNamespace(new V1NamespaceBuilder().withNewMetadata().withName(NAMESPACE_B).and().build(), null, null, - null, null); - k8SUtils.setUpClusterWide(NAMESPACE_DEFAULT, Set.of(NAMESPACE_A, NAMESPACE_B)); - deployBusyboxManifests(); + void beforeEach() { + util.createNamespace(NAMESPACE_A); + util.createNamespace(NAMESPACE_B); + util.setUpClusterWide(NAMESPACE_DEFAULT, Set.of(NAMESPACE_A, NAMESPACE_B)); + util.busybox(NAMESPACE_A, Phase.CREATE); + util.busybox(NAMESPACE_B, Phase.CREATE); } @AfterEach - void afterEach() throws Exception { - deleteApp(); - k8SUtils.deleteNamespace(NAMESPACE_A); - k8SUtils.deleteNamespace(NAMESPACE_B); + void afterEach() { + util.deleteNamespace(NAMESPACE_A); + util.deleteNamespace(NAMESPACE_B); } /** @@ -131,16 +101,18 @@ public class KubernetesClientCatalogWatchNamespacesIT { */ @Test void testCatalogWatchWithEndpoints() throws Exception { - deployApp(false); + app(false, Phase.CREATE); assertLogStatement("stateGenerator is of type: KubernetesEndpointsCatalogWatch"); test(); + app(false, Phase.DELETE); } @Test void testCatalogWatchWithEndpointSlices() throws Exception { - deployApp(true); + app(true, Phase.CREATE); assertLogStatement("stateGenerator is of type: KubernetesEndpointSlicesCatalogWatch"); test(); + app(true, Phase.DELETE); } /** @@ -149,10 +121,8 @@ public class KubernetesClientCatalogWatchNamespacesIT { * type. */ private void assertLogStatement(String log) throws Exception { - String appPodName = K3S - .execInContainer("kubectl", "get", "pods", "-l", - "app=spring-cloud-kubernetes-client-catalog-watcher", "-o=name", "--no-headers") - .getStdout(); + String appPodName = K3S.execInContainer("kubectl", "get", "pods", "-l", + "app=spring-cloud-kubernetes-client-catalog-watcher", "-o=name", "--no-headers").getStdout(); String allLogs = K3S.execInContainer("kubectl", "logs", appPodName.trim()).getStdout(); Assertions.assertTrue(allLogs.contains(log)); } @@ -161,11 +131,10 @@ public class KubernetesClientCatalogWatchNamespacesIT { * the test is the same for both endpoints and endpoint slices, the set-up for them is * different. */ - @SuppressWarnings("unchecked") - private void test() throws Exception { + private void test() { WebClient client = builder().baseUrl("localhost/result").build(); - EndpointNameAndNamespace[] holder = new EndpointNameAndNamespace[2]; + EndpointNameAndNamespace[] holder = new EndpointNameAndNamespace[4]; ResolvableType resolvableType = ResolvableType.forClassWithGenerics(List.class, EndpointNameAndNamespace.class); await().pollInterval(Duration.ofSeconds(1)).atMost(Duration.ofSeconds(240)).until(() -> { @@ -173,12 +142,13 @@ public class KubernetesClientCatalogWatchNamespacesIT { .retrieve().bodyToMono(ParameterizedTypeReference.forType(resolvableType.getType())) .retryWhen(retrySpec()).block(); - // we get 3 pods as input, but because they are sorted by name in the catalog - // watcher implementation - // we will get the first busybox instances here. if (result != null) { + // 2 from namespace-a, 2 from namespace-b + Assertions.assertEquals(result.size(), 4); holder[0] = result.get(0); holder[1] = result.get(1); + holder[2] = result.get(2); + holder[3] = result.get(3); return true; } @@ -187,159 +157,61 @@ public class KubernetesClientCatalogWatchNamespacesIT { EndpointNameAndNamespace resultOne = holder[0]; EndpointNameAndNamespace resultTwo = holder[1]; - - Assertions.assertNotNull(resultOne); - Assertions.assertNotNull(resultTwo); + EndpointNameAndNamespace resultThree = holder[2]; + EndpointNameAndNamespace resultFour = holder[3]; Assertions.assertTrue(resultOne.endpointName().contains("busybox")); Assertions.assertTrue(resultTwo.endpointName().contains("busybox")); - Assertions.assertEquals(NAMESPACE_A, resultOne.namespace()); - Assertions.assertEquals(NAMESPACE_A, resultTwo.namespace()); + Assertions.assertTrue(resultThree.endpointName().contains("busybox")); + Assertions.assertTrue(resultFour.endpointName().contains("busybox")); - deleteBusyboxApp(); + List sorted = Arrays.stream(holder) + .sorted(Comparator.comparing(EndpointNameAndNamespace::namespace)).toList(); - // what we get after delete - EndpointNameAndNamespace[] afterDelete = new EndpointNameAndNamespace[1]; + Assertions.assertEquals(NAMESPACE_A, sorted.get(0).namespace()); + Assertions.assertEquals(NAMESPACE_A, sorted.get(1).namespace()); + Assertions.assertEquals(NAMESPACE_B, sorted.get(2).namespace()); + Assertions.assertEquals(NAMESPACE_B, sorted.get(3).namespace()); + + util.busybox(NAMESPACE_A, Phase.DELETE); + util.busybox(NAMESPACE_B, Phase.DELETE); await().pollInterval(Duration.ofSeconds(1)).atMost(Duration.ofSeconds(240)).until(() -> { List result = (List) client.method(HttpMethod.GET) .retrieve().bodyToMono(ParameterizedTypeReference.forType(resolvableType.getType())) .retryWhen(retrySpec()).block(); - // we need to get the event from KubernetesCatalogWatch, but that happens - // on periodic bases. So in order to be sure we got the event we care about - // we wait until the result has a single entry, which means busybox was - // deleted - // + KubernetesCatalogWatch received the new update. - if (result != null && result.size() != 1) { - return false; - } - - // we will only receive one pod here, our own - if (result != null) { - afterDelete[0] = result.get(0); - return true; - } - - return false; + // there is no update to receive anymore, as there is nothing in namespacea + // and namespaceb + return result.size() == 0; }); - Assertions.assertTrue(afterDelete[0].endpointName().contains(APP_NAME)); - Assertions.assertEquals("default", afterDelete[0].namespace()); - } - private void deployBusyboxManifests() throws Exception { + private void app(boolean useEndpointSlices, Phase phase) { + V1Deployment deployment = useEndpointSlices + ? (V1Deployment) util.yaml("app/watcher-endpoint-slices-deployment.yaml") + : (V1Deployment) util.yaml("app/watcher-endpoints-deployment.yaml"); + V1Service service = (V1Service) util.yaml("app/watcher-service.yaml"); + V1Ingress ingress = (V1Ingress) util.yaml("app/watcher-ingress.yaml"); - V1Deployment busyboxDeployment = (V1Deployment) K8SUtils.readYamlFromClasspath(getBusyboxDeployment()); + if (phase.equals(Phase.CREATE)) { + V1EnvVar one = new V1EnvVarBuilder().withName("SPRING_CLOUD_KUBERNETES_DISCOVERY_NAMESPACES_0") + .withValue(NAMESPACE_A).build(); - String[] image = K8SUtils.getImageFromDeployment(busyboxDeployment).split(":"); - Commons.pullImage(image[0], image[1], K3S); - Commons.loadImage(image[0], image[1], "busybox", K3S); + V1EnvVar two = new V1EnvVarBuilder().withName("SPRING_CLOUD_KUBERNETES_DISCOVERY_NAMESPACES_1") + .withValue(NAMESPACE_B).build(); - // namespace_a - appsApi.createNamespacedDeployment(NAMESPACE_A, busyboxDeployment, null, null, null, null); - busyboxDeploymentNameA = busyboxDeployment.getMetadata().getName(); - - V1Service busyboxServiceA = (V1Service) K8SUtils.readYamlFromClasspath(getBusyboxService()); - busyboxServiceNameA = busyboxServiceA.getMetadata().getName(); - api.createNamespacedService(NAMESPACE_A, busyboxServiceA, null, null, null, null); - - k8SUtils.waitForDeployment(busyboxDeploymentNameA, NAMESPACE_A); - - // namespace_b - appsApi.createNamespacedDeployment(NAMESPACE_B, busyboxDeployment, null, null, null, null); - busyboxDeploymentNameB = busyboxDeployment.getMetadata().getName(); - - V1Service busyboxServiceB = (V1Service) K8SUtils.readYamlFromClasspath(getBusyboxService()); - busyboxServiceNameB = busyboxServiceB.getMetadata().getName(); - api.createNamespacedService(NAMESPACE_B, busyboxServiceB, null, null, null, null); - - k8SUtils.waitForDeployment(busyboxDeploymentNameA, NAMESPACE_A); - - } - - private static void deployApp(boolean useEndpointSlices) throws Exception { - - V1Deployment appDeployment = useEndpointSlices - ? (V1Deployment) K8SUtils.readYamlFromClasspath(getEndpointSlicesAppDeployment()) - : (V1Deployment) K8SUtils.readYamlFromClasspath(getEndpointsAppDeployment()); - - String version = K8SUtils.getPomVersion(); - String currentImage = appDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - appDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version); - - List envVars = new ArrayList<>( - appDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv()); - V1EnvVar namespaceAEnvVar = new V1EnvVarBuilder().withName("SPRING_CLOUD_KUBERNETES_DISCOVERY_NAMESPACES_0") - .withValue(NAMESPACE_A).build(); - V1EnvVar namespaceDefaultEnvVar = new V1EnvVarBuilder() - .withName("SPRING_CLOUD_KUBERNETES_DISCOVERY_NAMESPACES_1").withValue(NAMESPACE_DEFAULT).build(); - envVars.add(namespaceAEnvVar); - envVars.add(namespaceDefaultEnvVar); - - appDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(envVars); - - appsApi.createNamespacedDeployment(NAMESPACE_DEFAULT, appDeployment, null, null, null, null); - appDeploymentName = appDeployment.getMetadata().getName(); - - V1Service appService = (V1Service) K8SUtils.readYamlFromClasspath(getAppService()); - appServiceName = appService.getMetadata().getName(); - api.createNamespacedService(NAMESPACE_DEFAULT, appService, null, null, null, null); - - k8SUtils.waitForDeployment(appDeploymentName, NAMESPACE_DEFAULT); - - V1Ingress appIngress = (V1Ingress) K8SUtils.readYamlFromClasspath(getAppIngress()); - appIngressName = appIngress.getMetadata().getName(); - networkingApi.createNamespacedIngress(NAMESPACE_DEFAULT, appIngress, null, null, null, null); - - k8SUtils.waitForIngress(appIngressName, NAMESPACE_DEFAULT); - - } - - private void deleteBusyboxApp() throws Exception { - // namespacea - appsApi.deleteNamespacedDeployment(busyboxDeploymentNameA, NAMESPACE_A, null, null, null, null, null, null); - api.deleteNamespacedService(busyboxServiceNameA, NAMESPACE_A, null, null, null, null, null, null); - k8SUtils.waitForDeploymentToBeDeleted(busyboxDeploymentNameA, NAMESPACE_A); - - // namespaceb - appsApi.deleteNamespacedDeployment(busyboxDeploymentNameB, NAMESPACE_B, null, null, null, null, null, null); - api.deleteNamespacedService(busyboxServiceNameB, NAMESPACE_B, null, null, null, null, null, null); - k8SUtils.waitForDeploymentToBeDeleted(busyboxDeploymentNameB, NAMESPACE_B); - } - - private void deleteApp() throws Exception { - appsApi.deleteNamespacedDeployment(appDeploymentName, NAMESPACE_DEFAULT, null, null, null, null, null, null); - api.deleteNamespacedService(appServiceName, NAMESPACE_DEFAULT, null, null, null, null, null, null); - networkingApi.deleteNamespacedIngress(appIngressName, NAMESPACE_DEFAULT, null, null, null, null, null, null); - } - - private static String getBusyboxService() { - return "busybox/service.yaml"; - } - - private static String getBusyboxDeployment() { - return "busybox/deployment.yaml"; - } - - /** - * deployment where support for endpoint slices is equal to false - */ - private static String getEndpointsAppDeployment() { - return "app/watcher-endpoints-deployment.yaml"; - } - - private static String getEndpointSlicesAppDeployment() { - return "app/watcher-endpoint-slices-deployment.yaml"; - } - - private static String getAppIngress() { - return "app/watcher-ingress.yaml"; - } - - private static String getAppService() { - return "app/watcher-service.yaml"; + List existing = new ArrayList<>( + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv()); + existing.add(one); + existing.add(two); + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(existing); + util.createAndWait(NAMESPACE_DEFAULT, null, deployment, service, ingress, true); + } + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE_DEFAULT, deployment, service, ingress); + } } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/configmap.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/configmap.yaml deleted file mode 100644 index 6a4e128c..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/configmap.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -data: - application.yaml: |- - my: - config: - myProperty: from-config-map -kind: ConfigMap -metadata: - name: spring-cloud-kubernetes-client-config-it diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/deployment-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/deployment-it.yaml deleted file mode 100644 index 1977d8cc..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/deployment-it.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-client-config-it - name: spring-cloud-kubernetes-client-config-it-deployment -spec: - replicas: 1 - selector: - matchLabels: - app: spring-cloud-kubernetes-client-config-it - strategy: {} - template: - metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-client-config-it - spec: - serviceAccountName: spring-cloud-kubernetes-serviceaccount - containers: - - image: springcloud/spring-cloud-kubernetes-client-config-it:3.0.0-SNAPSHOT - imagePullPolicy: IfNotPresent - name: spring-cloud-kubernetes-client-config-it - resources: {} - env: - - name: SPRING_PROFILES_ACTIVE - value: kubernetes -status: {} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/deployment-polling-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/deployment-polling-it.yaml deleted file mode 100644 index d159fd2e..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/deployment-polling-it.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-client-config-it - name: spring-cloud-kubernetes-client-config-it-deployment -spec: - replicas: 1 - selector: - matchLabels: - app: spring-cloud-kubernetes-client-config-it - strategy: {} - template: - metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-client-config-it - spec: - serviceAccountName: spring-cloud-kubernetes-serviceaccount - containers: - - image: springcloud/spring-cloud-kubernetes-client-config-it:3.0.0-SNAPSHOT - imagePullPolicy: IfNotPresent - name: spring-cloud-kubernetes-client-config-it - resources: {} - env: - - name: SPRING_PROFILES_ACTIVE - value: kubernetes - - name: SPRING_CLOUD_KUBERNETES_RELOAD_MODE - value: polling -status: {} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/secret.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/secret.yaml deleted file mode 100644 index 9b68d973..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/secret.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -data: - my.config.mySecret: cDQ1NXcwcmQ= -kind: Secret -metadata: - name: spring-cloud-kubernetes-client-config-it -type: Opaque diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/service-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/service-it.yaml deleted file mode 100644 index 06324a87..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/service-it.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-client-config-it - name: spring-cloud-kubernetes-client-config-it -spec: - ports: - - name: 80-8080 - port: 80 - protocol: TCP - targetPort: 8080 - selector: - app: spring-cloud-kubernetes-client-config-it - type: ClusterIP -status: - loadBalancer: {} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/skaffold.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/skaffold.yaml deleted file mode 100644 index 8e04873e..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/skaffold.yaml +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: skaffold/v2alpha3 -kind: Config -metadata: - name: spring-cloud-kubernetes-client-config-it -build: - artifacts: - - image: springcloud/spring-cloud-kubernetes-client-config-it - custom: - buildCommand: "../../mvnw clean install -Pskaffold" - dependencies: - paths: - - src - - pom.xml - -profiles: - - name: polling - deploy: - kubectl: - manifests: - - k8s/deployment-polling-it.yaml - - k8s/service-it.yaml - - k8s/configmap.yaml - - k8s/secret.yaml - - ../permissions.yaml - -deploy: - kubectl: - manifests: - - k8s/deployment-it.yaml - - k8s/service-it.yaml - - k8s/configmap.yaml - - k8s/secret.yaml - - ../permissions.yaml diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/java/org/springframework/cloud/kubernetes/client/config/it/ConfigMapAndSecretIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/java/org/springframework/cloud/kubernetes/client/config/it/ConfigMapAndSecretIT.java index 64798eab..631a65fc 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/java/org/springframework/cloud/kubernetes/client/config/it/ConfigMapAndSecretIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/java/org/springframework/cloud/kubernetes/client/config/it/ConfigMapAndSecretIT.java @@ -17,36 +17,38 @@ package org.springframework.cloud.kubernetes.client.config.it; import java.time.Duration; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Objects; -import io.kubernetes.client.openapi.apis.AppsV1Api; +import io.kubernetes.client.openapi.ApiException; import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.apis.NetworkingV1Api; import io.kubernetes.client.openapi.models.V1ConfigMap; import io.kubernetes.client.openapi.models.V1Deployment; +import io.kubernetes.client.openapi.models.V1EnvVar; +import io.kubernetes.client.openapi.models.V1EnvVarBuilder; import io.kubernetes.client.openapi.models.V1Ingress; import io.kubernetes.client.openapi.models.V1Secret; import io.kubernetes.client.openapi.models.V1Service; 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.Test; import org.testcontainers.k3s.K3sContainer; -import org.testcontainers.shaded.org.awaitility.Awaitility; import reactor.netty.http.client.HttpClient; import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util; 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.integration.tests.commons.K8SUtils.createApiClient; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion; +import static org.awaitility.Awaitility.await; /** * @author Ryan Baxter @@ -57,37 +59,26 @@ class ConfigMapAndSecretIT { private static final String SECRET_URL = "localhost:80/mySecret"; - private static final String SPRING_CLOUD_CLIENT_CONFIG_IT_DEPLOYMENT_NAME = "spring-cloud-kubernetes-client-config-it-deployment"; - - private static final String K8S_CONFIG_CLIENT_IT_NAME = "spring-cloud-kubernetes-client-config-it-deployment"; - private static final String K8S_CONFIG_CLIENT_IT_SERVICE_NAME = "spring-cloud-kubernetes-client-config-it"; private static final String NAMESPACE = "default"; private static final String APP_NAME = "spring-cloud-kubernetes-client-config-it"; - private static CoreV1Api api; - - private static AppsV1Api appsApi; - - private static NetworkingV1Api networkingApi; - - private static K8SUtils k8SUtils; - private static final K3sContainer K3S = Commons.container(); + private static Util util; + + private static CoreV1Api coreV1Api; + @BeforeAll static void setup() throws Exception { K3S.start(); Commons.validateImage(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, K3S); - createApiClient(K3S.getKubeConfigYaml()); - api = new CoreV1Api(); - appsApi = new AppsV1Api(); - networkingApi = new NetworkingV1Api(); - k8SUtils = new K8SUtils(api, appsApi); - k8SUtils.setUp(NAMESPACE); + util = new Util(K3S); + coreV1Api = new CoreV1Api(); + util.setUp(NAMESPACE); } @AfterAll @@ -96,117 +87,93 @@ class ConfigMapAndSecretIT { } @AfterEach - void after() throws Exception { - appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null, - "metadata.name=" + K8S_CONFIG_CLIENT_IT_NAME, null, null, null, null, null, null, null, null, null); - api.deleteNamespacedService(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, NAMESPACE, null, null, null, null, null, null); - networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedConfigMap(APP_NAME, NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedSecret(APP_NAME, NAMESPACE, null, null, null, null, null, null); + void after() { + configK8sClientIt(false, Phase.DELETE); } @Test - void testConfigMapAndSecretWatchRefresh() throws Exception { - deployConfigK8sClientIt(); - - // Check to make sure the controller deployment is ready - k8SUtils.waitForDeployment(SPRING_CLOUD_CLIENT_CONFIG_IT_DEPLOYMENT_NAME, NAMESPACE); + void testConfigMapAndSecretWatchRefresh() { + configK8sClientIt(false, Phase.CREATE); testConfigMapAndSecretRefresh(); } @Test - void testConfigMapAndSecretPollingRefresh() throws Exception { - deployConfigK8sClientPollingIt(); - - // Check to make sure the controller deployment is ready - k8SUtils.waitForDeployment(SPRING_CLOUD_CLIENT_CONFIG_IT_DEPLOYMENT_NAME, NAMESPACE); + void testConfigMapAndSecretPollingRefresh() { + configK8sClientIt(true, Phase.CREATE); testConfigMapAndSecretRefresh(); } - void testConfigMapAndSecretRefresh() throws Exception { + /** + *
+	 *     - read configmap/secrets the way we initially build them and assert their values
+	 *     - replace the above and assert we get the new values.
+	 * 
+ */ + void testConfigMapAndSecretRefresh() { WebClient.Builder builder = builder(); WebClient propertyClient = builder.baseUrl(PROPERTY_URL).build(); - String property = propertyClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) - .retryWhen(retrySpec()).block(); - assertThat(property).isEqualTo("from-config-map"); + await().timeout(Duration.ofSeconds(60)).pollInterval(Duration.ofSeconds(2)).until(() -> propertyClient + .method(HttpMethod.GET).retrieve().bodyToMono(String.class).block().equals("from-config-map")); WebClient secretClient = builder.baseUrl(SECRET_URL).build(); String secret = secretClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec()) .block(); - assertThat(secret).isEqualTo("p455w0rd"); + Assertions.assertEquals(secret, "p455w0rd"); - V1ConfigMap configMap = getConfigK8sClientItConfigMap(); + V1ConfigMap configMap = (V1ConfigMap) util.yaml("spring-cloud-kubernetes-client-config-it-configmap.yaml"); Map data = configMap.getData(); data.replace("application.yaml", data.get("application.yaml").replace("from-config-map", "from-unit-test")); configMap.data(data); - api.replaceNamespacedConfigMap(APP_NAME, NAMESPACE, configMap, null, null, null, null); - Awaitility.await().timeout(Duration.ofSeconds(60)).pollInterval(Duration.ofSeconds(2)) - .until(() -> propertyClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).block() - .equals("from-unit-test")); - V1Secret v1Secret = getConfigK8sClientItCSecret(); + try { + coreV1Api.replaceNamespacedConfigMap(APP_NAME, NAMESPACE, configMap, null, null, null, null); + } + catch (ApiException e) { + throw new RuntimeException(e); + } + await().timeout(Duration.ofSeconds(60)).pollInterval(Duration.ofSeconds(2)).until(() -> propertyClient + .method(HttpMethod.GET).retrieve().bodyToMono(String.class).block().equals("from-unit-test")); + V1Secret v1Secret = (V1Secret) util.yaml("spring-cloud-kubernetes-client-config-it-secret.yaml"); Map secretData = v1Secret.getData(); secretData.replace("my.config.mySecret", "p455w1rd".getBytes()); v1Secret.setData(secretData); - api.replaceNamespacedSecret(APP_NAME, NAMESPACE, v1Secret, null, null, null, null); - Awaitility.await().timeout(Duration.ofSeconds(60)).pollInterval(Duration.ofSeconds(2)).until(() -> secretClient + try { + coreV1Api.replaceNamespacedSecret(APP_NAME, NAMESPACE, v1Secret, null, null, null, null); + } + catch (ApiException e) { + throw new RuntimeException(e); + } + await().timeout(Duration.ofSeconds(60)).pollInterval(Duration.ofSeconds(2)).until(() -> secretClient .method(HttpMethod.GET).retrieve().bodyToMono(String.class).block().equals("p455w1rd")); } - private static void deployConfigK8sClientIt() throws Exception { - k8SUtils.waitForDeploymentToBeDeleted(K8S_CONFIG_CLIENT_IT_NAME, NAMESPACE); - api.createNamespacedSecret(NAMESPACE, getConfigK8sClientItCSecret(), null, null, null, null); - api.createNamespacedConfigMap(NAMESPACE, getConfigK8sClientItConfigMap(), null, null, null, null); - appsApi.createNamespacedDeployment(NAMESPACE, getConfigK8sClientItDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getConfigK8sClientItService(), null, null, null, null); + private static void configK8sClientIt(boolean pooling, Phase phase) { + V1Deployment deployment = (V1Deployment) util.yaml("spring-cloud-kubernetes-client-config-it-deployment.yaml"); - V1Ingress ingress = getConfigK8sClientItIngress(); - networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null, null); - k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE); - } + if (pooling) { + V1EnvVar one = new V1EnvVarBuilder().withName("SPRING_CLOUD_KUBERNETES_RELOAD_MODE").withValue("polling") + .build(); + List existing = new ArrayList<>( + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv()); + existing.add(one); + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(existing); + } - private static void deployConfigK8sClientPollingIt() throws Exception { - k8SUtils.waitForDeploymentToBeDeleted(K8S_CONFIG_CLIENT_IT_NAME, NAMESPACE); - api.createNamespacedSecret(NAMESPACE, getConfigK8sClientItCSecret(), null, null, null, null); - api.createNamespacedConfigMap(NAMESPACE, getConfigK8sClientItConfigMap(), null, null, null, null); - appsApi.createNamespacedDeployment(NAMESPACE, getConfigK8sClientItPollingDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getConfigK8sClientItService(), null, null, null, null); - networkingApi.createNamespacedIngress(NAMESPACE, getConfigK8sClientItIngress(), null, null, null, null); - } + V1Service service = (V1Service) util.yaml("spring-cloud-kubernetes-client-config-it-service.yaml"); + V1Ingress ingress = (V1Ingress) util.yaml("spring-cloud-kubernetes-client-config-it-ingress.yaml"); - private static V1Deployment getConfigK8sClientItDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) K8SUtils - .readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-deployment.yaml"); - String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":" - + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } + V1ConfigMap configMap = (V1ConfigMap) util.yaml("spring-cloud-kubernetes-client-config-it-configmap.yaml"); + V1Secret secret = (V1Secret) util.yaml("spring-cloud-kubernetes-client-config-it-secret.yaml"); - private static V1Deployment getConfigK8sClientItPollingDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) K8SUtils - .readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-polling-deployment.yaml"); - String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":" - + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private static V1Service getConfigK8sClientItService() throws Exception { - return (V1Service) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-service.yaml"); - } - - private static V1Ingress getConfigK8sClientItIngress() throws Exception { - return (V1Ingress) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-ingress.yaml"); - } - - private static V1ConfigMap getConfigK8sClientItConfigMap() throws Exception { - return (V1ConfigMap) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-configmap.yaml"); - } - - private static V1Secret getConfigK8sClientItCSecret() throws Exception { - return (V1Secret) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-secret.yaml"); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); + util.createAndWait(NAMESPACE, configMap, secret); + } + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); + util.deleteAndWait(NAMESPACE, configMap, secret); + } } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-polling-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-polling-deployment.yaml deleted file mode 100644 index 3ea26285..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-polling-deployment.yaml +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: spring-cloud-kubernetes-client-config-it-deployment -spec: - selector: - matchLabels: - app: spring-cloud-kubernetes-client-config-it - template: - metadata: - labels: - app: spring-cloud-kubernetes-client-config-it - spec: - serviceAccountName: spring-cloud-kubernetes-serviceaccount - containers: - - name: spring-cloud-kubernetes-client-config-it - image: docker.io/springcloud/spring-cloud-kubernetes-client-config-it - imagePullPolicy: IfNotPresent - readinessProbe: - httpGet: - port: 8080 - path: /actuator/health/readiness - livenessProbe: - httpGet: - port: 8080 - path: /actuator/health/liveness - env: - - name: SPRING_PROFILES_ACTIVE - value: kubernetes - - name: SPRING_CLOUD_KUBERNETES_RELOAD_MODE - value: polling - ports: - - containerPort: 8080 diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/pom.xml index 5c43fd3d..e640594f 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/pom.xml @@ -18,11 +18,6 @@ spring-boot-starter-test test - - org.junit.vintage - junit-vintage-engine - test - org.springframework.cloud spring-cloud-kubernetes-test-support diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/multiple/apps/ConfigurationWatcherMultipleAppsIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/multiple/apps/ConfigurationWatcherMultipleAppsIT.java index 48f31106..b0dfe92f 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/multiple/apps/ConfigurationWatcherMultipleAppsIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/multiple/apps/ConfigurationWatcherMultipleAppsIT.java @@ -18,19 +18,15 @@ package org.springframework.cloud.kubernetes.configuration.watcher.multiple.apps import java.time.Duration; import java.util.Objects; -import java.util.concurrent.TimeUnit; -import io.kubernetes.client.openapi.apis.AppsV1Api; -import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.apis.NetworkingV1Api; import io.kubernetes.client.openapi.models.V1ConfigMap; import io.kubernetes.client.openapi.models.V1ConfigMapBuilder; 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.Test; @@ -40,14 +36,13 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util; import org.springframework.http.HttpMethod; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; import static org.awaitility.Awaitility.await; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion; /** * @author wind57 @@ -58,39 +53,20 @@ class ConfigurationWatcherMultipleAppsIT { private static final String CONFIG_WATCHER_APP_B_IMAGE = "spring-cloud-kubernetes-client-configuration-watcher-configmap-app-b"; - private static final String CONFIG_WATCHER_DEPLOYMENT_APP_A_NAME = "app-a-deployment"; - - private static final String CONFIG_WATCHER_DEPLOYMENT_APP_B_NAME = "app-b-deployment"; - - private static final String SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME = "spring-cloud-kubernetes-configuration-watcher-deployment"; - private static final String SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME = "spring-cloud-kubernetes-configuration-watcher"; private static final String CONFIG_MAP_NAME = "multiple-apps"; private static final String NAMESPACE = "default"; - private static final String KAFKA_BROKER = "kafka-broker"; - - private static final String KAFKA_SERVICE = "kafka"; - - private static final String ZOOKEEPER_SERVICE = "zookeeper"; - - private static final String ZOOKEEPER_DEPLOYMENT = "zookeeper"; - - private static CoreV1Api api; - - private static AppsV1Api appsApi; - - private static NetworkingV1Api networkingApi; - - private static K8SUtils k8SUtils; - private static final K3sContainer K3S = Commons.container(); + private static Util util; + @BeforeAll static void beforeAll() throws Exception { K3S.start(); + util = new Util(K3S); Commons.validateImage(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, K3S); Commons.loadSpringCloudKubernetesImage(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, K3S); @@ -101,12 +77,8 @@ class ConfigurationWatcherMultipleAppsIT { Commons.validateImage(CONFIG_WATCHER_APP_B_IMAGE, K3S); Commons.loadSpringCloudKubernetesImage(CONFIG_WATCHER_APP_B_IMAGE, K3S); - createApiClient(K3S.getKubeConfigYaml()); - api = new CoreV1Api(); - appsApi = new AppsV1Api(); - k8SUtils = new K8SUtils(api, appsApi); - networkingApi = new NetworkingV1Api(); - k8SUtils.setUp(NAMESPACE); + util = new Util(K3S); + util.setUp(NAMESPACE); } @AfterAll @@ -117,41 +89,25 @@ class ConfigurationWatcherMultipleAppsIT { } @BeforeEach - void setup() throws Exception { - - deployZookeeper(); - deployKafka(); - deployAppA(); - deployAppB(); - deployIngress(); - deployConfigWatcher(); - - waitForDeployment(ZOOKEEPER_DEPLOYMENT); - waitForDeployment(KAFKA_BROKER); - waitForDeployment(CONFIG_WATCHER_DEPLOYMENT_APP_A_NAME); - waitForDeployment(CONFIG_WATCHER_DEPLOYMENT_APP_B_NAME); - waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME); + void setup() { + util.zookeeper(NAMESPACE, Phase.CREATE); + util.kafka(NAMESPACE, Phase.CREATE); + appA(Phase.CREATE); + appB(Phase.CREATE); + configWatcher(Phase.CREATE); } @AfterEach - void after() throws Exception { - - cleanUpKafka(); - cleanUpZookeeper(); - cleanUpServices(); - cleanUpDeployments(); - cleanUpIngress(); - cleanUpConfigMaps(); - - k8SUtils.waitForDeploymentToBeDeleted(KAFKA_BROKER, NAMESPACE); - k8SUtils.waitForDeploymentToBeDeleted(ZOOKEEPER_DEPLOYMENT, NAMESPACE); - k8SUtils.waitForDeploymentToBeDeleted(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, NAMESPACE); - k8SUtils.waitForDeploymentToBeDeleted(CONFIG_WATCHER_DEPLOYMENT_APP_A_NAME, NAMESPACE); - k8SUtils.waitForDeploymentToBeDeleted(CONFIG_WATCHER_DEPLOYMENT_APP_B_NAME, NAMESPACE); + void afterEach() { + util.zookeeper(NAMESPACE, Phase.DELETE); + util.kafka(NAMESPACE, Phase.DELETE); + appA(Phase.DELETE); + appB(Phase.DELETE); + configWatcher(Phase.DELETE); } @Test - void testRefresh() throws Exception { + void testRefresh() { // configmap has one label, one that says that we should refresh // and one annotation that says that we should refresh some specific services @@ -161,7 +117,7 @@ class ConfigurationWatcherMultipleAppsIT { "spring-cloud-kubernetes-client-configuration-watcher-configmap-app-a, " + "spring-cloud-kubernetes-client-configuration-watcher-configmap-app-b") .endMetadata().addToData("foo", "hello world").build(); - api.createNamespacedConfigMap(NAMESPACE, configMap, null, null, null, null); + util.createAndWait(NAMESPACE, configMap, null); WebClient.Builder builderA = builder(); WebClient serviceClientA = builderA.baseUrl("http://localhost:80/app-a").build(); @@ -176,7 +132,7 @@ class ConfigurationWatcherMultipleAppsIT { return valueA[0]; }); - Assertions.assertThat(valueA[0]).isTrue(); + Assertions.assertTrue(valueA[0]); Boolean[] valueB = new Boolean[1]; await().pollInterval(Duration.ofSeconds(3)).atMost(Duration.ofSeconds(240)).until(() -> { @@ -185,191 +141,48 @@ class ConfigurationWatcherMultipleAppsIT { return valueB[0]; }); - Assertions.assertThat(valueB[0]).isTrue(); + Assertions.assertTrue(valueB[0]); + util.deleteAndWait(NAMESPACE, configMap, null); } - /** - *
-	 --------------------------------------------------- zookeeper ----------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 
- */ - private void deployZookeeper() throws Exception { - api.createNamespacedService(NAMESPACE, getZookeeperService(), null, null, null, null); - V1Deployment deployment = getZookeeperDeployment(); - String[] image = K8SUtils.getImageFromDeployment(deployment).split(":"); - Commons.pullImage(image[0], image[1], K3S); - Commons.loadImage(image[0], image[1], "zookeeper", K3S); - appsApi.createNamespacedDeployment(NAMESPACE, deployment, null, null, null, null); + private void appA(Phase phase) { + V1Deployment deployment = (V1Deployment) util.yaml("app-a/app-a-deployment.yaml"); + V1Service service = (V1Service) util.yaml("app-a/app-a-service.yaml"); + V1Ingress ingress = (V1Ingress) util + .yaml("ingress/spring-cloud-kubernetes-configuration-watcher-multiple-apps-ingress.yaml"); + + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); + } + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); + } } - private V1Deployment getZookeeperDeployment() throws Exception { - return (V1Deployment) K8SUtils.readYamlFromClasspath("zookeeper/zookeeper-deployment.yaml"); + private void appB(Phase phase) { + V1Deployment deployment = (V1Deployment) util.yaml("app-b/app-b-deployment.yaml"); + V1Service service = (V1Service) util.yaml("app-b/app-b-service.yaml"); + + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, null, true); + } + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE, deployment, service, null); + } } - private V1Service getZookeeperService() throws Exception { - return (V1Service) K8SUtils.readYamlFromClasspath("zookeeper/zookeeper-service.yaml"); - } + private void configWatcher(Phase phase) { + V1Deployment deployment = (V1Deployment) util + .yaml("config-watcher/spring-cloud-kubernetes-configuration-watcher-bus-kafka-deployment.yaml"); + V1Service service = (V1Service) util + .yaml("config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml"); - /** - *
-	 ----------------------------------------------------- kafka ------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 
- */ - private void deployKafka() throws Exception { - api.createNamespacedService(NAMESPACE, getKafkaService(), null, null, null, null); - V1Deployment deployment = getKafkaDeployment(); - String[] image = K8SUtils.getImageFromDeployment(deployment).split(":"); - Commons.pullImage(image[0], image[1], K3S); - Commons.loadImage(image[0], image[1], "kafka", K3S); - appsApi.createNamespacedDeployment(NAMESPACE, getKafkaDeployment(), null, null, null, null); - } - - private V1Deployment getKafkaDeployment() throws Exception { - return (V1Deployment) K8SUtils.readYamlFromClasspath("kafka/kafka-deployment.yaml"); - } - - private V1Service getKafkaService() throws Exception { - return (V1Service) K8SUtils.readYamlFromClasspath("kafka/kafka-service.yaml"); - } - - /** - *
-	 ----------------------------------------------------- app-a ------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 
- */ - private void deployAppA() throws Exception { - appsApi.createNamespacedDeployment(NAMESPACE, getAppADeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getAppAService(), null, null, null, null); - } - - private V1Deployment getAppADeployment() throws Exception { - String urlString = "app-a/app-a-deployment.yaml"; - V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath(urlString); - String image = K8SUtils.getImageFromDeployment(deployment) + ":" + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private V1Service getAppAService() throws Exception { - return (V1Service) K8SUtils.readYamlFromClasspath("app-a/app-a-service.yaml"); - } - - /** - *
-	 --------------------------------------------------- app-b --------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 
- */ - private void deployAppB() throws Exception { - appsApi.createNamespacedDeployment(NAMESPACE, getAppBDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getAppBService(), null, null, null, null); - } - - private V1Deployment getAppBDeployment() throws Exception { - String urlString = "app-b/app-b-deployment.yaml"; - V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath(urlString); - String image = K8SUtils.getImageFromDeployment(deployment) + ":" + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private V1Service getAppBService() throws Exception { - return (V1Service) K8SUtils.readYamlFromClasspath("app-b/app-b-service.yaml"); - } - - /** - *
-	 ------------------------------------------------ config-watcher --------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 
- */ - private void deployConfigWatcher() throws Exception { - appsApi.createNamespacedDeployment(NAMESPACE, getConfigWatcherDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getConfigWatcherService(), null, null, null, null); - } - - private V1Deployment getConfigWatcherDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath( - "config-watcher/spring-cloud-kubernetes-configuration-watcher-bus-kafka-deployment.yaml"); - String image = K8SUtils.getImageFromDeployment(deployment) + ":" + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private V1Service getConfigWatcherService() throws Exception { - return (V1Service) K8SUtils - .readYamlFromClasspath("config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml"); - } - - /** - *
-		------------------------------------------------ common ----------------------------------------------------
-		------------------------------------------------------------------------------------------------------------
-		------------------------------------------------------------------------------------------------------------
-		------------------------------------------------------------------------------------------------------------
-	 
- */ - - private void deployIngress() throws Exception { - V1Ingress ingress = (V1Ingress) K8SUtils.readYamlFromClasspath( - "ingress/spring-cloud-kubernetes-configuration-watcher-multiple-apps-ingress.yaml"); - - networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null, null); - k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE); - } - - private void waitForDeployment(String deploymentName) { - await().pollInterval(Duration.ofSeconds(3)).atMost(600, TimeUnit.SECONDS) - .until(() -> k8SUtils.isDeploymentReady(deploymentName, NAMESPACE)); - } - - private void cleanUpKafka() throws Exception { - appsApi.deleteNamespacedDeployment(KAFKA_BROKER, NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedService(KAFKA_SERVICE, NAMESPACE, null, null, null, null, null, null); - } - - private void cleanUpZookeeper() throws Exception { - appsApi.deleteNamespacedDeployment(ZOOKEEPER_DEPLOYMENT, NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedService(ZOOKEEPER_SERVICE, NAMESPACE, null, null, null, null, null, null); - } - - private void cleanUpServices() throws Exception { - api.deleteNamespacedService("app-a", NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedService("app-b", NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedService(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, NAMESPACE, null, null, null, null, null, - null); - } - - private void cleanUpDeployments() throws Exception { - appsApi.deleteNamespacedDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, NAMESPACE, null, null, null, - null, null, null); - appsApi.deleteNamespacedDeployment(CONFIG_WATCHER_DEPLOYMENT_APP_A_NAME, NAMESPACE, null, null, null, null, - null, null); - - appsApi.deleteNamespacedDeployment(CONFIG_WATCHER_DEPLOYMENT_APP_B_NAME, NAMESPACE, null, null, null, null, - null, null); - } - - private void cleanUpConfigMaps() throws Exception { - api.deleteNamespacedConfigMap(CONFIG_MAP_NAME, NAMESPACE, null, null, null, null, null, null); - } - - private void cleanUpIngress() throws Exception { - networkingApi.deleteNamespacedIngress("it-ingress-multiple-apps", NAMESPACE, null, null, null, null, null, - null); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, null, true); + } + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE, deployment, service, null); + } } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/ConfigMapEventReloadIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/ConfigMapEventReloadIT.java index 3b4bda8b..14dd80e2 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/ConfigMapEventReloadIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/ConfigMapEventReloadIT.java @@ -24,9 +24,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; import io.kubernetes.client.openapi.ApiException; -import io.kubernetes.client.openapi.apis.AppsV1Api; import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.apis.NetworkingV1Api; import io.kubernetes.client.openapi.models.V1ConfigMap; import io.kubernetes.client.openapi.models.V1ConfigMapBuilder; import io.kubernetes.client.openapi.models.V1Deployment; @@ -34,6 +32,7 @@ import io.kubernetes.client.openapi.models.V1Ingress; import io.kubernetes.client.openapi.models.V1ObjectMeta; import io.kubernetes.client.openapi.models.V1Service; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.testcontainers.k3s.K3sContainer; @@ -42,15 +41,13 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util; 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.integration.tests.commons.Commons.processExecResult; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient; -import static org.testcontainers.shaded.org.awaitility.Awaitility.await; +import static org.awaitility.Awaitility.await; /** * @author wind57 @@ -61,46 +58,28 @@ class ConfigMapEventReloadIT { private static final String NAMESPACE = "default"; - private static String deploymentName; + private static final K3sContainer K3S = Commons.container(); - private static String serviceName; - - private static String ingressName; - - private static String leftConfigMapName; - - private static String rightConfigMapName; - - private static String rightWithLabelConfigMapName; + private static Util util; private static CoreV1Api api; - private static AppsV1Api appsApi; - - private static NetworkingV1Api networkingApi; - - private static K8SUtils k8SUtils; - - private static final K3sContainer K3S = Commons.container(); - @BeforeAll static void beforeAll() throws Exception { K3S.start(); Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); - createApiClient(K3S.getKubeConfigYaml()); - createNamespaces(); + util = new Util(K3S); + util.createNamespace("left"); + util.createNamespace("right"); + util.setUpClusterWide(NAMESPACE, Set.of("left", "right")); api = new CoreV1Api(); - appsApi = new AppsV1Api(); - networkingApi = new NetworkingV1Api(); - k8SUtils = new K8SUtils(api, appsApi); - - k8SUtils.setUpClusterWide(NAMESPACE, Set.of("left", "right")); } @AfterAll static void afterAll() throws Exception { - deleteNamespaces(); + util.deleteNamespace("left"); + util.deleteNamespace("right"); Commons.cleanUp(IMAGE_NAME, K3S); } @@ -114,19 +93,19 @@ class ConfigMapEventReloadIT { */ @Test void testInformFromOneNamespaceEventNotTriggered() throws Exception { - deployManifests("one"); + manifests("one", Phase.CREATE); WebClient webClient = builder().baseUrl("localhost/left").build(); String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec()) .block(); // we first read the initial value from the left-configmap - assertThat("left-initial").isEqualTo(result); + Assertions.assertEquals("left-initial", result); // then read the value from the right-configmap webClient = builder().baseUrl("localhost/right").build(); result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec()).block(); - assertThat("right-initial").isEqualTo(result); + Assertions.assertEquals("right-initial", result); // then deploy a new version of right-configmap V1ConfigMap rightConfigMapAfterChange = new V1ConfigMapBuilder() @@ -141,9 +120,9 @@ class ConfigMapEventReloadIT { webClient = builder().baseUrl("localhost/left").build(); result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec()).block(); // left configmap has not changed, no restart of app has happened - assertThat("left-initial").isEqualTo(result); + Assertions.assertEquals("left-initial", result); - deleteManifests(); + manifests("one", Phase.DELETE); } /** @@ -156,13 +135,13 @@ class ConfigMapEventReloadIT { */ @Test void testInformFromOneNamespaceEventTriggered() throws Exception { - deployManifests("two"); + manifests("two", Phase.CREATE); // read the value from the right-configmap WebClient webClient = builder().baseUrl("localhost/right").build(); String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec()) .block(); - assertThat("right-initial").isEqualTo(result); + Assertions.assertEquals("right-initial", result); // then deploy a new version of right-configmap V1ConfigMap rightConfigMapAfterChange = new V1ConfigMapBuilder() @@ -180,9 +159,9 @@ class ConfigMapEventReloadIT { resultAfterChange[0] = innerResult; return innerResult != null; }); - assertThat("right-after-change").isEqualTo(resultAfterChange[0]); + Assertions.assertEquals("right-after-change", resultAfterChange[0]); - deleteManifests(); + manifests("two", Phase.DELETE); } /** @@ -196,19 +175,19 @@ class ConfigMapEventReloadIT { */ @Test void testInform() throws Exception { - deployManifests("three"); + manifests("three", Phase.CREATE); // read the initial value from the right-configmap WebClient rightWebClient = builder().baseUrl("localhost/right").build(); String rightResult = rightWebClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) .retryWhen(retrySpec()).block(); - assertThat("right-initial").isEqualTo(rightResult); + Assertions.assertEquals("right-initial", rightResult); // then read the initial value from the right-with-label-configmap WebClient rightWithLabelWebClient = builder().baseUrl("localhost/with-label").build(); String rightWithLabelResult = rightWithLabelWebClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) .retryWhen(retrySpec()).block(); - assertThat("right-with-label-initial").isEqualTo(rightWithLabelResult); + Assertions.assertEquals("right-with-label-initial", rightWithLabelResult); // then deploy a new version of right-configmap V1ConfigMap rightConfigMapAfterChange = new V1ConfigMapBuilder() @@ -223,7 +202,7 @@ class ConfigMapEventReloadIT { // nothing changes in our app, because we are watching only labeled configmaps rightResult = rightWebClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec()) .block(); - assertThat("right-initial").isEqualTo(rightResult); + Assertions.assertEquals("right-initial", rightResult); // then deploy a new version of right-with-label-configmap V1ConfigMap rightWithLabelConfigMapAfterChange = new V1ConfigMapBuilder() @@ -242,62 +221,47 @@ class ConfigMapEventReloadIT { resultAfterChange[0] = innerResult; return innerResult != null; }); - assertThat("right-with-label-after-change").isEqualTo(resultAfterChange[0]); + Assertions.assertEquals("right-with-label-after-change", resultAfterChange[0]); // right-configmap now will see the new value also, but only because the other // configmap has triggered the restart rightResult = rightWebClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec()) .block(); - assertThat("right-after-change").isEqualTo(rightResult); + Assertions.assertEquals("right-after-change", rightResult); - deleteManifests(); + manifests("three", Phase.DELETE); } - private static void createNamespaces() throws Exception { - processExecResult(K3S.execInContainer("sh", "-c", "kubectl create namespace left")); - processExecResult(K3S.execInContainer("sh", "-c", "kubectl create namespace right")); - } - - private static void deleteNamespaces() throws Exception { - processExecResult(K3S.execInContainer("sh", "-c", "kubectl delete namespace left")); - processExecResult(K3S.execInContainer("sh", "-c", "kubectl delete namespace right")); - } - - private static void deployManifests(String deploymentRoot) { + private static void manifests(String deploymentRoot, Phase phase) { try { - V1ConfigMap leftConfigMap = leftConfigMap(); - leftConfigMapName = leftConfigMap.getMetadata().getName(); - api.createNamespacedConfigMap("left", leftConfigMap, null, null, null, null); + V1ConfigMap leftConfigMap = (V1ConfigMap) util.yaml("left-configmap.yaml"); + V1ConfigMap rightConfigMap = (V1ConfigMap) util.yaml("right-configmap.yaml"); + V1ConfigMap rightWithLabelConfigMap = (V1ConfigMap) util.yaml("right-configmap-with-label.yaml"); - V1ConfigMap rightConfigMap = rightConfigMap(); - rightConfigMapName = rightConfigMap.getMetadata().getName(); - api.createNamespacedConfigMap("right", rightConfigMap, null, null, null, null); + V1Deployment deployment = (V1Deployment) util.yaml(deploymentRoot + "/deployment.yaml"); + V1Service service = (V1Service) util.yaml("service.yaml"); + V1Ingress ingress = (V1Ingress) util.yaml("ingress.yaml"); - if ("three".equals(deploymentRoot)) { - V1ConfigMap rightWithLabelConfigMap = rightWithLabelConfigMap(); - rightWithLabelConfigMapName = rightWithLabelConfigMap.getMetadata().getName(); - api.createNamespacedConfigMap("right", rightWithLabelConfigMap, null, null, null, null); + if (phase.equals(Phase.CREATE)) { + util.createAndWait("left", leftConfigMap, null); + util.createAndWait("right", rightConfigMap, null); + + if ("three".equals(deploymentRoot)) { + util.createAndWait("right", rightWithLabelConfigMap, null); + } + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); } - V1Deployment deployment = getDeployment(deploymentRoot); - String version = K8SUtils.getPomVersion(); - String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version); - deploymentName = deployment.getMetadata().getName(); - appsApi.createNamespacedDeployment(NAMESPACE, deployment, null, null, null, null); - - V1Service service = getService(); - serviceName = service.getMetadata().getName(); - api.createNamespacedService(NAMESPACE, service, null, null, null, null); - - V1Ingress ingress = getIngress(); - ingressName = ingress.getMetadata().getName(); - networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null, null); - - k8SUtils.waitForIngress(ingressName, NAMESPACE); - k8SUtils.waitForDeployment("spring-cloud-kubernetes-client-configmap-deployment-event-reload", NAMESPACE); + if (phase.equals(Phase.DELETE)) { + util.deleteAndWait("left", leftConfigMap, null); + util.deleteAndWait("right", rightConfigMap, null); + if ("three".equals(deploymentRoot)) { + util.deleteAndWait("right", rightWithLabelConfigMap, null); + } + util.deleteAndWait(NAMESPACE, deployment, service, ingress); + } } catch (Exception e) { @@ -306,52 +270,6 @@ class ConfigMapEventReloadIT { } - private static void deleteManifests() { - - try { - - api.deleteNamespacedConfigMap(leftConfigMapName, "left", null, null, null, null, null, null); - api.deleteNamespacedConfigMap(rightConfigMapName, "right", null, null, null, null, null, null); - - if (rightWithLabelConfigMapName != null) { - api.deleteNamespacedConfigMap(rightWithLabelConfigMapName, "right", null, null, null, null, null, null); - } - - appsApi.deleteNamespacedDeployment(deploymentName, NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedService(serviceName, NAMESPACE, null, null, null, null, null, null); - networkingApi.deleteNamespacedIngress(ingressName, NAMESPACE, null, null, null, null, null, null); - - } - catch (Exception e) { - throw new RuntimeException(e); - } - - } - - private static V1ConfigMap leftConfigMap() throws Exception { - return (V1ConfigMap) K8SUtils.readYamlFromClasspath("left-configmap.yaml"); - } - - private static V1ConfigMap rightConfigMap() throws Exception { - return (V1ConfigMap) K8SUtils.readYamlFromClasspath("right-configmap.yaml"); - } - - private static V1ConfigMap rightWithLabelConfigMap() throws Exception { - return (V1ConfigMap) K8SUtils.readYamlFromClasspath("right-configmap-with-label.yaml"); - } - - private static V1Deployment getDeployment(String root) throws Exception { - return (V1Deployment) K8SUtils.readYamlFromClasspath(root + "/deployment.yaml"); - } - - private static V1Service getService() throws Exception { - return (V1Service) K8SUtils.readYamlFromClasspath("service.yaml"); - } - - private static V1Ingress getIngress() throws Exception { - return (V1Ingress) K8SUtils.readYamlFromClasspath("ingress.yaml"); - } - private WebClient.Builder builder() { return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create())); } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/k8s/deployment-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/k8s/deployment-it.yaml deleted file mode 100644 index 1054a71c..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/k8s/deployment-it.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-client-loadbalancer-it - name: spring-cloud-kubernetes-client-loadbalancer-it-deployment -spec: - replicas: 1 - selector: - matchLabels: - app: spring-cloud-kubernetes-client-loadbalancer-it - strategy: {} - template: - metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-client-loadbalancer-it - spec: - serviceAccountName: spring-cloud-kubernetes-serviceaccount - containers: - - image: springcloud/spring-cloud-kubernetes-client-loadbalancer-it:3.0.0-SNAPSHOT - imagePullPolicy: IfNotPresent - name: spring-cloud-kubernetes-client-loadbalancer-it - resources: {} -status: {} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/k8s/service-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/k8s/service-it.yaml deleted file mode 100644 index 52b7cd81..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/k8s/service-it.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-client-loadbalancer-it - name: spring-cloud-kubernetes-client-loadbalancer-it -spec: - ports: - - name: 80-8080 - port: 80 - protocol: TCP - targetPort: 8080 - selector: - app: spring-cloud-kubernetes-client-loadbalancer-it - type: ClusterIP -status: - loadBalancer: {} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/skaffold.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/skaffold.yaml deleted file mode 100644 index ef0e427f..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/skaffold.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: skaffold/v2alpha3 -kind: Config -metadata: - name: spring-cloud-kubernetes-client-loadbalancer-it -build: - artifacts: - - image: springcloud/spring-cloud-kubernetes-client-loadbalancer-it - custom: - buildCommand: "../../mvnw clean install -Pskaffold" - dependencies: - paths: - - src - - pom.xml -deploy: - kubectl: - manifests: - - k8s/deployment-it.yaml - - k8s/service-it.yaml - - ../permissions.yaml diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/KubernetesClientLoadBalancerApplicationIt.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/KubernetesClientLoadBalancerApplicationIt.java index 728ee4a4..f9cdee80 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/KubernetesClientLoadBalancerApplicationIt.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/KubernetesClientLoadBalancerApplicationIt.java @@ -40,7 +40,7 @@ import org.springframework.web.reactive.function.client.WebClient; @RestController public class KubernetesClientLoadBalancerApplicationIt { - private static final String URL = "http://servicea-wiremock/__admin/mappings"; + private static final String URL = "http://service-wiremock/__admin/mappings"; private final DiscoveryClient discoveryClient; @@ -58,7 +58,7 @@ public class KubernetesClientLoadBalancerApplicationIt { return WebClient.builder(); } - @GetMapping("/loadbalancer-it/servicea") + @GetMapping("/loadbalancer-it/service") @SuppressWarnings("unchecked") public Map greeting() { return (Map) client().clientConnector(new ReactorClientHttpConnector(HttpClient.create())) diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/LoadBalancerIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/LoadBalancerIT.java index c673730c..0a4c0256 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/LoadBalancerIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/LoadBalancerIT.java @@ -20,16 +20,12 @@ import java.time.Duration; import java.util.Map; import java.util.Objects; -import io.kubernetes.client.openapi.ApiException; -import io.kubernetes.client.openapi.apis.AppsV1Api; -import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.apis.NetworkingV1Api; 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.Test; @@ -39,93 +35,68 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +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.K8SUtils.createApiClient; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion; - /** * @author Ryan Baxter */ class LoadBalancerIT { - private static final String SERVICE_URL = "localhost:80/loadbalancer-it/servicea"; - - private static final String SPRING_CLOUD_K8S_LOADBALANCER_DEPLOYMENT_NAME = "spring-cloud-kubernetes-client-loadbalancer-it-deployment"; + private static final String SERVICE_URL = "localhost:80/loadbalancer-it/service"; private static final String SPRING_CLOUD_K8S_LOADBALANCER_APP_NAME = "spring-cloud-kubernetes-client-loadbalancer-it"; private static final String NAMESPACE = "default"; - private static CoreV1Api api; - - private static AppsV1Api appsApi; - - private static NetworkingV1Api networkingApi; - - private static K8SUtils k8SUtils; - private static final K3sContainer K3S = Commons.container(); + private static Util util; + @BeforeAll static void beforeAll() throws Exception { K3S.start(); Commons.validateImage(SPRING_CLOUD_K8S_LOADBALANCER_APP_NAME, K3S); Commons.loadSpringCloudKubernetesImage(SPRING_CLOUD_K8S_LOADBALANCER_APP_NAME, K3S); - createApiClient(K3S.getKubeConfigYaml()); - api = new CoreV1Api(); - appsApi = new AppsV1Api(); - networkingApi = new NetworkingV1Api(); - k8SUtils = new K8SUtils(api, appsApi); - k8SUtils.setUp(NAMESPACE); + util = new Util(K3S); + util.setUp(NAMESPACE); } @AfterAll static void afterAll() throws Exception { Commons.cleanUp(SPRING_CLOUD_K8S_LOADBALANCER_APP_NAME, K3S); - k8SUtils.removeWiremockImage(); } @BeforeEach - void setup() throws Exception { - k8SUtils.deployWiremock(NAMESPACE, false, K3S); + void setup() { + util.wiremock(NAMESPACE, "/wiremock", Phase.CREATE); } @AfterEach - void afterEach() throws Exception { - cleanup(); - k8SUtils.cleanUpWiremock(NAMESPACE); + void afterEach() { + util.wiremock(NAMESPACE, "/wiremock", Phase.DELETE); } @Test - void testLoadBalancerServiceMode() throws Exception { - deployLoadbalancerServiceIt(); + void testLoadBalancerServiceMode() { + loadbalancerIt(false, Phase.CREATE); testLoadBalancer(); + loadbalancerIt(false, Phase.DELETE); } @Test - void testLoadBalancerPodMode() throws Exception { - deployLoadbalancerPodIt(); + void testLoadBalancerPodMode() { + loadbalancerIt(true, Phase.CREATE); testLoadBalancer(); - } - - private void cleanup() throws ApiException { - appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null, - "metadata.name=" + SPRING_CLOUD_K8S_LOADBALANCER_DEPLOYMENT_NAME, null, null, null, null, null, null, - null, null, null); - api.deleteNamespacedService(SPRING_CLOUD_K8S_LOADBALANCER_APP_NAME, NAMESPACE, null, null, null, null, null, - null); - networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null); + loadbalancerIt(true, Phase.DELETE); } private void testLoadBalancer() { - // Check to make sure the controller deployment is ready - k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_LOADBALANCER_DEPLOYMENT_NAME, NAMESPACE); WebClient.Builder builder = builder(); WebClient serviceClient = builder.baseUrl(SERVICE_URL).build(); @@ -136,55 +107,24 @@ class LoadBalancerIT { .bodyToMono(ParameterizedTypeReference.forType(resolvableType.getType())).retryWhen(retrySpec()) .block(); - Assertions.assertThat(result.containsKey("mappings")).isTrue(); - Assertions.assertThat(result.containsKey("meta")).isTrue(); + Assertions.assertTrue(result.containsKey("mappings")); + Assertions.assertTrue(result.containsKey("meta")); } - private void deployLoadbalancerServiceIt() throws Exception { - appsApi.createNamespacedDeployment(NAMESPACE, getLoadbalancerServiceItDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getLoadbalancerItService(), null, null, null, null); - deployIngress(); - } + 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"); + 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"); - private void deployLoadbalancerPodIt() throws Exception { - appsApi.createNamespacedDeployment(NAMESPACE, getLoadbalancerPodItDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getLoadbalancerItService(), null, null, null, null); - deployIngress(); - } - - private void deployIngress() throws Exception { - V1Ingress ingress = getLoadbalancerItIngress(); - networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null, null); - k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE); - } - - private V1Deployment getLoadbalancerServiceItDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) K8SUtils - .readYamlFromClasspath("spring-cloud-kubernetes-client-loadbalancer-service-it-deployment.yaml"); - String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":" - + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private V1Deployment getLoadbalancerPodItDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) K8SUtils - .readYamlFromClasspath("spring-cloud-kubernetes-client-loadbalancer-service-it-deployment.yaml"); - String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":" - + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private V1Ingress getLoadbalancerItIngress() throws Exception { - return (V1Ingress) K8SUtils - .readYamlFromClasspath("spring-cloud-kubernetes-client-loadbalancer-it-ingress.yaml"); - } - - private V1Service getLoadbalancerItService() throws Exception { - return (V1Service) K8SUtils - .readYamlFromClasspath("spring-cloud-kubernetes-client-loadbalancer-it-service.yaml"); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); + } + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); + } } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-deployment.yaml deleted file mode 100644 index 9d28eb62..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-deployment.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: servicea-wiremock-deployment -spec: - selector: - matchLabels: - app: servicea-wiremock - template: - metadata: - labels: - app: servicea-wiremock - spec: - containers: - - name: servicea-wiremock - image: wiremock/wiremock:2.32.0 - imagePullPolicy: IfNotPresent - readinessProbe: - httpGet: - port: 8080 - path: /__admin/mappings - livenessProbe: - httpGet: - port: 8080 - path: /__admin/mappings - ports: - - containerPort: 8080 diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-ingress.yaml deleted file mode 100644 index 8786d59a..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-ingress.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: wiremock-ingress - namespace: default -spec: - rules: - - http: - paths: - - path: /wiremock/ - pathType: Prefix - backend: - service: - name: servicea-wiremock - port: - number: 8080 - diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-service.yaml deleted file mode 100644 index ef30d58a..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: servicea-wiremock - name: servicea-wiremock -spec: - ports: - - name: http - port: 8080 - targetPort: 8080 - selector: - app: servicea-wiremock - type: ClusterIP diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/k8s/deployment-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/k8s/deployment-it.yaml deleted file mode 100644 index 693b8b52..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/k8s/deployment-it.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-client-reactive-discovery-it - name: spring-cloud-kubernetes-client-reactive-discovery-it-deployment -spec: - replicas: 1 - selector: - matchLabels: - app: spring-cloud-kubernetes-client-reactive-discovery-it - strategy: {} - template: - metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-client-reactive-discovery-it - spec: - serviceAccountName: spring-cloud-kubernetes-serviceaccount - containers: - - image: springcloud/spring-cloud-kubernetes-client-reactive-discovery-it:3.0.0-SNAPSHOT - imagePullPolicy: IfNotPresent - name: spring-cloud-kubernetes-client-reactive-discovery-it - resources: {} -status: {} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/k8s/service-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/k8s/service-it.yaml deleted file mode 100644 index 4c319497..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/k8s/service-it.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-client-reactive-discovery-it - name: spring-cloud-kubernetes-client-reactive-discovery-it -spec: - ports: - - name: 80-8080 - port: 80 - protocol: TCP - targetPort: 8080 - selector: - app: spring-cloud-kubernetes-client-reactive-discovery-it - type: ClusterIP -status: - loadBalancer: {} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/skaffold.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/skaffold.yaml deleted file mode 100644 index 0c8f1903..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/skaffold.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: skaffold/v2alpha3 -kind: Config -metadata: - name: spring-cloud-kubernetes-client-reactive-discovery-it -build: - artifacts: - - image: springcloud/spring-cloud-kubernetes-client-reactive-discovery-it - custom: - buildCommand: "../../mvnw clean install -Pskaffold" - dependencies: - paths: - - src - - pom.xml -deploy: - kubectl: - manifests: - - k8s/deployment-it.yaml - - k8s/service-it.yaml - - ../permissions.yaml diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/client/reactive/discovery/it/ReactiveDiscoveryClientIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/client/reactive/discovery/it/ReactiveDiscoveryClientIT.java index 8d983875..542dfc70 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/client/reactive/discovery/it/ReactiveDiscoveryClientIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/client/reactive/discovery/it/ReactiveDiscoveryClientIT.java @@ -21,16 +21,12 @@ import java.util.Arrays; import java.util.Map; import java.util.Objects; -import io.kubernetes.client.openapi.ApiException; -import io.kubernetes.client.openapi.apis.AppsV1Api; -import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.apis.NetworkingV1Api; 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.Test; @@ -40,17 +36,14 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +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.integration.tests.commons.K8SUtils.createApiClient; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion; - /** * @author Ryan Baxter */ @@ -60,55 +53,42 @@ class ReactiveDiscoveryClientIT { private static final String SERVICES_URL = "localhost:80/reactive-discovery-it/services"; - private static final String SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_DEPLOYMENT_NAME = "spring-cloud-kubernetes-client-reactive-discoveryclient-it-deployment"; - private static final String SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_APP_NAME = "spring-cloud-kubernetes-client-reactive-discoveryclient-it"; private static final String NAMESPACE = "default"; - private static CoreV1Api api; - - private static AppsV1Api appsApi; - - private static NetworkingV1Api networkingApi; - - private static K8SUtils k8SUtils; - private static final K3sContainer K3S = Commons.container(); + private static Util util; + @BeforeAll static void beforeAll() throws Exception { K3S.start(); Commons.validateImage(SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_APP_NAME, K3S); Commons.loadSpringCloudKubernetesImage(SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_APP_NAME, K3S); - createApiClient(K3S.getKubeConfigYaml()); - api = new CoreV1Api(); - appsApi = new AppsV1Api(); - networkingApi = new NetworkingV1Api(); - k8SUtils = new K8SUtils(api, appsApi); - k8SUtils.setUp(NAMESPACE); + util = new Util(K3S); + util.setUp(NAMESPACE); } @AfterAll static void afterAll() throws Exception { Commons.cleanUp(SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_APP_NAME, K3S); - k8SUtils.removeWiremockImage(); } @BeforeEach - void setup() throws Exception { - k8SUtils.deployWiremock(NAMESPACE, false, K3S); + void setup() { + util.wiremock(NAMESPACE, "/wiremock", Phase.CREATE); } @AfterEach - void after() throws Exception { - k8SUtils.cleanUpWiremock(NAMESPACE); - cleanup(); + void after() { + util.wiremock(NAMESPACE, "/wiremock", Phase.DELETE); + reactiveDiscoveryIt(Phase.DELETE); } @Test - void testReactiveDiscoveryClient() throws Exception { - deployReactiveDiscoveryIt(); + void testReactiveDiscoveryClient() { + reactiveDiscoveryIt(Phase.CREATE); testLoadBalancer(); testHealth(); } @@ -126,64 +106,36 @@ class ReactiveDiscoveryClientIT { Map components = (Map) health.get("components"); - assertThat(components.containsKey("reactiveDiscoveryClients")).isTrue(); + Assertions.assertTrue(components.containsKey("reactiveDiscoveryClients")); Map discoveryComposite = (Map) components.get("discoveryComposite"); - assertThat(discoveryComposite.get("status")).isEqualTo("UP"); - } - - private void cleanup() throws ApiException { - appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null, - "metadata.name=" + SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_DEPLOYMENT_NAME, null, null, null, null, null, - null, null, null, null); - api.deleteNamespacedService(SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_APP_NAME, NAMESPACE, null, null, null, null, - null, null); - networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null); + Assertions.assertEquals(discoveryComposite.get("status"), "UP"); } private void testLoadBalancer() { - // Check to make sure the controller deployment is ready - k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_DEPLOYMENT_NAME, NAMESPACE); - WebClient.Builder builder = builder(); WebClient serviceClient = builder.baseUrl(SERVICES_URL).build(); String servicesResponse = serviceClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) .retryWhen(retrySpec()).block(); Assertions - .assertThat(Arrays.stream(servicesResponse.split(",")).anyMatch("servicea-wiremock"::equalsIgnoreCase)) - .isTrue(); - + .assertTrue(Arrays.stream(servicesResponse.split(",")).anyMatch("service-wiremock"::equalsIgnoreCase)); } - private void deployIngress(V1Ingress ingress) throws Exception { - networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null, null); - k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE); - } + private void reactiveDiscoveryIt(Phase phase) { + V1Deployment deployment = (V1Deployment) util + .yaml("spring-cloud-kubernetes-client-reactive-discoveryclient-it-deployment.yaml"); + V1Service service = (V1Service) util + .yaml("spring-cloud-kubernetes-client-reactive-discoveryclient-it-service.yaml"); + V1Ingress ingress = (V1Ingress) util + .yaml("spring-cloud-kubernetes-client-reactive-discoveryclient-it-ingress.yaml"); - private void deployReactiveDiscoveryIt() throws Exception { - appsApi.createNamespacedDeployment(NAMESPACE, getReactiveDiscoveryItDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getReactiveDiscoveryService(), null, null, null, null); - deployIngress(getReactiveDiscoveryItIngress()); - } - - private V1Deployment getReactiveDiscoveryItDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) K8SUtils - .readYamlFromClasspath("spring-cloud-kubernetes-client-reactive-discoveryclient-it-deployment.yaml"); - String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":" - + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private V1Service getReactiveDiscoveryService() throws Exception { - return (V1Service) K8SUtils - .readYamlFromClasspath("spring-cloud-kubernetes-client-reactive-discoveryclient-it-service.yaml"); - } - - private V1Ingress getReactiveDiscoveryItIngress() throws Exception { - return (V1Ingress) K8SUtils - .readYamlFromClasspath("spring-cloud-kubernetes-client-reactive-discoveryclient-it-ingress.yaml"); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); + } + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); + } } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/pom.xml index 3a0ee6e6..656d98d8 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/pom.xml @@ -18,11 +18,6 @@ spring-boot-starter-test test
- - org.junit.vintage - junit-vintage-engine - test - org.springframework.cloud spring-cloud-kubernetes-test-support diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/multiple/apps/ConfigurationWatcherMultipleAppIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/multiple/apps/ConfigurationWatcherMultipleAppIT.java index b078c04a..9f68bf07 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/multiple/apps/ConfigurationWatcherMultipleAppIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/multiple/apps/ConfigurationWatcherMultipleAppIT.java @@ -18,20 +18,15 @@ package org.springframework.cloud.kubernetes.configuration.watcher.multiple.apps import java.time.Duration; import java.util.Objects; -import java.util.concurrent.TimeUnit; -import io.kubernetes.client.openapi.apis.AppsV1Api; -import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.apis.NetworkingV1Api; import io.kubernetes.client.openapi.models.V1Deployment; import io.kubernetes.client.openapi.models.V1Ingress; -import io.kubernetes.client.openapi.models.V1ReplicationController; import io.kubernetes.client.openapi.models.V1Secret; import io.kubernetes.client.openapi.models.V1SecretBuilder; 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.Test; @@ -41,14 +36,13 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util; import org.springframework.http.HttpMethod; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; import static org.awaitility.Awaitility.await; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion; /** * @author wind57 @@ -59,28 +53,16 @@ class ConfigurationWatcherMultipleAppIT { private static final String CONFIG_WATCHER_APP_B_IMAGE = "spring-cloud-kubernetes-client-configuration-watcher-secrets-app-b"; - private static final String CONFIG_WATCHER_DEPLOYMENT_APP_A_NAME = "app-a-deployment"; - - private static final String CONFIG_WATCHER_DEPLOYMENT_APP_B_NAME = "app-b-deployment"; - - private static final String SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME = "spring-cloud-kubernetes-configuration-watcher-deployment"; - private static final String SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME = "spring-cloud-kubernetes-configuration-watcher"; private static final String SECRET_NAME = "multiple-apps"; private static final String NAMESPACE = "default"; - private static CoreV1Api api; - - private static AppsV1Api appsApi; - - private static NetworkingV1Api networkingApi; - - private static K8SUtils k8SUtils; - private static final K3sContainer K3S = Commons.container(); + private static Util util; + @BeforeAll static void beforeAll() throws Exception { K3S.start(); @@ -94,12 +76,8 @@ class ConfigurationWatcherMultipleAppIT { Commons.validateImage(CONFIG_WATCHER_APP_B_IMAGE, K3S); Commons.loadSpringCloudKubernetesImage(CONFIG_WATCHER_APP_B_IMAGE, K3S); - createApiClient(K3S.getKubeConfigYaml()); - api = new CoreV1Api(); - appsApi = new AppsV1Api(); - k8SUtils = new K8SUtils(api, appsApi); - networkingApi = new NetworkingV1Api(); - k8SUtils.setUp(NAMESPACE); + util = new Util(K3S); + util.setUp(NAMESPACE); } @AfterAll @@ -110,36 +88,23 @@ class ConfigurationWatcherMultipleAppIT { } @BeforeEach - void setup() throws Exception { - - deployRabbitMq(); - deployAppA(); - deployAppB(); - deployIngress(); - deployConfigWatcher(); - - k8SUtils.waitForReplicationController("rabbitmq-controller", NAMESPACE); - waitForDeployment(CONFIG_WATCHER_DEPLOYMENT_APP_A_NAME); - waitForDeployment(CONFIG_WATCHER_DEPLOYMENT_APP_B_NAME); - waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME); + void setup() { + util.rabbitMq(NAMESPACE, Phase.CREATE); + appA(Phase.CREATE); + appB(Phase.CREATE); + configWatcher(Phase.CREATE); } @AfterEach - void after() throws Exception { - - cleanRabbitMq(); - cleanUpServices(); - cleanUpDeployments(); - cleanUpIngress(); - cleanUpConfigMaps(); - - k8SUtils.waitForDeploymentToBeDeleted(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, NAMESPACE); - k8SUtils.waitForDeploymentToBeDeleted(CONFIG_WATCHER_DEPLOYMENT_APP_A_NAME, NAMESPACE); - k8SUtils.waitForDeploymentToBeDeleted(CONFIG_WATCHER_DEPLOYMENT_APP_B_NAME, NAMESPACE); + void after() { + util.rabbitMq(NAMESPACE, Phase.DELETE); + appA(Phase.DELETE); + appB(Phase.DELETE); + configWatcher(Phase.DELETE); } @Test - void testRefresh() throws Exception { + void testRefresh() { // secret has one label, one that says that we should refresh // and one annotation that says that we should refresh some specific services @@ -149,7 +114,7 @@ class ConfigurationWatcherMultipleAppIT { "spring-cloud-kubernetes-client-configuration-watcher-secret-app-a, " + "spring-cloud-kubernetes-client-configuration-watcher-secret-app-b") .endMetadata().build(); - api.createNamespacedSecret(NAMESPACE, secret, null, null, null, null); + util.createAndWait(NAMESPACE, null, secret); WebClient.Builder builderA = builder(); WebClient serviceClientA = builderA.baseUrl("http://localhost:80/app-a").build(); @@ -164,7 +129,7 @@ class ConfigurationWatcherMultipleAppIT { return valueA[0]; }); - Assertions.assertThat(valueA[0]).isTrue(); + Assertions.assertTrue(valueA[0]); Boolean[] valueB = new Boolean[1]; await().pollInterval(Duration.ofSeconds(3)).atMost(Duration.ofSeconds(240)).until(() -> { @@ -173,170 +138,48 @@ class ConfigurationWatcherMultipleAppIT { return valueB[0]; }); - Assertions.assertThat(valueB[0]).isTrue(); + Assertions.assertTrue(valueB[0]); + util.deleteAndWait(NAMESPACE, null, secret); } - /** - *
-	 --------------------------------------------------- rabbitmq -----------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 
- */ - private void deployRabbitMq() throws Exception { - api.createNamespacedService(NAMESPACE, getRabbitMqService(), null, null, null, null); - String[] image = getRabbitMQReplicationController().getSpec().getTemplate().getSpec().getContainers().get(0) - .getImage().split(":"); - Commons.pullImage(image[0], image[1], K3S); - Commons.loadImage(image[0], image[1], "rabbitmq", K3S); - api.createNamespacedReplicationController(NAMESPACE, getRabbitMQReplicationController(), null, null, null, - null); - } + private void appA(Phase phase) { + V1Deployment deployment = (V1Deployment) util.yaml("app-a/app-a-deployment.yaml"); + V1Service service = (V1Service) util.yaml("app-a/app-a-service.yaml"); + V1Ingress ingress = (V1Ingress) util + .yaml("ingress/spring-cloud-kubernetes-configuration-watcher-multiple-apps-ingress.yaml"); - private V1ReplicationController getRabbitMQReplicationController() throws Exception { - return (V1ReplicationController) K8SUtils.readYamlFromClasspath("rabbitmq/rabbitmq-controller.yaml"); - } - - private V1Service getRabbitMqService() throws Exception { - return (V1Service) K8SUtils.readYamlFromClasspath("rabbitmq/rabbitmq-service.yaml"); - } - - /** - *
-	 ----------------------------------------------------- app-a ------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 
- */ - private void deployAppA() throws Exception { - appsApi.createNamespacedDeployment(NAMESPACE, getAppADeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getAppAService(), null, null, null, null); - } - - private V1Deployment getAppADeployment() throws Exception { - String urlString = "app-a/app-a-deployment.yaml"; - V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath(urlString); - String image = K8SUtils.getImageFromDeployment(deployment) + ":" + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private V1Service getAppAService() throws Exception { - return (V1Service) K8SUtils.readYamlFromClasspath("app-a/app-a-service.yaml"); - } - - /** - *
-	 --------------------------------------------------- app-b --------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 
- */ - private void deployAppB() throws Exception { - appsApi.createNamespacedDeployment(NAMESPACE, getAppBDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getAppBService(), null, null, null, null); - } - - private V1Deployment getAppBDeployment() throws Exception { - String urlString = "app-b/app-b-deployment.yaml"; - V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath(urlString); - String image = K8SUtils.getImageFromDeployment(deployment) + ":" + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private V1Service getAppBService() throws Exception { - return (V1Service) K8SUtils.readYamlFromClasspath("app-b/app-b-service.yaml"); - } - - /** - *
-	 ------------------------------------------------ config-watcher --------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 ------------------------------------------------------------------------------------------------------------
-	 
- */ - private void deployConfigWatcher() throws Exception { - appsApi.createNamespacedDeployment(NAMESPACE, getConfigWatcherDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getConfigWatcherService(), null, null, null, null); - } - - private V1Deployment getConfigWatcherDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath( - "config-watcher/spring-cloud-kubernetes-configuration-watcher-it-bus-amqp-deployment.yaml"); - String image = K8SUtils.getImageFromDeployment(deployment) + ":" + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private V1Service getConfigWatcherService() throws Exception { - return (V1Service) K8SUtils - .readYamlFromClasspath("config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml"); - } - - /** - *
-		------------------------------------------------ common ----------------------------------------------------
-		------------------------------------------------------------------------------------------------------------
-		------------------------------------------------------------------------------------------------------------
-		------------------------------------------------------------------------------------------------------------
-	 
- */ - - private void deployIngress() throws Exception { - V1Ingress ingress = (V1Ingress) K8SUtils.readYamlFromClasspath( - "ingress/spring-cloud-kubernetes-configuration-watcher-multiple-apps-ingress.yaml"); - - networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null, null); - k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE); - } - - private void waitForDeployment(String deploymentName) { - await().pollInterval(Duration.ofSeconds(3)).atMost(600, TimeUnit.SECONDS) - .until(() -> k8SUtils.isDeploymentReady(deploymentName, NAMESPACE)); - } - - private void cleanRabbitMq() throws Exception { - api.deleteNamespacedService("rabbitmq-service", NAMESPACE, null, null, null, null, null, null); - try { - api.deleteNamespacedReplicationController("rabbitmq-controller", NAMESPACE, null, null, null, null, null, - null); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); } - catch (Exception e) { - // swallowing this exception, delete does actually happen, it's a problem - // downstream from the k8s client; see: - // https://github.com/kubernetes-client/java/issues/86#issuecomment-411234259 + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); } } - private void cleanUpServices() throws Exception { - api.deleteNamespacedService("app-a", NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedService("app-b", NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedService(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, NAMESPACE, null, null, null, null, null, - null); + private void appB(Phase phase) { + V1Deployment deployment = (V1Deployment) util.yaml("app-b/app-b-deployment.yaml"); + V1Service service = (V1Service) util.yaml("app-b/app-b-service.yaml"); + + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, null, true); + } + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE, deployment, service, null); + } } - private void cleanUpDeployments() throws Exception { - appsApi.deleteNamespacedDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, NAMESPACE, null, null, null, - null, null, null); - appsApi.deleteNamespacedDeployment(CONFIG_WATCHER_DEPLOYMENT_APP_A_NAME, NAMESPACE, null, null, null, null, - null, null); + private void configWatcher(Phase phase) { + V1Deployment deployment = (V1Deployment) util + .yaml("config-watcher/spring-cloud-kubernetes-configuration-watcher-it-bus-amqp-deployment.yaml"); + V1Service service = (V1Service) util + .yaml("config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml"); - appsApi.deleteNamespacedDeployment(CONFIG_WATCHER_DEPLOYMENT_APP_B_NAME, NAMESPACE, null, null, null, null, - null, null); - } - - private void cleanUpConfigMaps() throws Exception { - api.deleteNamespacedSecret(SECRET_NAME, NAMESPACE, null, null, null, null, null, null); - } - - private void cleanUpIngress() throws Exception { - networkingApi.deleteNamespacedIngress("it-ingress-multiple-apps", NAMESPACE, null, null, null, null, null, - null); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, null, true); + } + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE, deployment, service, null); + } } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/src/test/resources/rabbitmq/rabbitmq-controller.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/src/test/resources/rabbitmq/rabbitmq-controller.yaml deleted file mode 100644 index 6fa3b0f1..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/src/test/resources/rabbitmq/rabbitmq-controller.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - labels: - component: rabbitmq - name: rabbitmq-controller -spec: - replicas: 1 - template: - metadata: - labels: - app: taskQueue - component: rabbitmq - spec: - containers: - - image: rabbitmq:3-management - name: rabbitmq - ports: - - name: amqp - containerPort: 5672 - - name: http-stats - containerPort: 15672 - readinessProbe: - httpGet: - port: 15672 - path: /api/healthchecks/node - httpHeaders: - - name: Authorization - value: Basic Z3Vlc3Q6Z3Vlc3Q= diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/event/reload/SecretsEventReloadIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/event/reload/SecretsEventReloadIT.java index 9399c3b3..8b9d67a7 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/event/reload/SecretsEventReloadIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/event/reload/SecretsEventReloadIT.java @@ -20,9 +20,7 @@ import java.time.Duration; import java.util.Map; import java.util.Objects; -import io.kubernetes.client.openapi.apis.AppsV1Api; import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.apis.NetworkingV1Api; import io.kubernetes.client.openapi.models.V1Deployment; import io.kubernetes.client.openapi.models.V1Ingress; import io.kubernetes.client.openapi.models.V1Secret; @@ -32,20 +30,18 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.testcontainers.k3s.K3sContainer; -import org.testcontainers.shaded.org.awaitility.Awaitility; import reactor.netty.http.client.HttpClient; import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util; 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.integration.tests.commons.K8SUtils.createApiClient; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion; +import static org.awaitility.Awaitility.await; /** * @author wind57 @@ -54,33 +50,24 @@ class SecretsEventReloadIT { private static final String PROPERTY_URL = "localhost:80/key"; - private static final String SPRING_CLOUD_CLIENT_CONFIG_IT_DEPLOYMENT_NAME = "spring-cloud-kubernetes-client-secrets-deployment-event-reload"; - private static final String K8S_CONFIG_CLIENT_IT_SERVICE_NAME = "spring-cloud-kubernetes-client-secrets-event-reload"; private static final String NAMESPACE = "default"; - private static CoreV1Api api; - - private static AppsV1Api appsApi; - - private static NetworkingV1Api networkingApi; - - private static K8SUtils k8SUtils; - private static final K3sContainer K3S = Commons.container(); + private static Util util; + + private static CoreV1Api coreV1Api; + @BeforeAll static void setup() throws Exception { K3S.start(); Commons.validateImage(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, K3S); - createApiClient(K3S.getKubeConfigYaml()); - api = new CoreV1Api(); - appsApi = new AppsV1Api(); - networkingApi = new NetworkingV1Api(); - k8SUtils = new K8SUtils(api, appsApi); - k8SUtils.setUp(NAMESPACE); + util = new Util(K3S); + coreV1Api = new CoreV1Api(); + util.setUp(NAMESPACE); } @AfterAll @@ -89,22 +76,13 @@ class SecretsEventReloadIT { } @AfterEach - void after() throws Exception { - appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null, - "metadata.name=" + SPRING_CLOUD_CLIENT_CONFIG_IT_DEPLOYMENT_NAME, null, null, null, null, null, null, - null, null, null); - api.deleteNamespacedService(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, NAMESPACE, null, null, null, null, null, null); - networkingApi.deleteNamespacedIngress("spring-cloud-kubernetes-client-secrets-ingress-event-reload", NAMESPACE, - null, null, null, null, null, null); - api.deleteNamespacedSecret("event-reload", NAMESPACE, null, null, null, null, null, null); + void after() { + configK8sClientIt(Phase.DELETE); } @Test void testSecretReload() throws Exception { - deployConfigK8sClientIt(); - - // Check to make sure the controller deployment is ready - k8SUtils.waitForDeployment(SPRING_CLOUD_CLIENT_CONFIG_IT_DEPLOYMENT_NAME, NAMESPACE); + configK8sClientIt(Phase.CREATE); testSecretEventReload(); } @@ -112,50 +90,36 @@ class SecretsEventReloadIT { WebClient.Builder builder = builder(); WebClient secretClient = builder.baseUrl(PROPERTY_URL).build(); - String secret = secretClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec()) - .block(); - assertThat(secret).isEqualTo("initial"); - V1Secret v1Secret = getConfigK8sClientItCSecret(); + await().timeout(Duration.ofSeconds(120)).pollInterval(Duration.ofSeconds(2)) + .until(() -> secretClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) + .retryWhen(retrySpec()).block().equals("initial")); + + V1Secret v1Secret = (V1Secret) util.yaml("secret.yaml"); Map secretData = v1Secret.getData(); secretData.replace("application.properties", "from.properties.key: after-change".getBytes()); v1Secret.setData(secretData); - api.replaceNamespacedSecret("event-reload", NAMESPACE, v1Secret, null, null, null, null); + coreV1Api.replaceNamespacedSecret("event-reload", NAMESPACE, v1Secret, null, null, null, null); - Awaitility.await().timeout(Duration.ofSeconds(120)).pollInterval(Duration.ofSeconds(2)) + await().timeout(Duration.ofSeconds(120)).pollInterval(Duration.ofSeconds(2)) .until(() -> secretClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) .retryWhen(retrySpec()).block().equals("after-change")); } - private static void deployConfigK8sClientIt() throws Exception { - k8SUtils.waitForDeploymentToBeDeleted(SPRING_CLOUD_CLIENT_CONFIG_IT_DEPLOYMENT_NAME, NAMESPACE); - api.createNamespacedSecret(NAMESPACE, getConfigK8sClientItCSecret(), null, null, null, null); - appsApi.createNamespacedDeployment(NAMESPACE, getConfigK8sClientItDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getConfigK8sClientItService(), null, null, null, null); + private void configK8sClientIt(Phase phase) { + V1Deployment deployment = (V1Deployment) util.yaml("deployment.yaml"); + V1Service service = (V1Service) util.yaml("service.yaml"); + V1Ingress ingress = (V1Ingress) util.yaml("ingress.yaml"); + V1Secret secret = (V1Secret) util.yaml("secret.yaml"); - V1Ingress ingress = getConfigK8sClientItIngress(); - networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null, null); - k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE); - } - - private static V1Deployment getConfigK8sClientItDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath("deployment.yaml"); - String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":" - + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private static V1Service getConfigK8sClientItService() throws Exception { - return (V1Service) K8SUtils.readYamlFromClasspath("service.yaml"); - } - - private static V1Ingress getConfigK8sClientItIngress() throws Exception { - return (V1Ingress) K8SUtils.readYamlFromClasspath("ingress.yaml"); - } - - private static V1Secret getConfigK8sClientItCSecret() throws Exception { - return (V1Secret) K8SUtils.readYamlFromClasspath("secret.yaml"); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); + util.createAndWait(NAMESPACE, null, secret); + } + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); + util.deleteAndWait(NAMESPACE, null, secret); + } } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/pom.xml index f57b610e..99b7c17a 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/pom.xml @@ -38,11 +38,6 @@ spring-boot-starter-test test
- - org.junit.vintage - junit-vintage-engine - test - org.springframework.cloud spring-cloud-kubernetes-test-support diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshIT.java index f0465bcd..84bfb6d0 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshIT.java @@ -20,8 +20,6 @@ import java.time.Duration; import com.github.tomakehurst.wiremock.client.VerificationException; import com.github.tomakehurst.wiremock.client.WireMock; -import io.kubernetes.client.openapi.apis.AppsV1Api; -import io.kubernetes.client.openapi.apis.CoreV1Api; import io.kubernetes.client.openapi.models.V1ConfigMap; import io.kubernetes.client.openapi.models.V1ConfigMapBuilder; import io.kubernetes.client.openapi.models.V1Deployment; @@ -34,30 +32,18 @@ import org.junit.jupiter.api.Test; import org.testcontainers.k3s.K3sContainer; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.findAll; -import static com.github.tomakehurst.wiremock.client.WireMock.post; -import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; -import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static org.awaitility.Awaitility.await; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion; /** * @author Ryan Baxter */ class ActuatorRefreshIT { - private static final String SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME = "spring-cloud-kubernetes-configuration-watcher-deployment"; - private static final String SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME = "spring-cloud-kubernetes-configuration-watcher"; - private String configWatcherConfigMapName; - private static final String WIREMOCK_HOST = "localhost"; private static final String WIREMOCK_PATH = "/"; @@ -66,105 +52,83 @@ class ActuatorRefreshIT { private static final String NAMESPACE = "default"; - private static CoreV1Api api; - - private static AppsV1Api appsApi; - - private static K8SUtils k8SUtils; - private static final K3sContainer K3S = Commons.container(); + private static Util util; + @BeforeAll static void beforeAll() throws Exception { K3S.start(); Commons.validateImage(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, K3S); Commons.loadSpringCloudKubernetesImage(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, K3S); - createApiClient(K3S.getKubeConfigYaml()); - api = new CoreV1Api(); - appsApi = new AppsV1Api(); - k8SUtils = new K8SUtils(api, appsApi); - k8SUtils.setUp(NAMESPACE); + util = new Util(K3S); + util.setUp(NAMESPACE); } @AfterAll static void afterAll() throws Exception { Commons.cleanUp(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, K3S); - k8SUtils.removeWiremockImage(); } @BeforeEach - void setup() throws Exception { - deployConfigWatcher(); - k8SUtils.deployWiremock(NAMESPACE, true, K3S); + void setup() { + configWatcher(Phase.CREATE); + util.wiremock(NAMESPACE, "/", Phase.CREATE); } @AfterEach - void after() throws Exception { - - appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null, - "metadata.name=" + SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, null, null, null, null, null, null, - null, null, null); - api.deleteNamespacedService(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, NAMESPACE, null, null, null, null, null, - null); - - api.deleteNamespacedConfigMap(configWatcherConfigMapName, NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedConfigMap("servicea-wiremock", NAMESPACE, null, null, null, null, null, null); - k8SUtils.cleanUpWiremock(NAMESPACE); + void after() { + configWatcher(Phase.DELETE); + util.wiremock(NAMESPACE, "/", Phase.DELETE); } /* * this test loads uses two services: wiremock on port 8080 and configuration-watcher * on port 8888. we deploy configuration-watcher first and configure it via a * configmap with the same name. then, we mock the call to actuator/refresh endpoint - * and deploy a new configmap: "servicea-wiremock", this in turn will trigger that + * and deploy a new configmap: "service-wiremock", this in turn will trigger that * refresh that we capture and assert for. */ + // curl :8080/__admin/mappings @Test - void testActuatorRefresh() throws Exception { + void testActuatorRefresh() { WireMock.configureFor(WIREMOCK_HOST, WIREMOCK_PORT, WIREMOCK_PATH); await().timeout(Duration.ofSeconds(60)).ignoreException(VerificationException.class) - .until(() -> stubFor(post(urlEqualTo("/actuator/refresh")).willReturn(aResponse().withStatus(200))) + .until(() -> WireMock + .stubFor(WireMock.post(WireMock.urlEqualTo("/actuator/refresh")) + .willReturn(WireMock.aResponse().withBody("{}").withStatus(200))) .getResponse().wasConfigured()); // Create new configmap to trigger controller to signal app to refresh - V1ConfigMap configMap = new V1ConfigMapBuilder().editOrNewMetadata().withName("servicea-wiremock") + V1ConfigMap configMap = new V1ConfigMapBuilder().editOrNewMetadata().withName("service-wiremock") .addToLabels("spring.cloud.kubernetes.config", "true").endMetadata().addToData("foo", "bar").build(); - api.createNamespacedConfigMap(NAMESPACE, configMap, null, null, null, null); + util.createAndWait(NAMESPACE, configMap, null); // Wait a bit before we verify - await().atMost(Duration.ofSeconds(30)) - .until(() -> !findAll(postRequestedFor(urlEqualTo("/actuator/refresh"))).isEmpty()); + await().atMost(Duration.ofSeconds(30)).until( + () -> !WireMock.findAll(WireMock.postRequestedFor(WireMock.urlEqualTo("/actuator/refresh"))).isEmpty()); - verify(postRequestedFor(urlEqualTo("/actuator/refresh"))); + WireMock.verify(WireMock.postRequestedFor(WireMock.urlEqualTo("/actuator/refresh"))); + util.deleteAndWait(NAMESPACE, configMap, null); } - private void deployConfigWatcher() throws Exception { - V1ConfigMap configMap = getConfigWatcherConfigMap(); - configWatcherConfigMapName = configMap.getMetadata().getName(); - api.createNamespacedConfigMap(NAMESPACE, configMap, null, null, null, null); - appsApi.createNamespacedDeployment(NAMESPACE, getConfigWatcherDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getConfigWatcherService(), null, null, null, null); + private void configWatcher(Phase phase) { + V1ConfigMap configMap = (V1ConfigMap) util + .yaml("config-watcher/spring-cloud-kubernetes-configuration-watcher-configmap.yaml"); + V1Deployment deployment = (V1Deployment) util + .yaml("config-watcher/spring-cloud-kubernetes-configuration-watcher-http-deployment.yaml"); + V1Service service = (V1Service) util + .yaml("config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml"); - // Check to make sure the controller deployment is ready - k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, NAMESPACE); - } + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, configMap, null); + util.createAndWait(NAMESPACE, null, deployment, service, null, true); + } + else { + util.deleteAndWait(NAMESPACE, configMap, null); + util.deleteAndWait(NAMESPACE, deployment, service, null); + } - private V1Deployment getConfigWatcherDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath( - "config-watcher/spring-cloud-kubernetes-configuration-watcher-http-deployment.yaml"); - String image = K8SUtils.getImageFromDeployment(deployment) + ":" + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private V1Service getConfigWatcherService() throws Exception { - return (V1Service) K8SUtils - .readYamlFromClasspath("config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml"); - } - - private V1ConfigMap getConfigWatcherConfigMap() throws Exception { - return (V1ConfigMap) K8SUtils - .readYamlFromClasspath("config-watcher/spring-cloud-kubernetes-configuration-watcher-configmap.yaml"); } } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshKafkaIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshKafkaIT.java index f13e6bdd..1d3dc920 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshKafkaIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshKafkaIT.java @@ -18,19 +18,15 @@ package org.springframework.cloud.kubernetes.configuration.watcher; import java.time.Duration; import java.util.Objects; -import java.util.concurrent.TimeUnit; -import io.kubernetes.client.openapi.apis.AppsV1Api; -import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.apis.NetworkingV1Api; import io.kubernetes.client.openapi.models.V1ConfigMap; import io.kubernetes.client.openapi.models.V1ConfigMapBuilder; 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.Test; @@ -40,14 +36,13 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util; import org.springframework.http.HttpMethod; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; import static org.awaitility.Awaitility.await; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion; /** * @author Kris Iyer @@ -56,32 +51,14 @@ class ActuatorRefreshKafkaIT { private static final String CONFIG_WATCHER_IT_IMAGE = "spring-cloud-kubernetes-configuration-watcher-it"; - private static final String SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME = "spring-cloud-kubernetes-configuration-watcher-deployment"; - - private static final String SPRING_CLOUD_K8S_CONFIG_WATCHER_IT_DEPLOYMENT_NAME = "spring-cloud-kubernetes-configuration-watcher-it-deployment"; - private static final String SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME = "spring-cloud-kubernetes-configuration-watcher"; private static final String NAMESPACE = "default"; - private static final String KAFKA_BROKER = "kafka-broker"; - - private static final String KAFKA_SERVICE = "kafka"; - - private static final String ZOOKEEPER_SERVICE = "zookeeper"; - - private static final String ZOOKEEPER_DEPLOYMENT = "zookeeper"; - - private static CoreV1Api api; - - private static AppsV1Api appsApi; - - private static NetworkingV1Api networkingApi; - - private static K8SUtils k8SUtils; - private static final K3sContainer K3S = Commons.container(); + private static Util util; + @BeforeAll static void beforeAll() throws Exception { K3S.start(); @@ -91,13 +68,8 @@ class ActuatorRefreshKafkaIT { Commons.validateImage(CONFIG_WATCHER_IT_IMAGE, K3S); Commons.loadSpringCloudKubernetesImage(CONFIG_WATCHER_IT_IMAGE, K3S); - - createApiClient(K3S.getKubeConfigYaml()); - api = new CoreV1Api(); - appsApi = new AppsV1Api(); - k8SUtils = new K8SUtils(api, appsApi); - networkingApi = new NetworkingV1Api(); - k8SUtils.setUp(NAMESPACE); + util = new Util(K3S); + util.setUp(NAMESPACE); } @AfterAll @@ -107,46 +79,28 @@ class ActuatorRefreshKafkaIT { } @BeforeEach - void setup() throws Exception { - - deployZookeeper(); - deployKafka(); - deployTestApp(); - deployConfigWatcher(); - - // Check to make sure the controller deployment is ready - waitForDeployment(ZOOKEEPER_DEPLOYMENT); - waitForDeployment(KAFKA_BROKER); - waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_IT_DEPLOYMENT_NAME); - waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME); + void setup() { + util.zookeeper(NAMESPACE, Phase.CREATE); + util.kafka(NAMESPACE, Phase.CREATE); + testApp(Phase.CREATE); + configWatcher(Phase.CREATE); } @AfterEach - void after() throws Exception { - - cleanUpKafka(); - cleanUpZookeeper(); - cleanUpServices(); - cleanUpDeployments(); - - networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null); - - cleanUpConfigMaps(); - - // Check to make sure the controller deployment is deleted - k8SUtils.waitForDeploymentToBeDeleted(KAFKA_BROKER, NAMESPACE); - k8SUtils.waitForDeploymentToBeDeleted(ZOOKEEPER_DEPLOYMENT, NAMESPACE); - k8SUtils.waitForDeploymentToBeDeleted(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, NAMESPACE); - k8SUtils.waitForDeploymentToBeDeleted(SPRING_CLOUD_K8S_CONFIG_WATCHER_IT_DEPLOYMENT_NAME, NAMESPACE); + void after() { + util.zookeeper(NAMESPACE, Phase.DELETE); + util.kafka(NAMESPACE, Phase.DELETE); + testApp(Phase.DELETE); + configWatcher(Phase.DELETE); } @Test - void testRefresh() throws Exception { + void testRefresh() { // Create new configmap to trigger controller to signal app to refresh V1ConfigMap configMap = new V1ConfigMapBuilder().editOrNewMetadata().withName(CONFIG_WATCHER_IT_IMAGE) .addToLabels("spring.cloud.kubernetes.config", "true").endMetadata().addToData("foo", "hello world") .build(); - api.createNamespacedConfigMap(NAMESPACE, configMap, null, null, null, null); + util.createAndWait(NAMESPACE, configMap, null); WebClient.Builder builder = builder(); WebClient serviceClient = builder.baseUrl("http://localhost:80/it").build(); @@ -158,126 +112,42 @@ class ActuatorRefreshKafkaIT { return value[0]; }); - Assertions.assertThat(value[0]).isTrue(); + Assertions.assertTrue(value[0]); + + util.deleteAndWait(NAMESPACE, configMap, null); } - private void waitForDeployment(String deploymentName) { - await().pollInterval(Duration.ofSeconds(3)).atMost(600, TimeUnit.SECONDS) - .until(() -> k8SUtils.isDeploymentReady(deploymentName, NAMESPACE)); + private void testApp(Phase phase) { + V1Deployment deployment = (V1Deployment) util + .yaml("app/spring-cloud-kubernetes-configuration-watcher-it-bus-kafka-deployment.yaml"); + V1Service service = (V1Service) util.yaml("app/spring-cloud-kubernetes-configuration-watcher-it-service.yaml"); + V1Ingress ingress = (V1Ingress) util.yaml("app/spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml"); + + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); + } + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); + } } - private void deployTestApp() throws Exception { - appsApi.createNamespacedDeployment(NAMESPACE, getItDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getItAppService(), null, null, null, null); + private void configWatcher(Phase phase) { + V1Deployment deployment = (V1Deployment) util + .yaml("app-watcher/spring-cloud-kubernetes-configuration-watcher-bus-kafka-deployment.yaml"); + V1Service service = (V1Service) util + .yaml("config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml"); - V1Ingress ingress = getItIngress(); - networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null, null); - k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE); - } + V1ConfigMap configMap = (V1ConfigMap) util + .yaml("config-watcher/spring-cloud-kubernetes-configuration-watcher-configmap.yaml"); - private void deployConfigWatcher() throws Exception { - api.createNamespacedConfigMap(NAMESPACE, getConfigWatcherConfigMap(), null, null, null, null); - appsApi.createNamespacedDeployment(NAMESPACE, getConfigWatcherDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getConfigWatcherService(), null, null, null, null); - } - - private void deployZookeeper() throws Exception { - api.createNamespacedService(NAMESPACE, getZookeeperService(), null, null, null, null); - V1Deployment deployment = getZookeeperDeployment(); - String[] image = K8SUtils.getImageFromDeployment(deployment).split(":"); - Commons.pullImage(image[0], image[1], K3S); - Commons.loadImage(image[0], image[1], "zookeeper", K3S); - appsApi.createNamespacedDeployment(NAMESPACE, deployment, null, null, null, null); - } - - private void deployKafka() throws Exception { - api.createNamespacedService(NAMESPACE, getKafkaService(), null, null, null, null); - V1Deployment deployment = getKafkaDeployment(); - String[] image = K8SUtils.getImageFromDeployment(deployment).split(":"); - Commons.pullImage(image[0], image[1], K3S); - Commons.loadImage(image[0], image[1], "kafka", K3S); - appsApi.createNamespacedDeployment(NAMESPACE, getKafkaDeployment(), null, null, null, null); - } - - private void cleanUpKafka() throws Exception { - appsApi.deleteNamespacedDeployment(KAFKA_BROKER, NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedService(KAFKA_SERVICE, NAMESPACE, null, null, null, null, null, null); - } - - private void cleanUpZookeeper() throws Exception { - appsApi.deleteNamespacedDeployment(ZOOKEEPER_DEPLOYMENT, NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedService(ZOOKEEPER_SERVICE, NAMESPACE, null, null, null, null, null, null); - } - - private V1Deployment getConfigWatcherDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath( - "app-watcher/spring-cloud-kubernetes-configuration-watcher-bus-kafka-deployment.yaml"); - String image = K8SUtils.getImageFromDeployment(deployment) + ":" + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private V1Deployment getItDeployment() throws Exception { - String urlString = "app/spring-cloud-kubernetes-configuration-watcher-it-bus-kafka-deployment.yaml"; - V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath(urlString); - String image = K8SUtils.getImageFromDeployment(deployment) + ":" + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private V1Service getConfigWatcherService() throws Exception { - return (V1Service) K8SUtils - .readYamlFromClasspath("config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml"); - } - - private V1ConfigMap getConfigWatcherConfigMap() throws Exception { - return (V1ConfigMap) K8SUtils - .readYamlFromClasspath("config-watcher/spring-cloud-kubernetes-configuration-watcher-configmap.yaml"); - } - - private V1Service getItAppService() throws Exception { - return (V1Service) K8SUtils - .readYamlFromClasspath("app/spring-cloud-kubernetes-configuration-watcher-it-service.yaml"); - } - - private V1Ingress getItIngress() throws Exception { - return (V1Ingress) K8SUtils - .readYamlFromClasspath("app/spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml"); - } - - private V1Deployment getKafkaDeployment() throws Exception { - return (V1Deployment) K8SUtils.readYamlFromClasspath("kafka/kafka-deployment.yaml"); - } - - private V1Service getKafkaService() throws Exception { - return (V1Service) K8SUtils.readYamlFromClasspath("kafka/kafka-service.yaml"); - } - - private V1Deployment getZookeeperDeployment() throws Exception { - return (V1Deployment) K8SUtils.readYamlFromClasspath("zookeeper/zookeeper-deployment.yaml"); - } - - private V1Service getZookeeperService() throws Exception { - return (V1Service) K8SUtils.readYamlFromClasspath("zookeeper/zookeeper-service.yaml"); - } - - private void cleanUpConfigMaps() throws Exception { - api.deleteNamespacedConfigMap(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, NAMESPACE, null, null, null, null, null, - null); - api.deleteNamespacedConfigMap(CONFIG_WATCHER_IT_IMAGE, NAMESPACE, null, null, null, null, null, null); - } - - private void cleanUpDeployments() throws Exception { - appsApi.deleteNamespacedDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, NAMESPACE, null, null, null, - null, null, null); - appsApi.deleteNamespacedDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_IT_DEPLOYMENT_NAME, NAMESPACE, null, null, - null, null, null, null); - } - - private void cleanUpServices() throws Exception { - api.deleteNamespacedService(CONFIG_WATCHER_IT_IMAGE, NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedService(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, NAMESPACE, null, null, null, null, null, - null); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, null, true); + util.createAndWait(NAMESPACE, configMap, null); + } + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE, deployment, service, null); + util.deleteAndWait(NAMESPACE, configMap, null); + } } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshRabbitMQIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshRabbitMQIT.java index b6dcad22..830dc635 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshRabbitMQIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshRabbitMQIT.java @@ -18,20 +18,15 @@ package org.springframework.cloud.kubernetes.configuration.watcher; import java.time.Duration; import java.util.Objects; -import java.util.concurrent.TimeUnit; -import io.kubernetes.client.openapi.apis.AppsV1Api; -import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.apis.NetworkingV1Api; import io.kubernetes.client.openapi.models.V1ConfigMap; import io.kubernetes.client.openapi.models.V1ConfigMapBuilder; import io.kubernetes.client.openapi.models.V1Deployment; import io.kubernetes.client.openapi.models.V1Ingress; -import io.kubernetes.client.openapi.models.V1ReplicationController; 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.Test; @@ -41,14 +36,13 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util; import org.springframework.http.HttpMethod; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; import static org.awaitility.Awaitility.await; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion; /** * @author Ryan Baxter @@ -57,26 +51,14 @@ class ActuatorRefreshRabbitMQIT { private static final String CONFIG_WATCHER_IT_IMAGE = "spring-cloud-kubernetes-configuration-watcher-it"; - private static final String SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME = "spring-cloud-kubernetes-configuration-watcher-deployment"; - - private static final String SPRING_CLOUD_K8S_CONFIG_WATCHER_IT_DEPLOYMENT_NAME = "spring-cloud-kubernetes-configuration-watcher-it-deployment"; - private static final String SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME = "spring-cloud-kubernetes-configuration-watcher"; private static final String NAMESPACE = "default"; - private static final String RABBIT_MQ_CONTROLLER_NAME = "rabbitmq-controller"; - - private static CoreV1Api api; - - private static AppsV1Api appsApi; - - private static NetworkingV1Api networkingApi; - - private static K8SUtils k8SUtils; - private static final K3sContainer K3S = Commons.container(); + private static Util util; + @BeforeAll static void beforeAll() throws Exception { K3S.start(); @@ -86,13 +68,8 @@ class ActuatorRefreshRabbitMQIT { Commons.validateImage(CONFIG_WATCHER_IT_IMAGE, K3S); Commons.loadSpringCloudKubernetesImage(CONFIG_WATCHER_IT_IMAGE, K3S); - - createApiClient(K3S.getKubeConfigYaml()); - api = new CoreV1Api(); - appsApi = new AppsV1Api(); - k8SUtils = new K8SUtils(api, appsApi); - networkingApi = new NetworkingV1Api(); - k8SUtils.setUp(NAMESPACE); + util = new Util(K3S); + util.setUp(NAMESPACE); } @AfterAll @@ -102,25 +79,26 @@ class ActuatorRefreshRabbitMQIT { } @BeforeEach - void setup() throws Exception { + void setup() { + util.rabbitMq(NAMESPACE, Phase.CREATE); + app(Phase.CREATE); + configWatcher(Phase.CREATE); + } - deployRabbitMQ(); - deployTestApp(); - deployConfigWatcher(); - - // Check to make sure the controller deployment is ready - k8SUtils.waitForReplicationController(RABBIT_MQ_CONTROLLER_NAME, NAMESPACE); - waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_IT_DEPLOYMENT_NAME); - waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME); + @AfterEach + void afterEach() { + util.rabbitMq(NAMESPACE, Phase.DELETE); + app(Phase.DELETE); + configWatcher(Phase.DELETE); } @Test - void testRefresh() throws Exception { + void testRefresh() { // Create new configmap to trigger controller to signal app to refresh V1ConfigMap configMap = new V1ConfigMapBuilder().editOrNewMetadata().withName(CONFIG_WATCHER_IT_IMAGE) .addToLabels("spring.cloud.kubernetes.config", "true").endMetadata().addToData("foo", "hello world") .build(); - api.createNamespacedConfigMap(NAMESPACE, configMap, null, null, null, null); + util.createAndWait(NAMESPACE, configMap, null); WebClient.Builder builder = builder(); WebClient serviceClient = builder.baseUrl("http://localhost:80/it").build(); @@ -132,115 +110,40 @@ class ActuatorRefreshRabbitMQIT { return value[0]; }); - Assertions.assertThat(value[0]).isTrue(); + Assertions.assertTrue(value[0]); + util.deleteAndWait(NAMESPACE, configMap, null); } - @AfterEach - void after() throws Exception { - api.deleteNamespacedService("rabbitmq-service", NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedService(CONFIG_WATCHER_IT_IMAGE, NAMESPACE, null, null, null, null, null, null); - api.deleteNamespacedService(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, NAMESPACE, null, null, null, null, null, - null); + private void app(Phase phase) { + V1Deployment deployment = (V1Deployment) util + .yaml("app-watcher/spring-cloud-kubernetes-configuration-watcher-it-bus-amqp-deployment.yaml"); + V1Service service = (V1Service) util.yaml("app/spring-cloud-kubernetes-configuration-watcher-it-service.yaml"); + V1Ingress ingress = (V1Ingress) util.yaml("app/spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml"); - appsApi.deleteNamespacedDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, NAMESPACE, null, null, null, - null, null, null); - appsApi.deleteNamespacedDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_IT_DEPLOYMENT_NAME, NAMESPACE, null, null, - null, null, null, null); - - try { - api.deleteNamespacedReplicationController(RABBIT_MQ_CONTROLLER_NAME, NAMESPACE, null, null, null, null, - null, null); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); } - catch (Exception e) { - // swallowing this exception, delete does actually happen, it's a problem - // downstream from the k8s client; see: - // https://github.com/kubernetes-client/java/issues/86#issuecomment-411234259 + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); } - - networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null); - - api.deleteNamespacedConfigMap(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, NAMESPACE, null, null, null, null, null, - null); - api.deleteNamespacedConfigMap(CONFIG_WATCHER_IT_IMAGE, NAMESPACE, null, null, null, null, null, null); - - // Check to make sure the controller deployment is deleted - k8SUtils.waitForDeploymentToBeDeleted(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, NAMESPACE); - k8SUtils.waitForDeploymentToBeDeleted(SPRING_CLOUD_K8S_CONFIG_WATCHER_IT_DEPLOYMENT_NAME, NAMESPACE); - } - private void deployTestApp() throws Exception { - appsApi.createNamespacedDeployment(NAMESPACE, getItDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getItAppService(), null, null, null, null); + private void configWatcher(Phase phase) { + V1Deployment deployment = (V1Deployment) util + .yaml("app-watcher/spring-cloud-kubernetes-configuration-watcher-bus-amqp-deployment.yaml"); + V1Service service = (V1Service) util + .yaml("config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml"); + V1ConfigMap configMap = (V1ConfigMap) util + .yaml("config-watcher/spring-cloud-kubernetes-configuration-watcher-configmap.yaml"); - V1Ingress ingress = getItIngress(); - networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null, null); - k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE); - } - - private void deployConfigWatcher() throws Exception { - api.createNamespacedConfigMap(NAMESPACE, getConfigWatcherConfigMap(), null, null, null, null); - appsApi.createNamespacedDeployment(NAMESPACE, getConfigWatcherDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getConfigWatcherService(), null, null, null, null); - } - - private void deployRabbitMQ() throws Exception { - api.createNamespacedService(NAMESPACE, getRabbitMQService(), null, null, null, null); - String[] image = getRabbitMQReplicationController().getSpec().getTemplate().getSpec().getContainers().get(0) - .getImage().split(":"); - Commons.pullImage(image[0], image[1], K3S); - Commons.loadImage(image[0], image[1], "rabbitmq", K3S); - api.createNamespacedReplicationController(NAMESPACE, getRabbitMQReplicationController(), null, null, null, - null); - } - - private V1Deployment getConfigWatcherDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath( - "app-watcher/spring-cloud-kubernetes-configuration-watcher-bus-amqp-deployment.yaml"); - String image = K8SUtils.getImageFromDeployment(deployment) + ":" + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private V1Deployment getItDeployment() throws Exception { - String urlString = "app-watcher/spring-cloud-kubernetes-configuration-watcher-it-bus-amqp-deployment.yaml"; - V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath(urlString); - String image = K8SUtils.getImageFromDeployment(deployment) + ":" + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private V1Service getItAppService() throws Exception { - return (V1Service) K8SUtils - .readYamlFromClasspath("app/spring-cloud-kubernetes-configuration-watcher-it-service.yaml"); - } - - private V1Service getConfigWatcherService() throws Exception { - return (V1Service) K8SUtils - .readYamlFromClasspath("config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml"); - } - - private V1ConfigMap getConfigWatcherConfigMap() throws Exception { - return (V1ConfigMap) K8SUtils - .readYamlFromClasspath("config-watcher/spring-cloud-kubernetes-configuration-watcher-configmap.yaml"); - } - - private V1Ingress getItIngress() throws Exception { - return (V1Ingress) K8SUtils - .readYamlFromClasspath("app/spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml"); - } - - private V1ReplicationController getRabbitMQReplicationController() throws Exception { - return (V1ReplicationController) K8SUtils.readYamlFromClasspath("rabbitmq/rabbitmq-controller.yaml"); - } - - private V1Service getRabbitMQService() throws Exception { - return (V1Service) K8SUtils.readYamlFromClasspath("rabbitmq/rabbitmq-service.yaml"); - } - - private void waitForDeployment(String deploymentName) { - await().pollInterval(Duration.ofSeconds(3)).atMost(600, TimeUnit.SECONDS) - .until(() -> k8SUtils.isDeploymentReady(deploymentName, NAMESPACE)); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, null, true); + util.createAndWait(NAMESPACE, configMap, null); + } + else if (phase.equals(Phase.DELETE)) { + util.deleteAndWait(NAMESPACE, deployment, service, null); + util.deleteAndWait(NAMESPACE, configMap, null); + } } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka/kafka-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka/kafka-deployment.yaml deleted file mode 100644 index 6cce9e91..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka/kafka-deployment.yaml +++ /dev/null @@ -1,54 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: kafka - component: kafka-broker - name: kafka-broker -spec: - replicas: 1 - selector: - matchLabels: - app: kafka - component: kafka-broker - template: - metadata: - labels: - app: kafka - component: kafka-broker - spec: - # otherwise we will get an env var "KAFKA_PORT" (from service name: "kafka" and appended with "_PORT") - # and this will cause this problem: https://github.com/confluentinc/cp-docker-images/blob/master/debian/kafka/include/etc/confluent/docker/configure#L58-L62 - # Another solution is to rename the service. - enableServiceLinks: false - containers: - - name: kafka - image: confluentinc/cp-kafka:7.2.1 - ports: - - containerPort: 9092 - env: - - name: KAFKA_LISTENERS - value: "INTERNAL://0.0.0.0:9092,OUTSIDE://0.0.0.0:9094" - - - name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP - value: "INTERNAL:PLAINTEXT,OUTSIDE:PLAINTEXT" - - - name: KAFKA_ADVERTISED_LISTENERS - value: "INTERNAL://kafka:9092,OUTSIDE://localhost:9094" - - - name: KAFKA_INTER_BROKER_LISTENER_NAME - value: "INTERNAL" - - - name: KAFKA_ADVERTISED_HOST_NAME - valueFrom: - fieldRef: - fieldPath: status.podIP - - - name: KAFKA_ZOOKEEPER_CONNECT - value: zookeeper:2181 - - # we have enabled auto creation of topics and when this happens there is a replication factor of 3 - # that is set automatically. Since we don't have that many, producers will fail. - # This setting ensures that there is just one replication - - name: KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR - value: "1" diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka/kafka-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka/kafka-service.yaml deleted file mode 100644 index 88bea315..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka/kafka-service.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: kafka - labels: - app: kafka - component: kafka-broker -spec: - ports: - - port: 9092 - name: kafka-port - targetPort: 9092 - protocol: TCP - selector: - app: kafka - component: kafka-broker diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq/rabbitmq-controller.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq/rabbitmq-controller.yaml deleted file mode 100644 index 81dd5aec..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq/rabbitmq-controller.yaml +++ /dev/null @@ -1,36 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - labels: - component: rabbitmq - name: rabbitmq-controller -spec: - replicas: 1 - template: - metadata: - labels: - app: taskQueue - component: rabbitmq - spec: - containers: - - image: rabbitmq:3-management - name: rabbitmq - ports: - - name: amqp - containerPort: 5672 - - name: http-stats - containerPort: 15672 - readinessProbe: - httpGet: - port: 15672 - path: /api/healthchecks/node - httpHeaders: - - name: Authorization - value: Basic Z3Vlc3Q6Z3Vlc3Q= -# livenessProbe: -# httpGet: -# port: 15672 -# path: /api/healthchecks/node -# httpHeaders: -# - name: Authorization -# value: Basic Z3Vlc3Q6Z3Vlc3Q= diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq/rabbitmq-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq/rabbitmq-service.yaml deleted file mode 100644 index e960e5f4..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq/rabbitmq-service.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - component: rabbitmq - name: rabbitmq-service -spec: - ports: - - port: 5672 - name: amqp - targetPort: 5672 - - port: 15672 - name: http-stats - targetPort: 15672 - selector: - app: taskQueue - component: rabbitmq diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper/zookeeper-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper/zookeeper-deployment.yaml deleted file mode 100644 index 3c285c30..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper/zookeeper-deployment.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: kafka - component: zookeeper - name: zookeeper -spec: - replicas: 1 - selector: - matchLabels: - app: kafka - component: zookeeper - template: - metadata: - labels: - app: kafka - component: zookeeper - spec: - containers: - - name: zookeeper - image: confluentinc/cp-zookeeper:7.2.1 - ports: - - containerPort: 2181 - env: - - name: ZOOKEEPER_ID - value: "1" - - name: ZOOKEEPER_SERVER_1 - value: zookeeper - - name: ZOOKEEPER_CLIENT_PORT - value: 2181 diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper/zookeeper-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper/zookeeper-service.yaml deleted file mode 100644 index eb025d3c..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper/zookeeper-service.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: zookeeper - labels: - app: kafka - component: zookeeper -spec: - ports: - - port: 2181 - name: zookeeper-port - targetPort: 2181 - protocol: TCP - selector: - app: kafka - component: zookeeper diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/k8s/deployment-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/k8s/deployment-it.yaml deleted file mode 100644 index def88038..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/k8s/deployment-it.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-core-k8s-client-it - name: spring-cloud-kubernetes-core-k8s-client-it-deployment -spec: - replicas: 1 - selector: - matchLabels: - app: spring-cloud-kubernetes-core-k8s-client-it - strategy: {} - template: - metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-core-k8s-client-it - spec: - serviceAccountName: spring-cloud-kubernetes-serviceaccount - containers: - - image: springcloud/spring-cloud-kubernetes-core-k8s-client-it:3.0.0-SNAPSHOT - imagePullPolicy: IfNotPresent - name: spring-cloud-kubernetes-core-k8s-client-it - resources: {} -status: {} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/k8s/service-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/k8s/service-it.yaml deleted file mode 100644 index 02b976c4..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/k8s/service-it.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-core-k8s-client-it - name: spring-cloud-kubernetes-core-k8s-client-it -spec: - ports: - - name: 80-8080 - port: 80 - protocol: TCP - targetPort: 8080 - selector: - app: spring-cloud-kubernetes-core-k8s-client-it - type: ClusterIP -status: - loadBalancer: {} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/skaffold.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/skaffold.yaml deleted file mode 100644 index 89b4eab2..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/skaffold.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: skaffold/v2alpha3 -kind: Config -metadata: - name: spring-cloud-kubernetes-core-k8s-client-it -build: - artifacts: - - image: springcloud/spring-cloud-kubernetes-core-k8s-client-it - custom: - buildCommand: "../../mvnw clean install -Pskaffold" - dependencies: - paths: - - src - - pom.xml -deploy: - kubectl: - manifests: - - k8s/deployment-it.yaml - - k8s/service-it.yaml - - ../permissions.yaml diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/java/org/springframework/cloud/kubernetes/core/k8s/it/ActuatorEndpointIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/java/org/springframework/cloud/kubernetes/core/k8s/it/ActuatorEndpointIT.java index 5c9a1b04..b96604d8 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/java/org/springframework/cloud/kubernetes/core/k8s/it/ActuatorEndpointIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/java/org/springframework/cloud/kubernetes/core/k8s/it/ActuatorEndpointIT.java @@ -20,9 +20,6 @@ import java.time.Duration; import java.util.Map; import java.util.Objects; -import io.kubernetes.client.openapi.apis.AppsV1Api; -import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.apis.NetworkingV1Api; import io.kubernetes.client.openapi.models.V1Deployment; import io.kubernetes.client.openapi.models.V1Ingress; import io.kubernetes.client.openapi.models.V1Service; @@ -35,65 +32,42 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +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.AssertionsForInterfaceTypes.assertThat; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Ryan Baxter */ class ActuatorEndpointIT { - private static final String SPRING_CLOUD_K8S_CLIENT_IT_DEPLOYMENT_NAME = "spring-cloud-kubernetes-core-k8s-client-it-deployment"; - - private static final String K8S_CONFIG_CLIENT_IT_NAME = "spring-cloud-kubernetes-core-k8s-client-it-deployment"; - private static final String K8S_CONFIG_CLIENT_IT_SERVICE_NAME = "spring-cloud-kubernetes-core-k8s-client-it"; private static final String NAMESPACE = "default"; - private static CoreV1Api api; - - private static AppsV1Api appsApi; - - private static K8SUtils k8SUtils; - - private static NetworkingV1Api networkingApi; - private static final K3sContainer K3S = Commons.container(); + private static Util util; + @BeforeAll static void beforeAll() throws Exception { K3S.start(); Commons.validateImage(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, K3S); - createApiClient(K3S.getKubeConfigYaml()); - api = new CoreV1Api(); - appsApi = new AppsV1Api(); - networkingApi = new NetworkingV1Api(); - k8SUtils = new K8SUtils(api, appsApi); - k8SUtils.setUp(NAMESPACE); - - deployCoreK8sClientIt(); - - // Check to make sure the controller deployment is ready - k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_CLIENT_IT_DEPLOYMENT_NAME, NAMESPACE); + util = new Util(K3S); + util.setUp(NAMESPACE); + coreK8sClientIt(Phase.CREATE); } @AfterAll - static void after() throws Exception { - Commons.cleanUp(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, K3S); - appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null, - "metadata.name=" + K8S_CONFIG_CLIENT_IT_NAME, null, null, null, null, null, null, null, null, null); - api.deleteNamespacedService(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, NAMESPACE, null, null, null, null, null, null); - networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null); + static void afterAll() { + coreK8sClientIt(Phase.DELETE); } @Test @@ -152,30 +126,18 @@ class ActuatorEndpointIT { assertThat(kubernetes.containsKey("serviceAccount")).isTrue(); } - private static void deployCoreK8sClientIt() throws Exception { - appsApi.createNamespacedDeployment(NAMESPACE, getCoreK8sClientItDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getCoreK8sClientItService(), null, null, null, null); + private static void coreK8sClientIt(Phase phase) { + V1Deployment deployment = (V1Deployment) util + .yaml("spring-cloud-kubernetes-core-k8s-client-it-deployment.yaml"); + V1Service service = (V1Service) util.yaml("spring-cloud-kubernetes-core-k8s-client-it-service.yaml"); + V1Ingress ingress = (V1Ingress) util.yaml("spring-cloud-kubernetes-core-k8s-client-it-ingress.yaml"); - V1Ingress ingress = getCoreK8sClientItIngress(); - networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null, null); - k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE); - } - - private static V1Deployment getCoreK8sClientItDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) K8SUtils - .readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-it-deployment.yaml"); - String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":" - + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private static V1Service getCoreK8sClientItService() throws Exception { - return (V1Service) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-it-service.yaml"); - } - - private static V1Ingress getCoreK8sClientItIngress() throws Exception { - return (V1Ingress) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-it-ingress.yaml"); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); + } + else { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); + } } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/k8s/deployment-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/k8s/deployment-it.yaml deleted file mode 100644 index fe4cb2a0..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/k8s/deployment-it.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-discoveryclient-it - name: spring-cloud-kubernetes-discoveryclient-it-deployment -spec: - replicas: 1 - selector: - matchLabels: - app: spring-cloud-kubernetes-discoveryclient-it - strategy: {} - template: - metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-discoveryclient-it - spec: - serviceAccountName: spring-cloud-kubernetes-serviceaccount - containers: - - image: springcloud/spring-cloud-kubernetes-discoveryclient-it:3.0.0-SNAPSHOT - imagePullPolicy: IfNotPresent - name: spring-cloud-kubernetes-discoveryclient-it - resources: {} -status: {} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/k8s/service-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/k8s/service-it.yaml deleted file mode 100644 index 518bb63b..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/k8s/service-it.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - creationTimestamp: null - labels: - app: spring-cloud-kubernetes-discoveryclient-it - name: spring-cloud-kubernetes-discoveryclient-it -spec: - ports: - - name: 80-8080 - port: 80 - protocol: TCP - targetPort: 8080 - selector: - app: spring-cloud-kubernetes-discoveryclient-it - type: ClusterIP -status: - loadBalancer: {} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientFilterNamespaceIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientFilterNamespaceIT.java index d1d2742e..b1eb9ad6 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientFilterNamespaceIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientFilterNamespaceIT.java @@ -17,15 +17,10 @@ package org.springframework.cloud.kubernetes.discoveryclient.it; import java.time.Duration; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; -import io.kubernetes.client.openapi.ApiException; -import io.kubernetes.client.openapi.apis.AppsV1Api; -import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.apis.NetworkingV1Api; import io.kubernetes.client.openapi.apis.RbacAuthorizationV1Api; import io.kubernetes.client.openapi.models.V1ClusterRoleBinding; import io.kubernetes.client.openapi.models.V1Container; @@ -33,11 +28,7 @@ import io.kubernetes.client.openapi.models.V1Deployment; import io.kubernetes.client.openapi.models.V1EnvVar; import io.kubernetes.client.openapi.models.V1EnvVarBuilder; import io.kubernetes.client.openapi.models.V1Ingress; -import io.kubernetes.client.openapi.models.V1Namespace; -import io.kubernetes.client.openapi.models.V1ObjectMeta; import io.kubernetes.client.openapi.models.V1Service; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -49,7 +40,8 @@ import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.discovery.KubernetesServiceInstance; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +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; @@ -57,48 +49,28 @@ 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.integration.tests.commons.K8SUtils.createApiClient; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion; /** * @author mbialkowski1 */ class DiscoveryClientFilterNamespaceIT { - private static final Log LOG = LogFactory.getLog(DiscoveryClientFilterNamespaceIT.class); - - private static final String DISCOVERY_SERVER_DEPLOYMENT_NAME = "spring-cloud-kubernetes-discoveryserver-deployment"; - private static final String DISCOVERY_SERVER_APP_NAME = "spring-cloud-kubernetes-discoveryserver"; - private static final String SPRING_CLOUD_K8S_DISCOVERY_CLIENT_DEPLOYMENT_NAME = "spring-cloud-kubernetes-discoveryclient-it-deployment"; - private static final String SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME = "spring-cloud-kubernetes-discoveryclient-it"; - private static final String MOCK_DEPLOYMENT_NAME = "wiremock-deployment"; - - private static final String MOCK_CLIENT_APP_NAME = "wiremock"; - - private static final String MOCK_IMAGE_NAME = "wiremock"; - private static final String NAMESPACE = "default"; - private static final String NAMESPACE_LEFT = "left-namespace-k8s-client"; + private static final String NAMESPACE_LEFT = "left"; - private static final String NAMESPACE_RIGHT = "right-namespace-k8s-client"; - - private static CoreV1Api api; - - private static AppsV1Api appsApi; - - private static NetworkingV1Api networkingApi; - - private static RbacAuthorizationV1Api authApi; - - private static K8SUtils k8SUtils; + private static final String NAMESPACE_RIGHT = "right"; private static final K3sContainer K3S = Commons.container(); + private static Util util; + + private static RbacAuthorizationV1Api rbacApi; + @BeforeAll static void beforeAll() throws Exception { K3S.start(); @@ -109,97 +81,56 @@ class DiscoveryClientFilterNamespaceIT { Commons.validateImage(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, K3S); Commons.loadSpringCloudKubernetesImage(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, K3S); - String[] mockImage = K8SUtils.getImageFromDeployment(getMockServiceDeployment()).split(":"); - Commons.pullImage(mockImage[0], mockImage[1], K3S); - Commons.loadImage(mockImage[0], mockImage[1], MOCK_IMAGE_NAME, K3S); + util = new Util(K3S); + rbacApi = new RbacAuthorizationV1Api(); + util.createNamespace(NAMESPACE_LEFT); + util.createNamespace(NAMESPACE_RIGHT); + util.setUp(NAMESPACE); - createApiClient(K3S.getKubeConfigYaml()); - api = new CoreV1Api(); - appsApi = new AppsV1Api(); - networkingApi = new NetworkingV1Api(); - authApi = new RbacAuthorizationV1Api(); - k8SUtils = new K8SUtils(api, appsApi); - k8SUtils.setUp(NAMESPACE); - - deployDiscoveryServer(); - - // Check to make sure the discovery server deployment is ready - k8SUtils.waitForDeployment(DISCOVERY_SERVER_DEPLOYMENT_NAME, NAMESPACE); - - // Check to see if endpoint is ready - k8SUtils.waitForEndpointReady(DISCOVERY_SERVER_APP_NAME, NAMESPACE); + V1ClusterRoleBinding clusterRole = (V1ClusterRoleBinding) util + .yaml("namespace-filter/cluster-admin-serviceaccount-role.yaml"); + rbacApi.createClusterRoleBinding(clusterRole, null, null, null, null); + discoveryServer(Phase.CREATE); } @AfterAll static void afterAll() throws Exception { Commons.cleanUp(DISCOVERY_SERVER_APP_NAME, K3S); Commons.cleanUp(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, K3S); - Commons.cleanUpDownloadedImage(MOCK_IMAGE_NAME); - - appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null, - "metadata.name=" + DISCOVERY_SERVER_DEPLOYMENT_NAME, null, null, null, null, null, null, null, null, - null); - - api.deleteNamespacedService(DISCOVERY_SERVER_APP_NAME, NAMESPACE, null, null, null, null, null, null); - networkingApi.deleteNamespacedIngress("discoveryserver-ingress", NAMESPACE, null, null, null, null, null, null); + discoveryServer(Phase.DELETE); + util.deleteNamespace(NAMESPACE_LEFT); + util.deleteNamespace(NAMESPACE_RIGHT); } @AfterEach - void afterEach() throws ApiException { - cleanup(); + void afterEach() { + util.wiremock(NAMESPACE_LEFT, "/wiremock-" + NAMESPACE_LEFT, Phase.DELETE); + util.wiremock(NAMESPACE_RIGHT, "/wiremock-" + NAMESPACE_RIGHT, Phase.DELETE); + discoveryIt(Phase.DELETE); } @Test - void testDiscoveryClient() throws Exception { - deploySampleAppInNamespace(NAMESPACE_LEFT); - deploySampleAppInNamespace(NAMESPACE_RIGHT); - deployDiscoveryIt(); + void testDiscoveryClient() { + util.wiremock(NAMESPACE_LEFT, "/wiremock-" + NAMESPACE_LEFT, Phase.CREATE); + util.wiremock(NAMESPACE_RIGHT, "/wiremock-" + NAMESPACE_RIGHT, Phase.CREATE); + discoveryIt(Phase.CREATE); testLoadBalancer(); testHealth(); } - private void cleanup() throws ApiException { - appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null, - "metadata.name=" + SPRING_CLOUD_K8S_DISCOVERY_CLIENT_DEPLOYMENT_NAME, null, null, null, null, null, - null, null, null, null); - api.deleteNamespacedService(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, NAMESPACE, null, null, null, null, null, - null); - networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null); - - appsApi.deleteCollectionNamespacedDeployment(NAMESPACE_LEFT, null, null, null, - "metadata.name=" + MOCK_DEPLOYMENT_NAME, null, null, null, null, null, null, null, null, null); - appsApi.deleteCollectionNamespacedDeployment(NAMESPACE_RIGHT, null, null, null, - "metadata.name=" + MOCK_DEPLOYMENT_NAME, null, null, null, null, null, null, null, null, null); - - api.deleteNamespacedService(MOCK_CLIENT_APP_NAME, NAMESPACE_LEFT, null, null, null, null, null, null); - api.deleteNamespacedService(MOCK_CLIENT_APP_NAME, NAMESPACE_RIGHT, null, null, null, null, null, null); - - networkingApi.deleteNamespacedIngress("wiremock-ingress", NAMESPACE_LEFT, null, null, null, null, null, null); - networkingApi.deleteNamespacedIngress("wiremock-ingress", NAMESPACE_RIGHT, null, null, null, null, null, null); - - authApi.deleteClusterRoleBinding("admin-default-k8s-client", null, null, null, null, null, null); - - api.deleteNamespace(NAMESPACE_LEFT, null, null, null, null, null, null); - api.deleteNamespace(NAMESPACE_RIGHT, null, null, null, null, null, null); - - } - private void testLoadBalancer() { - // Check to make sure the controller deployment is ready - k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_DEPLOYMENT_NAME, NAMESPACE); 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(); - LOG.info("Services: " + Arrays.toString(result)); - assertThat(result).containsAnyOf("wiremock"); + assertThat(result).containsAnyOf("service-wiremock"); // ServiceInstance - WebClient serviceInstanceClient = builder.baseUrl("http://localhost:80/discoveryclient-it/service/wiremock") - .build(); + WebClient serviceInstanceClient = builder + .baseUrl("http://localhost:80/discoveryclient-it/service/service-wiremock").build(); List serviceInstances = serviceInstanceClient.method(HttpMethod.GET).retrieve() .bodyToMono(new ParameterizedTypeReference>() { }).retryWhen(retrySpec()).block(); @@ -227,119 +158,48 @@ class DiscoveryClientFilterNamespaceIT { assertThat(discoveryComposite.get("status")).isEqualTo("UP"); } - private void deployDiscoveryIt() throws Exception { - appsApi.createNamespacedDeployment(NAMESPACE, getDiscoveryItDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getDiscoveryService(), null, null, null, null); + private void discoveryIt(Phase phase) { + + V1Deployment deployment = (V1Deployment) util + .yaml("client/spring-cloud-kubernetes-discoveryclient-it-deployment.yaml"); + V1Service service = (V1Service) util.yaml("client/spring-cloud-kubernetes-discoveryclient-it-service.yaml"); + V1Ingress ingress = (V1Ingress) util.yaml("client/spring-cloud-kubernetes-discoveryclient-it-ingress.yaml"); + + if (phase.equals(Phase.CREATE)) { + // add namespaces filter property for left namespace + var env = new V1EnvVarBuilder().withName("SPRING_CLOUD_KUBERNETES_DISCOVERY_NAMESPACES_0") + .withValue(NAMESPACE_LEFT).build(); + var container = deployment.getSpec().getTemplate().getSpec().getContainers().get(0); + container.setEnv(List.of(env)); + + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); + } + else { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); + } - V1Ingress ingress = getDiscoveryItIngress(); - networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null, null); - k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE); } - private static V1Deployment getDiscoveryItDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) K8SUtils - .readYamlFromClasspath("client/spring-cloud-kubernetes-discoveryclient-it-deployment.yaml"); + private static void discoveryServer(Phase phase) { - // add namespaces filter property for left namespace - var env = new V1EnvVarBuilder().withName("SPRING_CLOUD_KUBERNETES_DISCOVERY_NAMESPACES_0") - .withValue(NAMESPACE_LEFT).build(); - var container = deployment.getSpec().getTemplate().getSpec().getContainers().get(0); - container.setEnv(List.of(env)); + V1Deployment deployment = (V1Deployment) util + .yaml("server/spring-cloud-kubernetes-discoveryserver-deployment.yaml"); + V1Service service = (V1Service) util.yaml("server/spring-cloud-kubernetes-discoveryserver-service.yaml"); + V1Ingress ingress = (V1Ingress) util.yaml("server/spring-cloud-kubernetes-discoveryserver-ingress.yaml"); - String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":" - + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } + if (phase.equals(Phase.CREATE)) { + // add namespaces filter property for left namespace + // setup all-namespaces property + V1EnvVar env = new V1EnvVarBuilder().withName("SPRING_CLOUD_KUBERNETES_DISCOVERY_ALL_NAMESPACES") + .withValue("TRUE").build(); + V1Container container = deployment.getSpec().getTemplate().getSpec().getContainers().get(0); + container.setEnv(List.of(env)); - private static void deployDiscoveryServer() throws Exception { - - V1ClusterRoleBinding clusterRoleBinding = getClusterRoleBinding(); - authApi.createClusterRoleBinding(clusterRoleBinding, null, null, null, null); - - appsApi.createNamespacedDeployment(NAMESPACE, getDiscoveryServerDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getDiscoveryServerService(), null, null, null, null); - - V1Ingress ingress = getDiscoveryServerIngress(); - networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null, null); - k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE); - } - - private static void deploySampleAppInNamespace(final String namespace) throws Exception { - - V1Namespace v1Namespace = new V1Namespace(); - V1ObjectMeta meta = new V1ObjectMeta(); - meta.setName(namespace); - v1Namespace.setMetadata(meta); - - api.createNamespace(v1Namespace, null, null, null, null); - - V1Deployment deployment = getMockServiceDeployment(); - deployment.getMetadata().setNamespace(namespace); - - appsApi.createNamespacedDeployment(namespace, deployment, null, null, null, null); - V1Service service = getMockServiceService(); - service.getMetadata().setNamespace(namespace); - api.createNamespacedService(namespace, service, null, null, null, null); - V1Ingress ingress = getMockIngress(); - ingress.getMetadata().setNamespace(namespace); - - ingress.getSpec().getRules().get(0).getHttp().getPaths().get(0).setPath("/wiremock-" + namespace); - networkingApi.createNamespacedIngress(namespace, ingress, null, null, null, null); - k8SUtils.waitForIngress(ingress.getMetadata().getName(), namespace); - } - - private static V1Deployment getDiscoveryServerDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) K8SUtils - .readYamlFromClasspath("server/spring-cloud-kubernetes-discoveryserver-deployment.yaml"); - String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":" - + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - // setup all-namespaces property - V1EnvVar env = new V1EnvVarBuilder().withName("SPRING_CLOUD_KUBERNETES_DISCOVERY_ALL_NAMESPACES") - .withValue("TRUE").build(); - V1Container container = deployment.getSpec().getTemplate().getSpec().getContainers().get(0); - container.setEnv(List.of(env)); - - return deployment; - } - - private static V1Ingress getDiscoveryServerIngress() throws Exception { - return (V1Ingress) K8SUtils - .readYamlFromClasspath("server/spring-cloud-kubernetes-discoveryserver-ingress.yaml"); - } - - private static V1Service getDiscoveryServerService() throws Exception { - return (V1Service) K8SUtils - .readYamlFromClasspath("server/spring-cloud-kubernetes-discoveryserver-service.yaml"); - } - - private static V1Ingress getDiscoveryItIngress() throws Exception { - return (V1Ingress) K8SUtils - .readYamlFromClasspath("client/spring-cloud-kubernetes-discoveryclient-it-ingress.yaml"); - } - - private static V1Service getDiscoveryService() throws Exception { - return (V1Service) K8SUtils - .readYamlFromClasspath("client/spring-cloud-kubernetes-discoveryclient-it-service.yaml"); - } - - private static V1ClusterRoleBinding getClusterRoleBinding() throws Exception { - return (V1ClusterRoleBinding) K8SUtils - .readYamlFromClasspath("namespace-filter/cluster-admin-serviceaccount-role.yaml"); - } - - private static V1Deployment getMockServiceDeployment() throws Exception { - return (V1Deployment) K8SUtils.readYamlFromClasspath("wiremock/discovery-wiremock-deployment.yaml"); - } - - private static V1Service getMockServiceService() throws Exception { - - return (V1Service) K8SUtils.readYamlFromClasspath("wiremock/discovery-wiremock-service.yaml"); - } - - private static V1Ingress getMockIngress() throws Exception { - return (V1Ingress) K8SUtils.readYamlFromClasspath("wiremock/discovery-wiremock-ingress.yaml"); + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); + } + else { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); + } } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientIT.java index e3e24a04..8f6269a9 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientIT.java @@ -21,17 +21,10 @@ import java.util.Arrays; import java.util.Map; import java.util.Objects; -import io.kubernetes.client.openapi.ApiException; -import io.kubernetes.client.openapi.apis.AppsV1Api; -import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.apis.NetworkingV1Api; import io.kubernetes.client.openapi.models.V1Deployment; import io.kubernetes.client.openapi.models.V1Ingress; import io.kubernetes.client.openapi.models.V1Service; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.testcontainers.k3s.K3sContainer; @@ -40,7 +33,8 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +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; @@ -48,36 +42,22 @@ 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.integration.tests.commons.K8SUtils.createApiClient; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion; /** * @author Ryan Baxter */ class DiscoveryClientIT { - private static final Log LOG = LogFactory.getLog(DiscoveryClientIT.class); - - private static final String DISCOVERY_SERVER_DEPLOYMENT_NAME = "spring-cloud-kubernetes-discoveryserver-deployment"; - private static final String DISCOVERY_SERVER_APP_NAME = "spring-cloud-kubernetes-discoveryserver"; - private static final String SPRING_CLOUD_K8S_DISCOVERY_CLIENT_DEPLOYMENT_NAME = "spring-cloud-kubernetes-discoveryclient-it-deployment"; - private static final String SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME = "spring-cloud-kubernetes-discoveryclient-it"; private static final String NAMESPACE = "default"; - private static CoreV1Api api; - - private static AppsV1Api appsApi; - - private static NetworkingV1Api networkingApi; - - private static K8SUtils k8SUtils; - private static final K3sContainer K3S = Commons.container(); + private static Util util; + @BeforeAll static void beforeAll() throws Exception { K3S.start(); @@ -87,21 +67,10 @@ 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); + discoveryServer(Phase.CREATE); - createApiClient(K3S.getKubeConfigYaml()); - api = new CoreV1Api(); - appsApi = new AppsV1Api(); - networkingApi = new NetworkingV1Api(); - k8SUtils = new K8SUtils(api, appsApi); - k8SUtils.setUp(NAMESPACE); - - deployDiscoveryServer(); - - // Check to make sure the discovery server deployment is ready - k8SUtils.waitForDeployment(DISCOVERY_SERVER_DEPLOYMENT_NAME, NAMESPACE); - - // Check to see if endpoint is ready - k8SUtils.waitForEndpointReady(DISCOVERY_SERVER_APP_NAME, NAMESPACE); } @AfterAll @@ -109,45 +78,23 @@ class DiscoveryClientIT { Commons.cleanUp(DISCOVERY_SERVER_APP_NAME, K3S); Commons.cleanUp(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, K3S); - appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null, - "metadata.name=" + DISCOVERY_SERVER_DEPLOYMENT_NAME, null, null, null, null, null, null, null, null, - null); - - api.deleteNamespacedService(DISCOVERY_SERVER_APP_NAME, NAMESPACE, null, null, null, null, null, null); - networkingApi.deleteNamespacedIngress("discoveryserver-ingress", NAMESPACE, null, null, null, null, null, null); - } - - @AfterEach - void afterEach() throws ApiException { - cleanup(); + discoveryServer(Phase.DELETE); + discoveryIt(Phase.DELETE); } @Test - void testDiscoveryClient() throws Exception { - deployDiscoveryIt(); + void testDiscoveryClient() { + discoveryIt(Phase.CREATE); testLoadBalancer(); testHealth(); } - private void cleanup() throws ApiException { - appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null, - "metadata.name=" + SPRING_CLOUD_K8S_DISCOVERY_CLIENT_DEPLOYMENT_NAME, null, null, null, null, null, - null, null, null, null); - api.deleteNamespacedService(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, NAMESPACE, null, null, null, null, null, - null); - networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null); - } - private void testLoadBalancer() { - - // Check to make sure the controller deployment is ready - k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_DEPLOYMENT_NAME, NAMESPACE); 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(); - LOG.info("Services: " + Arrays.toString(result)); assertThat(Arrays.stream(result).anyMatch("spring-cloud-kubernetes-discoveryserver"::equalsIgnoreCase)) .isTrue(); @@ -170,60 +117,32 @@ class DiscoveryClientIT { assertThat(discoveryComposite.get("status")).isEqualTo("UP"); } - private void deployDiscoveryIt() throws Exception { - appsApi.createNamespacedDeployment(NAMESPACE, getDiscoveryItDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getDiscoveryService(), null, null, null, null); + private static void discoveryIt(Phase phase) { + V1Deployment deployment = (V1Deployment) util + .yaml("client/spring-cloud-kubernetes-discoveryclient-it-deployment.yaml"); + V1Service service = (V1Service) util.yaml("client/spring-cloud-kubernetes-discoveryclient-it-service.yaml"); + V1Ingress ingress = (V1Ingress) util.yaml("client/spring-cloud-kubernetes-discoveryclient-it-ingress.yaml"); - V1Ingress ingress = getDiscoveryItIngress(); - networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null, null); - k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); + } + else { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); + } } - private V1Deployment getDiscoveryItDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) k8SUtils - .readYamlFromClasspath("client/spring-cloud-kubernetes-discoveryclient-it-deployment.yaml"); - String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":" - + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } + private static void discoveryServer(Phase phase) { + V1Deployment deployment = (V1Deployment) util + .yaml("server/spring-cloud-kubernetes-discoveryserver-deployment.yaml"); + V1Service service = (V1Service) util.yaml("server/spring-cloud-kubernetes-discoveryserver-service.yaml"); + V1Ingress ingress = (V1Ingress) util.yaml("server/spring-cloud-kubernetes-discoveryserver-ingress.yaml"); - private static void deployDiscoveryServer() throws Exception { - appsApi.createNamespacedDeployment(NAMESPACE, getDiscoveryServerDeployment(), null, null, null, null); - api.createNamespacedService(NAMESPACE, getDiscoveryServerService(), null, null, null, null); - - V1Ingress ingress = getDiscoveryServerIngress(); - networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null, null); - k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE); - } - - private static V1Deployment getDiscoveryServerDeployment() throws Exception { - V1Deployment deployment = (V1Deployment) k8SUtils - .readYamlFromClasspath("server/spring-cloud-kubernetes-discoveryserver-deployment.yaml"); - String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":" - + getPomVersion(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); - return deployment; - } - - private static V1Ingress getDiscoveryServerIngress() throws Exception { - return (V1Ingress) K8SUtils - .readYamlFromClasspath("server/spring-cloud-kubernetes-discoveryserver-ingress.yaml"); - } - - private static V1Service getDiscoveryServerService() throws Exception { - return (V1Service) K8SUtils - .readYamlFromClasspath("server/spring-cloud-kubernetes-discoveryserver-service.yaml"); - } - - private V1Ingress getDiscoveryItIngress() throws Exception { - return (V1Ingress) K8SUtils - .readYamlFromClasspath("client/spring-cloud-kubernetes-discoveryclient-it-ingress.yaml"); - } - - private V1Service getDiscoveryService() throws Exception { - return (V1Service) K8SUtils - .readYamlFromClasspath("client/spring-cloud-kubernetes-discoveryclient-it-service.yaml"); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); + } + else { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); + } } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/wiremock/discovery-wiremock-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/wiremock/discovery-wiremock-deployment.yaml deleted file mode 100644 index 7660d130..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/wiremock/discovery-wiremock-deployment.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: wiremock-deployment -spec: - selector: - matchLabels: - app: wiremock - template: - metadata: - labels: - app: wiremock - spec: - containers: - - name: wiremock - image: wiremock/wiremock:2.32.0 - imagePullPolicy: IfNotPresent - readinessProbe: - httpGet: - port: 8080 - path: /__admin/mappings - livenessProbe: - httpGet: - port: 8080 - path: /__admin/mappings - ports: - - containerPort: 8080 diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/wiremock/discovery-wiremock-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/wiremock/discovery-wiremock-ingress.yaml deleted file mode 100644 index 4a5d063a..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/wiremock/discovery-wiremock-ingress.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: wiremock-ingress -spec: - rules: - - http: - paths: - - path: /wiremock - pathType: Prefix - backend: - service: - name: wiremock - port: - number: 8080 diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/wiremock/discovery-wiremock-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/wiremock/discovery-wiremock-service.yaml deleted file mode 100644 index 0b9dfe3f..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/wiremock/discovery-wiremock-service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: wiremock - name: wiremock -spec: - ports: - - name: http - port: 8080 - targetPort: 8080 - selector: - app: wiremock - type: ClusterIP diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/fabric8/catalog/watch/Fabric8CatalogWatchIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/fabric8/catalog/watch/Fabric8CatalogWatchIT.java index e35dc51a..38f3d4b5 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/fabric8/catalog/watch/Fabric8CatalogWatchIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/fabric8/catalog/watch/Fabric8CatalogWatchIT.java @@ -24,10 +24,7 @@ import java.util.Objects; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.networking.v1.Ingress; -import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -39,8 +36,8 @@ import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.commons.discovery.EndpointNameAndNamespace; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util; import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ResolvableType; import org.springframework.http.HttpMethod; @@ -62,36 +59,23 @@ class Fabric8CatalogWatchIT { private static KubernetesClient client; - private static String busyboxServiceName; - - private static String busyboxDeploymentName; - - private static String appDeploymentName; - - private static String appServiceName; - - private static String appIngressName; + private static Util util; @BeforeAll static void beforeAll() throws Exception { K3S.start(); - Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml()); - client = new KubernetesClientBuilder().withConfig(config).build(); + util = new Util(K3S); + client = util.client(); Commons.validateImage(APP_NAME, K3S); Commons.loadSpringCloudKubernetesImage(APP_NAME, K3S); - Fabric8Utils.setUp(client, "default"); + util.setUp(NAMESPACE); } @BeforeEach - void beforeEach() throws Exception { - deployBusyboxManifests(); - } - - @AfterEach - void afterEach() { - deleteApp(); + void beforeEach() { + util.busybox(NAMESPACE, Phase.CREATE); } /** @@ -104,16 +88,18 @@ class Fabric8CatalogWatchIT { */ @Test void testCatalogWatchWithEndpoints() throws Exception { - deployApp(false); + app(false, Phase.CREATE); assertLogStatement("stateGenerator is of type: Fabric8EndpointsCatalogWatch"); test(); + app(false, Phase.DELETE); } @Test void testCatalogWatchWithEndpointSlices() throws Exception { - deployApp(true); + app(true, Phase.CREATE); assertLogStatement("stateGenerator is of type: Fabric8EndpointSliceV1CatalogWatch"); test(); + app(true, Phase.DELETE); } /** @@ -169,7 +155,7 @@ class Fabric8CatalogWatchIT { Assertions.assertEquals("default", resultOne.namespace()); Assertions.assertEquals("default", resultTwo.namespace()); - deleteBusyboxApp(); + util.busybox(NAMESPACE, Phase.DELETE); // what we get after delete EndpointNameAndNamespace[] afterDelete = new EndpointNameAndNamespace[1]; @@ -202,87 +188,26 @@ class Fabric8CatalogWatchIT { } - private void deployBusyboxManifests() throws Exception { + private static void app(boolean useEndpointSlices, Phase phase) { - Deployment deployment = client.apps().deployments().load(getBusyboxDeployment()).get(); + InputStream endpointsDeploymentStream = util.inputStream("app/watcher-endpoints-deployment.yaml"); + InputStream endpointSlicesDeploymentStream = util.inputStream("app/watcher-endpoint-slices-deployment.yaml"); + InputStream serviceStream = util.inputStream("app/watcher-service.yaml"); + InputStream ingressStream = util.inputStream("app/watcher-ingress.yaml"); - String[] image = K8SUtils.getImageFromDeployment(deployment).split(":"); - Commons.pullImage(image[0], image[1], K3S); - Commons.loadImage(image[0], image[1], "busybox", K3S); + Deployment deployment = useEndpointSlices + ? client.apps().deployments().load(endpointSlicesDeploymentStream).get() + : client.apps().deployments().load(endpointsDeploymentStream).get(); + Service service = client.services().load(serviceStream).get(); + Ingress ingress = client.network().v1().ingresses().load(ingressStream).get(); - client.apps().deployments().inNamespace(NAMESPACE).resource(deployment).create(); - busyboxDeploymentName = deployment.getMetadata().getName(); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(Fabric8CatalogWatchIT.NAMESPACE, null, deployment, service, ingress, true); + } + else { + util.deleteAndWait(Fabric8CatalogWatchIT.NAMESPACE, deployment, service, ingress); + } - Service busyboxService = client.services().load(getBusyboxService()).get(); - busyboxServiceName = busyboxService.getMetadata().getName(); - client.services().inNamespace(NAMESPACE).resource(busyboxService).create(); - - Fabric8Utils.waitForDeployment(client, busyboxDeploymentName, NAMESPACE, 2, 600); - - } - - private static void deployApp(boolean useEndpointSlices) { - - InputStream deployment = useEndpointSlices ? getEndpointSlicesAppDeployment() : getEndpointsAppDeployment(); - Deployment appDeployment = client.apps().deployments().load(deployment).get(); - - String version = K8SUtils.getPomVersion(); - String currentImage = appDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - appDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version); - - client.apps().deployments().inNamespace(NAMESPACE).resource(appDeployment).create(); - appDeploymentName = appDeployment.getMetadata().getName(); - - Service appService = client.services().load(getAppService()).get(); - appServiceName = appService.getMetadata().getName(); - client.services().inNamespace(NAMESPACE).resource(appService).create(); - - Fabric8Utils.waitForDeployment(client, appDeploymentName, NAMESPACE, 2, 600); - - Ingress appIngress = client.network().v1().ingresses().load(getAppIngress()).get(); - appIngressName = appIngress.getMetadata().getName(); - client.network().v1().ingresses().inNamespace(NAMESPACE).resource(appIngress).create(); - - Fabric8Utils.waitForIngress(client, appIngressName, NAMESPACE); - - } - - private void deleteBusyboxApp() { - Fabric8Utils.deleteDeployment(client, NAMESPACE, busyboxDeploymentName); - Fabric8Utils.deleteService(client, NAMESPACE, busyboxServiceName); - } - - private void deleteApp() { - Fabric8Utils.deleteDeployment(client, NAMESPACE, appDeploymentName); - Fabric8Utils.deleteService(client, NAMESPACE, appServiceName); - Fabric8Utils.deleteIngress(client, NAMESPACE, appIngressName); - } - - private static InputStream getBusyboxService() { - return Fabric8Utils.inputStream("busybox/service.yaml"); - } - - private static InputStream getBusyboxDeployment() { - return Fabric8Utils.inputStream("busybox/deployment.yaml"); - } - - /** - * deployment where support for endpoint slices is equal to false - */ - private static InputStream getEndpointsAppDeployment() { - return Fabric8Utils.inputStream("app/watcher-endpoints-deployment.yaml"); - } - - private static InputStream getEndpointSlicesAppDeployment() { - return Fabric8Utils.inputStream("app/watcher-endpoint-slices-deployment.yaml"); - } - - private static InputStream getAppIngress() { - return Fabric8Utils.inputStream("app/watcher-ingress.yaml"); - } - - private static InputStream getAppService() { - return Fabric8Utils.inputStream("app/watcher-service.yaml"); } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/fabric8/catalog/watch/Fabric8CatalogWatchWithNamespacesIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/fabric8/catalog/watch/Fabric8CatalogWatchWithNamespacesIT.java index a2a59fcc..bd8f74b1 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/fabric8/catalog/watch/Fabric8CatalogWatchWithNamespacesIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/fabric8/catalog/watch/Fabric8CatalogWatchWithNamespacesIT.java @@ -25,14 +25,11 @@ import java.util.Set; import io.fabric8.kubernetes.api.model.EnvVar; import io.fabric8.kubernetes.api.model.EnvVarBuilder; -import io.fabric8.kubernetes.api.model.NamespaceBuilder; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.networking.v1.Ingress; -import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; -import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -44,8 +41,8 @@ import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.commons.discovery.EndpointNameAndNamespace; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util; import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ResolvableType; import org.springframework.http.HttpMethod; @@ -71,46 +68,33 @@ class Fabric8CatalogWatchWithNamespacesIT { private static KubernetesClient client; - private static String busyboxServiceNameA; - - private static String busyboxServiceNameB; - - private static String busyboxDeploymentNameA; - - private static String busyboxDeploymentNameB; - - private static String appDeploymentName; - - private static String appServiceName; - - private static String appIngressName; + private static Util util; @BeforeAll static void beforeAll() throws Exception { K3S.start(); - Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml()); - client = new KubernetesClientBuilder().withConfig(config).build(); + util = new Util(K3S); + client = util.client(); Commons.validateImage(APP_NAME, K3S); Commons.loadSpringCloudKubernetesImage(APP_NAME, K3S); + + util.createNamespace(NAMESPACE_A); + util.createNamespace(NAMESPACE_B); + + util.setUpClusterWide(NAMESPACE_DEFAULT, Set.of(NAMESPACE_DEFAULT, NAMESPACE_A, NAMESPACE_B)); } @BeforeEach - void beforeEach() throws Exception { - client.namespaces().resource(new NamespaceBuilder().withNewMetadata().withName(NAMESPACE_A).and().build()) - .create(); - client.namespaces().resource(new NamespaceBuilder().withNewMetadata().withName(NAMESPACE_B).and().build()) - .create(); - Fabric8Utils.setUpClusterWide(client, NAMESPACE_DEFAULT, Set.of(NAMESPACE_DEFAULT, NAMESPACE_A, NAMESPACE_B)); - deployBusyboxManifests(); + void beforeEach() { + util.busybox(NAMESPACE_A, Phase.CREATE); + util.busybox(NAMESPACE_B, Phase.CREATE); } - @AfterEach - void afterEach() { - Fabric8Utils.cleanUpClusterWide(client, NAMESPACE_DEFAULT, Set.of(NAMESPACE_DEFAULT, NAMESPACE_A, NAMESPACE_B)); - Fabric8Utils.deleteNamespace(client, NAMESPACE_A); - Fabric8Utils.deleteNamespace(client, NAMESPACE_B); - deleteApp(); + @AfterAll + static void afterAll() { + util.deleteNamespace(NAMESPACE_A); + util.deleteNamespace(NAMESPACE_B); } /** @@ -125,16 +109,18 @@ class Fabric8CatalogWatchWithNamespacesIT { */ @Test void testCatalogWatchWithEndpoints() throws Exception { - deployApp(false); + app(false, Phase.CREATE); assertLogStatement("stateGenerator is of type: Fabric8EndpointsCatalogWatch"); test(); + app(false, Phase.DELETE); } @Test void testCatalogWatchWithEndpointSlices() throws Exception { - deployApp(true); + app(true, Phase.CREATE); assertLogStatement("stateGenerator is of type: Fabric8EndpointSliceV1CatalogWatch"); test(); + app(true, Phase.DELETE); } /** @@ -190,7 +176,8 @@ class Fabric8CatalogWatchWithNamespacesIT { Assertions.assertEquals(NAMESPACE_A, resultOne.namespace()); Assertions.assertEquals(NAMESPACE_A, resultTwo.namespace()); - deleteBusyboxApp(); + util.busybox(NAMESPACE_A, Phase.DELETE); + util.busybox(NAMESPACE_B, Phase.DELETE); // what we get after delete EndpointNameAndNamespace[] afterDelete = new EndpointNameAndNamespace[1]; @@ -223,43 +210,19 @@ class Fabric8CatalogWatchWithNamespacesIT { } - private void deployBusyboxManifests() throws Exception { + private static void app(boolean useEndpointSlices, Phase phase) { - Deployment deployment = client.apps().deployments().load(getBusyboxDeployment()).get(); + InputStream endpointsDeploymentStream = util.inputStream("app/watcher-endpoints-deployment.yaml"); + InputStream endpointSlicesDeploymentStream = util.inputStream("app/watcher-endpoint-slices-deployment.yaml"); + InputStream serviceStream = util.inputStream("app/watcher-service.yaml"); + InputStream ingressStream = util.inputStream("app/watcher-ingress.yaml"); - String[] image = K8SUtils.getImageFromDeployment(deployment).split(":"); - Commons.pullImage(image[0], image[1], K3S); - Commons.loadImage(image[0], image[1], "busybox", K3S); - - // namespace_a - client.apps().deployments().inNamespace(NAMESPACE_A).resource(deployment).create(); - busyboxDeploymentNameA = deployment.getMetadata().getName(); - - Service busyboxServiceA = client.services().load(getBusyboxService()).get(); - busyboxServiceNameA = busyboxServiceA.getMetadata().getName(); - client.services().inNamespace(NAMESPACE_A).resource(busyboxServiceA).create(); - - Fabric8Utils.waitForDeployment(client, busyboxDeploymentNameA, NAMESPACE_A, 2, 600); - - // namespace_b - client.apps().deployments().inNamespace(NAMESPACE_B).resource(deployment).create(); - busyboxDeploymentNameB = deployment.getMetadata().getName(); - - Service busyboxServiceB = client.services().load(getBusyboxService()).get(); - busyboxServiceNameB = busyboxServiceB.getMetadata().getName(); - client.services().inNamespace(NAMESPACE_B).resource(busyboxServiceB).create(); - - Fabric8Utils.waitForDeployment(client, busyboxDeploymentNameB, NAMESPACE_B, 2, 600); - - } - - private static void deployApp(boolean useEndpointSlices) { - - InputStream deployment = useEndpointSlices ? getEndpointSlicesAppDeployment() : getEndpointsAppDeployment(); - Deployment appDeployment = client.apps().deployments().load(deployment).get(); + Deployment deployment = useEndpointSlices + ? client.apps().deployments().load(endpointSlicesDeploymentStream).get() + : client.apps().deployments().load(endpointsDeploymentStream).get(); List envVars = new ArrayList<>( - appDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv()); + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv()); EnvVar namespaceAEnvVar = new EnvVarBuilder().withName("SPRING_CLOUD_KUBERNETES_DISCOVERY_NAMESPACES_0") .withValue(NAMESPACE_A).build(); EnvVar namespaceDefaultEnvVar = new EnvVarBuilder().withName("SPRING_CLOUD_KUBERNETES_DISCOVERY_NAMESPACES_1") @@ -267,70 +230,19 @@ class Fabric8CatalogWatchWithNamespacesIT { envVars.add(namespaceAEnvVar); envVars.add(namespaceDefaultEnvVar); - appDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(envVars); + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(envVars); - String version = K8SUtils.getPomVersion(); - String currentImage = appDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - appDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version); + Service service = client.services().load(serviceStream).get(); + Ingress ingress = client.network().v1().ingresses().load(ingressStream).get(); - client.apps().deployments().inNamespace(NAMESPACE_DEFAULT).resource(appDeployment).create(); - appDeploymentName = appDeployment.getMetadata().getName(); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(Fabric8CatalogWatchWithNamespacesIT.NAMESPACE_DEFAULT, null, deployment, service, + ingress, true); + } + else { + util.deleteAndWait(Fabric8CatalogWatchWithNamespacesIT.NAMESPACE_DEFAULT, deployment, service, ingress); + } - Service appService = client.services().load(getAppService()).get(); - appServiceName = appService.getMetadata().getName(); - client.services().inNamespace(NAMESPACE_DEFAULT).resource(appService).create(); - - Fabric8Utils.waitForDeployment(client, appDeploymentName, NAMESPACE_DEFAULT, 2, 600); - - Ingress appIngress = client.network().v1().ingresses().load(getAppIngress()).get(); - appIngressName = appIngress.getMetadata().getName(); - client.network().v1().ingresses().inNamespace(NAMESPACE_DEFAULT).resource(appIngress).create(); - - Fabric8Utils.waitForIngress(client, appIngressName, NAMESPACE_DEFAULT); - - } - - private void deleteBusyboxApp() { - // namespacea - Fabric8Utils.deleteDeployment(client, NAMESPACE_A, busyboxDeploymentNameA); - Fabric8Utils.deleteService(client, NAMESPACE_A, busyboxServiceNameA); - - // namespaceb - Fabric8Utils.deleteDeployment(client, NAMESPACE_B, busyboxDeploymentNameB); - Fabric8Utils.deleteService(client, NAMESPACE_B, busyboxServiceNameB); - } - - private void deleteApp() { - Fabric8Utils.deleteDeployment(client, NAMESPACE_DEFAULT, appDeploymentName); - Fabric8Utils.deleteService(client, NAMESPACE_DEFAULT, appServiceName); - Fabric8Utils.deleteIngress(client, NAMESPACE_DEFAULT, appIngressName); - } - - private static InputStream getBusyboxService() { - return Fabric8Utils.inputStream("busybox/service.yaml"); - } - - private static InputStream getBusyboxDeployment() { - return Fabric8Utils.inputStream("busybox/deployment.yaml"); - } - - /** - * deployment where support for endpoint slices is equal to false - */ - private static InputStream getEndpointsAppDeployment() { - return Fabric8Utils.inputStream("app/watcher-endpoints-deployment.yaml"); - } - - private static InputStream getEndpointSlicesAppDeployment() { - return Fabric8Utils.inputStream("app/watcher-endpoint-slices-deployment.yaml"); - } - - private static InputStream getAppIngress() { - return Fabric8Utils.inputStream("app/watcher-ingress.yaml"); - } - - private static InputStream getAppService() { - return Fabric8Utils.inputStream("app/watcher-service.yaml"); } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/event/reload/ConfigMapEventReloadIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/event/reload/ConfigMapEventReloadIT.java index 56e9828f..afc9b511 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/event/reload/ConfigMapEventReloadIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/event/reload/ConfigMapEventReloadIT.java @@ -18,6 +18,8 @@ package org.springframework.cloud.kubernetes.fabric8.configmap.event.reload; import java.io.InputStream; import java.time.Duration; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -26,14 +28,13 @@ import java.util.concurrent.locks.LockSupport; import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.ConfigMapBuilder; +import io.fabric8.kubernetes.api.model.EnvVar; +import io.fabric8.kubernetes.api.model.EnvVarBuilder; import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.networking.v1.Ingress; -import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; -import io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperation; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -44,14 +45,13 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util; import org.springframework.http.HttpMethod; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; import static org.awaitility.Awaitility.await; -import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.processExecResult; /** * @author wind57 @@ -62,37 +62,30 @@ class ConfigMapEventReloadIT { private static final String NAMESPACE = "default"; - private static KubernetesClient client; - - private static String deploymentName; - - private static String serviceName; - - private static String ingressName; - - private static String leftConfigMapName; - - private static String rightConfigMapName; - - private static String rightWithLabelConfigMapName; - private static final K3sContainer K3S = Commons.container(); + private static Util util; + + private static KubernetesClient client; + @BeforeAll static void beforeAll() throws Exception { K3S.start(); Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); - Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml()); - client = new KubernetesClientBuilder().withConfig(config).build(); - createNamespaces(); - Fabric8Utils.setUpClusterWide(client, "default", Set.of("left", "right")); + util = new Util(K3S); + client = util.client(); + + util.createNamespace("left"); + util.createNamespace("right"); + util.setUpClusterWide(NAMESPACE, Set.of("left", "right")); } @AfterAll static void afterAll() throws Exception { - deleteNamespaces(); + util.deleteNamespace("left"); + util.deleteNamespace("right"); Commons.cleanUp(IMAGE_NAME, K3S); } @@ -106,7 +99,7 @@ class ConfigMapEventReloadIT { */ @Test void testInformFromOneNamespaceEventNotTriggered() { - deployManifests("one"); + manifests("one", Phase.CREATE); WebClient webClient = builder().baseUrl("localhost/left").build(); String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec()) @@ -125,7 +118,7 @@ class ConfigMapEventReloadIT { .withMetadata(new ObjectMetaBuilder().withNamespace("right").withName("right-configmap").build()) .withData(Map.of("right.value", "right-after-change")).build(); - replaceConfigMap(rightConfigMapAfterChange, "right-configmap"); + replaceConfigMap(rightConfigMapAfterChange); // wait dummy for 5 seconds LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(5)); @@ -135,7 +128,7 @@ class ConfigMapEventReloadIT { // left configmap has not changed, no restart of app has happened Assertions.assertEquals("left-initial", result); - deleteManifests(); + manifests("one", Phase.DELETE); } /** @@ -148,7 +141,7 @@ class ConfigMapEventReloadIT { */ @Test void testInformFromOneNamespaceEventTriggered() { - deployManifests("two"); + manifests("two", Phase.CREATE); // read the value from the right-configmap WebClient webClient = builder().baseUrl("localhost/right").build(); @@ -161,7 +154,7 @@ class ConfigMapEventReloadIT { .withMetadata(new ObjectMetaBuilder().withNamespace("right").withName("right-configmap").build()) .withData(Map.of("right.value", "right-after-change")).build(); - replaceConfigMap(rightConfigMapAfterChange, "right-configmap"); + replaceConfigMap(rightConfigMapAfterChange); String[] resultAfterChange = new String[1]; await().pollInterval(Duration.ofSeconds(3)).atMost(Duration.ofSeconds(90)).until(() -> { @@ -173,7 +166,7 @@ class ConfigMapEventReloadIT { }); Assertions.assertEquals("right-after-change", resultAfterChange[0]); - deleteManifests(); + manifests("two", Phase.DELETE); } /** @@ -187,7 +180,7 @@ class ConfigMapEventReloadIT { */ @Test void testInform() { - deployManifests("three"); + manifests("three", Phase.CREATE); // read the initial value from the right-configmap WebClient rightWebClient = builder().baseUrl("localhost/right").build(); @@ -206,7 +199,7 @@ class ConfigMapEventReloadIT { .withMetadata(new ObjectMetaBuilder().withNamespace("right").withName("right-configmap").build()) .withData(Map.of("right.value", "right-after-change")).build(); - replaceConfigMap(rightConfigMapAfterChange, "right-configmap"); + replaceConfigMap(rightConfigMapAfterChange); // sleep for 5 seconds LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(5)); @@ -222,7 +215,7 @@ class ConfigMapEventReloadIT { new ObjectMetaBuilder().withNamespace("right").withName("right-configmap-with-label").build()) .withData(Map.of("right.with.label.value", "right-with-label-after-change")).build(); - replaceConfigMap(rightWithLabelConfigMapAfterChange, "right-configmap-with-label"); + replaceConfigMap(rightWithLabelConfigMapAfterChange); // since we have changed a labeled configmap, app will restart and pick up the new // value @@ -242,111 +235,53 @@ class ConfigMapEventReloadIT { .block(); Assertions.assertEquals("right-after-change", rightResult); - deleteManifests(); + manifests("three", Phase.DELETE); } - private static void createNamespaces() throws Exception { - processExecResult(K3S.execInContainer("sh", "-c", "kubectl create namespace left")); - processExecResult(K3S.execInContainer("sh", "-c", "kubectl create namespace right")); - } + private static void manifests(String activeProfile, Phase phase) { - private static void deleteNamespaces() throws Exception { - processExecResult(K3S.execInContainer("sh", "-c", "kubectl delete namespace left")); - processExecResult(K3S.execInContainer("sh", "-c", "kubectl delete namespace right")); - } + InputStream deploymentStream = util.inputStream("deployment.yaml"); + InputStream serviceStream = util.inputStream("service.yaml"); + InputStream ingressStream = util.inputStream("ingress.yaml"); + InputStream leftConfigMapStream = util.inputStream("left-configmap.yaml"); + InputStream rightConfigMapStream = util.inputStream("right-configmap.yaml"); + InputStream rightWithLabelConfigMapStream = util.inputStream("right-configmap-with-label.yaml"); - private static void deployManifests(String deploymentRoot) { + Deployment deployment = client.apps().deployments().load(deploymentStream).get(); - try { + List envVars = new ArrayList<>( + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv()); + EnvVar activeProfileProperty = new EnvVarBuilder().withName("SPRING_PROFILES_ACTIVE").withValue(activeProfile) + .build(); + envVars.add(activeProfileProperty); - ConfigMap leftConfigMap = client.configMaps().load(leftConfigMap()).get(); - leftConfigMapName = leftConfigMap.getMetadata().getName(); - client.configMaps().create(leftConfigMap); + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(envVars); - ConfigMap rightConfigMap = client.configMaps().load(rightConfigMap()).get(); - rightConfigMapName = rightConfigMap.getMetadata().getName(); - client.configMaps().create(rightConfigMap); + Service service = client.services().load(serviceStream).get(); + Ingress ingress = client.network().v1().ingresses().load(ingressStream).get(); + ConfigMap leftConfigMap = client.configMaps().load(leftConfigMapStream).get(); + ConfigMap rightConfigMap = client.configMaps().load(rightConfigMapStream).get(); + ConfigMap rightWithLabelConfigMap = client.configMaps().load(rightWithLabelConfigMapStream).get(); - if ("three".equals(deploymentRoot)) { - ConfigMap rightWithLabelConfigMap = client.configMaps().load(rightWithLabelConfigMap()).get(); - rightWithLabelConfigMapName = rightWithLabelConfigMap.getMetadata().getName(); - client.configMaps().create(rightWithLabelConfigMap); + if (phase.equals(Phase.CREATE)) { + util.createAndWait("left", leftConfigMap, null); + util.createAndWait("right", rightConfigMap, null); + if ("three".equals(activeProfile)) { + util.createAndWait("right", rightWithLabelConfigMap, null); } - - Deployment deployment = client.apps().deployments().load(getDeployment(deploymentRoot)).get(); - - String version = K8SUtils.getPomVersion(); - String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version); - - client.apps().deployments().inNamespace(NAMESPACE).create(deployment); - deploymentName = deployment.getMetadata().getName(); - - Service service = client.services().load(getService()).get(); - serviceName = service.getMetadata().getName(); - client.services().inNamespace(NAMESPACE).create(service); - - Ingress ingress = client.network().v1().ingresses().load(getIngress()).get(); - ingressName = ingress.getMetadata().getName(); - client.network().v1().ingresses().inNamespace(NAMESPACE).create(ingress); - - Fabric8Utils.waitForDeployment(client, - "spring-cloud-kubernetes-fabric8-client-configmap-deployment-event-reload", NAMESPACE, 2, 600); - + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); } - catch (Exception e) { - throw new RuntimeException(e); - } - - } - - private static void deleteManifests() { - - try { - - client.configMaps().inNamespace("left").withName(leftConfigMapName).delete(); - Fabric8Utils.waitForConfigMapDelete(client, "left", leftConfigMapName); - client.configMaps().inNamespace("right").withName(rightConfigMapName).delete(); - Fabric8Utils.waitForConfigMapDelete(client, "right", rightConfigMapName); - if (rightWithLabelConfigMapName != null) { - client.configMaps().inNamespace("right").withName(rightWithLabelConfigMapName).delete(); - Fabric8Utils.waitForConfigMapDelete(client, "right", rightWithLabelConfigMapName); + else { + util.deleteAndWait("left", leftConfigMap, null); + util.deleteAndWait("right", rightConfigMap, null); + if ("three".equals(activeProfile)) { + util.deleteAndWait("right", rightWithLabelConfigMap, null); } - client.apps().deployments().inNamespace(NAMESPACE).withName(deploymentName).delete(); - client.services().inNamespace(NAMESPACE).withName(serviceName).delete(); - client.network().v1().ingresses().inNamespace(NAMESPACE).withName(ingressName).delete(); - - } - catch (Exception e) { - throw new RuntimeException(e); + util.deleteAndWait(NAMESPACE, deployment, service, ingress); } } - private static InputStream leftConfigMap() { - return Fabric8Utils.inputStream("left-configmap.yaml"); - } - - private static InputStream rightConfigMap() { - return Fabric8Utils.inputStream("right-configmap.yaml"); - } - - private static InputStream rightWithLabelConfigMap() { - return Fabric8Utils.inputStream("right-configmap-with-label.yaml"); - } - - private static InputStream getDeployment(String root) { - return Fabric8Utils.inputStream(root + "/deployment.yaml"); - } - - private static InputStream getService() { - return Fabric8Utils.inputStream("service.yaml"); - } - - private static InputStream getIngress() { - return Fabric8Utils.inputStream("ingress.yaml"); - } - private WebClient.Builder builder() { return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create())); } @@ -355,11 +290,8 @@ class ConfigMapEventReloadIT { return Retry.fixedDelay(120, Duration.ofSeconds(2)).filter(Objects::nonNull); } - // the weird cast comes from : - // https://github.com/fabric8io/kubernetes-client/issues/2445 - @SuppressWarnings({ "unchecked", "raw" }) - private static void replaceConfigMap(ConfigMap configMap, String name) { - ((HasMetadataOperation) client.configMaps().inNamespace("right").withName(name)).createOrReplace(configMap); + private static void replaceConfigMap(ConfigMap configMap) { + client.configMaps().inNamespace("right").resource(configMap).createOrReplace(); } } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/resources/two/deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/resources/deployment.yaml similarity index 91% rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/resources/two/deployment.yaml rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/resources/deployment.yaml index c37316bf..864f23d5 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/resources/two/deployment.yaml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/resources/deployment.yaml @@ -26,6 +26,3 @@ spec: path: /actuator/health/liveness ports: - containerPort: 8080 - env: - - name: SPRING_PROFILES_ACTIVE - value: two diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/resources/one/deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/resources/one/deployment.yaml deleted file mode 100644 index 0e10021a..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/resources/one/deployment.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: spring-cloud-kubernetes-fabric8-client-configmap-deployment-event-reload -spec: - selector: - matchLabels: - app: spring-cloud-kubernetes-fabric8-client-configmap-event-reload - template: - metadata: - labels: - app: spring-cloud-kubernetes-fabric8-client-configmap-event-reload - spec: - serviceAccountName: spring-cloud-kubernetes-serviceaccount - containers: - - name: spring-cloud-kubernetes-fabric8-client-configmap-event-reload - image: docker.io/springcloud/spring-cloud-kubernetes-fabric8-client-configmap-event-reload - imagePullPolicy: IfNotPresent - readinessProbe: - httpGet: - port: 8080 - path: /actuator/health/readiness - livenessProbe: - httpGet: - port: 8080 - path: /actuator/health/liveness - ports: - - containerPort: 8080 - env: - - name: SPRING_PROFILES_ACTIVE - value: one diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/resources/three/deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/resources/three/deployment.yaml deleted file mode 100644 index dda8ce62..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-event-reload/src/test/resources/three/deployment.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: spring-cloud-kubernetes-fabric8-client-configmap-deployment-event-reload -spec: - selector: - matchLabels: - app: spring-cloud-kubernetes-fabric8-client-configmap-event-reload - template: - metadata: - labels: - app: spring-cloud-kubernetes-fabric8-client-configmap-event-reload - spec: - serviceAccountName: spring-cloud-kubernetes-serviceaccount - containers: - - name: spring-cloud-kubernetes-fabric8-client-configmap-event-reload - image: docker.io/springcloud/spring-cloud-kubernetes-fabric8-client-configmap-event-reload - imagePullPolicy: IfNotPresent - readinessProbe: - httpGet: - port: 8080 - path: /actuator/health/readiness - livenessProbe: - httpGet: - port: 8080 - path: /actuator/health/liveness - ports: - - containerPort: 8080 - env: - - name: SPRING_PROFILES_ACTIVE - value: three diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-polling-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/polling/reload/ConfigMapPollingReloadIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-polling-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/polling/reload/ConfigMapPollingReloadIT.java index 957249f2..ce48eceb 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-polling-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/polling/reload/ConfigMapPollingReloadIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap-polling-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/polling/reload/ConfigMapPollingReloadIT.java @@ -27,10 +27,7 @@ import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.networking.v1.Ingress; -import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; -import io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperation; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -41,8 +38,8 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util; import org.springframework.http.HttpMethod; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; @@ -58,16 +55,10 @@ class ConfigMapPollingReloadIT { private static final String NAMESPACE = "default"; + private static Util util; + private static KubernetesClient client; - private static String deploymentName; - - private static String serviceName; - - private static String ingressName; - - private static String configMapName; - private static final K3sContainer K3S = Commons.container(); @BeforeAll @@ -75,19 +66,18 @@ class ConfigMapPollingReloadIT { K3S.start(); Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); - Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml()); - client = new KubernetesClientBuilder().withConfig(config).build(); - Fabric8Utils.setUp(client, NAMESPACE); - deployManifests(); + util = new Util(K3S); + client = util.client(); + util.setUp(NAMESPACE); + manifests(Phase.CREATE); } @AfterAll static void after() throws Exception { - deleteManifests(); + manifests(Phase.DELETE); Commons.cleanUp(IMAGE_NAME, K3S); } - @SuppressWarnings({ "raw", "unchecked" }) @Test void test() { WebClient webClient = builder().baseUrl("localhost/key").build(); @@ -103,83 +93,36 @@ class ConfigMapPollingReloadIT { .withMetadata(new ObjectMetaBuilder().withNamespace("default").withName("poll-reload").build()) .withData(Map.of("application.properties", "from.properties.key=after-change")).build(); - // the weird cast comes from : - // https://github.com/fabric8io/kubernetes-client/issues/2445 - ((HasMetadataOperation) client.configMaps().inNamespace("default").withName("poll-reload")).resource(map) - .createOrReplace(); + client.configMaps().inNamespace("default").resource(map).createOrReplace(); await().timeout(Duration.ofSeconds(60)).until(() -> webClient.method(HttpMethod.GET).retrieve() .bodyToMono(String.class).retryWhen(retrySpec()).block().equals("after-change")); } - private static void deleteManifests() { + private static void manifests(Phase phase) { - try { + InputStream deploymentStream = util.inputStream("deployment.yaml"); + InputStream serviceStream = util.inputStream("service.yaml"); + InputStream ingressStream = util.inputStream("ingress.yaml"); + InputStream configMapStream = util.inputStream("configmap.yaml"); - client.configMaps().inNamespace(NAMESPACE).withName(configMapName).delete(); - client.apps().deployments().inNamespace(NAMESPACE).withName(deploymentName).delete(); - client.services().inNamespace(NAMESPACE).withName(serviceName).delete(); - client.network().v1().ingresses().inNamespace(NAMESPACE).withName(ingressName).delete(); + Deployment deployment = client.apps().deployments().load(deploymentStream).get(); + Service service = client.services().load(serviceStream).get(); + Ingress ingress = client.network().v1().ingresses().load(ingressStream).get(); + ConfigMap configMap = client.configMaps().load(configMapStream).get(); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, configMap, null); + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); } - catch (Exception e) { - throw new RuntimeException(e); + else { + util.deleteAndWait(NAMESPACE, configMap, null); + util.deleteAndWait(NAMESPACE, deployment, service, ingress); } } - private static void deployManifests() { - - try { - - ConfigMap configMap = client.configMaps().load(getConfigMap()).get(); - configMapName = configMap.getMetadata().getName(); - client.configMaps().resource(configMap).create(); - - Deployment deployment = client.apps().deployments().load(getDeployment()).get(); - - String version = K8SUtils.getPomVersion(); - String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version); - - client.apps().deployments().inNamespace(NAMESPACE).create(deployment); - deploymentName = deployment.getMetadata().getName(); - - Service service = client.services().load(getService()).get(); - serviceName = service.getMetadata().getName(); - client.services().inNamespace(NAMESPACE).resource(service).create(); - - Ingress ingress = client.network().v1().ingresses().load(getIngress()).get(); - ingressName = ingress.getMetadata().getName(); - client.network().v1().ingresses().inNamespace(NAMESPACE).resource(ingress).create(); - - Fabric8Utils.waitForDeployment(client, - "spring-cloud-kubernetes-fabric8-client-configmap-deployment-polling-reload", NAMESPACE, 2, 600); - - } - catch (Exception e) { - throw new RuntimeException(e); - } - - } - - private static InputStream getService() { - return Fabric8Utils.inputStream("service.yaml"); - } - - private static InputStream getDeployment() { - return Fabric8Utils.inputStream("deployment.yaml"); - } - - private static InputStream getIngress() { - return Fabric8Utils.inputStream("ingress.yaml"); - } - - private static InputStream getConfigMap() { - return Fabric8Utils.inputStream("configmap.yaml"); - } - private WebClient.Builder builder() { return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create())); } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8ConfigMapIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8ConfigMapIT.java index d43e0300..50f60c94 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8ConfigMapIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8ConfigMapIT.java @@ -24,9 +24,7 @@ import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.networking.v1.Ingress; -import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -37,8 +35,8 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util; import org.springframework.http.HttpMethod; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; @@ -51,30 +49,26 @@ class Fabric8ConfigMapIT { private static KubernetesClient client; - private static String deploymentName; - - private static String serviceName; - - private static String ingressName; - - private static String configMapName; - private static final K3sContainer K3S = Commons.container(); + private static Util util; + @BeforeAll static void beforeAll() throws Exception { K3S.start(); + util = new Util(K3S); + client = util.client(); + Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); - Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml()); - client = new KubernetesClientBuilder().withConfig(config).build(); - Fabric8Utils.setUp(client, NAMESPACE); - deployManifests(); + + util.setUp(NAMESPACE); + manifests(Phase.CREATE); } @AfterAll - static void after() throws Exception { - deleteManifests(); + static void afterAll() throws Exception { + manifests(Phase.DELETE); Commons.cleanUp(IMAGE_NAME, K3S); } @@ -88,73 +82,29 @@ class Fabric8ConfigMapIT { Assertions.assertEquals("value1", result); } - private static void deleteManifests() { + private static void manifests(Phase phase) { - try { + InputStream deploymentStream = util.inputStream("fabric8-deployment.yaml"); + InputStream serviceStream = util.inputStream("fabric8-service.yaml"); + InputStream ingressStream = util.inputStream("fabric8-ingress.yaml"); + InputStream configMapStream = util.inputStream("fabric8-configmap.yaml"); - client.configMaps().inNamespace(NAMESPACE).withName(configMapName).delete(); - client.apps().deployments().inNamespace(NAMESPACE).withName(deploymentName).delete(); - client.services().inNamespace(NAMESPACE).withName(serviceName).delete(); - client.network().v1().ingresses().inNamespace(NAMESPACE).withName(ingressName).delete(); + Deployment deployment = client.apps().deployments().load(deploymentStream).get(); + Service service = client.services().load(serviceStream).get(); + Ingress ingress = client.network().v1().ingresses().load(ingressStream).get(); + ConfigMap configMap = client.configMaps().load(configMapStream).get(); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, configMap, null); + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); } - catch (Exception e) { - throw new RuntimeException(e); + else { + util.deleteAndWait(NAMESPACE, configMap, null); + util.deleteAndWait(NAMESPACE, deployment, service, ingress); } } - private static void deployManifests() { - - try { - - ConfigMap configMap = client.configMaps().load(getConfigMap()).get(); - configMapName = configMap.getMetadata().getName(); - client.configMaps().resource(configMap).create(); - - Deployment deployment = client.apps().deployments().load(getDeployment()).get(); - - String version = K8SUtils.getPomVersion(); - String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version); - - client.apps().deployments().inNamespace(NAMESPACE).resource(deployment).create(); - deploymentName = deployment.getMetadata().getName(); - - Service service = client.services().load(getService()).get(); - serviceName = service.getMetadata().getName(); - client.services().inNamespace(NAMESPACE).resource(service).create(); - - Ingress ingress = client.network().v1().ingresses().load(getIngress()).get(); - ingressName = ingress.getMetadata().getName(); - client.network().v1().ingresses().inNamespace(NAMESPACE).resource(ingress).create(); - - Fabric8Utils.waitForDeployment(client, "spring-cloud-kubernetes-fabric8-client-configmap-deployment", - NAMESPACE, 2, 600); - - } - catch (Exception e) { - throw new RuntimeException(e); - } - - } - - private static InputStream getService() { - return Fabric8Utils.inputStream("fabric8-service.yaml"); - } - - private static InputStream getDeployment() { - return Fabric8Utils.inputStream("fabric8-deployment.yaml"); - } - - private static InputStream getIngress() { - return Fabric8Utils.inputStream("fabric8-ingress.yaml"); - } - - private static InputStream getConfigMap() { - return Fabric8Utils.inputStream("fabric8-configmap.yaml"); - } - private WebClient.Builder builder() { return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create())); } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8DiscoveryIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8DiscoveryIT.java index f01902ff..cf84a372 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8DiscoveryIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8DiscoveryIT.java @@ -24,9 +24,7 @@ import java.util.Objects; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.networking.v1.Ingress; -import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -37,8 +35,8 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util; import org.springframework.http.HttpMethod; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; @@ -54,17 +52,7 @@ class Fabric8DiscoveryIT { private static KubernetesClient client; - private static String deploymentName; - - private static String serviceName; - - private static String ingressName; - - private static String mockServiceName; - - private static String mockDeploymentName; - - private static String mockDeploymentImage; + private static Util util; private static final K3sContainer K3S = Commons.container(); @@ -74,19 +62,20 @@ class Fabric8DiscoveryIT { Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); - Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml()); - client = new KubernetesClientBuilder().withConfig(config).build(); - Fabric8Utils.setUp(client, NAMESPACE); + util = new Util(K3S); + client = util.client(); - deployManifests(); - deployMockManifests(); + util.setUp(NAMESPACE); + + manifests(Phase.CREATE); + util.wiremock(NAMESPACE, "/wiremock", Phase.CREATE); } @AfterAll static void after() throws Exception { - deleteManifests(); + util.wiremock(NAMESPACE, "/wiremock", Phase.DELETE); + manifests(Phase.DELETE); Commons.cleanUp(IMAGE_NAME, K3S); - Commons.cleanUpDownloadedImage(mockDeploymentImage); } @Test @@ -100,103 +89,28 @@ class Fabric8DiscoveryIT { Assertions.assertEquals(result.size(), 3); Assertions.assertTrue(result.contains("kubernetes")); Assertions.assertTrue(result.contains("spring-cloud-kubernetes-fabric8-client-discovery")); - Assertions.assertTrue(result.contains("wiremock")); + Assertions.assertTrue(result.contains("service-wiremock")); } - private static void deleteManifests() { + private static void manifests(Phase phase) { - try { + InputStream deploymentStream = util.inputStream("fabric8-discovery-deployment.yaml"); + InputStream serviceStream = util.inputStream("fabric8-discovery-service.yaml"); + InputStream ingressStream = util.inputStream("fabric8-discovery-ingress.yaml"); - client.apps().deployments().inNamespace(NAMESPACE).withName(deploymentName).delete(); - client.services().inNamespace(NAMESPACE).withName(serviceName).delete(); - client.network().v1().ingresses().inNamespace(NAMESPACE).withName(ingressName).delete(); - - client.services().inNamespace(NAMESPACE).withName(mockServiceName).delete(); - client.apps().deployments().inNamespace(NAMESPACE).withName(mockDeploymentName).delete(); + Deployment deployment = client.apps().deployments().load(deploymentStream).get(); + Service service = client.services().load(serviceStream).get(); + Ingress ingress = client.network().v1().ingresses().load(ingressStream).get(); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); } - catch (Exception e) { - throw new RuntimeException(e); + else { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); } } - private static void deployManifests() { - - try { - - Deployment deployment = client.apps().deployments().load(getDeployment()).get(); - - String version = K8SUtils.getPomVersion(); - String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version); - - client.apps().deployments().inNamespace(NAMESPACE).resource(deployment).create(); - deploymentName = deployment.getMetadata().getName(); - - Service service = client.services().load(getService()).get(); - serviceName = service.getMetadata().getName(); - client.services().inNamespace(NAMESPACE).resource(service).create(); - - Ingress ingress = client.network().v1().ingresses().load(getIngress()).get(); - ingressName = ingress.getMetadata().getName(); - client.network().v1().ingresses().inNamespace(NAMESPACE).resource(ingress).create(); - - Fabric8Utils.waitForDeployment(client, "spring-cloud-kubernetes-fabric8-client-discovery-deployment", - NAMESPACE, 2, 600); - - } - catch (Exception e) { - throw new RuntimeException(e); - } - - } - - private static void deployMockManifests() { - - try { - - Deployment deployment = client.apps().deployments().load(getMockDeployment()).get(); - String[] image = K8SUtils.getImageFromDeployment(deployment).split(":"); - Commons.pullImage(image[0], image[1], K3S); - Commons.loadImage(image[0], image[1], "wiremock", K3S); - client.apps().deployments().inNamespace(NAMESPACE).resource(deployment).create(); - mockDeploymentName = deployment.getMetadata().getName(); - mockDeploymentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - - Service service = client.services().load(getMockService()).get(); - mockServiceName = service.getMetadata().getName(); - client.services().inNamespace(NAMESPACE).resource(service).create(); - - Fabric8Utils.waitForDeployment(client, "wiremock-deployment", NAMESPACE, 2, 600); - - } - catch (Exception e) { - throw new RuntimeException(e); - } - - } - - private static InputStream getService() { - return Fabric8Utils.inputStream("fabric8-discovery-service.yaml"); - } - - private static InputStream getDeployment() { - return Fabric8Utils.inputStream("fabric8-discovery-deployment.yaml"); - } - - private static InputStream getIngress() { - return Fabric8Utils.inputStream("fabric8-discovery-ingress.yaml"); - } - - private static InputStream getMockService() { - return Fabric8Utils.inputStream("wiremock/wiremock-service.yaml"); - } - - private static InputStream getMockDeployment() { - return Fabric8Utils.inputStream("wiremock/wiremock-deployment.yaml"); - } - private WebClient.Builder builder() { return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create())); } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8DiscoveryNamespaceFilterIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8DiscoveryNamespaceFilterIT.java index a32fba34..9c0ec7f2 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8DiscoveryNamespaceFilterIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8DiscoveryNamespaceFilterIT.java @@ -18,19 +18,17 @@ package org.springframework.cloud.kubernetes.fabric8.configmap; import java.io.InputStream; import java.time.Duration; +import java.util.ArrayList; import java.util.List; import java.util.Objects; import io.fabric8.kubernetes.api.model.Endpoints; import io.fabric8.kubernetes.api.model.EnvVar; -import io.fabric8.kubernetes.api.model.Namespace; -import io.fabric8.kubernetes.api.model.ObjectMeta; +import io.fabric8.kubernetes.api.model.EnvVarBuilder; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.networking.v1.Ingress; -import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -41,8 +39,8 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpMethod; import org.springframework.http.client.reactive.ReactorClientHttpConnector; @@ -61,20 +59,10 @@ class Fabric8DiscoveryNamespaceFilterIT { private static final String IMAGE_NAME = "spring-cloud-kubernetes-fabric8-client-discovery"; + private static Util util; + private static KubernetesClient client; - private static String deploymentName; - - private static String serviceName; - - private static String ingressName; - - private static String mockServiceName; - - private static String mockDeploymentName; - - private static String mockDeploymentImage; - private static final K3sContainer K3S = Commons.container(); @BeforeAll @@ -83,19 +71,25 @@ class Fabric8DiscoveryNamespaceFilterIT { Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); - Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml()); - client = new KubernetesClientBuilder().withConfig(config).build(); - Fabric8Utils.setUp(client, NAMESPACE); + util = new Util(K3S); + client = util.client(); + util.setUp(NAMESPACE); - deployManifests(); - deployMockManifests(); + manifests(Phase.CREATE); + util.createNamespace(NAMESPACE_LEFT); + util.createNamespace(NAMESPACE_RIGHT); + util.wiremock(NAMESPACE_LEFT, "/wiremock", Phase.CREATE); + util.wiremock(NAMESPACE_RIGHT, "/wiremock", Phase.CREATE); } @AfterAll static void after() throws Exception { - deleteManifests(); + manifests(Phase.DELETE); + util.wiremock(NAMESPACE_LEFT, "/wiremock", Phase.DELETE); + util.wiremock(NAMESPACE_RIGHT, "/wiremock", Phase.DELETE); + util.deleteNamespace(NAMESPACE_LEFT); + util.deleteNamespace(NAMESPACE_RIGHT); Commons.cleanUp(IMAGE_NAME, K3S); - Commons.cleanUpDownloadedImage(mockDeploymentImage); } @Test @@ -107,9 +101,9 @@ class Fabric8DiscoveryNamespaceFilterIT { .retryWhen(retrySpec()).block(); Assertions.assertEquals(services.size(), 1); - Assertions.assertTrue(services.contains("wiremock")); + Assertions.assertTrue(services.contains("service-wiremock")); - WebClient clientEndpoints = builder().baseUrl("localhost/endpoints/wiremock").build(); + WebClient clientEndpoints = builder().baseUrl("localhost/endpoints/service-wiremock").build(); List endpoints = clientEndpoints.method(HttpMethod.GET).retrieve() .bodyToMono(new ParameterizedTypeReference>() { @@ -120,127 +114,36 @@ class Fabric8DiscoveryNamespaceFilterIT { } - private static void deleteManifests() { + private static void manifests(Phase phase) { - try { + InputStream deploymentStream = util.inputStream("fabric8-discovery-deployment.yaml"); + InputStream serviceStream = util.inputStream("fabric8-discovery-service.yaml"); + InputStream ingressStream = util.inputStream("fabric8-discovery-ingress.yaml"); - client.apps().deployments().inNamespace(NAMESPACE).withName(deploymentName).delete(); - client.services().inNamespace(NAMESPACE).withName(serviceName).delete(); - client.network().v1().ingresses().inNamespace(NAMESPACE).withName(ingressName).delete(); + Deployment deployment = client.apps().deployments().load(deploymentStream).get(); + List envVars = new ArrayList<>( + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv()); + EnvVar activeProfileProperty = new EnvVarBuilder().withName("SPRING_CLOUD_KUBERNETES_DISCOVERY_NAMESPACES_0") + .withValue(NAMESPACE_LEFT).build(); + envVars.add(activeProfileProperty); + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(envVars); - client.services().inNamespace(NAMESPACE_LEFT).withName(mockServiceName).delete(); - client.apps().deployments().inNamespace(NAMESPACE_LEFT).withName(mockDeploymentName).delete(); - - client.services().inNamespace(NAMESPACE_RIGHT).withName(mockServiceName).delete(); - client.apps().deployments().inNamespace(NAMESPACE_RIGHT).withName(mockDeploymentName).delete(); - - client.rbac().clusterRoleBindings().withName("admin-default").delete(); - client.namespaces().withName(NAMESPACE_LEFT).delete(); - client.namespaces().withName(NAMESPACE_RIGHT).delete(); - - } - catch (Exception e) { - throw new RuntimeException(e); - } - - } - - private static void deployManifests() { - - try { - - Deployment deployment = client.apps().deployments().load(getDeployment()).get(); - - String version = K8SUtils.getPomVersion(); - String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version); - List env = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv(); - env.add(new EnvVar("SPRING_CLOUD_KUBERNETES_DISCOVERY_NAMESPACES_0", NAMESPACE_LEFT, null)); - - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(env); - - client.apps().deployments().inNamespace(NAMESPACE).resource(deployment).create(); - deploymentName = deployment.getMetadata().getName(); - - Service service = client.services().load(getService()).get(); - serviceName = service.getMetadata().getName(); - client.services().inNamespace(NAMESPACE).resource(service).create(); - - Ingress ingress = client.network().v1().ingresses().load(getIngress()).get(); - ingressName = ingress.getMetadata().getName(); - client.network().v1().ingresses().inNamespace(NAMESPACE).resource(ingress).create(); + Service service = client.services().load(serviceStream).get(); + Ingress ingress = client.network().v1().ingresses().load(ingressStream).get(); + if (phase.equals(Phase.CREATE)) { client.rbac().clusterRoleBindings().resource(client.rbac().clusterRoleBindings().load(getAdminRole()).get()) .create(); - - Fabric8Utils.waitForDeployment(client, "spring-cloud-kubernetes-fabric8-client-discovery-deployment", - NAMESPACE, 2, 600); - + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); } - catch (Exception e) { - throw new RuntimeException(e); + else { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); } } - private static void deployMockManifests() { - - try { - deployInMockInNamespace(NAMESPACE_LEFT); - deployInMockInNamespace(NAMESPACE_RIGHT); - } - catch (Exception e) { - throw new RuntimeException(e); - } - - } - - private static void deployInMockInNamespace(String namespace) throws Exception { - - Namespace namespaceDef = new Namespace(); - ObjectMeta meta = new ObjectMeta(); - meta.setName(namespace); - meta.setNamespace(namespace); - namespaceDef.setMetadata(meta); - client.namespaces().resource(namespaceDef).create(); - - Deployment deployment = client.apps().deployments().load(getMockDeployment()).get(); - String[] image = K8SUtils.getImageFromDeployment(deployment).split(":"); - Commons.pullImage(image[0], image[1], K3S); - Commons.loadImage(image[0], image[1], "wiremock", K3S); - client.apps().deployments().inNamespace(namespace).resource(deployment).create(); - mockDeploymentName = deployment.getMetadata().getName(); - mockDeploymentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - - Service service = client.services().load(getMockService()).get(); - mockServiceName = service.getMetadata().getName(); - client.services().inNamespace(namespace).resource(service).create(); - - Fabric8Utils.waitForDeployment(client, "wiremock-deployment", namespace, 2, 600); - } - - private static InputStream getService() { - return Fabric8Utils.inputStream("fabric8-discovery-service.yaml"); - } - - private static InputStream getDeployment() { - return Fabric8Utils.inputStream("fabric8-discovery-deployment.yaml"); - } - private static InputStream getAdminRole() { - return Fabric8Utils.inputStream("namespace-filter/fabric8-cluster-admin-serviceaccount-role.yaml"); - } - - private static InputStream getIngress() { - return Fabric8Utils.inputStream("fabric8-discovery-ingress.yaml"); - } - - private static InputStream getMockService() { - return Fabric8Utils.inputStream("wiremock/wiremock-service.yaml"); - } - - private static InputStream getMockDeployment() { - return Fabric8Utils.inputStream("wiremock/wiremock-deployment.yaml"); + return util.inputStream("namespace-filter/fabric8-cluster-admin-serviceaccount-role.yaml"); } private WebClient.Builder builder() { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/wiremock/wiremock-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/wiremock/wiremock-deployment.yaml deleted file mode 100644 index 7660d130..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/wiremock/wiremock-deployment.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: wiremock-deployment -spec: - selector: - matchLabels: - app: wiremock - template: - metadata: - labels: - app: wiremock - spec: - containers: - - name: wiremock - image: wiremock/wiremock:2.32.0 - imagePullPolicy: IfNotPresent - readinessProbe: - httpGet: - port: 8080 - path: /__admin/mappings - livenessProbe: - httpGet: - port: 8080 - path: /__admin/mappings - ports: - - containerPort: 8080 diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/wiremock/wiremock-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/wiremock/wiremock-service.yaml deleted file mode 100644 index 0b9dfe3f..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/wiremock/wiremock-service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: wiremock - name: wiremock -spec: - ports: - - name: http - port: 8080 - targetPort: 8080 - selector: - app: wiremock - type: ClusterIP diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/fabric8/cliend/loadbalancer/Fabric8ClientLoadbalancerApp.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/fabric8/cliend/loadbalancer/Fabric8ClientLoadbalancerApp.java index db15000f..1ada6110 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/fabric8/cliend/loadbalancer/Fabric8ClientLoadbalancerApp.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/fabric8/cliend/loadbalancer/Fabric8ClientLoadbalancerApp.java @@ -54,7 +54,7 @@ public class Fabric8ClientLoadbalancerApp { @GetMapping("/servicea") public Mono greeting() { - return builder().build().method(HttpMethod.GET).uri(URI.create("http://servicea-wiremock/__admin/mappings")) + return builder().build().method(HttpMethod.GET).uri(URI.create("http://service-wiremock/__admin/mappings")) .retrieve().bodyToMono(Map.class); } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/Fabric8ClientLoadbalancerIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/Fabric8ClientLoadbalancerIT.java index 0a5c4f54..384d65e3 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/Fabric8ClientLoadbalancerIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/Fabric8ClientLoadbalancerIT.java @@ -18,17 +18,20 @@ package org.springframework.cloud.kubernetes.client.loadbalancer.it; import java.io.InputStream; import java.time.Duration; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Objects; +import io.fabric8.kubernetes.api.model.EnvVar; +import io.fabric8.kubernetes.api.model.EnvVarBuilder; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.networking.v1.Ingress; -import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; 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.Test; @@ -38,14 +41,12 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util; 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; - /** * @author wind57 */ @@ -57,17 +58,7 @@ public class Fabric8ClientLoadbalancerIT { private static KubernetesClient client; - private static String deploymentName; - - private static String serviceName; - - private static String ingressName; - - private static String mockServiceName; - - private static String mockDeploymentName; - - private static String mockIngressName; + private static Util util; private static final K3sContainer K3S = Commons.container(); @@ -77,9 +68,9 @@ public class Fabric8ClientLoadbalancerIT { Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); - Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml()); - client = new KubernetesClientBuilder().withConfig(config).build(); - Fabric8Utils.setUp(client, NAMESPACE); + util = new Util(K3S); + client = util.client(); + util.setUp(NAMESPACE); } @AfterAll @@ -89,18 +80,18 @@ public class Fabric8ClientLoadbalancerIT { @BeforeEach void beforeEach() { - deployMockManifests(); + util.wiremock(NAMESPACE, "/", Phase.CREATE); } @AfterEach - void after() { - deleteManifests(); + void afterEach() { + util.wiremock(NAMESPACE, "/", Phase.DELETE); } @Test void testLoadBalancerServiceMode() { - deployServiceManifests(); + manifests("SERVICE", Phase.CREATE); WebClient client = builder().baseUrl("localhost/loadbalancer-it/servicea").build(); @@ -108,15 +99,17 @@ public class Fabric8ClientLoadbalancerIT { Map mapResult = (Map) client.method(HttpMethod.GET).retrieve() .bodyToMono(Map.class).retryWhen(retrySpec()).block(); - assertThat(mapResult.containsKey("mappings")).isTrue(); - assertThat(mapResult.containsKey("meta")).isTrue(); + Assertions.assertTrue(mapResult.containsKey("mappings")); + Assertions.assertTrue(mapResult.containsKey("meta")); + + manifests("SERVICE", Phase.DELETE); } @Test public void testLoadBalancerPodMode() { - deployPodManifests(); + manifests("POD", Phase.CREATE); WebClient client = builder().baseUrl("localhost/loadbalancer-it/servicea").build(); @@ -124,148 +117,42 @@ public class Fabric8ClientLoadbalancerIT { Map mapResult = (Map) client.method(HttpMethod.GET).retrieve() .bodyToMono(Map.class).retryWhen(retrySpec()).block(); - assertThat(mapResult.containsKey("mappings")).isTrue(); - assertThat(mapResult.containsKey("meta")).isTrue(); + Assertions.assertTrue(mapResult.containsKey("mappings")); + Assertions.assertTrue(mapResult.containsKey("meta")); + + manifests("SERVICE", Phase.DELETE); } - private static void deleteManifests() { + private static void manifests(String type, Phase phase) { - try { + InputStream deploymentStream = util + .inputStream("spring-cloud-kubernetes-fabric8-client-loadbalancer-deployment.yaml"); + InputStream serviceStream = util + .inputStream("spring-cloud-kubernetes-fabric8-client-loadbalancer-service.yaml"); + InputStream ingressStream = util + .inputStream("spring-cloud-kubernetes-fabric8-client-loadbalancer-ingress.yaml"); - client.apps().deployments().inNamespace(NAMESPACE).withName(deploymentName).delete(); - client.services().inNamespace(NAMESPACE).withName(serviceName).delete(); - client.network().v1().ingresses().inNamespace(NAMESPACE).withName(ingressName).delete(); + Deployment deployment = client.apps().deployments().load(deploymentStream).get(); + List envVars = new ArrayList<>( + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv()); + EnvVar activeProfileProperty = new EnvVarBuilder().withName("SPRING_CLOUD_KUBERNETES_LOADBALANCER_MODE") + .withValue(type).build(); + envVars.add(activeProfileProperty); + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(envVars); - client.services().inNamespace(NAMESPACE).withName(mockServiceName).delete(); - client.apps().deployments().inNamespace(NAMESPACE).withName(mockDeploymentName).delete(); - client.network().v1().ingresses().inNamespace(NAMESPACE).withName(mockIngressName).delete(); + Service service = client.services().load(serviceStream).get(); + Ingress ingress = client.network().v1().ingresses().load(ingressStream).get(); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); } - catch (Exception e) { - throw new RuntimeException(e); + else { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); } } - private static void deployServiceManifests() { - - try { - - Deployment deployment = client.apps().deployments().load(getServiceDeployment()).get(); - - String version = K8SUtils.getPomVersion(); - String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version); - - client.apps().deployments().inNamespace(NAMESPACE).resource(deployment).create(); - deploymentName = deployment.getMetadata().getName(); - - Service service = client.services().load(getService()).get(); - serviceName = service.getMetadata().getName(); - client.services().inNamespace(NAMESPACE).resource(service).create(); - - Ingress ingress = client.network().v1().ingresses().load(getIngress()).get(); - ingressName = ingress.getMetadata().getName(); - client.network().v1().ingresses().inNamespace(NAMESPACE).resource(ingress).create(); - - Fabric8Utils.waitForDeployment(client, "spring-cloud-kubernetes-fabric8-client-loadbalancer-deployment", - NAMESPACE, 2, 600); - - } - catch (Exception e) { - throw new RuntimeException(e); - } - - } - - private static void deployPodManifests() { - - try { - - Deployment deployment = client.apps().deployments().load(getPodDeployment()).get(); - - String version = K8SUtils.getPomVersion(); - String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version); - - client.apps().deployments().inNamespace(NAMESPACE).resource(deployment).create(); - deploymentName = deployment.getMetadata().getName(); - - Service service = client.services().load(getService()).get(); - serviceName = service.getMetadata().getName(); - client.services().inNamespace(NAMESPACE).resource(service).create(); - - Ingress ingress = client.network().v1().ingresses().load(getIngress()).get(); - ingressName = ingress.getMetadata().getName(); - client.network().v1().ingresses().inNamespace(NAMESPACE).resource(ingress).create(); - - Fabric8Utils.waitForDeployment(client, "spring-cloud-kubernetes-fabric8-client-loadbalancer-deployment", - NAMESPACE, 2, 600); - - } - catch (Exception e) { - throw new RuntimeException(e); - } - - } - - private static void deployMockManifests() { - - try { - - Deployment deployment = client.apps().deployments().load(getMockDeployment()).get(); - String[] image = K8SUtils.getImageFromDeployment(deployment).split(":"); - Commons.pullImage(image[0], image[1], K3S); - Commons.loadImage(image[0], image[1], "wiremock", K3S); - client.apps().deployments().inNamespace(NAMESPACE).resource(deployment).create(); - mockDeploymentName = deployment.getMetadata().getName(); - - Service service = client.services().load(getMockService()).get(); - mockServiceName = service.getMetadata().getName(); - client.services().inNamespace(NAMESPACE).resource(service).create(); - - Ingress ingress = client.network().v1().ingresses().load(getMockIngress()).get(); - mockIngressName = ingress.getMetadata().getName(); - - Fabric8Utils.waitForDeployment(client, "servicea-wiremock-deployment", NAMESPACE, 2, 600); - Fabric8Utils.waitForEndpoint(client, "servicea-wiremock", NAMESPACE, 2, 600); - - } - catch (Exception e) { - throw new RuntimeException(e); - } - - } - - private static InputStream getIngress() { - return Fabric8Utils.inputStream("spring-cloud-kubernetes-fabric8-client-loadbalancer-ingress.yaml"); - } - - private static InputStream getService() { - return Fabric8Utils.inputStream("spring-cloud-kubernetes-fabric8-client-loadbalancer-service.yaml"); - } - - private static InputStream getPodDeployment() { - return Fabric8Utils.inputStream("spring-cloud-kubernetes-fabric8-client-loadbalancer-pod-deployment.yaml"); - } - - private static InputStream getServiceDeployment() { - return Fabric8Utils.inputStream("spring-cloud-kubernetes-fabric8-client-loadbalancer-service-deployment.yaml"); - } - - private static InputStream getMockIngress() { - return Fabric8Utils.inputStream("wiremock/wiremock-ingress.yaml"); - } - - private static InputStream getMockService() { - return Fabric8Utils.inputStream("wiremock/wiremock-service.yaml"); - } - - private static InputStream getMockDeployment() { - return Fabric8Utils.inputStream("wiremock/wiremock-deployment.yaml"); - } - private WebClient.Builder builder() { return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create())); } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-pod-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-deployment.yaml similarity index 90% rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-pod-deployment.yaml rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-deployment.yaml index a3285b69..ab0e659d 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-pod-deployment.yaml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-deployment.yaml @@ -14,9 +14,6 @@ spec: serviceAccountName: spring-cloud-kubernetes-serviceaccount containers: - name: spring-cloud-kubernetes-fabric8-client-loadbalancer - env: - - name: SPRING_CLOUD_KUBERNETES_LOADBALANCER_MODE - value: POD image: docker.io/springcloud/spring-cloud-kubernetes-fabric8-client-loadbalancer imagePullPolicy: IfNotPresent readinessProbe: diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-service-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-service-deployment.yaml deleted file mode 100644 index 71d5120a..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-service-deployment.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: spring-cloud-kubernetes-fabric8-client-loadbalancer-deployment -spec: - selector: - matchLabels: - app: spring-cloud-kubernetes-fabric8-client-loadbalancer - template: - metadata: - labels: - app: spring-cloud-kubernetes-fabric8-client-loadbalancer - spec: - serviceAccountName: spring-cloud-kubernetes-serviceaccount - containers: - - name: spring-cloud-kubernetes-fabric8-client-loadbalancer - env: - - name: SPRING_CLOUD_KUBERNETES_LOADBALANCER_MODE - value: SERVICE - image: docker.io/springcloud/spring-cloud-kubernetes-fabric8-client-loadbalancer - imagePullPolicy: IfNotPresent - readinessProbe: - httpGet: - port: 8080 - path: /loadbalancer-it/actuator/health/readiness - livenessProbe: - httpGet: - port: 8080 - path: /loadbalancer-it/actuator/health/liveness - ports: - - containerPort: 8080 diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-deployment.yaml deleted file mode 100644 index 9d28eb62..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-deployment.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: servicea-wiremock-deployment -spec: - selector: - matchLabels: - app: servicea-wiremock - template: - metadata: - labels: - app: servicea-wiremock - spec: - containers: - - name: servicea-wiremock - image: wiremock/wiremock:2.32.0 - imagePullPolicy: IfNotPresent - readinessProbe: - httpGet: - port: 8080 - path: /__admin/mappings - livenessProbe: - httpGet: - port: 8080 - path: /__admin/mappings - ports: - - containerPort: 8080 diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-ingress.yaml deleted file mode 100644 index bd2d857a..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-ingress.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: wiremock-ingress - namespace: default -spec: - rules: - - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: servicea-wiremock - port: - number: 8080 - diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-service.yaml deleted file mode 100644 index ef30d58a..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: servicea-wiremock - name: servicea-wiremock -spec: - ports: - - name: http - port: 8080 - targetPort: 8080 - selector: - app: servicea-wiremock - type: ClusterIP diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsEventsReloadIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsEventsReloadIT.java index 4dc98054..e2dcaa38 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsEventsReloadIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsEventsReloadIT.java @@ -28,10 +28,7 @@ import io.fabric8.kubernetes.api.model.SecretBuilder; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.networking.v1.Ingress; -import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; -import io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperation; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -42,8 +39,8 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util; import org.springframework.http.HttpMethod; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; @@ -61,13 +58,7 @@ class SecretsEventsReloadIT { private static KubernetesClient client; - private static String deploymentName; - - private static String serviceName; - - private static String ingressName; - - private static String secretName; + private static Util util; private static final K3sContainer K3S = Commons.container(); @@ -76,19 +67,19 @@ class SecretsEventsReloadIT { K3S.start(); Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); - Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml()); - client = new KubernetesClientBuilder().withConfig(config).build(); - Fabric8Utils.setUp(client, NAMESPACE); - deployManifests(); + + util = new Util(K3S); + client = util.client(); + util.setUp(NAMESPACE); + manifests(Phase.CREATE); } @AfterAll static void after() throws Exception { - deleteManifests(); + manifests(Phase.DELETE); Commons.cleanUp(IMAGE_NAME, K3S); } - @SuppressWarnings({ "raw", "unchecked" }) @Test void test() { WebClient webClient = builder().baseUrl("localhost/key").build(); @@ -106,83 +97,36 @@ class SecretsEventsReloadIT { Base64.getEncoder().encodeToString("from.properties.key=after-change".getBytes()))) .build(); - // the weird cast comes from : - // https://github.com/fabric8io/kubernetes-client/issues/2445 - ((HasMetadataOperation) client.secrets().inNamespace("default").withName("event-reload")) - .createOrReplace(secret); + client.secrets().inNamespace("default").resource(secret).createOrReplace(); await().timeout(Duration.ofSeconds(120)).until(() -> webClient.method(HttpMethod.GET).retrieve() .bodyToMono(String.class).retryWhen(retrySpec()).block().equals("after-change")); } - private static void deleteManifests() { + private static void manifests(Phase phase) { - try { + InputStream deploymentStream = util.inputStream("deployment.yaml"); + InputStream serviceStream = util.inputStream("service.yaml"); + InputStream ingressStream = util.inputStream("ingress.yaml"); + InputStream secretStream = util.inputStream("secret.yaml"); - client.secrets().inNamespace(NAMESPACE).withName(secretName).delete(); - client.apps().deployments().inNamespace(NAMESPACE).withName(deploymentName).delete(); - client.services().inNamespace(NAMESPACE).withName(serviceName).delete(); - client.network().v1().ingresses().inNamespace(NAMESPACE).withName(ingressName).delete(); + Deployment deployment = client.apps().deployments().load(deploymentStream).get(); + Service service = client.services().load(serviceStream).get(); + Ingress ingress = client.network().v1().ingresses().load(ingressStream).get(); + Secret secret = client.secrets().load(secretStream).get(); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, secret); + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); } - catch (Exception e) { - throw new RuntimeException(e); + else { + util.deleteAndWait(NAMESPACE, null, secret); + util.deleteAndWait(NAMESPACE, deployment, service, ingress); } } - private static void deployManifests() { - - try { - - Secret configMap = client.secrets().load(getSecret()).get(); - secretName = configMap.getMetadata().getName(); - client.secrets().resource(configMap).create(); - - Deployment deployment = client.apps().deployments().load(getDeployment()).get(); - - String version = K8SUtils.getPomVersion(); - String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version); - - client.apps().deployments().inNamespace(NAMESPACE).resource(deployment).create(); - deploymentName = deployment.getMetadata().getName(); - - Service service = client.services().load(getService()).get(); - serviceName = service.getMetadata().getName(); - client.services().inNamespace(NAMESPACE).resource(service).create(); - - Ingress ingress = client.network().v1().ingresses().load(getIngress()).get(); - ingressName = ingress.getMetadata().getName(); - client.network().v1().ingresses().inNamespace(NAMESPACE).resource(ingress).create(); - - Fabric8Utils.waitForDeployment(client, - "spring-cloud-kubernetes-fabric8-client-secrets-deployment-event-reload", NAMESPACE, 2, 600); - - } - catch (Exception e) { - throw new RuntimeException(e); - } - - } - - private static InputStream getService() { - return Fabric8Utils.inputStream("service.yaml"); - } - - private static InputStream getDeployment() { - return Fabric8Utils.inputStream("deployment.yaml"); - } - - private static InputStream getIngress() { - return Fabric8Utils.inputStream("ingress.yaml"); - } - - private static InputStream getSecret() { - return Fabric8Utils.inputStream("secret.yaml"); - } - private WebClient.Builder builder() { return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create())); } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/src/test/java/org/springframework/cloud/kubernetes/fabric8/core/SimpleCoreIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/src/test/java/org/springframework/cloud/kubernetes/fabric8/core/SimpleCoreIT.java index ad698992..1f391f99 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/src/test/java/org/springframework/cloud/kubernetes/fabric8/core/SimpleCoreIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/src/test/java/org/springframework/cloud/kubernetes/fabric8/core/SimpleCoreIT.java @@ -23,9 +23,7 @@ import java.util.Objects; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.networking.v1.Ingress; -import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -36,8 +34,8 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util; import org.springframework.http.HttpMethod; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; @@ -53,11 +51,7 @@ class SimpleCoreIT { private static KubernetesClient client; - private static String deploymentName; - - private static String serviceName; - - private static String ingressName; + private static Util util; private static final K3sContainer K3S = Commons.container(); @@ -67,16 +61,16 @@ class SimpleCoreIT { Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); - Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml()); - client = new KubernetesClientBuilder().withConfig(config).build(); - Fabric8Utils.setUp(client, NAMESPACE); + util = new Util(K3S); + client = util.client(); + util.setUp(NAMESPACE); - deployManifests(); + manifests(Phase.CREATE); } @AfterAll static void after() throws Exception { - deleteManifests(); + manifests(Phase.DELETE); Commons.cleanUp(IMAGE_NAME, K3S); } @@ -91,64 +85,25 @@ class SimpleCoreIT { Assertions.assertEquals("Hello from k8s profile", result); } - private static void deleteManifests() { + private static void manifests(Phase phase) { - try { + InputStream deploymentStream = util.inputStream("simple-core-deployment.yaml"); + InputStream serviceStream = util.inputStream("simple-core-service.yaml"); + InputStream ingressStream = util.inputStream("simple-core-ingress.yaml"); - client.apps().deployments().inNamespace(NAMESPACE).withName(deploymentName).delete(); - client.services().inNamespace(NAMESPACE).withName(serviceName).delete(); - client.network().v1().ingresses().inNamespace(NAMESPACE).withName(ingressName).delete(); + Deployment deployment = client.apps().deployments().load(deploymentStream).get(); + Service service = client.services().load(serviceStream).get(); + Ingress ingress = client.network().v1().ingresses().load(ingressStream).get(); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); } - catch (Exception e) { - throw new RuntimeException(e); + else { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); } } - private static void deployManifests() { - - try { - - Deployment deployment = client.apps().deployments().load(getDeployment()).get(); - - String version = K8SUtils.getPomVersion(); - String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version); - - client.apps().deployments().inNamespace(NAMESPACE).resource(deployment).create(); - deploymentName = deployment.getMetadata().getName(); - - Service service = client.services().load(getService()).get(); - serviceName = service.getMetadata().getName(); - client.services().inNamespace(NAMESPACE).resource(service).create(); - - Ingress ingress = client.network().v1().ingresses().load(getIngress()).get(); - ingressName = ingress.getMetadata().getName(); - client.network().v1().ingresses().inNamespace(NAMESPACE).resource(ingress).create(); - - Fabric8Utils.waitForDeployment(client, "spring-cloud-kubernetes-fabric8-client-simple-core-deployment", - NAMESPACE, 2, 600); - - } - catch (Exception e) { - throw new RuntimeException(e); - } - - } - - private static InputStream getService() { - return Fabric8Utils.inputStream("simple-core-service.yaml"); - } - - private static InputStream getDeployment() { - return Fabric8Utils.inputStream("simple-core-deployment.yaml"); - } - - private static InputStream getIngress() { - return Fabric8Utils.inputStream("simple-core-ingress.yaml"); - } - private WebClient.Builder builder() { return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create())); } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/Fabric8IstioIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/Fabric8IstioIT.java index 83364f33..708df47e 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/Fabric8IstioIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/Fabric8IstioIT.java @@ -25,9 +25,7 @@ import java.util.Objects; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.networking.v1.Ingress; -import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -38,8 +36,8 @@ import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils; -import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils; +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; +import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util; import org.springframework.http.HttpMethod; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; @@ -67,11 +65,7 @@ class Fabric8IstioIT { private static KubernetesClient client; - private static String deploymentName; - - private static String serviceName; - - private static String ingressName; + private static Util util; private static K3sContainer K3S; @@ -81,6 +75,8 @@ class Fabric8IstioIT { String absolutePath = new File(LOCAL_ISTIO_BIN_PATH).getAbsolutePath(); K3S = Commons.container().withFileSystemBind(absolutePath, CONTAINER_ISTIO_BIN_PATH); K3S.start(); + util = new Util(K3S); + client = util.client(); Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); @@ -93,21 +89,12 @@ class Fabric8IstioIT { processExecResult( K3S.execInContainer("sh", "-c", "kubectl label namespace istio-test istio-injection=enabled")); - // for Mac M1 with aarch64 - if (System.getProperty("os.arch").equals("aarch64")) { - processExecResult(K3S.execInContainer("sh", "-c", CONTAINER_ISTIO_BIN_PATH + "istioctl" - + " --kubeconfig=/etc/rancher/k3s/k3s.yaml install --set hub=docker.io/querycapistio --set profile=minimal -y")); - } - else { - processExecResult(K3S.execInContainer("sh", "-c", CONTAINER_ISTIO_BIN_PATH + "istioctl" - + " --kubeconfig=/etc/rancher/k3s/k3s.yaml install --set profile=minimal -y")); - } + processExecResult(K3S.execInContainer("sh", "-c", CONTAINER_ISTIO_BIN_PATH + "istioctl" + + " --kubeconfig=/etc/rancher/k3s/k3s.yaml install --set profile=minimal -y")); - Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml()); - client = new KubernetesClientBuilder().withConfig(config).build(); - Fabric8Utils.setUpIstio(client, NAMESPACE); + util.setUpIstio(NAMESPACE); - deployManifests(); + manifests(Phase.CREATE); } @AfterAll @@ -117,7 +104,7 @@ class Fabric8IstioIT { @AfterAll static void after() { - deleteManifests(); + manifests(Phase.DELETE); } @Test @@ -132,67 +119,25 @@ class Fabric8IstioIT { Assertions.assertTrue(result.contains("istio")); } - private static void deleteManifests() { + private static void manifests(Phase phase) { - try { + InputStream deploymentStream = util.inputStream("istio-deployment.yaml"); + InputStream serviceStream = util.inputStream("istio-service.yaml"); + InputStream ingressStream = util.inputStream("istio-ingress.yaml"); - client.apps().deployments().inNamespace(NAMESPACE).withName(deploymentName).delete(); - client.services().inNamespace(NAMESPACE).withName(serviceName).delete(); - client.network().v1().ingresses().inNamespace(NAMESPACE).withName(ingressName).delete(); + Deployment deployment = client.apps().deployments().load(deploymentStream).get(); + Service service = client.services().load(serviceStream).get(); + Ingress ingress = client.network().v1().ingresses().load(ingressStream).get(); + if (phase.equals(Phase.CREATE)) { + util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); } - catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(e); + else { + util.deleteAndWait(NAMESPACE, deployment, service, ingress); } } - private static void deployManifests() { - - try { - - Deployment deployment = client.apps().deployments().load(getDeployment()).get(); - - String version = K8SUtils.getPomVersion(); - String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version); - - client.apps().deployments().inNamespace(NAMESPACE).resource(deployment).create(); - deploymentName = deployment.getMetadata().getName(); - - Service service = client.services().load(getService()).get(); - serviceName = service.getMetadata().getName(); - client.services().inNamespace(NAMESPACE).resource(service).create(); - - Ingress ingress = client.network().v1().ingresses().load(getIngress()).get(); - ingressName = ingress.getMetadata().getName(); - client.network().v1().ingresses().inNamespace(NAMESPACE).resource(ingress).create(); - - Fabric8Utils.waitForIngress(client, ingressName, NAMESPACE); - Fabric8Utils.waitForDeployment(client, "spring-cloud-kubernetes-fabric8-istio-it-deployment", NAMESPACE, 2, - 600); - - } - catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - - } - - private static InputStream getService() { - return Fabric8Utils.inputStream("istio-service.yaml"); - } - - private static InputStream getDeployment() { - return Fabric8Utils.inputStream("istio-deployment.yaml"); - } - - private static InputStream getIngress() { - return Fabric8Utils.inputStream("istio-ingress.yaml"); - } - private WebClient.Builder builder() { return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create())); } diff --git a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Commons.java b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Commons.java index de1b05fa..37c4bed6 100644 --- a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Commons.java +++ b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Commons.java @@ -17,7 +17,9 @@ package org.springframework.cloud.kubernetes.integration.tests.commons; import java.io.File; +import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -32,7 +34,10 @@ import org.testcontainers.containers.Container; import org.testcontainers.k3s.K3sContainer; import org.testcontainers.utility.DockerImageName; -import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion; +import org.springframework.core.io.ClassPathResource; +import org.springframework.util.ReflectionUtils; +import org.springframework.util.StreamUtils; +import org.springframework.util.StringUtils; /** * A few commons things that can be re-used across clients. This is meant to be used for @@ -46,6 +51,8 @@ public final class Commons { throw new AssertionError("No instance provided"); } + private static final String KUBERNETES_VERSION_FILE = "META-INF/springcloudkubernetes-version.txt"; + /** * Rancher version to use for test-containers. */ @@ -76,7 +83,7 @@ public final class Commons { } public static void loadSpringCloudKubernetesImage(String project, K3sContainer container) throws Exception { - loadImage("springcloud/" + project, getPomVersion(), project, container); + loadImage("springcloud/" + project, pomVersion(), project, container); } public static void loadImage(String image, String tag, String tarName, K3sContainer container) throws Exception { @@ -95,7 +102,7 @@ public final class Commons { } public static void cleanUp(String image, K3sContainer container) throws Exception { - container.execInContainer("crictl", "rmi", "docker.io/springcloud/" + image + ":" + getPomVersion()); + container.execInContainer("crictl", "rmi", "docker.io/springcloud/" + image + ":" + pomVersion()); container.execInContainer("rm", TEMP_FOLDER + "/" + image + ".tar"); } @@ -132,6 +139,21 @@ public final class Commons { return execResult.getStdout(); } + public static String pomVersion() { + try (InputStream in = new ClassPathResource(KUBERNETES_VERSION_FILE).getInputStream()) { + String version = StreamUtils.copyToString(in, StandardCharsets.UTF_8); + if (StringUtils.hasText(version)) { + version = version.trim(); + } + return version; + } + catch (IOException e) { + ReflectionUtils.rethrowRuntimeException(e); + } + // not reachable since exception rethrown at runtime + return null; + } + /** * A K3sContainer, but with fixed port mappings. This is needed because of the nature * of some integration tests. diff --git a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Fabric8Utils.java b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Fabric8Utils.java deleted file mode 100644 index e1afee53..00000000 --- a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Fabric8Utils.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * 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.integration.tests.commons; - -import java.io.InputStream; -import java.time.Duration; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import io.fabric8.kubernetes.api.model.ConfigMap; -import io.fabric8.kubernetes.api.model.Endpoints; -import io.fabric8.kubernetes.api.model.LoadBalancerIngress; -import io.fabric8.kubernetes.api.model.Namespace; -import io.fabric8.kubernetes.api.model.Pod; -import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.api.model.ServiceAccount; -import io.fabric8.kubernetes.api.model.apps.Deployment; -import io.fabric8.kubernetes.api.model.networking.v1.Ingress; -import io.fabric8.kubernetes.api.model.rbac.ClusterRole; -import io.fabric8.kubernetes.api.model.rbac.Role; -import io.fabric8.kubernetes.api.model.rbac.RoleBinding; -import io.fabric8.kubernetes.client.KubernetesClient; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import static org.awaitility.Awaitility.await; -import static org.junit.Assert.fail; - -/** - * @author wind57 - */ -public final class Fabric8Utils { - - private static final Log LOG = LogFactory.getLog(Fabric8Utils.class); - - private Fabric8Utils() { - throw new AssertionError("no instance provided"); - } - - public static InputStream inputStream(String fileName) { - return Fabric8Utils.class.getClassLoader().getResourceAsStream(fileName); - } - - public static void waitForDeployment(KubernetesClient client, String deploymentName, String namespace, - int pollSeconds, int maxSeconds) { - await().pollInterval(Duration.ofSeconds(pollSeconds)).atMost(maxSeconds, TimeUnit.SECONDS) - .until(() -> isDeploymentReady(client, deploymentName, namespace)); - } - - public static void waitForEndpoint(KubernetesClient client, String endpointName, String namespace, int pollSeconds, - int maxSeconds) { - await().pollInterval(Duration.ofSeconds(pollSeconds)).atMost(maxSeconds, TimeUnit.SECONDS) - .until(() -> isEndpointReady(client, endpointName, namespace)); - } - - private static boolean isDeploymentReady(KubernetesClient client, String deploymentName, String namespace) { - - Deployment deployment = client.apps().deployments().inNamespace(namespace).withName(deploymentName).get(); - - Integer availableReplicas = deployment.getStatus().getAvailableReplicas(); - LOG.info("Available replicas for " + deploymentName + ": " + ((availableReplicas == null) ? 0 : 1)); - return availableReplicas != null && availableReplicas >= 1; - } - - private static boolean isEndpointReady(KubernetesClient client, String endpointName, String namespace) { - - Endpoints endpoint = client.endpoints().inNamespace(namespace).withName(endpointName).get(); - - if (endpoint.getSubsets().isEmpty()) { - fail("no endpoints for " + endpointName); - } - - return endpoint.getSubsets().get(0).getAddresses().size() >= 1; - } - - public static void setUp(KubernetesClient client, String namespace) throws Exception { - InputStream serviceAccountAsStream = inputStream("setup/service-account.yaml"); - InputStream roleBindingAsStream = inputStream("setup/role-binding.yaml"); - InputStream roleAsStream = inputStream("setup/role.yaml"); - - innerSetup(client, namespace, serviceAccountAsStream, roleBindingAsStream, roleAsStream); - } - - public static void setUpClusterWide(KubernetesClient client, String serviceAccountNamespace, - Set namespaces) { - InputStream clusterRoleBindingAsStream = inputStream("cluster/cluster-role.yaml"); - InputStream serviceAccountAsStream = inputStream("cluster/service-account.yaml"); - InputStream roleBindingAsStream = inputStream("cluster/role-binding.yaml"); - - ClusterRole clusterRole = client.rbac().clusterRoles().load(clusterRoleBindingAsStream).get(); - if (client.rbac().clusterRoles().withName(clusterRole.getMetadata().getName()).get() == null) { - client.rbac().clusterRoles().resource(clusterRole).create(); - } - - ServiceAccount serviceAccountFromStream = client.serviceAccounts().load(serviceAccountAsStream).get(); - serviceAccountFromStream.getMetadata().setNamespace(serviceAccountNamespace); - if (client.serviceAccounts().inNamespace(serviceAccountNamespace) - .withName(serviceAccountFromStream.getMetadata().getName()).get() == null) { - client.serviceAccounts().inNamespace(serviceAccountNamespace).resource(serviceAccountFromStream).create(); - } - - RoleBinding roleBindingFromStream = client.rbac().roleBindings().load(roleBindingAsStream).get(); - namespaces.forEach(namespace -> { - roleBindingFromStream.getMetadata().setNamespace(namespace); - - if (client.rbac().roleBindings().inNamespace(namespace) - .withName(roleBindingFromStream.getMetadata().getName()).get() == null) { - client.rbac().roleBindings().inNamespace(namespace).resource(roleBindingFromStream).create(); - } - }); - - } - - public static void cleanUpClusterWide(KubernetesClient client, String serviceAccountNamespace, - Set namespaces) { - - InputStream clusterRoleBindingAsStream = inputStream("cluster/cluster-role.yaml"); - InputStream serviceAccountAsStream = inputStream("cluster/service-account.yaml"); - InputStream roleBindingAsStream = inputStream("cluster/role-binding.yaml"); - - ClusterRole clusterRole = client.rbac().clusterRoles().load(clusterRoleBindingAsStream).get(); - client.rbac().clusterRoles().withName(clusterRole.getMetadata().getName()).delete(); - - await().pollInterval(Duration.ofSeconds(1)).atMost(30, TimeUnit.SECONDS).until(() -> { - ClusterRole innerClusterRole = client.rbac().clusterRoles().withName(clusterRole.getMetadata().getName()) - .get(); - return innerClusterRole == null; - }); - - ServiceAccount serviceAccount = client.serviceAccounts().load(serviceAccountAsStream).get(); - client.serviceAccounts().inNamespace(serviceAccountNamespace).withName(serviceAccount.getMetadata().getName()) - .delete(); - await().pollInterval(Duration.ofSeconds(1)).atMost(30, TimeUnit.SECONDS).until(() -> { - ServiceAccount innerServiceAccount = client.serviceAccounts().inNamespace(serviceAccountNamespace) - .withName(serviceAccount.getMetadata().getName()).get(); - return innerServiceAccount == null; - }); - - RoleBinding roleBinding = client.rbac().roleBindings().load(roleBindingAsStream).get(); - namespaces.forEach(namespace -> { - client.rbac().roleBindings().inNamespace(namespace).withName(roleBinding.getMetadata().getName()).delete(); - - await().pollInterval(Duration.ofSeconds(1)).atMost(30, TimeUnit.SECONDS).until(() -> { - RoleBinding innerRoleBinding = client.rbac().roleBindings().inNamespace(namespace) - .withName(roleBinding.getMetadata().getName()).get(); - return innerRoleBinding == null; - }); - }); - - } - - public static void setUpIstio(KubernetesClient client, String namespace) { - InputStream serviceAccountAsStream = inputStream("istio/service-account.yaml"); - InputStream roleBindingAsStream = inputStream("istio/role-binding.yaml"); - InputStream roleAsStream = inputStream("istio/role.yaml"); - - innerSetup(client, namespace, serviceAccountAsStream, roleBindingAsStream, roleAsStream); - } - - public static void waitForIngress(KubernetesClient client, String ingressName, String namespace) { - - try { - await().pollInterval(Duration.ofSeconds(2)).atMost(180, TimeUnit.SECONDS).until(() -> { - Ingress ingress = client.network().v1().ingresses().inNamespace(namespace).withName(ingressName).get(); - - if (ingress == null) { - System.out.println("ingress : " + ingressName + " not ready yet present"); - return false; - } - - List loadBalancerIngress = ingress.getStatus().getLoadBalancer().getIngress(); - if (loadBalancerIngress == null || loadBalancerIngress.isEmpty()) { - System.out.println( - "ingress : " + ingressName + " not ready yet (loadbalancer ingress not yet present)"); - return false; - } - - String ip = loadBalancerIngress.get(0).getIp(); - if (ip == null) { - System.out.println("ingress : " + ingressName + " not ready yet"); - return false; - } - - System.out.println("ingress : " + ingressName + " ready with ip : " + ip); - return true; - - }); - } - catch (Exception e) { - System.out.println("Error waiting for ingress"); - e.printStackTrace(); - } - - } - - public static void waitForConfigMapDelete(KubernetesClient client, String namespace, String name) { - await().pollInterval(Duration.ofSeconds(1)).atMost(30, TimeUnit.SECONDS).until(() -> { - ConfigMap configMap = client.configMaps().inNamespace(namespace).withName(name).get(); - return configMap == null; - }); - } - - /** - * delete a deployment and every pod by spec.select.matchLabels, waits until - * everything is deleted. - */ - public static void deleteDeployment(KubernetesClient client, String namespace, String name) { - - Deployment deployment = client.apps().deployments().inNamespace(namespace).withName(name).get(); - Map matchLabels = deployment.getSpec().getSelector().getMatchLabels(); - - client.apps().deployments().inNamespace(namespace).resource(deployment).delete(); - - await().pollInterval(Duration.ofSeconds(1)).atMost(30, TimeUnit.SECONDS).until(() -> { - Deployment inner = client.apps().deployments().inNamespace(namespace).withName(name).get(); - return inner == null; - }); - - await().pollInterval(Duration.ofSeconds(1)).atMost(60, TimeUnit.SECONDS).until(() -> { - List podList = client.pods().inNamespace(namespace).withLabels(matchLabels).list().getItems(); - return podList == null || podList.isEmpty(); - }); - - } - - /** - * delete the service and wait for it to be deleted. - */ - public static void deleteService(KubernetesClient client, String namespace, String name) { - - client.services().inNamespace(namespace).withName(name).delete(); - - await().pollInterval(Duration.ofSeconds(1)).atMost(30, TimeUnit.SECONDS).until(() -> { - Service service = client.services().inNamespace(namespace).withName(name).get(); - return service == null; - }); - } - - /** - * delete ingress and wait for it to be deleted. - */ - public static void deleteIngress(KubernetesClient client, String namespace, String name) { - client.network().v1().ingresses().inNamespace(namespace).withName(name).delete(); - - await().pollInterval(Duration.ofSeconds(1)).atMost(30, TimeUnit.SECONDS).until(() -> { - Ingress ingress = client.network().v1().ingresses().inNamespace(namespace).withName(name).get(); - return ingress == null; - }); - } - - public static void deleteNamespace(KubernetesClient client, String name) { - client.namespaces().withName(name).delete(); - - await().pollInterval(Duration.ofSeconds(1)).atMost(30, TimeUnit.SECONDS).until(() -> { - Namespace namespace = client.namespaces().withName(name).get(); - return namespace == null; - }); - } - - private static void innerSetup(KubernetesClient client, String namespace, InputStream serviceAccountAsStream, - InputStream roleBindingAsStream, InputStream roleAsStream) { - ServiceAccount serviceAccountFromStream = client.serviceAccounts().load(serviceAccountAsStream).get(); - if (client.serviceAccounts().inNamespace(namespace).withName(serviceAccountFromStream.getMetadata().getName()) - .get() == null) { - client.serviceAccounts().inNamespace(namespace).resource(serviceAccountFromStream).create(); - } - - RoleBinding roleBindingFromStream = client.rbac().roleBindings().load(roleBindingAsStream).get(); - if (client.rbac().roleBindings().inNamespace(namespace).withName(roleBindingFromStream.getMetadata().getName()) - .get() == null) { - client.rbac().roleBindings().inNamespace(namespace).resource(roleBindingFromStream).create(); - } - - Role roleFromStream = client.rbac().roles().load(roleAsStream).get(); - if (client.rbac().roles().inNamespace(namespace).withName(roleFromStream.getMetadata().getName()) - .get() == null) { - client.rbac().roles().inNamespace(namespace).resource(roleFromStream).create(); - } - } - -} diff --git a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Phase.java b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Phase.java new file mode 100644 index 00000000..fe872a49 --- /dev/null +++ b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Phase.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013-2022 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.integration.tests.commons; + +/** + * @author wind57 + */ +public enum Phase { + + /** + * Apply the manifests. + */ + CREATE, + + /** + * Deleted the manifests. + */ + DELETE + +} diff --git a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/fabric8_client/Util.java b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/fabric8_client/Util.java new file mode 100644 index 00000000..5e2469d8 --- /dev/null +++ b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/fabric8_client/Util.java @@ -0,0 +1,400 @@ +/* + * Copyright 2013-2022 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.integration.tests.commons.fabric8_client; + +import java.io.InputStream; +import java.time.Duration; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.fabric8.kubernetes.api.model.LoadBalancerIngress; +import io.fabric8.kubernetes.api.model.NamespaceBuilder; +import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.api.model.Secret; +import io.fabric8.kubernetes.api.model.Service; +import io.fabric8.kubernetes.api.model.ServiceAccount; +import io.fabric8.kubernetes.api.model.apps.Deployment; +import io.fabric8.kubernetes.api.model.networking.v1.Ingress; +import io.fabric8.kubernetes.api.model.rbac.ClusterRole; +import io.fabric8.kubernetes.api.model.rbac.Role; +import io.fabric8.kubernetes.api.model.rbac.RoleBinding; +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientBuilder; +import jakarta.annotation.Nullable; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.testcontainers.k3s.K3sContainer; + +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; + +import static org.awaitility.Awaitility.await; +import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.loadImage; +import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.pomVersion; +import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.pullImage; + +/** + * @author wind57 + */ +public final class Util { + + private static final Log LOG = LogFactory.getLog(Util.class); + + private final K3sContainer container; + + private final KubernetesClient client; + + public Util(K3sContainer container) { + this.container = container; + this.client = new KubernetesClientBuilder().withConfig(Config.fromKubeconfig(container.getKubeConfigYaml())) + .build(); + } + + /** + * This is the preferred method to use when creating a deployment alongside with a + * service. It creates the given resources as-well as waits for them to be created. + * The delay check is intentionally not taken as an argument, so that it stays as + * tight as possible, providing reasonable defaults. + * + */ + public void createAndWait(String namespace, String name, Deployment deployment, Service service, + @Nullable Ingress ingress, boolean changeVersion) { + try { + + String imageFromDeployment = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); + if (changeVersion) { + deployment.getSpec().getTemplate().getSpec().getContainers().get(0) + .setImage(imageFromDeployment + ":" + pomVersion()); + } + else { + String[] image = imageFromDeployment.split(":", 2); + pullImage(image[0], image[1], container); + loadImage(image[0], image[1], name, container); + } + + client.apps().deployments().inNamespace(namespace).resource(deployment).create(); + client.services().inNamespace(namespace).resource(service).create(); + waitForDeployment(namespace, deployment); + if (ingress != null) { + client.network().v1().ingresses().inNamespace(namespace).resource(ingress).create(); + waitForIngress(namespace, ingress); + } + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void busybox(String namespace, Phase phase) { + InputStream deploymentStream = inputStream("busybox/deployment.yaml"); + InputStream serviceStream = inputStream("busybox/service.yaml"); + Deployment deployment = client.apps().deployments().load(deploymentStream).get(); + Service service = client.services().load(serviceStream).get(); + + if (phase.equals(Phase.CREATE)) { + createAndWait(namespace, "busybox", deployment, service, null, false); + } + else if (phase.equals(Phase.DELETE)) { + deleteAndWait(namespace, deployment, service, null); + } + } + + public void deleteAndWait(String namespace, Deployment deployment, Service service, @Nullable Ingress ingress) { + try { + client.apps().deployments().inNamespace(namespace).resource(deployment).delete(); + client.services().inNamespace(namespace).resource(service).delete(); + waitForDeploymentToBeDeleted(namespace, deployment); + + if (ingress != null) { + client.network().v1().ingresses().inNamespace(namespace).resource(ingress).delete(); + waitForIngressToBeDeleted(namespace, ingress); + } + + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void setUp(String namespace) throws Exception { + InputStream serviceAccountAsStream = inputStream("setup/service-account.yaml"); + InputStream roleBindingAsStream = inputStream("setup/role-binding.yaml"); + InputStream roleAsStream = inputStream("setup/role.yaml"); + + innerSetup(namespace, serviceAccountAsStream, roleBindingAsStream, roleAsStream); + } + + public InputStream inputStream(String fileName) { + return Util.class.getClassLoader().getResourceAsStream(fileName); + } + + public void createNamespace(String name) { + try { + client.namespaces().resource(new NamespaceBuilder().withNewMetadata().withName(name).and().build()) + .create(); + + await().pollInterval(Duration.ofSeconds(1)).atMost(30, TimeUnit.SECONDS).until(() -> client.namespaces() + .list().getItems().stream().anyMatch(x -> x.getMetadata().getName().equals(name))); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void deleteNamespace(String name) { + try { + client.namespaces().resource(new NamespaceBuilder().withNewMetadata().withName(name).and().build()) + .delete(); + + await().pollInterval(Duration.ofSeconds(1)).atMost(30, TimeUnit.SECONDS).until(() -> client.namespaces() + .list().getItems().stream().noneMatch(x -> x.getMetadata().getName().equals(name))); + } + catch (Exception e) { + throw new RuntimeException(e); + } + + } + + public void setUpClusterWide(String serviceAccountNamespace, Set namespaces) { + InputStream clusterRoleBindingAsStream = inputStream("cluster/cluster-role.yaml"); + InputStream serviceAccountAsStream = inputStream("cluster/service-account.yaml"); + InputStream roleBindingAsStream = inputStream("cluster/role-binding.yaml"); + + ClusterRole clusterRole = client.rbac().clusterRoles().load(clusterRoleBindingAsStream).get(); + if (client.rbac().clusterRoles().withName(clusterRole.getMetadata().getName()).get() == null) { + client.rbac().clusterRoles().resource(clusterRole).create(); + } + + ServiceAccount serviceAccountFromStream = client.serviceAccounts().load(serviceAccountAsStream).get(); + serviceAccountFromStream.getMetadata().setNamespace(serviceAccountNamespace); + if (client.serviceAccounts().inNamespace(serviceAccountNamespace) + .withName(serviceAccountFromStream.getMetadata().getName()).get() == null) { + client.serviceAccounts().inNamespace(serviceAccountNamespace).resource(serviceAccountFromStream).create(); + } + + RoleBinding roleBindingFromStream = client.rbac().roleBindings().load(roleBindingAsStream).get(); + namespaces.forEach(namespace -> { + roleBindingFromStream.getMetadata().setNamespace(namespace); + + if (client.rbac().roleBindings().inNamespace(namespace) + .withName(roleBindingFromStream.getMetadata().getName()).get() == null) { + client.rbac().roleBindings().inNamespace(namespace).resource(roleBindingFromStream).create(); + } + }); + + } + + public void createAndWait(String namespace, @Nullable ConfigMap configMap, @Nullable Secret secret) { + if (configMap != null) { + client.configMaps().resource(configMap).create(); + waitForConfigMap(namespace, configMap, Phase.CREATE); + } + + if (secret != null) { + client.secrets().resource(secret).create(); + waitForSecret(namespace, secret, Phase.CREATE); + } + } + + public void deleteAndWait(String namespace, @Nullable ConfigMap configMap, @Nullable Secret secret) { + if (configMap != null) { + client.configMaps().resource(configMap).delete(); + waitForConfigMap(namespace, configMap, Phase.DELETE); + } + + if (secret != null) { + client.secrets().resource(secret).delete(); + waitForSecret(namespace, secret, Phase.DELETE); + } + } + + public void setUpIstio(String namespace) { + InputStream serviceAccountAsStream = inputStream("istio/service-account.yaml"); + InputStream roleBindingAsStream = inputStream("istio/role-binding.yaml"); + InputStream roleAsStream = inputStream("istio/role.yaml"); + + innerSetup(namespace, serviceAccountAsStream, roleBindingAsStream, roleAsStream); + } + + private void waitForConfigMap(String namespace, ConfigMap configMap, Phase phase) { + String configMapName = configMapName(configMap); + await().pollInterval(Duration.ofSeconds(1)).atMost(600, TimeUnit.SECONDS).until(() -> { + int size = (int) client.configMaps().inNamespace(namespace).list().getItems().stream() + .filter(x -> x.getMetadata().getName().equals(configMapName)).count(); + if (size == 0) { + return !phase.equals(Phase.CREATE); + } + return phase.equals(Phase.CREATE); + }); + } + + public void wiremock(String namespace, String path, Phase phase) { + InputStream deploymentStream = inputStream("wiremock/wiremock-deployment.yaml"); + InputStream serviceStream = inputStream("wiremock/wiremock-service.yaml"); + InputStream ingressStream = inputStream("wiremock/wiremock-ingress.yaml"); + + Deployment deployment = client.apps().deployments().load(deploymentStream).get(); + Service service = client.services().load(serviceStream).get(); + Ingress ingress = client.network().v1().ingresses().load(ingressStream).get(); + + if (phase.equals(Phase.CREATE)) { + deployment.getMetadata().setNamespace(namespace); + service.getMetadata().setNamespace(namespace); + ingress.getMetadata().setNamespace(namespace); + ingress.getSpec().getRules().get(0).getHttp().getPaths().get(0).setPath(path); + createAndWait(namespace, "wiremock", deployment, service, ingress, false); + } + else { + deleteAndWait(namespace, deployment, service, ingress); + } + + } + + private void waitForSecret(String namespace, Secret secret, Phase phase) { + String secretName = secretName(secret); + await().pollInterval(Duration.ofSeconds(1)).atMost(600, TimeUnit.SECONDS).until(() -> { + int size = (int) client.secrets().inNamespace(namespace).list().getItems().stream() + .filter(x -> x.getMetadata().getName().equals(secretName)).count(); + if (size == 0) { + return !phase.equals(Phase.CREATE); + } + return phase.equals(Phase.CREATE); + }); + } + + private void waitForIngressToBeDeleted(String namespace, Ingress ingress) { + String ingressName = ingressName(ingress); + await().pollInterval(Duration.ofSeconds(1)).atMost(30, TimeUnit.SECONDS).until(() -> { + Ingress inner = client.network().v1().ingresses().inNamespace(namespace).withName(ingressName).get(); + return inner == null; + }); + } + + private void waitForDeploymentToBeDeleted(String namespace, Deployment deployment) { + + String deploymentName = deploymentName(deployment); + + Map matchLabels = deployment.getSpec().getSelector().getMatchLabels(); + + await().pollInterval(Duration.ofSeconds(1)).atMost(30, TimeUnit.SECONDS).until(() -> { + Deployment inner = client.apps().deployments().inNamespace(namespace).withName(deploymentName).get(); + return inner == null; + }); + + await().pollInterval(Duration.ofSeconds(1)).atMost(60, TimeUnit.SECONDS).until(() -> { + List podList = client.pods().inNamespace(namespace).withLabels(matchLabels).list().getItems(); + return podList == null || podList.isEmpty(); + }); + } + + private void waitForDeployment(String namespace, Deployment deployment) { + String deploymentName = deploymentName(deployment); + await().pollInterval(Duration.ofSeconds(2)).atMost(600, TimeUnit.SECONDS) + .until(() -> isDeploymentReady(namespace, deploymentName)); + } + + private boolean isDeploymentReady(String namespace, String deploymentName) { + + Deployment deployment = client.apps().deployments().inNamespace(namespace).withName(deploymentName).get(); + + Integer availableReplicas = deployment.getStatus().getAvailableReplicas(); + LOG.info("Available replicas for " + deploymentName + ": " + ((availableReplicas == null) ? 0 : 1)); + return availableReplicas != null && availableReplicas >= 1; + } + + public void waitForIngress(String namespace, Ingress ingress) { + + String ingressName = ingressName(ingress); + + try { + await().pollInterval(Duration.ofSeconds(2)).atMost(180, TimeUnit.SECONDS).until(() -> { + Ingress inner = client.network().v1().ingresses().inNamespace(namespace).withName(ingressName).get(); + + if (inner == null) { + LOG.info("ingress : " + ingressName + " not ready yet present"); + return false; + } + + List loadBalancerIngress = inner.getStatus().getLoadBalancer().getIngress(); + if (loadBalancerIngress == null || loadBalancerIngress.isEmpty()) { + LOG.info("ingress : " + ingressName + " not ready yet (loadbalancer ingress not yet present)"); + return false; + } + + String ip = loadBalancerIngress.get(0).getIp(); + if (ip == null) { + LOG.info("ingress : " + ingressName + " not ready yet"); + return false; + } + + LOG.info("ingress : " + ingressName + " ready with ip : " + ip); + return true; + + }); + } + catch (Exception e) { + LOG.error("Error waiting for ingress"); + e.printStackTrace(); + } + + } + + private void innerSetup(String namespace, InputStream serviceAccountAsStream, InputStream roleBindingAsStream, + InputStream roleAsStream) { + ServiceAccount serviceAccountFromStream = client.serviceAccounts().load(serviceAccountAsStream).get(); + if (client.serviceAccounts().inNamespace(namespace).withName(serviceAccountFromStream.getMetadata().getName()) + .get() == null) { + client.serviceAccounts().inNamespace(namespace).resource(serviceAccountFromStream).create(); + } + + RoleBinding roleBindingFromStream = client.rbac().roleBindings().load(roleBindingAsStream).get(); + if (client.rbac().roleBindings().inNamespace(namespace).withName(roleBindingFromStream.getMetadata().getName()) + .get() == null) { + client.rbac().roleBindings().inNamespace(namespace).resource(roleBindingFromStream).create(); + } + + Role roleFromStream = client.rbac().roles().load(roleAsStream).get(); + if (client.rbac().roles().inNamespace(namespace).withName(roleFromStream.getMetadata().getName()) + .get() == null) { + client.rbac().roles().inNamespace(namespace).resource(roleFromStream).create(); + } + } + + private String deploymentName(Deployment deployment) { + return deployment.getMetadata().getName(); + } + + private String ingressName(Ingress ingress) { + return ingress.getMetadata().getName(); + } + + private String configMapName(ConfigMap configMap) { + return configMap.getMetadata().getName(); + } + + private String secretName(Secret secret) { + return secret.getMetadata().getName(); + } + + public KubernetesClient client() { + return client; + } + +} diff --git a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/native_client/Util.java b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/native_client/Util.java new file mode 100644 index 00000000..326bbdad --- /dev/null +++ b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/native_client/Util.java @@ -0,0 +1,517 @@ +/* + * Copyright 2013-2022 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.integration.tests.commons.native_client; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.net.HttpURLConnection; +import java.time.Duration; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import io.kubernetes.client.openapi.ApiClient; +import io.kubernetes.client.openapi.ApiException; +import io.kubernetes.client.openapi.Configuration; +import io.kubernetes.client.openapi.apis.AppsV1Api; +import io.kubernetes.client.openapi.apis.CoreV1Api; +import io.kubernetes.client.openapi.apis.NetworkingV1Api; +import io.kubernetes.client.openapi.apis.RbacAuthorizationV1Api; +import io.kubernetes.client.openapi.models.V1ClusterRole; +import io.kubernetes.client.openapi.models.V1ConfigMap; +import io.kubernetes.client.openapi.models.V1Deployment; +import io.kubernetes.client.openapi.models.V1DeploymentList; +import io.kubernetes.client.openapi.models.V1Ingress; +import io.kubernetes.client.openapi.models.V1LoadBalancerIngress; +import io.kubernetes.client.openapi.models.V1LoadBalancerStatus; +import io.kubernetes.client.openapi.models.V1NamespaceBuilder; +import io.kubernetes.client.openapi.models.V1Role; +import io.kubernetes.client.openapi.models.V1RoleBinding; +import io.kubernetes.client.openapi.models.V1Secret; +import io.kubernetes.client.openapi.models.V1Service; +import io.kubernetes.client.openapi.models.V1ServiceAccount; +import io.kubernetes.client.util.Config; +import io.kubernetes.client.util.Yaml; +import jakarta.annotation.Nullable; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.testcontainers.k3s.K3sContainer; + +import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; + +import static org.awaitility.Awaitility.await; +import static org.junit.Assert.fail; +import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.loadImage; +import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.pomVersion; +import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.pullImage; + +/** + * @author wind57 + */ +public final class Util { + + private static final Log LOG = LogFactory.getLog(Util.class); + + private final CoreV1Api coreV1Api; + + private final AppsV1Api appsV1Api; + + private final NetworkingV1Api networkingV1Api; + + private final RbacAuthorizationV1Api rbacApi; + + private final K3sContainer container; + + public Util(K3sContainer container) { + + ApiClient client; + try { + client = Config.fromConfig(new StringReader(container.getKubeConfigYaml())); + } + catch (IOException e) { + throw new RuntimeException(e); + } + client.setHttpClient(client.getHttpClient().newBuilder().readTimeout(Duration.ofSeconds(15)).build()); + client.setDebugging(false); + Configuration.setDefaultApiClient(client); + + this.container = container; + this.coreV1Api = new CoreV1Api(); + this.appsV1Api = new AppsV1Api(); + this.networkingV1Api = new NetworkingV1Api(); + rbacApi = new RbacAuthorizationV1Api(); + } + + /** + * This is the preferred method to use when creating a deployment alongside with a + * service. It creates the given resources as-well as waits for them to be created. + * The delay check is intentionally not taken as an argument, so that it stays as + * tight as possible, providing reasonable defaults. + * + */ + public void createAndWait(String namespace, String name, V1Deployment deployment, V1Service service, + @Nullable V1Ingress ingress, boolean changeVersion) { + try { + + String imageFromDeployment = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); + if (changeVersion) { + deployment.getSpec().getTemplate().getSpec().getContainers().get(0) + .setImage(imageFromDeployment + ":" + pomVersion()); + } + else { + String[] image = imageFromDeployment.split(":", 2); + pullImage(image[0], image[1], container); + loadImage(image[0], image[1], name, container); + } + + appsV1Api.createNamespacedDeployment(namespace, deployment, null, null, null, null); + coreV1Api.createNamespacedService(namespace, service, null, null, null, null); + waitForDeployment(namespace, deployment); + if (ingress != null) { + networkingV1Api.createNamespacedIngress(namespace, ingress, null, null, null, null); + waitForIngress(namespace, ingress); + } + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void createAndWait(String namespace, @Nullable V1ConfigMap configMap, @Nullable V1Secret secret) { + try { + if (configMap != null) { + coreV1Api.createNamespacedConfigMap(namespace, configMap, null, null, null, null); + waitForConfigMap(namespace, configMap, Phase.CREATE); + } + + if (secret != null) { + coreV1Api.createNamespacedSecret(namespace, secret, null, null, null, null); + waitForSecret(namespace, secret, Phase.CREATE); + } + + } + catch (ApiException e) { + throw new RuntimeException(e); + } + } + + public void deleteAndWait(String namespace, @Nullable V1ConfigMap configMap, @Nullable V1Secret secret) { + try { + if (configMap != null) { + String configMapName = configMapName(configMap); + coreV1Api.deleteNamespacedConfigMap(configMapName, namespace, null, null, null, null, null, null); + waitForConfigMap(namespace, configMap, Phase.DELETE); + } + + if (secret != null) { + String secretName = secretName(secret); + coreV1Api.deleteNamespacedSecret(secretName, namespace, null, null, null, null, null, null); + waitForSecret(namespace, secret, Phase.DELETE); + } + + } + catch (ApiException e) { + throw new RuntimeException(e); + } + } + + public void createNamespace(String name) { + try { + coreV1Api.createNamespace(new V1NamespaceBuilder().withNewMetadata().withName(name).and().build(), null, + null, null, null); + } + catch (ApiException e) { + throw new RuntimeException(e); + } + } + + public void deleteAndWait(String namespace, V1Deployment deployment, V1Service service, + @Nullable V1Ingress ingress) { + String deploymentName = deploymentName(deployment); + String serviceName = serviceName(service); + try { + appsV1Api.deleteNamespacedDeployment(deploymentName, namespace, null, null, null, null, null, null); + coreV1Api.deleteNamespacedService(serviceName, namespace, null, null, null, null, null, null); + waitForDeploymentToBeDeleted(deploymentName, namespace); + + if (ingress != null) { + String ingressName = ingressName(ingress); + networkingV1Api.deleteNamespacedIngress(ingressName, namespace, null, null, null, null, null, null); + waitForIngressToBeDeleted(ingressName, namespace); + } + + } + catch (ApiException e) { + throw new RuntimeException(e); + } + } + + public void busybox(String namespace, Phase phase) { + V1Deployment deployment = (V1Deployment) yaml("busybox/deployment.yaml"); + V1Service service = (V1Service) yaml("busybox/service.yaml"); + if (phase.equals(Phase.CREATE)) { + createAndWait(namespace, "busybox", deployment, service, null, false); + } + else if (phase.equals(Phase.DELETE)) { + deleteAndWait(namespace, deployment, service, null); + } + } + + public void kafka(String namespace, Phase phase) { + V1Deployment deployment = (V1Deployment) yaml("kafka/kafka-deployment.yaml"); + V1Service service = (V1Service) yaml("kafka/kafka-service.yaml"); + + if (phase.equals(Phase.CREATE)) { + createAndWait(namespace, "kafka", deployment, service, null, false); + } + else if (phase.equals(Phase.DELETE)) { + deleteAndWait(namespace, deployment, service, null); + } + } + + public void rabbitMq(String namespace, Phase phase) { + V1Deployment deployment = (V1Deployment) yaml("rabbitmq/rabbitmq-deployment.yaml"); + V1Service service = (V1Service) yaml("rabbitmq/rabbitmq-service.yaml"); + + if (phase.equals(Phase.CREATE)) { + createAndWait(namespace, "rabbitmq", deployment, service, null, false); + } + else if (phase.equals(Phase.DELETE)) { + deleteAndWait(namespace, deployment, service, null); + } + } + + public void zookeeper(String namespace, Phase phase) { + V1Deployment deployment = (V1Deployment) yaml("zookeeper/zookeeper-deployment.yaml"); + V1Service service = (V1Service) yaml("zookeeper/zookeeper-service.yaml"); + + if (phase.equals(Phase.CREATE)) { + createAndWait(namespace, "zookeeper", deployment, service, null, false); + } + else if (phase.equals(Phase.DELETE)) { + deleteAndWait(namespace, deployment, service, null); + } + } + + /** + * reads a yaml from classpath, fails if not found. + */ + public Object yaml(String fileName) { + ClassLoader classLoader = Util.class.getClassLoader(); + String file = new BufferedReader(new InputStreamReader(classLoader.getResourceAsStream(fileName))).lines() + .collect(Collectors.joining("\n")); + try { + return Yaml.load(file); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void setUp(String namespace) { + + try { + V1ServiceAccount serviceAccount = (V1ServiceAccount) yaml("setup/service-account.yaml"); + CheckedSupplier accountSupplier = () -> coreV1Api + .readNamespacedServiceAccount(serviceAccount.getMetadata().getName(), namespace, null); + CheckedSupplier accountDefaulter = () -> coreV1Api + .createNamespacedServiceAccount(namespace, serviceAccount, null, null, null, null); + notExistsHandler(accountSupplier, accountDefaulter); + + V1RoleBinding roleBinding = (V1RoleBinding) yaml("setup/role-binding.yaml"); + notExistsHandler( + () -> rbacApi.readNamespacedRoleBinding(roleBinding.getMetadata().getName(), namespace, null), + () -> rbacApi.createNamespacedRoleBinding(namespace, roleBinding, null, null, null, null)); + + V1Role role = (V1Role) yaml("setup/role.yaml"); + notExistsHandler(() -> rbacApi.readNamespacedRole(role.getMetadata().getName(), namespace, null), + () -> rbacApi.createNamespacedRole(namespace, role, null, null, null, null)); + } + catch (Exception e) { + throw new RuntimeException(e); + } + + } + + public void setUpClusterWide(String serviceAccountNamespace, Set namespaces) { + + try { + V1ServiceAccount serviceAccount = (V1ServiceAccount) yaml("cluster/service-account.yaml"); + CheckedSupplier accountSupplier = () -> coreV1Api.readNamespacedServiceAccount( + serviceAccount.getMetadata().getName(), serviceAccountNamespace, null); + CheckedSupplier accountDefaulter = () -> coreV1Api + .createNamespacedServiceAccount(serviceAccountNamespace, serviceAccount, null, null, null, null); + notExistsHandler(accountSupplier, accountDefaulter); + + V1ClusterRole clusterRole = (V1ClusterRole) yaml("cluster/cluster-role.yaml"); + notExistsHandler(() -> rbacApi.readClusterRole(clusterRole.getMetadata().getName(), null), + () -> rbacApi.createClusterRole(clusterRole, null, null, null, null)); + + V1RoleBinding roleBinding = (V1RoleBinding) yaml("cluster/role-binding.yaml"); + namespaces.forEach(namespace -> { + roleBinding.getMetadata().setNamespace(namespace); + try { + notExistsHandler( + () -> rbacApi.readNamespacedRoleBinding(roleBinding.getMetadata().getName(), namespace, + null), + () -> rbacApi.createNamespacedRoleBinding(namespace, roleBinding, null, null, null, null)); + } + catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + catch (Exception e) { + throw new RuntimeException(e); + } + + } + + public void deleteNamespace(String name) { + try { + coreV1Api.deleteNamespace(name, null, null, null, null, null, null); + } + catch (ApiException e) { + throw new RuntimeException(e); + } + + await().pollInterval(Duration.ofSeconds(1)).atMost(30, TimeUnit.SECONDS) + .until(() -> coreV1Api.listNamespace(null, null, null, null, null, null, null, null, null, null) + .getItems().stream().noneMatch(x -> x.getMetadata().getName().equals(name))); + } + + public void wiremock(String namespace, String path, Phase phase) { + V1Deployment deployment = (V1Deployment) yaml("wiremock/wiremock-deployment.yaml"); + V1Service service = (V1Service) yaml("wiremock/wiremock-service.yaml"); + V1Ingress ingress = (V1Ingress) yaml("wiremock/wiremock-ingress.yaml"); + + if (phase.equals(Phase.CREATE)) { + deployment.getMetadata().setNamespace(namespace); + service.getMetadata().setNamespace(namespace); + ingress.getMetadata().setNamespace(namespace); + ingress.getSpec().getRules().get(0).getHttp().getPaths().get(0).setPath(path); + createAndWait(namespace, "wiremock", deployment, service, ingress, false); + } + else { + deleteAndWait(namespace, deployment, service, ingress); + } + + } + + private String deploymentName(V1Deployment deployment) { + return deployment.getMetadata().getName(); + } + + private String serviceName(V1Service service) { + return service.getMetadata().getName(); + } + + private String ingressName(V1Ingress ingress) { + return ingress.getMetadata().getName(); + } + + private String configMapName(V1ConfigMap configMap) { + return configMap.getMetadata().getName(); + } + + private String secretName(V1Secret secret) { + return secret.getMetadata().getName(); + } + + private void waitForDeployment(String namespace, V1Deployment deployment) { + String deploymentName = deploymentName(deployment); + await().pollInterval(Duration.ofSeconds(1)).atMost(600, TimeUnit.SECONDS) + .until(() -> isDeploymentReady(deploymentName, namespace)); + } + + private void waitForConfigMap(String namespace, V1ConfigMap configMap, Phase phase) { + String configMapName = configMapName(configMap); + await().pollInterval(Duration.ofSeconds(1)).atMost(600, TimeUnit.SECONDS).until(() -> { + try { + coreV1Api.readNamespacedConfigMap(configMapName, namespace, null); + return phase.equals(Phase.CREATE); + } + catch (ApiException e) { + if (e.getCode() == HttpURLConnection.HTTP_NOT_FOUND) { + return !phase.equals(Phase.CREATE); + + } + throw new RuntimeException(e); + } + }); + } + + private void waitForSecret(String namespace, V1Secret secret, Phase phase) { + String secretName = secretName(secret); + await().pollInterval(Duration.ofSeconds(1)).atMost(600, TimeUnit.SECONDS).until(() -> { + try { + coreV1Api.readNamespacedSecret(secretName, namespace, null); + return phase.equals(Phase.CREATE); + } + catch (ApiException e) { + if (e.getCode() == HttpURLConnection.HTTP_NOT_FOUND) { + return !phase.equals(Phase.CREATE); + } + throw new RuntimeException(e); + } + }); + } + + private void waitForIngress(String namespace, V1Ingress ingress) { + String ingressName = ingressName(ingress); + await().timeout(Duration.ofSeconds(90)).pollInterval(Duration.ofSeconds(3)).until(() -> { + try { + V1LoadBalancerStatus status = networkingV1Api.readNamespacedIngress(ingressName, namespace, null) + .getStatus().getLoadBalancer(); + + if (status == null) { + LOG.info("ingress : " + ingressName + " not ready yet (loadbalancer not yet present)"); + return false; + } + + List loadBalancerIngress = status.getIngress(); + if (loadBalancerIngress == null) { + LOG.info("ingress : " + ingressName + " not ready yet (loadbalancer ingress not yet present)"); + return false; + } + + String ip = loadBalancerIngress.get(0).getIp(); + if (ip == null) { + LOG.info("ingress : " + ingressName + " not ready yet"); + return false; + } + + LOG.info("ingress : " + ingressName + " ready with ip : " + ip); + return true; + } + catch (ApiException e) { + if (e.getCode() == HttpURLConnection.HTTP_NOT_FOUND) { + return false; + } + throw new RuntimeException(e); + } + }); + } + + private void waitForDeploymentToBeDeleted(String deploymentName, String namespace) { + await().timeout(Duration.ofSeconds(90)).until(() -> { + try { + appsV1Api.readNamespacedDeployment(deploymentName, namespace, null); + return false; + } + catch (ApiException e) { + if (e.getCode() == HttpURLConnection.HTTP_NOT_FOUND) { + return true; + } + throw new RuntimeException(e); + } + }); + } + + private void waitForIngressToBeDeleted(String ingressName, String namespace) { + await().timeout(Duration.ofSeconds(90)).until(() -> { + try { + networkingV1Api.readNamespacedIngress(ingressName, namespace, null); + return false; + } + catch (ApiException e) { + if (e.getCode() == HttpURLConnection.HTTP_NOT_FOUND) { + return true; + } + throw new RuntimeException(e); + } + }); + } + + private boolean isDeploymentReady(String deploymentName, String namespace) throws ApiException { + V1DeploymentList deployments = appsV1Api.listNamespacedDeployment(namespace, null, null, null, + "metadata.name=" + deploymentName, null, null, null, null, null, null); + if (deployments.getItems().size() < 1) { + fail("No deployments with the name " + deploymentName); + } + V1Deployment deployment = deployments.getItems().get(0); + Integer availableReplicas = deployment.getStatus().getAvailableReplicas(); + LOG.info("Available replicas for " + deploymentName + ": " + + (availableReplicas == null ? 0 : availableReplicas)); + return availableReplicas != null && availableReplicas >= 1; + } + + private static void notExistsHandler(CheckedSupplier callee, CheckedSupplier defaulter) throws Exception { + try { + callee.get(); + } + catch (Exception exception) { + if (exception instanceof ApiException apiException) { + if (apiException.getCode() == 404) { + defaulter.get(); + return; + } + } + throw new RuntimeException(exception); + } + } + + private interface CheckedSupplier { + + T get() throws Exception; + + } + +} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-catalog-watcher/src/test/resources/busybox/deployment.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/busybox/deployment.yaml similarity index 100% rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-catalog-watcher/src/test/resources/busybox/deployment.yaml rename to spring-cloud-kubernetes-test-support/src/main/resources/busybox/deployment.yaml diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-catalog-watcher/src/test/resources/busybox/service.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/busybox/service.yaml similarity index 100% rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-catalog-watcher/src/test/resources/busybox/service.yaml rename to spring-cloud-kubernetes-test-support/src/main/resources/busybox/service.yaml diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test/resources/kafka/kafka-deployment.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/kafka/kafka-deployment.yaml similarity index 100% rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test/resources/kafka/kafka-deployment.yaml rename to spring-cloud-kubernetes-test-support/src/main/resources/kafka/kafka-deployment.yaml diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test/resources/kafka/kafka-service.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/kafka/kafka-service.yaml similarity index 100% rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test/resources/kafka/kafka-service.yaml rename to spring-cloud-kubernetes-test-support/src/main/resources/kafka/kafka-service.yaml diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/rabbitmq/rabbitmq-deployment.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/rabbitmq/rabbitmq-deployment.yaml new file mode 100644 index 00000000..9f5e7cd9 --- /dev/null +++ b/spring-cloud-kubernetes-test-support/src/main/resources/rabbitmq/rabbitmq-deployment.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: rabbitmq + labels: + app: taskqueue + component: rabbitmq +spec: + selector: + matchLabels: + app: taskqueue + component: rabbitmq + template: + metadata: + labels: + app: taskqueue + component: rabbitmq + spec: + containers: + - name: taskqueue + image: rabbitmq:3-management + imagePullPolicy: IfNotPresent + + diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/src/test/resources/rabbitmq/rabbitmq-service.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/rabbitmq/rabbitmq-service.yaml similarity index 93% rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/src/test/resources/rabbitmq/rabbitmq-service.yaml rename to spring-cloud-kubernetes-test-support/src/main/resources/rabbitmq/rabbitmq-service.yaml index e960e5f4..2f039726 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-secrets-test-app/src/test/resources/rabbitmq/rabbitmq-service.yaml +++ b/spring-cloud-kubernetes-test-support/src/main/resources/rabbitmq/rabbitmq-service.yaml @@ -13,5 +13,5 @@ spec: name: http-stats targetPort: 15672 selector: - app: taskQueue + app: taskqueue component: rabbitmq diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-deployment.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-deployment.yaml index 8ee19126..1799c71d 100644 --- a/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-deployment.yaml +++ b/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-deployment.yaml @@ -1,19 +1,19 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: servicea-wiremock-deployment + name: service-wiremock-deployment spec: selector: matchLabels: - app: servicea-wiremock + app: service-wiremock template: metadata: labels: - app: servicea-wiremock + app: service-wiremock spec: containers: - - name: servicea-wiremock - image: wiremock/wiremock:2.32.0 + - name: service-wiremock + image: wiremock/wiremock:2.35.0 args: ["--verbose"] imagePullPolicy: IfNotPresent readinessProbe: diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-ingress.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-ingress.yaml index 8786d59a..18d50519 100644 --- a/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-ingress.yaml +++ b/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-ingress.yaml @@ -11,7 +11,7 @@ spec: pathType: Prefix backend: service: - name: servicea-wiremock + name: service-wiremock port: number: 8080 diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-root-path-ingress.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-root-path-ingress.yaml deleted file mode 100644 index bd2d857a..00000000 --- a/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-root-path-ingress.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: wiremock-ingress - namespace: default -spec: - rules: - - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: servicea-wiremock - port: - number: 8080 - diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-service.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-service.yaml index ef30d58a..af4d4e00 100644 --- a/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-service.yaml +++ b/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-service.yaml @@ -2,13 +2,13 @@ apiVersion: v1 kind: Service metadata: labels: - app: servicea-wiremock - name: servicea-wiremock + app: service-wiremock + name: service-wiremock spec: ports: - name: http port: 8080 targetPort: 8080 selector: - app: servicea-wiremock + app: service-wiremock type: ClusterIP diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test/resources/zookeeper/zookeeper-deployment.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/zookeeper/zookeeper-deployment.yaml similarity index 100% rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test/resources/zookeeper/zookeeper-deployment.yaml rename to spring-cloud-kubernetes-test-support/src/main/resources/zookeeper/zookeeper-deployment.yaml diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test/resources/zookeeper/zookeeper-service.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/zookeeper/zookeeper-service.yaml similarity index 100% rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps/spring-cloud-kubernetes-client-configuration-watcher-configmap-test-app/src/test/resources/zookeeper/zookeeper-service.yaml rename to spring-cloud-kubernetes-test-support/src/main/resources/zookeeper/zookeeper-service.yaml