From df8ad3c411cef81144e980f2be5092fc25caf4ae Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 6 Apr 2023 18:21:05 +0200 Subject: [PATCH 01/21] feat: run tests in parallel --- pom.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pom.xml b/pom.xml index 7a3a557..0fa748a 100644 --- a/pom.xml +++ b/pom.xml @@ -223,6 +223,15 @@ org.apache.maven.plugins maven-surefire-plugin ${maven-surefire-plugin.version} + + + + junit.jupiter.execution.parallel.enabled = true + junit.jupiter.execution.parallel.mode.default = concurrent + junit.jupiter.execution.parallel.mode.classes.default = concurrent + + + net.revelc.code.formatter From 5a9d3a9cc3098949c5ca99f0003b9c3cd1950d03 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 6 Apr 2023 18:24:01 +0200 Subject: [PATCH 02/21] wip --- .../jenvtest/sample/KubeApiServerTest.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/core/src/test/java/io/javaoperatorsdk/jenvtest/sample/KubeApiServerTest.java b/core/src/test/java/io/javaoperatorsdk/jenvtest/sample/KubeApiServerTest.java index b6189d3..f67de1e 100644 --- a/core/src/test/java/io/javaoperatorsdk/jenvtest/sample/KubeApiServerTest.java +++ b/core/src/test/java/io/javaoperatorsdk/jenvtest/sample/KubeApiServerTest.java @@ -26,18 +26,6 @@ void apiServerWithSpecificVersion() { .build())); } - @Test - void usingKubeConfigFileToInitClient() { - var kubeApi = new KubeAPIServer(KubeAPIServerConfigBuilder.anAPIServerConfig() - .withUpdateKubeConfig(true) - .build()); - kubeApi.start(); - - var client = new KubernetesClientBuilder().build(); - - TestUtils.simpleTest(client); - } - @Test void canWaitForEtcdHealthCheckOnStartup() { var kubeApi = new KubeAPIServer(KubeAPIServerConfigBuilder.anAPIServerConfig() From 18a66051e97758dbcf4c725ca91fad89b11d93a4 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 6 Apr 2023 18:29:49 +0200 Subject: [PATCH 03/21] wip --- .../jenvtest/junit/TestUtils.java | 16 +++++++++++++--- .../sample/JUnitFabric8ClientInjectionTest.java | 5 +++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/fabric8/src/test/java/io/javaoperatorsdk/jenvtest/junit/TestUtils.java b/fabric8/src/test/java/io/javaoperatorsdk/jenvtest/junit/TestUtils.java index 916642f..fc23779 100644 --- a/fabric8/src/test/java/io/javaoperatorsdk/jenvtest/junit/TestUtils.java +++ b/fabric8/src/test/java/io/javaoperatorsdk/jenvtest/junit/TestUtils.java @@ -12,10 +12,16 @@ public class TestUtils { + public static final String TEST_1 = "test1"; + public static ConfigMap testConfigMap() { + return testConfigMap(TEST_1); + } + + public static ConfigMap testConfigMap(String name) { return new ConfigMapBuilder() .withMetadata(new ObjectMetaBuilder() - .withName("test1") + .withName(name) .withNamespace("default") .build()) .withData(Map.of("key", "data")) @@ -23,11 +29,15 @@ public static ConfigMap testConfigMap() { } public static void simpleTest() { - simpleTest(new KubernetesClientBuilder().build()); + simpleTest(new KubernetesClientBuilder().build(), "test1"); } public static void simpleTest(KubernetesClient client) { - client.resource(TestUtils.testConfigMap()).create(); + simpleTest(client, TEST_1); + } + + public static void simpleTest(KubernetesClient client, String testResourceName) { + client.resource(TestUtils.testConfigMap(testResourceName)).create(); var cm = client.resource(TestUtils.testConfigMap()).get(); Assertions.assertThat(cm).isNotNull(); diff --git a/fabric8/src/test/java/io/javaoperatorsdk/jenvtest/junit/sample/JUnitFabric8ClientInjectionTest.java b/fabric8/src/test/java/io/javaoperatorsdk/jenvtest/junit/sample/JUnitFabric8ClientInjectionTest.java index 8056cfb..63898db 100644 --- a/fabric8/src/test/java/io/javaoperatorsdk/jenvtest/junit/sample/JUnitFabric8ClientInjectionTest.java +++ b/fabric8/src/test/java/io/javaoperatorsdk/jenvtest/junit/sample/JUnitFabric8ClientInjectionTest.java @@ -21,11 +21,12 @@ class JUnitFabric8ClientInjectionTest { @Test void testClientInjection() { - simpleTest(client); + simpleTest(client, "test1"); } @Test void testKubeConfigInjectionAlsoWorks() { - simpleTest(new KubernetesClientBuilder().withConfig(Config.fromKubeconfig(configYaml)).build()); + simpleTest(new KubernetesClientBuilder().withConfig(Config.fromKubeconfig(configYaml)).build(), + "test2"); } } From b886d1de2d5c1824ecede87c20f2a9e7ed9fbc05 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 6 Apr 2023 18:44:29 +0200 Subject: [PATCH 04/21] test fix --- .../test/java/io/javaoperatorsdk/jenvtest/junit/TestUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fabric8/src/test/java/io/javaoperatorsdk/jenvtest/junit/TestUtils.java b/fabric8/src/test/java/io/javaoperatorsdk/jenvtest/junit/TestUtils.java index fc23779..7a6aff2 100644 --- a/fabric8/src/test/java/io/javaoperatorsdk/jenvtest/junit/TestUtils.java +++ b/fabric8/src/test/java/io/javaoperatorsdk/jenvtest/junit/TestUtils.java @@ -38,7 +38,7 @@ public static void simpleTest(KubernetesClient client) { public static void simpleTest(KubernetesClient client, String testResourceName) { client.resource(TestUtils.testConfigMap(testResourceName)).create(); - var cm = client.resource(TestUtils.testConfigMap()).get(); + var cm = client.resource(TestUtils.testConfigMap(testResourceName)).get(); Assertions.assertThat(cm).isNotNull(); From 2f046d17b7519ceb715278fd6fb137e48aa47443 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 6 Apr 2023 20:17:23 +0200 Subject: [PATCH 05/21] feat: locking file for parallel testing --- .../jenvtest/binary/BinaryDownloader.java | 34 +++++++--- .../jenvtest/binary/DownloadLock.java | 68 +++++++++++++++++++ 2 files changed, 92 insertions(+), 10 deletions(-) create mode 100644 core/src/main/java/io/javaoperatorsdk/jenvtest/binary/DownloadLock.java diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/BinaryDownloader.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/BinaryDownloader.java index 0e001ac..d477b3f 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/BinaryDownloader.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/BinaryDownloader.java @@ -32,7 +32,6 @@ public BinaryDownloader(String jenvtestDir, OSInfo osInfoProvider) { this.jenvtestDir = jenvtestDir; this.osInfoProvider = osInfoProvider; this.binaryRepo = new BinaryRepo(osInfoProvider); - } BinaryDownloader(String jenvtestDir, BinaryRepo binaryRepo, OSInfo osInfoProvider) { @@ -43,14 +42,25 @@ public BinaryDownloader(String jenvtestDir, OSInfo osInfoProvider) { public File download(String version) { log.info("Downloading binaries with version: {}", version); - var tempFile = binaryRepo.downloadVersionToTempFile(version); - File dir = createDirForBinaries(version); - extractFiles(tempFile, dir); - var deleted = tempFile.delete(); - if (!deleted) { - log.warn("Unable to delete temp file: {}", tempFile.getPath()); + DownloadLock lock = + new DownloadLock(version, new File(jenvtestDir, BinaryManager.BINARY_LIST_DIR).getPath()); + + if (lock.tryLock()) { + var tempFile = binaryRepo.downloadVersionToTempFile(version); + File dir = createDirForBinaries(version); + extractFiles(tempFile, dir); + var deleted = tempFile.delete(); + if (!deleted) { + log.warn("Unable to delete temp file: {}", tempFile.getPath()); + } + lock.releaseLock(); + return dir; + } else { + log.debug("Waiting for lock to be deleted for version: {}", version); + lock.waitUntilLockDeleted(); + log.debug("Lock deleted for version: {}", version); + return dirForVersion(version); } - return dir; } public File downloadLatest() { @@ -99,14 +109,18 @@ private File extractEntry(TarArchiveEntry entry, File dir, TarArchiveInputStream } private File createDirForBinaries(String version) { - var dir = new File(jenvtestDir, BinaryManager.BINARY_LIST_DIR + File.separator - + version + Utils.platformSuffix(osInfoProvider)); + var dir = dirForVersion(version); if (!dir.mkdirs()) { throw new JenvtestException("Cannot created director: " + dir.getPath()); } return dir; } + private File dirForVersion(String version) { + return new File(jenvtestDir, BinaryManager.BINARY_LIST_DIR + File.separator + + version + Utils.platformSuffix(osInfoProvider)); + } + public String findLatestVersion() { var allRelevantVersions = listAllRelevantVersions().sorted(Utils.SEMVER_COMPARATOR).collect(Collectors.toList()); diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/DownloadLock.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/DownloadLock.java new file mode 100644 index 0000000..77b72a0 --- /dev/null +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/DownloadLock.java @@ -0,0 +1,68 @@ +package io.javaoperatorsdk.jenvtest.binary; + +import java.io.File; +import java.io.IOException; +import java.nio.file.*; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.javaoperatorsdk.jenvtest.JenvtestException; + +public class DownloadLock { + + private static final Logger log = LoggerFactory.getLogger(DownloadLock.class); + + public static final String LOCK_SUFFIX = ".lock"; + private final String downloadDir; + private final String lockFileName; + + public DownloadLock(String version, String downloadDir) { + this.downloadDir = downloadDir; + this.lockFileName = version + LOCK_SUFFIX; + } + + public boolean tryLock() { + File file = new File(downloadDir, lockFileName); + try { + return file.createNewFile(); + } catch (IOException e) { + throw new JenvtestException(e); + } + } + + public void releaseLock() { + File file = new File(downloadDir, lockFileName); + var deleted = file.delete(); + if (!deleted) { + throw new JenvtestException("Lock file not deleted: " + file.getPath()); + } + } + + public void waitUntilLockDeleted() { + var file = new File(downloadDir); + var path = file.toPath(); + + try (final WatchService watchService = FileSystems.getDefault().newWatchService()) { + path.register(watchService, StandardWatchEventKinds.ENTRY_DELETE); + while (true) { + final WatchKey wk = watchService.take(); + for (WatchEvent event : wk.pollEvents()) { + final Path changed = (Path) event.context(); + log.info("!! Event path: {} event: {}", changed, event); + if (changed.endsWith(lockFileName)) { + return; + } + } + // reset the key + boolean valid = wk.reset(); + if (!valid) { + log.warn("Watch key no longer valid"); + } + } + } catch (IOException | InterruptedException e) { + throw new JenvtestException(e); + } + } + +} From 779a32ac303e8f8cab0f781ff41563cd09b8cfc3 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 6 Apr 2023 20:22:52 +0200 Subject: [PATCH 06/21] fixes --- .../io/javaoperatorsdk/jenvtest/binary/BinaryDownloader.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/BinaryDownloader.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/BinaryDownloader.java index d477b3f..494bd49 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/BinaryDownloader.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/BinaryDownloader.java @@ -42,8 +42,10 @@ public BinaryDownloader(String jenvtestDir, OSInfo osInfoProvider) { public File download(String version) { log.info("Downloading binaries with version: {}", version); + var downloadDir = new File(jenvtestDir, BinaryManager.BINARY_LIST_DIR); + downloadDir.mkdirs(); DownloadLock lock = - new DownloadLock(version, new File(jenvtestDir, BinaryManager.BINARY_LIST_DIR).getPath()); + new DownloadLock(version, downloadDir.getPath()); if (lock.tryLock()) { var tempFile = binaryRepo.downloadVersionToTempFile(version); From 863b0b7fcad6f4f8a9736060fd943f8971263292 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 6 Apr 2023 20:37:38 +0200 Subject: [PATCH 07/21] improvements --- .../jenvtest/binary/BinaryDownloader.java | 12 +++++++---- .../DownloadLock.java => lock/LockFile.java} | 21 +++++++++---------- 2 files changed, 18 insertions(+), 15 deletions(-) rename core/src/main/java/io/javaoperatorsdk/jenvtest/{binary/DownloadLock.java => lock/LockFile.java} (72%) diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/BinaryDownloader.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/BinaryDownloader.java index 494bd49..5cb76f1 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/BinaryDownloader.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/BinaryDownloader.java @@ -17,6 +17,7 @@ import io.javaoperatorsdk.jenvtest.JenvtestException; import io.javaoperatorsdk.jenvtest.Utils; import io.javaoperatorsdk.jenvtest.binary.repo.BinaryRepo; +import io.javaoperatorsdk.jenvtest.lock.LockFile; public class BinaryDownloader { @@ -44,10 +45,13 @@ public File download(String version) { log.info("Downloading binaries with version: {}", version); var downloadDir = new File(jenvtestDir, BinaryManager.BINARY_LIST_DIR); downloadDir.mkdirs(); - DownloadLock lock = - new DownloadLock(version, downloadDir.getPath()); - + LockFile lock = + new LockFile(version + ".lock", downloadDir.getPath()); + var dirForVersion = dirForVersion(version); if (lock.tryLock()) { + if (dirForVersion.exists()) { + return dirForVersion; + } var tempFile = binaryRepo.downloadVersionToTempFile(version); File dir = createDirForBinaries(version); extractFiles(tempFile, dir); @@ -61,7 +65,7 @@ public File download(String version) { log.debug("Waiting for lock to be deleted for version: {}", version); lock.waitUntilLockDeleted(); log.debug("Lock deleted for version: {}", version); - return dirForVersion(version); + return dirForVersion; } } diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/DownloadLock.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/lock/LockFile.java similarity index 72% rename from core/src/main/java/io/javaoperatorsdk/jenvtest/binary/DownloadLock.java rename to core/src/main/java/io/javaoperatorsdk/jenvtest/lock/LockFile.java index 77b72a0..41d5a0b 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/binary/DownloadLock.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/lock/LockFile.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.jenvtest.binary; +package io.javaoperatorsdk.jenvtest.lock; import java.io.File; import java.io.IOException; @@ -9,21 +9,20 @@ import io.javaoperatorsdk.jenvtest.JenvtestException; -public class DownloadLock { +public class LockFile { - private static final Logger log = LoggerFactory.getLogger(DownloadLock.class); + private static final Logger log = LoggerFactory.getLogger(LockFile.class); - public static final String LOCK_SUFFIX = ".lock"; - private final String downloadDir; + private final String dir; private final String lockFileName; - public DownloadLock(String version, String downloadDir) { - this.downloadDir = downloadDir; - this.lockFileName = version + LOCK_SUFFIX; + public LockFile(String lockFileName, String dir) { + this.dir = dir; + this.lockFileName = lockFileName; } public boolean tryLock() { - File file = new File(downloadDir, lockFileName); + File file = new File(dir, lockFileName); try { return file.createNewFile(); } catch (IOException e) { @@ -32,7 +31,7 @@ public boolean tryLock() { } public void releaseLock() { - File file = new File(downloadDir, lockFileName); + File file = new File(dir, lockFileName); var deleted = file.delete(); if (!deleted) { throw new JenvtestException("Lock file not deleted: " + file.getPath()); @@ -40,7 +39,7 @@ public void releaseLock() { } public void waitUntilLockDeleted() { - var file = new File(downloadDir); + var file = new File(dir); var path = file.toPath(); try (final WatchService watchService = FileSystems.getDefault().newWatchService()) { From a685a98dfa1c0a0885bf1035a28bf50d32ded9b5 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 6 Apr 2023 22:54:31 +0200 Subject: [PATCH 08/21] fixed parallelism --- pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index 0fa748a..9f0f719 100644 --- a/pom.xml +++ b/pom.xml @@ -229,6 +229,8 @@ junit.jupiter.execution.parallel.enabled = true junit.jupiter.execution.parallel.mode.default = concurrent junit.jupiter.execution.parallel.mode.classes.default = concurrent + junit.jupiter.execution.parallel.config.strategy = fixed + junit.jupiter.execution.parallel.config.fixed.parallelism = 3 From 4fdfbf364320341503cb889aff24402887ddda45 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 6 Apr 2023 23:02:28 +0200 Subject: [PATCH 09/21] wip --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9f0f719..56e9137 100644 --- a/pom.xml +++ b/pom.xml @@ -230,7 +230,7 @@ junit.jupiter.execution.parallel.mode.default = concurrent junit.jupiter.execution.parallel.mode.classes.default = concurrent junit.jupiter.execution.parallel.config.strategy = fixed - junit.jupiter.execution.parallel.config.fixed.parallelism = 3 + junit.jupiter.execution.parallel.config.fixed.parallelism = 4 From 22b192904cd7eec2986bced0a4527a943434f403 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 6 Apr 2023 23:29:06 +0200 Subject: [PATCH 10/21] wip --- pom.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 56e9137..1a09d4e 100644 --- a/pom.xml +++ b/pom.xml @@ -226,11 +226,11 @@ - junit.jupiter.execution.parallel.enabled = true - junit.jupiter.execution.parallel.mode.default = concurrent - junit.jupiter.execution.parallel.mode.classes.default = concurrent - junit.jupiter.execution.parallel.config.strategy = fixed - junit.jupiter.execution.parallel.config.fixed.parallelism = 4 + + + + + From faca7a009cb2e8d20300d42df336fff2e19c0fc6 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 6 Apr 2023 23:38:33 +0200 Subject: [PATCH 11/21] fix maven --- pom.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 1a09d4e..56e9137 100644 --- a/pom.xml +++ b/pom.xml @@ -226,11 +226,11 @@ - - - - - + junit.jupiter.execution.parallel.enabled = true + junit.jupiter.execution.parallel.mode.default = concurrent + junit.jupiter.execution.parallel.mode.classes.default = concurrent + junit.jupiter.execution.parallel.config.strategy = fixed + junit.jupiter.execution.parallel.config.fixed.parallelism = 4 From 96f0d924bd385c36961124376116242339233764 Mon Sep 17 00:00:00 2001 From: csviri Date: Mon, 10 Apr 2023 15:36:50 +0200 Subject: [PATCH 12/21] wip --- .../jenvtest/process/ProcessReadinessChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java index d7b1ccd..c64f1e8 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java @@ -28,7 +28,7 @@ public class ProcessReadinessChecker { private static final Logger log = LoggerFactory.getLogger(ProcessReadinessChecker.class); - public static final int STARTUP_TIMEOUT = 10_000; + public static final int STARTUP_TIMEOUT = 40_000; public static final int POLLING_INTERVAL = 150; private final int port; From 0121b6491c21998d64ae47be5bbb7b5f56818177 Mon Sep 17 00:00:00 2001 From: csviri Date: Mon, 10 Apr 2023 15:54:09 +0200 Subject: [PATCH 13/21] wip --- .../io/javaoperatorsdk/jenvtest/KubeAPIServerConfigBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfigBuilder.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfigBuilder.java index c423354..c863ae5 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfigBuilder.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfigBuilder.java @@ -72,7 +72,7 @@ public KubeAPIServerConfig build() { this.waitForEtcdHealthCheckOnStartup = Boolean.parseBoolean(waitForEtcdHealthCheckOnStartup); } else { - this.waitForEtcdHealthCheckOnStartup = false; + this.waitForEtcdHealthCheckOnStartup = true; } } return new KubeAPIServerConfig(jenvtestDir, apiServerVersion, offlineMode, apiServerFlags, From f07efe22a12cd6cf1e31376518d69fa8a1534af5 Mon Sep 17 00:00:00 2001 From: csviri Date: Mon, 10 Apr 2023 16:02:32 +0200 Subject: [PATCH 14/21] wip --- .../javaoperatorsdk/jenvtest/KubeAPIServerConfigBuilder.java | 4 ++-- .../jenvtest/process/ProcessReadinessChecker.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfigBuilder.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfigBuilder.java index c863ae5..8ae75d2 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfigBuilder.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfigBuilder.java @@ -67,12 +67,12 @@ public KubeAPIServerConfig build() { } } if (waitForEtcdHealthCheckOnStartup == null) { - var waitForEtcdHealthCheckOnStartup = System.getenv(JENVTEST_API_SERVER_VERSION_ENV_VAR); + var waitForEtcdHealthCheckOnStartup = System.getenv(JENVTEST_WAIT_FOR_ETCD_HEALTH_CHECK); if (waitForEtcdHealthCheckOnStartup != null) { this.waitForEtcdHealthCheckOnStartup = Boolean.parseBoolean(waitForEtcdHealthCheckOnStartup); } else { - this.waitForEtcdHealthCheckOnStartup = true; + this.waitForEtcdHealthCheckOnStartup = false; } } return new KubeAPIServerConfig(jenvtestDir, apiServerVersion, offlineMode, apiServerFlags, diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java index c64f1e8..56e27fa 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java @@ -28,7 +28,7 @@ public class ProcessReadinessChecker { private static final Logger log = LoggerFactory.getLogger(ProcessReadinessChecker.class); - public static final int STARTUP_TIMEOUT = 40_000; + public static final int STARTUP_TIMEOUT = 120_000; public static final int POLLING_INTERVAL = 150; private final int port; From 815089ec9df77e5e5dbf40e7fc7ff79e95ba6521 Mon Sep 17 00:00:00 2001 From: csviri Date: Mon, 10 Apr 2023 16:05:51 +0200 Subject: [PATCH 15/21] parallelism --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 56e9137..161ab66 100644 --- a/pom.xml +++ b/pom.xml @@ -230,7 +230,7 @@ junit.jupiter.execution.parallel.mode.default = concurrent junit.jupiter.execution.parallel.mode.classes.default = concurrent junit.jupiter.execution.parallel.config.strategy = fixed - junit.jupiter.execution.parallel.config.fixed.parallelism = 4 + junit.jupiter.execution.parallel.config.fixed.parallelism = 2 From 826cb2bb2e370edd47e5d85461835fbc215923c1 Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 11 Apr 2023 09:24:23 +0200 Subject: [PATCH 16/21] experiment --- .../jenvtest/process/KubeAPIServerProcess.java | 5 +++++ pom.xml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java index 65f6c80..5ee8644 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java @@ -86,6 +86,11 @@ private List createCommand(File apiServerBinary, int apiServerPort, int public void waitUntilReady() { new ProcessReadinessChecker(apiServerPort, "readyz", "Kube API Server", true).waitUntilReady(); + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } } public void stopApiServer() { diff --git a/pom.xml b/pom.xml index 161ab66..f6738b8 100644 --- a/pom.xml +++ b/pom.xml @@ -230,7 +230,7 @@ junit.jupiter.execution.parallel.mode.default = concurrent junit.jupiter.execution.parallel.mode.classes.default = concurrent junit.jupiter.execution.parallel.config.strategy = fixed - junit.jupiter.execution.parallel.config.fixed.parallelism = 2 + junit.jupiter.execution.parallel.config.fixed.parallelism = 5 From 3c2f8820ed4631f58eb4ffa7ff43299bcad9256c Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 11 Apr 2023 10:38:05 +0200 Subject: [PATCH 17/21] cert lock --- .../jenvtest/cert/CertManager.java | 37 +++++++++++++------ .../process/KubeAPIServerProcess.java | 5 --- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/cert/CertManager.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/cert/CertManager.java index a924eee..653ece2 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/cert/CertManager.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/cert/CertManager.java @@ -28,6 +28,7 @@ import org.slf4j.LoggerFactory; import io.javaoperatorsdk.jenvtest.JenvtestException; +import io.javaoperatorsdk.jenvtest.lock.LockFile; public class CertManager { @@ -46,16 +47,33 @@ public CertManager(String jenvtestDir) { } public void createCertificatesIfNeeded() { - generateAPIServerCertificates(); - generateUserCertificates(); + if (certFilesPresent()) { + return; + } + // locking is for parallel execution + LockFile lockFile = new LockFile("cert.lock", jenvtestDir); + if (lockFile.tryLock()) { + try { + generateAPIServerCertificates(); + generateUserCertificates(); + } finally { + lockFile.releaseLock(); + } + } else { + lockFile.waitUntilLockDeleted(); + } + } + + private boolean certFilesPresent() { + var apiCert = new File(jenvtestDir, API_SERVER_CERT_NAME); + var apiKey = new File(jenvtestDir, API_SERVER_KEY_NAME); + var clientCert = new File(jenvtestDir, CLIENT_CERT_NAME); + var clientKey = new File(jenvtestDir, CLIENT_KEY_NAME); + + return apiCert.exists() && apiKey.exists() && clientCert.exists() && clientKey.exists(); } private void generateAPIServerCertificates() { - var cert = new File(jenvtestDir, API_SERVER_CERT_NAME); - var key = new File(jenvtestDir, API_SERVER_KEY_NAME); - if (cert.exists() && key.exists()) { - return; - } log.info("Generating API Server certificates"); generateKeyAndCertificate("CN=example.org", new File(jenvtestDir, API_SERVER_KEY_NAME), new File(jenvtestDir, API_SERVER_CERT_NAME), @@ -70,11 +88,6 @@ private GeneralName dns(String dns) { } private void generateUserCertificates() { - var cert = new File(jenvtestDir, CLIENT_CERT_NAME); - var key = new File(jenvtestDir, CLIENT_KEY_NAME); - if (cert.exists() && key.exists()) { - return; - } log.info("Generating Client certificates"); generateKeyAndCertificate("O=system:masters,CN=jenvtest", new File(jenvtestDir, CLIENT_KEY_NAME), diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java index 5ee8644..65f6c80 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java @@ -86,11 +86,6 @@ private List createCommand(File apiServerBinary, int apiServerPort, int public void waitUntilReady() { new ProcessReadinessChecker(apiServerPort, "readyz", "Kube API Server", true).waitUntilReady(); - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } } public void stopApiServer() { From 141b31ff3d2c4dd12f42741b396a5c195b0bbe87 Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 11 Apr 2023 13:25:03 +0200 Subject: [PATCH 18/21] wip --- .../jenvtest/process/EtcdProcess.java | 2 +- .../process/KubeAPIServerProcess.java | 4 +- .../process/ProcessReadinessChecker.java | 66 ++++++++++++++----- 3 files changed, 52 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/EtcdProcess.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/EtcdProcess.java index 23b7b56..91982f9 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/EtcdProcess.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/EtcdProcess.java @@ -79,7 +79,7 @@ public int startEtcd() { } private void waitUntilEtcdHealthy(int port) { - new ProcessReadinessChecker(port, "health", "etcd", false).waitUntilReady(); + new ProcessReadinessChecker().waitUntilReady(port, "health", "etcd", false); } public void cleanEtcdData() { diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java index 65f6c80..5df49b4 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java @@ -85,7 +85,9 @@ private List createCommand(File apiServerBinary, int apiServerPort, int } public void waitUntilReady() { - new ProcessReadinessChecker(apiServerPort, "readyz", "Kube API Server", true).waitUntilReady(); + var readinessChecker = new ProcessReadinessChecker(); + readinessChecker.waitUntilReady(apiServerPort, "readyz", "Kube API Server", true); + readinessChecker.waitUntilDefaultNamespaceAvailable(apiServerPort, binaryManager, certManager); } public void stopApiServer() { diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java index 56e27fa..be0ab8e 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java @@ -14,6 +14,7 @@ import java.security.cert.X509Certificate; import java.time.LocalTime; import java.time.temporal.ChronoUnit; +import java.util.function.BooleanSupplier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; @@ -24,34 +25,59 @@ import org.slf4j.LoggerFactory; import io.javaoperatorsdk.jenvtest.JenvtestException; +import io.javaoperatorsdk.jenvtest.binary.BinaryManager; +import io.javaoperatorsdk.jenvtest.cert.CertManager; public class ProcessReadinessChecker { + private static final Logger log = LoggerFactory.getLogger(ProcessReadinessChecker.class); - public static final int STARTUP_TIMEOUT = 120_000; - public static final int POLLING_INTERVAL = 150; + public static final int STARTUP_TIMEOUT = 60_000; + public static final int POLLING_INTERVAL = 200; - private final int port; - private final String readyCheckPath; - private final String processName; - private final boolean useTLS; + public void waitUntilDefaultNamespaceAvailable(int apiServerPort, + BinaryManager binaryManager, + CertManager certManager) { + try { + var startedAt = LocalTime.now(); + while (true) { + if (defaultNamespaceExists(apiServerPort, binaryManager, certManager)) { + return; + } + if (LocalTime.now().isAfter(startedAt.plus(STARTUP_TIMEOUT, ChronoUnit.MILLIS))) { + throw new JenvtestException("Cannot find default namespace in api server"); + } + Thread.sleep(POLLING_INTERVAL); + } + } catch (IOException e) { + throw new JenvtestException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new JenvtestException(e); + } - public ProcessReadinessChecker(int port, String readyCheckPath, String processName, - boolean useTLS) { - this.port = port; - this.readyCheckPath = readyCheckPath; - this.processName = processName; - this.useTLS = useTLS; } - public void waitUntilReady() { + private boolean defaultNamespaceExists(int apiServerPort, BinaryManager binaryManager, + CertManager certManager) throws IOException, InterruptedException { + var process = new ProcessBuilder(binaryManager.binaries().getKubectl().getPath(), + "--client-certificate=" + certManager.getClientCertPath(), + "--client-key=" + certManager.getClientKeyPath(), + "--certificate-authority=" + certManager.getAPIServerCertPath(), + "--server=https://127.0.0.1:" + apiServerPort, + "get", "ns", "default").start(); + return process.waitFor() == 0; + } + + public void waitUntilReady(int port, String readyCheckPath, String processName, + boolean useTLS) { try { var client = getHttpClient(); - var request = getHttpRequest(); + var request = getHttpRequest(useTLS, readyCheckPath, port); var startedAt = LocalTime.now(); while (true) { - if (ready(client, request)) { + if (ready(client, request, processName, port)) { return; } if (LocalTime.now().isAfter(startedAt.plus(STARTUP_TIMEOUT, ChronoUnit.MILLIS))) { @@ -65,7 +91,11 @@ public void waitUntilReady() { } } - private boolean ready(HttpClient client, HttpRequest request) { + private static void waitUntilWithTimeout(BooleanSupplier predicate) { + + } + + private boolean ready(HttpClient client, HttpRequest request, String processName, int port) { try { var response = client.send(request, HttpResponse.BodyHandlers.ofString()); log.debug("Ready Response message:{} code: {} for {} on Port: {}", response.body(), @@ -84,7 +114,7 @@ private boolean ready(HttpClient client, HttpRequest request) { } } - private HttpRequest getHttpRequest() { + private HttpRequest getHttpRequest(boolean useTLS, String readyCheckPath, int port) { try { return HttpRequest.newBuilder() .uri(new URI((useTLS ? "https" : "http") + "://127.0.0.1:" + port + "/" + readyCheckPath)) @@ -128,7 +158,7 @@ public void checkServerTrusted( @Override public void checkClientTrusted(X509Certificate[] chain, String authType, - SSLEngine engine) throws CertificateException { + SSLEngine engine) { } From b8e720dcad88910c8861b340089d5fdee6b923b3 Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 11 Apr 2023 14:24:03 +0200 Subject: [PATCH 19/21] improvement --- .../process/KubeAPIServerProcess.java | 3 +- .../process/ProcessReadinessChecker.java | 56 +++++++++---------- 2 files changed, 27 insertions(+), 32 deletions(-) diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java index 5df49b4..7f184e5 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java @@ -17,6 +17,7 @@ public class KubeAPIServerProcess { private static final Logger log = LoggerFactory.getLogger(KubeAPIServerProcess.class); private static final Logger apiLog = LoggerFactory.getLogger(KubeAPIServerProcess.class .getName() + ".APIServerProcessLogs"); + public static final String KUBE_API_SERVER = "Kube API Server"; private final CertManager certManager; private final BinaryManager binaryManager; @@ -86,7 +87,7 @@ private List createCommand(File apiServerBinary, int apiServerPort, int public void waitUntilReady() { var readinessChecker = new ProcessReadinessChecker(); - readinessChecker.waitUntilReady(apiServerPort, "readyz", "Kube API Server", true); + readinessChecker.waitUntilReady(apiServerPort, "readyz", KUBE_API_SERVER, true); readinessChecker.waitUntilDefaultNamespaceAvailable(apiServerPort, binaryManager, certManager); } diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java index be0ab8e..4b20295 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java @@ -28,6 +28,8 @@ import io.javaoperatorsdk.jenvtest.binary.BinaryManager; import io.javaoperatorsdk.jenvtest.cert.CertManager; +import static io.javaoperatorsdk.jenvtest.process.KubeAPIServerProcess.KUBE_API_SERVER; + public class ProcessReadinessChecker { private static final Logger log = LoggerFactory.getLogger(ProcessReadinessChecker.class); @@ -39,45 +41,41 @@ public class ProcessReadinessChecker { public void waitUntilDefaultNamespaceAvailable(int apiServerPort, BinaryManager binaryManager, CertManager certManager) { + pollWithTimeout(() -> defaultNamespaceExists(apiServerPort, binaryManager, certManager), + KUBE_API_SERVER); + } + + private boolean defaultNamespaceExists(int apiServerPort, BinaryManager binaryManager, + CertManager certManager) { try { - var startedAt = LocalTime.now(); - while (true) { - if (defaultNamespaceExists(apiServerPort, binaryManager, certManager)) { - return; - } - if (LocalTime.now().isAfter(startedAt.plus(STARTUP_TIMEOUT, ChronoUnit.MILLIS))) { - throw new JenvtestException("Cannot find default namespace in api server"); - } - Thread.sleep(POLLING_INTERVAL); - } + Process process = new ProcessBuilder(binaryManager.binaries().getKubectl().getPath(), + "--client-certificate=" + certManager.getClientCertPath(), + "--client-key=" + certManager.getClientKeyPath(), + "--certificate-authority=" + certManager.getAPIServerCertPath(), + "--server=https://127.0.0.1:" + apiServerPort, + "--request-timeout=5s", + "get", "ns", "default").start(); + return process.waitFor() == 0; } catch (IOException e) { - throw new JenvtestException(e); + throw new RuntimeException(e); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - throw new JenvtestException(e); + throw new RuntimeException(e); } - - } - - private boolean defaultNamespaceExists(int apiServerPort, BinaryManager binaryManager, - CertManager certManager) throws IOException, InterruptedException { - var process = new ProcessBuilder(binaryManager.binaries().getKubectl().getPath(), - "--client-certificate=" + certManager.getClientCertPath(), - "--client-key=" + certManager.getClientKeyPath(), - "--certificate-authority=" + certManager.getAPIServerCertPath(), - "--server=https://127.0.0.1:" + apiServerPort, - "get", "ns", "default").start(); - return process.waitFor() == 0; } public void waitUntilReady(int port, String readyCheckPath, String processName, boolean useTLS) { + var client = getHttpClient(); + var request = getHttpRequest(useTLS, readyCheckPath, port); + pollWithTimeout(() -> ready(client, request, processName, port), processName); + } + + private static void pollWithTimeout(BooleanSupplier predicate, String processName) { try { - var client = getHttpClient(); - var request = getHttpRequest(useTLS, readyCheckPath, port); var startedAt = LocalTime.now(); while (true) { - if (ready(client, request, processName, port)) { + if (predicate.getAsBoolean()) { return; } if (LocalTime.now().isAfter(startedAt.plus(STARTUP_TIMEOUT, ChronoUnit.MILLIS))) { @@ -91,10 +89,6 @@ public void waitUntilReady(int port, String readyCheckPath, String processName, } } - private static void waitUntilWithTimeout(BooleanSupplier predicate) { - - } - private boolean ready(HttpClient client, HttpRequest request, String processName, int port) { try { var response = client.send(request, HttpResponse.BodyHandlers.ofString()); From dccfef149c4946ff96ec90b8636e9d1e73b276d2 Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 11 Apr 2023 14:31:56 +0200 Subject: [PATCH 20/21] improvements --- .../java/io/javaoperatorsdk/jenvtest/cert/CertManager.java | 3 +++ .../main/java/io/javaoperatorsdk/jenvtest/lock/LockFile.java | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/cert/CertManager.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/cert/CertManager.java index 653ece2..bbf2df1 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/cert/CertManager.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/cert/CertManager.java @@ -53,6 +53,9 @@ public void createCertificatesIfNeeded() { // locking is for parallel execution LockFile lockFile = new LockFile("cert.lock", jenvtestDir); if (lockFile.tryLock()) { + if (certFilesPresent()) { + return; + } try { generateAPIServerCertificates(); generateUserCertificates(); diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/lock/LockFile.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/lock/LockFile.java index 41d5a0b..d2fb3b5 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/lock/LockFile.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/lock/LockFile.java @@ -59,7 +59,10 @@ public void waitUntilLockDeleted() { log.warn("Watch key no longer valid"); } } - } catch (IOException | InterruptedException e) { + } catch (IOException e) { + throw new JenvtestException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); throw new JenvtestException(e); } } From d26707d8bc80b3f3a62598b223d089a42f77c828 Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 11 Apr 2023 14:48:38 +0200 Subject: [PATCH 21/21] improvements --- .../java/io/javaoperatorsdk/jenvtest/lock/LockFile.java | 7 ++++--- .../jenvtest/process/ProcessReadinessChecker.java | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/lock/LockFile.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/lock/LockFile.java index d2fb3b5..3d48dde 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/lock/LockFile.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/lock/LockFile.java @@ -32,9 +32,10 @@ public boolean tryLock() { public void releaseLock() { File file = new File(dir, lockFileName); - var deleted = file.delete(); - if (!deleted) { - throw new JenvtestException("Lock file not deleted: " + file.getPath()); + try { + Files.deleteIfExists(file.toPath()); + } catch (IOException e) { + throw new JenvtestException(e); } } diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java index 4b20295..eed7b54 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java @@ -57,10 +57,10 @@ private boolean defaultNamespaceExists(int apiServerPort, BinaryManager binaryMa "get", "ns", "default").start(); return process.waitFor() == 0; } catch (IOException e) { - throw new RuntimeException(e); + throw new JenvtestException(e); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - throw new RuntimeException(e); + throw new JenvtestException(e); } }