From 013b920bcf906578c3c6ff03336a6e7df1626633 Mon Sep 17 00:00:00 2001 From: erabii Date: Wed, 17 Apr 2024 17:13:15 +0300 Subject: [PATCH] Clean docker image cache (#1636) --- .../composites/env-variables/action.yaml | 1 - .../composites/pre-test-actions/action.yaml | 3 + .../restore-docker-images/action.yaml | 42 ++++++++ .../upload-docker-images/action.yaml | 19 ---- ...rnetesClientServicesListSupplierTests.java | 3 +- .../it/mode/service/AllNamespacesTest.java | 3 +- .../catalog/watch/Fabric8CatalogWatchIT.java | 3 + .../Fabric8DiscoveryPodMetadataIT.java | 4 + .../fabric8/client/istio/Fabric8IstioIT.java | 14 +-- .../KubernetesClientCatalogWatchIT.java | 4 + .../watcher/ActuatorRefreshIT.java | 4 + .../discoveryclient/it/DiscoveryClientIT.java | 3 + .../KubernetesClientDiscoveryClientIT.java | 4 + ...sClientDiscoverySelectiveNamespacesIT.java | 3 + .../ConfigurationWatcherMultipleAppsIT.java | 3 + .../ConfigurationWatcherMultipleAppIT.java | 3 + .../integration/tests/commons/Commons.java | 59 +++++++++- .../integration/tests/commons/Images.java | 101 ++++++++++++++++++ .../tests/commons/fabric8_client/Util.java | 19 +++- .../tests/commons/native_client/Util.java | 21 ++++ .../main/resources/busybox/deployment.yaml | 2 +- .../src/main/resources/current-images.txt | 5 + .../resources/istio/istioctl-deployment.yaml | 2 +- .../resources/kafka/kafka-deployment.yaml | 2 +- .../rabbitmq/rabbitmq-deployment.yaml | 2 +- .../wiremock/wiremock-deployment.yaml | 2 +- 26 files changed, 283 insertions(+), 48 deletions(-) create mode 100644 .github/workflows/composites/restore-docker-images/action.yaml delete mode 100644 .github/workflows/composites/upload-docker-images/action.yaml create mode 100644 spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Images.java create mode 100644 spring-cloud-kubernetes-test-support/src/main/resources/current-images.txt diff --git a/.github/workflows/composites/env-variables/action.yaml b/.github/workflows/composites/env-variables/action.yaml index a1d6764ff3..a33383182f 100644 --- a/.github/workflows/composites/env-variables/action.yaml +++ b/.github/workflows/composites/env-variables/action.yaml @@ -21,4 +21,3 @@ runs: echo "BRANCH_NAME=$(echo $GITHUB_HEAD_REF)" >> $GITHUB_ENV echo "BASE_BRANCH_NAME=$(echo $GITHUB_BASE_REF)" >> $GITHUB_ENV - echo "DOCKER_IMAGES_KEY=$(echo $GITHUB_RUN_ID)" >> $GITHUB_ENV diff --git a/.github/workflows/composites/pre-test-actions/action.yaml b/.github/workflows/composites/pre-test-actions/action.yaml index 657c55e886..0f12bad67a 100644 --- a/.github/workflows/composites/pre-test-actions/action.yaml +++ b/.github/workflows/composites/pre-test-actions/action.yaml @@ -22,6 +22,9 @@ runs: - name: cache local maven repository uses: ./.github/workflows/composites/cache + - name: restore common images + uses: ./.github/workflows/composites/restore-docker-images + - name: build project shell: bash run: | diff --git a/.github/workflows/composites/restore-docker-images/action.yaml b/.github/workflows/composites/restore-docker-images/action.yaml new file mode 100644 index 0000000000..c5a41a8592 --- /dev/null +++ b/.github/workflows/composites/restore-docker-images/action.yaml @@ -0,0 +1,42 @@ +name: restore-docker-images +description: upload docker images +runs: + using: "composite" + steps: + + - name: restore images if cache matches + uses: actions/cache/restore@v4 + id: images-cache + with: + path: /tmp/docker/images + key: docker-images-github-cache-${{ hashFiles('**/current-images.txt') }} + + - name: pull docker images + shell: bash + if: steps.images-cache.outputs.cache-hit != 'true' + run: | + echo 'start pulling common images' + mkdir -p /tmp/docker/images + result=$(find . -name 'current-images.txt') + while read line; do + docker pull "$line" + replace_slash=$(tr '/' '-' <<< "$line") + docker save "${line}" > "/tmp/docker/images/${replace_slash}.tar" + done <$result + + - name: save docker images + id: save-docker-images + uses: actions/cache/save@v4 + if: steps.images-cache.outputs.cache-hit != 'true' + with: + path: | + /tmp/docker/images + key: docker-images-github-cache-${{ hashFiles('**/current-images.txt') }} + + - name: print images + shell: bash + run: | + echo 'printing images' + ls /tmp/docker/images + + diff --git a/.github/workflows/composites/upload-docker-images/action.yaml b/.github/workflows/composites/upload-docker-images/action.yaml deleted file mode 100644 index 83c7657e19..0000000000 --- a/.github/workflows/composites/upload-docker-images/action.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# we are not going to use upload/download actions, since it is slower than cache usage -# as key to the cache we are going to use DOCKER_IMAGES_KEY, which is the same as GITHUB_RUN_ID - -name: upload docker images -description: upload docker images -runs: - using: "composite" - steps: - - - uses: Wandalen/wretry.action@master - with: - attempt_limit: 3 - action: buildjet/cache@v3 - with: | - path: /tmp/docker/images - key: docker-images-cache-${{ env.DOCKER_IMAGES_KEY }} - restore-keys: docker-images-cache-${{ env.DOCKER_IMAGES_KEY }} - - diff --git a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServicesListSupplierTests.java b/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServicesListSupplierTests.java index cbfa69a7b8..be18b3fb02 100644 --- a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServicesListSupplierTests.java +++ b/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServicesListSupplierTests.java @@ -23,7 +23,6 @@ import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; -import com.github.tomakehurst.wiremock.common.ConsoleNotifier; import io.kubernetes.client.openapi.ApiClient; import io.kubernetes.client.openapi.Configuration; import io.kubernetes.client.openapi.JSON; @@ -100,7 +99,7 @@ class KubernetesClientServicesListSupplierTests { @BeforeAll static void setup() { - wireMockServer = new WireMockServer(options().dynamicPort().notifier(new ConsoleNotifier(true))); + wireMockServer = new WireMockServer(options().dynamicPort()); wireMockServer.start(); WireMock.configureFor("localhost", wireMockServer.port()); diff --git a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/mode/service/AllNamespacesTest.java b/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/mode/service/AllNamespacesTest.java index 27ec8b26ee..3ec2160cbc 100644 --- a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/mode/service/AllNamespacesTest.java +++ b/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/mode/service/AllNamespacesTest.java @@ -18,7 +18,6 @@ import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; -import com.github.tomakehurst.wiremock.common.ConsoleNotifier; import io.kubernetes.client.openapi.ApiClient; import io.kubernetes.client.openapi.models.V1Endpoints; import io.kubernetes.client.openapi.models.V1EndpointsList; @@ -90,7 +89,7 @@ class AllNamespacesTest { @BeforeAll static void beforeAll() { - wireMockServer = new WireMockServer(options().dynamicPort().notifier(new ConsoleNotifier(true))); + wireMockServer = new WireMockServer(options().dynamicPort()); wireMockServer.start(); WireMock.configureFor("localhost", wireMockServer.port()); mockWatchers(); 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 92360824b9..bd82dfbb29 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 @@ -33,6 +33,7 @@ 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.Images; 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; @@ -73,6 +74,8 @@ static void beforeAll() throws Exception { Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); + Images.loadBusybox(K3S); + util = new Util(K3S); util.createNamespace(NAMESPACE_A); diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/discovery/Fabric8DiscoveryPodMetadataIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/discovery/Fabric8DiscoveryPodMetadataIT.java index 242310ca01..9aba3e0821 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/discovery/Fabric8DiscoveryPodMetadataIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/discovery/Fabric8DiscoveryPodMetadataIT.java @@ -42,6 +42,7 @@ import org.springframework.cloud.kubernetes.commons.discovery.DefaultKubernetesServiceInstance; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; +import org.springframework.cloud.kubernetes.integration.tests.commons.Images; 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; @@ -92,6 +93,9 @@ static void beforeAll() throws Exception { Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); + Images.loadBusybox(K3S); + Images.loadWiremock(K3S); + util = new Util(K3S); client = util.client(); diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/istio/Fabric8IstioIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/istio/Fabric8IstioIT.java index 4d640458b6..5cd75c50cb 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/istio/Fabric8IstioIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/istio/Fabric8IstioIT.java @@ -35,6 +35,7 @@ import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; +import org.springframework.cloud.kubernetes.integration.tests.commons.Images; 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; @@ -42,7 +43,6 @@ import org.springframework.web.reactive.function.client.WebClient; import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.processExecResult; -import static org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util.ISTIO_ISTIOCTL; /** * @author wind57 @@ -53,10 +53,6 @@ class Fabric8IstioIT { private static final String IMAGE_NAME = "spring-cloud-kubernetes-fabric8-client-istio"; - private static final String ISTIO_PROXY = "istio/proxyv2"; - - private static final String ISTIO_PILOT = "istio/pilot"; - private static Util util; private static K3sContainer K3S; @@ -69,12 +65,7 @@ static void beforeAll() throws Exception { Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); - Commons.pullImage(ISTIO_ISTIOCTL, Commons.ISTIO_VERSION, K3S); - Commons.loadImage(ISTIO_ISTIOCTL, Commons.ISTIO_VERSION, "istioctl", K3S); - Commons.pullImage(ISTIO_PROXY, Commons.ISTIO_VERSION, K3S); - Commons.loadImage(ISTIO_PROXY, Commons.ISTIO_VERSION, "istioproxy", K3S); - Commons.pullImage(ISTIO_PILOT, Commons.ISTIO_VERSION, K3S); - Commons.loadImage(ISTIO_PILOT, Commons.ISTIO_VERSION, "istiopilot", K3S); + Images.loadIstioctl(K3S); processExecResult(K3S.execInContainer("sh", "-c", "kubectl create namespace istio-test")); processExecResult( @@ -127,6 +118,7 @@ private static void appManifests(Phase phase) { InputStream ingressStream = util.inputStream("istio-ingress.yaml"); Deployment deployment = Serialization.unmarshal(deploymentStream, Deployment.class); + Service service = Serialization.unmarshal(serviceStream, Service.class); Ingress ingress = Serialization.unmarshal(ingressStream, Ingress.class); diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/k8s/client/catalog/watcher/KubernetesClientCatalogWatchIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/k8s/client/catalog/watcher/KubernetesClientCatalogWatchIT.java index 2dd5769748..26e582ace1 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/k8s/client/catalog/watcher/KubernetesClientCatalogWatchIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-catalog-watcher/src/test/java/org/springframework/cloud/kubernetes/k8s/client/catalog/watcher/KubernetesClientCatalogWatchIT.java @@ -39,6 +39,7 @@ 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.Images; 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; @@ -75,6 +76,9 @@ static void beforeAll() throws Exception { K3S.start(); Commons.validateImage(APP_NAME, K3S); Commons.loadSpringCloudKubernetesImage(APP_NAME, K3S); + + Images.loadBusybox(K3S); + util = new Util(K3S); util.setUp(NAMESPACE); app(Phase.CREATE); diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshIT.java index 38f0e15d12..4237ab13e8 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshIT.java @@ -34,6 +34,7 @@ import org.testcontainers.k3s.K3sContainer; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; +import org.springframework.cloud.kubernetes.integration.tests.commons.Images; import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util; @@ -66,6 +67,9 @@ 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); + + Images.loadWiremock(K3S); + util = new Util(K3S); util.setUp(NAMESPACE); diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery-server/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery-server/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientIT.java index be2e90a71d..b2987a8e7a 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery-server/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery-server/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientIT.java @@ -37,6 +37,7 @@ import org.springframework.boot.test.json.BasicJsonTester; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; +import org.springframework.cloud.kubernetes.integration.tests.commons.Images; 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; @@ -153,6 +154,8 @@ static void beforeAll() throws Exception { Commons.validateImage(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, K3S); Commons.loadSpringCloudKubernetesImage(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, K3S); + Images.loadWiremock(K3S); + util = new Util(K3S); rbacApi = new RbacAuthorizationV1Api(); util.setUp(NAMESPACE); diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientIT.java index a844f47506..02c0bc7178 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientIT.java @@ -43,6 +43,7 @@ import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.kubernetes.commons.discovery.DefaultKubernetesServiceInstance; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; +import org.springframework.cloud.kubernetes.integration.tests.commons.Images; 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; @@ -80,6 +81,9 @@ static void beforeAll() throws Exception { Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); + Images.loadWiremock(K3S); + Images.loadBusybox(K3S); + util = new Util(K3S); util.setUp(NAMESPACE); manifests(Phase.CREATE); diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoverySelectiveNamespacesIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoverySelectiveNamespacesIT.java index a8e51d5c1c..43aeb1732b 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoverySelectiveNamespacesIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoverySelectiveNamespacesIT.java @@ -42,6 +42,7 @@ import org.springframework.cloud.kubernetes.commons.discovery.DefaultKubernetesServiceInstance; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; +import org.springframework.cloud.kubernetes.integration.tests.commons.Images; 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; @@ -79,6 +80,8 @@ static void beforeAll() throws Exception { Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); + Images.loadWiremock(K3S); + util = new Util(K3S); util.createNamespace(NAMESPACE_A); diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-kafka-configmap-reload-multiple-apps/kafka-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-k8s-client-kafka-configmap-reload-multiple-apps/kafka-configmap-test-app/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/multiple/apps/ConfigurationWatcherMultipleAppsIT.java index 57c94a5b2b..5ffcf7f682 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-kafka-configmap-reload-multiple-apps/kafka-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-k8s-client-kafka-configmap-reload-multiple-apps/kafka-configmap-test-app/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/multiple/apps/ConfigurationWatcherMultipleAppsIT.java @@ -36,6 +36,7 @@ import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; +import org.springframework.cloud.kubernetes.integration.tests.commons.Images; 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; @@ -77,6 +78,8 @@ static void beforeAll() throws Exception { Commons.validateImage(CONFIG_WATCHER_APP_B_IMAGE, K3S); Commons.loadSpringCloudKubernetesImage(CONFIG_WATCHER_APP_B_IMAGE, K3S); + Images.loadKafka(K3S); + util = new Util(K3S); util.setUp(NAMESPACE); } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-rabbitmq-secret-reload-multiple-apps/rabbitmq-secret-test-app/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/multiple/apps/ConfigurationWatcherMultipleAppIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-rabbitmq-secret-reload-multiple-apps/rabbitmq-secret-test-app/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/multiple/apps/ConfigurationWatcherMultipleAppIT.java index 6ebc617304..2f0429d12a 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-rabbitmq-secret-reload-multiple-apps/rabbitmq-secret-test-app/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/multiple/apps/ConfigurationWatcherMultipleAppIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-rabbitmq-secret-reload-multiple-apps/rabbitmq-secret-test-app/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/multiple/apps/ConfigurationWatcherMultipleAppIT.java @@ -36,6 +36,7 @@ import reactor.util.retry.RetryBackoffSpec; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; +import org.springframework.cloud.kubernetes.integration.tests.commons.Images; 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; @@ -76,6 +77,8 @@ static void beforeAll() throws Exception { Commons.validateImage(CONFIG_WATCHER_APP_B_IMAGE, K3S); Commons.loadSpringCloudKubernetesImage(CONFIG_WATCHER_APP_B_IMAGE, K3S); + Images.loadRabbitmq(K3S); + util = new Util(K3S); util.setUp(NAMESPACE); } 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 9737b20b2f..9cf7b0b27e 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 @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 the original author or authors. + * Copyright 2013-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import java.time.Duration; import java.util.Arrays; import java.util.List; +import java.util.Optional; import java.util.concurrent.TimeUnit; import com.github.dockerjava.api.command.ListImagesCmd; @@ -57,9 +58,9 @@ public final class Commons { private static final Log LOG = LogFactory.getLog(Commons.class); /** - * istio version used in our integration tests. + * this path is generated by the pipeline of github actions. */ - public static final String ISTIO_VERSION = "1.20.5"; + private static final String TMP_IMAGES = "/tmp/docker/images"; private Commons() { throw new AssertionError("No instance provided"); @@ -90,7 +91,7 @@ private Commons() { private static final K3sContainer CONTAINER = new FixedPortsK3sContainer(DockerImageName.parse(Commons.RANCHER)) .configureFixedPorts(EXPOSED_PORTS).withFileSystemBind(TEMP_FOLDER, TEMP_FOLDER) - .withCommand(Commons.RANCHER_COMMAND).withReuse(true); + .withFileSystemBind(TMP_IMAGES, TMP_IMAGES).withCommand(Commons.RANCHER_COMMAND).withReuse(true); public static K3sContainer container() { return CONTAINER; @@ -166,6 +167,56 @@ public static void loadImage(String image, String tag, String tarName, K3sContai } + /** + * either get the tar from '/tmp/docker/images', or pull the image. + */ + public static void load(K3sContainer container, String tarName, String imageNameForDownload, String imageVersion) { + File dockerImagesRootDir = Paths.get(Commons.TMP_IMAGES).toFile(); + if (dockerImagesRootDir.exists() && dockerImagesRootDir.isDirectory()) { + File[] tars = dockerImagesRootDir.listFiles(); + if (tars != null && tars.length > 0) { + Optional found = Arrays.stream(tars).map(File::getName).filter(x -> x.contains(tarName)) + .findFirst(); + if (found.isPresent()) { + LOG.info("running in github actions, will load from : " + Commons.TMP_IMAGES + " tar : " + + found.get()); + Commons.loadImageFromPath(found.get(), container); + return; + } + else { + LOG.info(tarName + " not found, resorting to pulling the image"); + } + } + else { + LOG.info("no tars found, will resort to pulling the image"); + } + } + else { + LOG.info("running outside github actions"); + } + + try { + LOG.info("no tars found, will resort to pulling the image"); + LOG.info("using : " + imageVersion + " for : " + imageNameForDownload); + Commons.pullImage(imageNameForDownload, imageVersion, container); + Commons.loadImage(imageNameForDownload, imageVersion, tarName, container); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void loadImageFromPath(String tarName, K3sContainer container) { + await().atMost(Duration.ofMinutes(2)).pollInterval(Duration.ofSeconds(1)).until(() -> { + Container.ExecResult result = container.execInContainer("ctr", "i", "import", TMP_IMAGES + "/" + tarName); + boolean noErrors = result.getStderr() == null || result.getStderr().isEmpty(); + if (!noErrors) { + LOG.info("error is : " + result.getStderr()); + } + return noErrors; + }); + } + public static void cleanUp(String image, K3sContainer container) throws Exception { container.execInContainer("crictl", "rmi", "docker.io/springcloud/" + image + ":" + pomVersion()); container.execInContainer("rm", TEMP_FOLDER + "/" + image + ".tar"); diff --git a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Images.java b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Images.java new file mode 100644 index 0000000000..06a82370e4 --- /dev/null +++ b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Images.java @@ -0,0 +1,101 @@ +/* + * Copyright 2013-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.kubernetes.integration.tests.commons; + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +import org.testcontainers.k3s.K3sContainer; + +/** + * @author wind57 + */ +public final class Images { + + private static final String BUSYBOX = "busybox"; + + private static final String BUSYBOX_TAR = BUSYBOX + ":" + busyboxVersion(); + + private static final String WIREMOCK = "wiremock/wiremock"; + + private static final String WIREMOCK_TAR = WIREMOCK.replace('/', '-') + ":" + wiremockVersion(); + + private static final String ISTIOCTL = "istio/istioctl"; + + private static final String ISTIOCTL_TAR = ISTIOCTL.replace('/', '-') + ":" + istioctlVersion(); + + private static final String KAFKA = "confluentinc/cp-kafka"; + + private static final String KAFKA_TAR = KAFKA.replace('/', '-') + kafkaVersion(); + + private static final String RABBITMQ = "rabbitmq"; + + private static final String RABBITMQ_TAR = "rabbitmq"; + + private Images() { + + } + + public static String busyboxVersion() { + return imageVersion(BUSYBOX); + } + + public static String istioctlVersion() { + return imageVersion(ISTIOCTL); + } + + public static String kafkaVersion() { + return imageVersion(KAFKA); + } + + public static String rabbitMqVersion() { + return imageVersion(RABBITMQ); + } + + public static String wiremockVersion() { + return imageVersion(WIREMOCK); + } + + public static void loadBusybox(K3sContainer container) { + Commons.load(container, BUSYBOX_TAR, BUSYBOX, busyboxVersion()); + } + + public static void loadWiremock(K3sContainer container) { + Commons.load(container, WIREMOCK_TAR, WIREMOCK, wiremockVersion()); + } + + public static void loadIstioctl(K3sContainer container) { + Commons.load(container, ISTIOCTL_TAR, ISTIOCTL, istioctlVersion()); + } + + public static void loadKafka(K3sContainer container) { + Commons.load(container, KAFKA_TAR, KAFKA, kafkaVersion()); + } + + public static void loadRabbitmq(K3sContainer container) { + Commons.load(container, RABBITMQ_TAR, RABBITMQ, rabbitMqVersion()); + } + + // find the image version from current-images.txt + private static String imageVersion(String imageNameForDownload) { + BufferedReader reader = new BufferedReader( + new InputStreamReader(Commons.class.getClassLoader().getResourceAsStream("current-images.txt"))); + return reader.lines().filter(line -> line.contains(imageNameForDownload)).map(line -> line.split(":")[1]) + .findFirst().orElseThrow(); + } + +} 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 index 9833df50eb..fe01d5312d 100644 --- 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 @@ -48,7 +48,7 @@ import org.apache.commons.logging.LogFactory; import org.testcontainers.k3s.K3sContainer; -import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; +import org.springframework.cloud.kubernetes.integration.tests.commons.Images; import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; import static org.awaitility.Awaitility.await; @@ -123,6 +123,12 @@ 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).item(); + + String busyboxVersion = Images.busyboxVersion(); + String imageWithoutVersion = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); + String imageWithVersion = imageWithoutVersion + ":" + busyboxVersion; + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(imageWithVersion); + Service service = client.services().load(serviceStream).item(); if (phase.equals(Phase.CREATE)) { @@ -259,9 +265,10 @@ public void setUpIstioctl(String namespace, Phase phase) { InputStream istioctlDeploymentStream = inputStream("istio/istioctl-deployment.yaml"); Deployment istioctlDeployment = Serialization.unmarshal(istioctlDeploymentStream, Deployment.class); - // Ensure the version in the yaml is consistent with images we pulled. - istioctlDeployment.getSpec().getTemplate().getSpec().getContainers().get(0) - .setImage(ISTIO_ISTIOCTL + ":" + Commons.ISTIO_VERSION); + String imageWithoutVersion = istioctlDeployment.getSpec().getTemplate().getSpec().getContainers().get(0) + .getImage(); + String imageWithVersion = imageWithoutVersion + ":" + Images.istioctlVersion(); + istioctlDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(imageWithVersion); if (phase.equals(Phase.CREATE)) { createAndWait(namespace, null, istioctlDeployment, null, null, false); @@ -293,6 +300,10 @@ public void wiremock(String namespace, String path, Phase phase, boolean withIng InputStream ingressStream = inputStream("wiremock/wiremock-ingress.yaml"); Deployment deployment = client.apps().deployments().load(deploymentStream).item(); + String imageWithoutVersion = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); + String imageWithVersion = imageWithoutVersion + ":" + Images.wiremockVersion(); + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(imageWithVersion); + Service service = client.services().load(serviceStream).item(); Ingress ingress = null; 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 index 6dd5c90046..2d225082d3 100644 --- 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 @@ -60,6 +60,7 @@ import org.apache.commons.logging.LogFactory; import org.testcontainers.k3s.K3sContainer; +import org.springframework.cloud.kubernetes.integration.tests.commons.Images; import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; import static org.awaitility.Awaitility.await; @@ -233,6 +234,11 @@ public void deleteAndWait(String namespace, V1Deployment deployment, V1Service s public void busybox(String namespace, Phase phase) { V1Deployment deployment = (V1Deployment) yaml("busybox/deployment.yaml"); + + String imageWithoutVersion = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); + String imageWithVersion = imageWithoutVersion + ":" + Images.busyboxVersion(); + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(imageWithVersion); + V1Service service = (V1Service) yaml("busybox/service.yaml"); if (phase.equals(Phase.CREATE)) { createAndWait(namespace, "busybox", deployment, service, null, false); @@ -244,6 +250,11 @@ else if (phase.equals(Phase.DELETE)) { public void kafka(String namespace, Phase phase) { V1Deployment deployment = (V1Deployment) yaml("kafka/kafka-deployment.yaml"); + + String imageWithoutVersion = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); + String imageWithVersion = imageWithoutVersion + ":" + Images.kafkaVersion(); + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(imageWithVersion); + V1Service service = (V1Service) yaml("kafka/kafka-service.yaml"); V1ConfigMap configMap = (V1ConfigMap) yaml("kafka/kafka-configmap-startup-script.yaml"); @@ -259,6 +270,11 @@ else if (phase.equals(Phase.DELETE)) { public void rabbitMq(String namespace, Phase phase) { V1Deployment deployment = (V1Deployment) yaml("rabbitmq/rabbitmq-deployment.yaml"); + + String imageWithoutVersion = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); + String imageWithVersion = imageWithoutVersion + ":" + Images.rabbitMqVersion(); + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(imageWithVersion); + V1Service service = (V1Service) yaml("rabbitmq/rabbitmq-service.yaml"); if (phase.equals(Phase.CREATE)) { @@ -430,6 +446,11 @@ public void wiremock(String namespace, String path, Phase phase) { public void wiremock(String namespace, String path, Phase phase, boolean withIngress) { V1Deployment deployment = (V1Deployment) yaml("wiremock/wiremock-deployment.yaml"); + + String imageWithoutVersion = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage(); + String imageWithVersion = imageWithoutVersion + ":" + Images.wiremockVersion(); + deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(imageWithVersion); + V1Service service = (V1Service) yaml("wiremock/wiremock-service.yaml"); V1Ingress ingress = null; diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/busybox/deployment.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/busybox/deployment.yaml index 052a911e03..55405c2c57 100644 --- a/spring-cloud-kubernetes-test-support/src/main/resources/busybox/deployment.yaml +++ b/spring-cloud-kubernetes-test-support/src/main/resources/busybox/deployment.yaml @@ -17,6 +17,6 @@ spec: containers: - name: busybox # image: arm64/busybox:latest - image: busybox:1.35 + image: busybox command: ["/bin/sh"] args: ["-c", "sleep 100000"] diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/current-images.txt b/spring-cloud-kubernetes-test-support/src/main/resources/current-images.txt new file mode 100644 index 0000000000..de0626cdf0 --- /dev/null +++ b/spring-cloud-kubernetes-test-support/src/main/resources/current-images.txt @@ -0,0 +1,5 @@ +busybox:1.36.1 +istio/istioctl:1.20.5 +confluentinc/cp-kafka:7.2.1 +rabbitmq:3-management +wiremock/wiremock:3.4.2 diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/istio/istioctl-deployment.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/istio/istioctl-deployment.yaml index 658d87c205..ed5667da94 100644 --- a/spring-cloud-kubernetes-test-support/src/main/resources/istio/istioctl-deployment.yaml +++ b/spring-cloud-kubernetes-test-support/src/main/resources/istio/istioctl-deployment.yaml @@ -15,7 +15,7 @@ spec: spec: containers: - name: istio-ctl - image: istio/istioctl:1.20.5 + image: istio/istioctl imagePullPolicy: IfNotPresent command: [ "/bin/bash" ] args: [ "-c", "trap : TERM INT; sleep infinity & wait" ] diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/kafka/kafka-deployment.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/kafka/kafka-deployment.yaml index f0870b68c4..8a8db71379 100644 --- a/spring-cloud-kubernetes-test-support/src/main/resources/kafka/kafka-deployment.yaml +++ b/spring-cloud-kubernetes-test-support/src/main/resources/kafka/kafka-deployment.yaml @@ -33,7 +33,7 @@ spec: mountPath: /tmp command: - /tmp/kafka_start.sh - image: confluentinc/cp-kafka:7.2.1 + image: confluentinc/cp-kafka ports: - containerPort: 9092 env: 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 index 9f5e7cd97a..89f34d428a 100644 --- 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 @@ -18,7 +18,7 @@ spec: spec: containers: - name: taskqueue - image: rabbitmq:3-management + image: rabbitmq imagePullPolicy: IfNotPresent 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 b429648107..6ac4dd06bc 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 @@ -13,7 +13,7 @@ spec: spec: containers: - name: service-wiremock - image: wiremock/wiremock:3.4.2 + image: wiremock/wiremock args: ["--verbose"] imagePullPolicy: IfNotPresent readinessProbe: