Skip to content
This repository was archived by the owner on Apr 10, 2024. It is now read-only.

Commit 33e090c

Browse files
authored
feat: config startup timeout (#80)
1 parent bd9c173 commit 33e090c

File tree

7 files changed

+59
-16
lines changed

7 files changed

+59
-16
lines changed

core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public KubeAPIServer(KubeAPIServerConfig config) {
3131
this.certManager = new CertManager(config.getJenvtestDir());
3232
this.kubeConfig = new KubeConfig(certManager, binaryManager);
3333
this.etcdProcess = new EtcdProcess(binaryManager, this,
34-
config.isWaitForEtcdHealthCheckOnStartup());
34+
config.isWaitForEtcdHealthCheckOnStartup(), config.getStartupTimeout());
3535
this.kubeApiServerProcess =
3636
new KubeAPIServerProcess(certManager, binaryManager, this, config);
3737
}

core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfig.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,27 @@ public class KubeAPIServerConfig {
4343
private final boolean updateKubeConfig;
4444

4545
/**
46-
* This is mostly not needed, and increases startup time.
46+
* This is mostly not needed, and increases startup time. Might be removed in the future.
4747
*/
4848
private final boolean waitForEtcdHealthCheckOnStartup;
4949

50+
/**
51+
* Startup timeout of Kube API Server (and ETCD if enabled - might adds up in this case), the
52+
* default value is quite high, to support parallel tests. Tuning is possible based on the actual
53+
* setup.
54+
*/
55+
private final int startupTimeout;
56+
5057
KubeAPIServerConfig(String jenvtestDir, String apiServerVersion, boolean offlineMode,
5158
List<String> apiServerFlags, boolean updateKubeConfig,
52-
boolean waitForEtcdHealthCheckOnStartup) {
59+
boolean waitForEtcdHealthCheckOnStartup, int startupTimeout) {
5360
this.jenvtestDir = jenvtestDir;
5461
this.apiServerVersion = apiServerVersion;
5562
this.offlineMode = offlineMode;
5663
this.apiServerFlags = apiServerFlags;
5764
this.updateKubeConfig = updateKubeConfig;
5865
this.waitForEtcdHealthCheckOnStartup = waitForEtcdHealthCheckOnStartup;
66+
this.startupTimeout = startupTimeout;
5967
}
6068

6169
public String getJenvtestDir() {
@@ -81,4 +89,8 @@ public boolean isUpdateKubeConfig() {
8189
public boolean isWaitForEtcdHealthCheckOnStartup() {
8290
return waitForEtcdHealthCheckOnStartup;
8391
}
92+
93+
public int getStartupTimeout() {
94+
return startupTimeout;
95+
}
8496
}

core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfigBuilder.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public final class KubeAPIServerConfigBuilder {
1212
public static final String JENVTEST_API_SERVER_VERSION_ENV_VAR = "JENVTEST_API_SERVER_VERSION";
1313
public static final String JENVTEST_WAIT_FOR_ETCD_HEALTH_CHECK =
1414
"JENVTEST_WAIT_FOR_ETCD_HEALTH_CHECK";
15+
public static final String JENVTEST_STARTUP_TIMEOUT = "JENVTEST_STARTUP_TIMEOUT";
1516

1617
public static final String DIRECTORY_NAME = ".jenvtest";
1718

@@ -21,6 +22,7 @@ public final class KubeAPIServerConfigBuilder {
2122
private boolean updateKubeConfig = false;
2223
private final List<String> apiServerFlags = new ArrayList<>(0);
2324
private Boolean waitForEtcdHealthCheckOnStartup;
25+
private Integer startupTimeout;
2426

2527
public KubeAPIServerConfigBuilder() {}
2628

@@ -75,8 +77,16 @@ public KubeAPIServerConfig build() {
7577
this.waitForEtcdHealthCheckOnStartup = false;
7678
}
7779
}
80+
if (startupTimeout == null) {
81+
var envStartupTimeout = System.getenv(JENVTEST_STARTUP_TIMEOUT);
82+
if (envStartupTimeout != null) {
83+
this.startupTimeout = Integer.parseInt(envStartupTimeout);
84+
} else {
85+
this.startupTimeout = 60_000;
86+
}
87+
}
7888
return new KubeAPIServerConfig(jenvtestDir, apiServerVersion, offlineMode, apiServerFlags,
79-
updateKubeConfig, waitForEtcdHealthCheckOnStartup);
89+
updateKubeConfig, waitForEtcdHealthCheckOnStartup, startupTimeout);
8090
}
8191

8292
public KubeAPIServerConfigBuilder withUpdateKubeConfig(boolean updateKubeConfig) {
@@ -102,6 +112,11 @@ public KubeAPIServerConfigBuilder withApiServerFlag(String key) {
102112
return this;
103113
}
104114

115+
public KubeAPIServerConfigBuilder withStartupTimeout(Integer startupTimeout) {
116+
this.startupTimeout = startupTimeout;
117+
return this;
118+
}
119+
105120
public KubeAPIServerConfigBuilder withWaitForEtcdHealthCheckOnStartup(
106121
boolean waitForEtcdHealthCheckOnStartup) {
107122
this.waitForEtcdHealthCheckOnStartup = waitForEtcdHealthCheckOnStartup;

core/src/main/java/io/javaoperatorsdk/jenvtest/process/EtcdProcess.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,17 @@ public class EtcdProcess {
2424
private volatile boolean stopped = false;
2525
private final UnexpectedProcessStopHandler processStopHandler;
2626
private final boolean waitForHealthCheck;
27+
private final int startupTimeout;
2728
private File tempWalDir;
2829
private File tempDataDir;
2930

3031
public EtcdProcess(BinaryManager binaryManager,
31-
UnexpectedProcessStopHandler processStopHandler, boolean waitForHealthCheck) {
32+
UnexpectedProcessStopHandler processStopHandler, boolean waitForHealthCheck,
33+
int startupTimeout) {
3234
this.binaryManager = binaryManager;
3335
this.processStopHandler = processStopHandler;
3436
this.waitForHealthCheck = waitForHealthCheck;
37+
this.startupTimeout = startupTimeout;
3538
}
3639

3740
public int startEtcd() {
@@ -79,7 +82,7 @@ public int startEtcd() {
7982
}
8083

8184
private void waitUntilEtcdHealthy(int port) {
82-
new ProcessReadinessChecker().waitUntilReady(port, "health", "etcd", false);
85+
new ProcessReadinessChecker().waitUntilReady(port, "health", "etcd", false, startupTimeout);
8386
}
8487

8588
public void cleanEtcdData() {

core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,12 @@ private List<String> createCommand(File apiServerBinary, int apiServerPort, int
8787

8888
public void waitUntilReady() {
8989
var readinessChecker = new ProcessReadinessChecker();
90-
readinessChecker.waitUntilReady(apiServerPort, "readyz", KUBE_API_SERVER, true);
91-
readinessChecker.waitUntilDefaultNamespaceAvailable(apiServerPort, binaryManager, certManager);
90+
var timeout = config.getStartupTimeout();
91+
var startTime = System.currentTimeMillis();
92+
readinessChecker.waitUntilReady(apiServerPort, "readyz", KUBE_API_SERVER, true, timeout);
93+
int newTimout = (int) (timeout - (System.currentTimeMillis() - startTime));
94+
readinessChecker.waitUntilDefaultNamespaceAvailable(apiServerPort, binaryManager, certManager,
95+
newTimout);
9296
}
9397

9498
public void stopApiServer() {

core/src/main/java/io/javaoperatorsdk/jenvtest/process/ProcessReadinessChecker.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,13 @@ public class ProcessReadinessChecker {
3434

3535
private static final Logger log = LoggerFactory.getLogger(ProcessReadinessChecker.class);
3636

37-
public static final int STARTUP_TIMEOUT = 60_000;
3837
public static final int POLLING_INTERVAL = 200;
3938

40-
4139
public void waitUntilDefaultNamespaceAvailable(int apiServerPort,
4240
BinaryManager binaryManager,
43-
CertManager certManager) {
41+
CertManager certManager, int timeoutMillis) {
4442
pollWithTimeout(() -> defaultNamespaceExists(apiServerPort, binaryManager, certManager),
45-
KUBE_API_SERVER);
43+
KUBE_API_SERVER, timeoutMillis);
4644
}
4745

4846
private boolean defaultNamespaceExists(int apiServerPort, BinaryManager binaryManager,
@@ -65,20 +63,21 @@ private boolean defaultNamespaceExists(int apiServerPort, BinaryManager binaryMa
6563
}
6664

6765
public void waitUntilReady(int port, String readyCheckPath, String processName,
68-
boolean useTLS) {
66+
boolean useTLS, int timeoutMillis) {
6967
var client = getHttpClient();
7068
var request = getHttpRequest(useTLS, readyCheckPath, port);
71-
pollWithTimeout(() -> ready(client, request, processName, port), processName);
69+
pollWithTimeout(() -> ready(client, request, processName, port), processName, timeoutMillis);
7270
}
7371

74-
private static void pollWithTimeout(BooleanSupplier predicate, String processName) {
72+
private static void pollWithTimeout(BooleanSupplier predicate, String processName,
73+
int timeoutMillis) {
7574
try {
7675
var startedAt = LocalTime.now();
7776
while (true) {
7877
if (predicate.getAsBoolean()) {
7978
return;
8079
}
81-
if (LocalTime.now().isAfter(startedAt.plus(STARTUP_TIMEOUT, ChronoUnit.MILLIS))) {
80+
if (LocalTime.now().isAfter(startedAt.plus(timeoutMillis, ChronoUnit.MILLIS))) {
8281
throw new JenvtestException(processName + " did not start properly");
8382
}
8483
Thread.sleep(POLLING_INTERVAL);

core/src/test/java/io/javaoperatorsdk/jenvtest/sample/KubeApiServerTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
import io.fabric8.kubernetes.client.Config;
66
import io.fabric8.kubernetes.client.KubernetesClient;
77
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
8+
import io.javaoperatorsdk.jenvtest.JenvtestException;
89
import io.javaoperatorsdk.jenvtest.KubeAPIServer;
910
import io.javaoperatorsdk.jenvtest.KubeAPIServerConfigBuilder;
1011

1112
import static io.javaoperatorsdk.jenvtest.sample.TestUtils.NON_LATEST_API_SERVER_VERSION;
1213
import static io.javaoperatorsdk.jenvtest.sample.TestUtils.simpleTest;
1314
import static org.assertj.core.api.Assertions.assertThat;
15+
import static org.junit.jupiter.api.Assertions.assertThrows;
1416

1517
class KubeApiServerTest {
1618

@@ -66,6 +68,14 @@ void creatingClientFromConfigString() {
6668
kubeApi.stop();
6769
}
6870

71+
@Test
72+
void canSetStartupTimeout() {
73+
var kubeApi = new KubeAPIServer(KubeAPIServerConfigBuilder.anAPIServerConfig()
74+
.withStartupTimeout(500)
75+
.build());
76+
assertThrows(JenvtestException.class, kubeApi::start);
77+
}
78+
6979
void testWithAPIServer(KubeAPIServer kubeApi) {
7080
kubeApi.start();
7181
var client = createClient(kubeApi.getKubeConfigYaml());

0 commit comments

Comments
 (0)