diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfig.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfig.java index 1a60e8f..8d26ec7 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfig.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfig.java @@ -1,5 +1,6 @@ package io.javaoperatorsdk.jenvtest; +import java.util.List; import java.util.Optional; public class KubeAPIServerConfig { @@ -20,10 +21,19 @@ public class KubeAPIServerConfig { */ private final boolean offlineMode; - KubeAPIServerConfig(String jenvtestDir, String apiServerVersion, boolean offlineMode) { + /** + * Flags to pass to Kube API Server on startup. Key and value are two separated items, like + * specifying min-request-timeout needs to add in order two values: "--min-request-timeout" and + * "300" for the actual desired value. + */ + private final List apiServerFlags; + + KubeAPIServerConfig(String jenvtestDir, String apiServerVersion, boolean offlineMode, + List apiServerFlags) { this.jenvtestDir = jenvtestDir; this.apiServerVersion = apiServerVersion; this.offlineMode = offlineMode; + this.apiServerFlags = apiServerFlags; } public String getJenvtestDir() { @@ -37,4 +47,8 @@ public Optional getApiServerVersion() { public boolean isOfflineMode() { return offlineMode; } + + public List getApiServerFlags() { + return apiServerFlags; + } } diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfigBuilder.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfigBuilder.java index d630d18..4e59fb0 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfigBuilder.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/KubeAPIServerConfigBuilder.java @@ -1,6 +1,8 @@ package io.javaoperatorsdk.jenvtest; import java.io.File; +import java.util.ArrayList; +import java.util.List; public final class KubeAPIServerConfigBuilder { @@ -13,6 +15,7 @@ public final class KubeAPIServerConfigBuilder { private String jenvtestDir; private String apiServerVersion; private Boolean offlineMode; + private final List apiServerFlags = new ArrayList<>(0); public KubeAPIServerConfigBuilder() {} @@ -58,6 +61,28 @@ public KubeAPIServerConfig build() { this.apiServerVersion = apiServerVersionEnvVar; } } - return new KubeAPIServerConfig(jenvtestDir, apiServerVersion, offlineMode); + return new KubeAPIServerConfig(jenvtestDir, apiServerVersion, offlineMode, apiServerFlags); + } + + public void withApiServerFlags(List flags) { + apiServerFlags.addAll(flags); + } + + public void withApiServerFlag(String key, String value) { + checkKeyPrefix(key); + apiServerFlags.add(key); + apiServerFlags.add(value); + } + + public void withApiServerFlag(String key) { + checkKeyPrefix(key); + apiServerFlags.add(key); + } + + private void checkKeyPrefix(String key) { + if (!key.startsWith("--")) { + throw new JenvtestException( + "Kube API Server flag needs to start with double dash: '--'; Instead found key: " + key); + } } } diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/junit/EnableKubeAPIServer.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/junit/EnableKubeAPIServer.java index d1c44b3..c7c43c3 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/junit/EnableKubeAPIServer.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/junit/EnableKubeAPIServer.java @@ -20,4 +20,5 @@ */ String kubeAPIVersion() default NOT_SET; + String[] apiServerFlags() default {}; } diff --git a/core/src/main/java/io/javaoperatorsdk/jenvtest/junit/KubeAPIServerExtension.java b/core/src/main/java/io/javaoperatorsdk/jenvtest/junit/KubeAPIServerExtension.java index 9575752..b396a55 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/junit/KubeAPIServerExtension.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/junit/KubeAPIServerExtension.java @@ -2,6 +2,7 @@ import java.lang.reflect.AnnotatedElement; import java.util.Arrays; +import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -46,11 +47,11 @@ public void afterEach(ExtensionContext extensionContext) { private void startIfAnnotationPresent(ExtensionContext extensionContext) { extensionContext.getElement().ifPresent(ae -> { var annotation = getExtensionAnnotationInstance(ae); - annotation.ifPresent(a -> startApiServer(extensionContext, a)); + annotation.ifPresent(this::startApiServer); }); } - private void startApiServer(ExtensionContext context, EnableKubeAPIServer annotation) { + private void startApiServer(EnableKubeAPIServer annotation) { kubeApiServer = new KubeAPIServer(annotationToConfig(annotation)); kubeApiServer.start(); } @@ -69,6 +70,9 @@ private KubeAPIServerConfig annotationToConfig(EnableKubeAPIServer annotation) { if (!NOT_SET.equals(version)) { builder.withApiServerVersion(version); } + if (annotation.apiServerFlags().length > 0) { + builder.withApiServerFlags(List.of(annotation.apiServerFlags())); + } return builder.build(); } 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 8b2defa..22afbb8 100644 --- a/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java +++ b/core/src/main/java/io/javaoperatorsdk/jenvtest/process/KubeAPIServerProcess.java @@ -1,6 +1,9 @@ package io.javaoperatorsdk.jenvtest.process; +import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.Scanner; import java.util.concurrent.atomic.AtomicBoolean; @@ -39,21 +42,9 @@ public int startApiServer(int etcdPort) { throw new JenvtestException( "Missing binary for API Server on path: " + apiServerBinary.getAbsolutePath()); } - var port = Utils.findFreePort(); - apiServerProcess = new ProcessBuilder(apiServerBinary.getAbsolutePath(), - "--cert-dir", config.getJenvtestDir(), - "--secure-port", "" + port, - "--etcd-servers", "http://0.0.0.0:" + etcdPort, - "--authorization-mode", "RBAC", - "--service-account-issuer", "https://localhost", - "--service-account-signing-key-file", certManager.getAPIServerKeyPath(), - "--service-account-signing-key-file", certManager.getAPIServerKeyPath(), - "--service-account-key-file", certManager.getAPIServerKeyPath(), - "--service-account-issuer", certManager.getAPIServerCertPath(), - "--disable-admission-plugins", "ServiceAccount", - "--client-ca-file", certManager.getClientCertPath(), - "--service-cluster-ip-range", "10.0.0.0/24", - "--allow-privileged") + var apiServerPort = Utils.findFreePort(); + var command = createCommand(apiServerBinary, apiServerPort, etcdPort); + apiServerProcess = new ProcessBuilder(command) .start(); Utils.redirectProcessOutputToLogger(apiServerProcess.getInputStream(), apiLog); Utils.redirectProcessOutputToLogger(apiServerProcess.getErrorStream(), apiLog); @@ -66,12 +57,32 @@ public int startApiServer(int etcdPort) { return null; }); log.debug("API Server started"); - return port; + return apiServerPort; } catch (IOException e) { throw new JenvtestException(e); } } + private List createCommand(File apiServerBinary, int apiServerPort, int etcdPort) { + var command = new ArrayList(); + command.add(apiServerBinary.getAbsolutePath()); + command.addAll(config.getApiServerFlags()); + command.addAll(List.of("--cert-dir", config.getJenvtestDir(), + "--secure-port", "" + apiServerPort, + "--etcd-servers", "http://0.0.0.0:" + etcdPort, + "--authorization-mode", "RBAC", + "--service-account-issuer", "https://localhost", + "--service-account-signing-key-file", certManager.getAPIServerKeyPath(), + "--service-account-signing-key-file", certManager.getAPIServerKeyPath(), + "--service-account-key-file", certManager.getAPIServerKeyPath(), + "--service-account-issuer", certManager.getAPIServerCertPath(), + "--disable-admission-plugins", "ServiceAccount", + "--client-ca-file", certManager.getClientCertPath(), + "--service-cluster-ip-range", "10.0.0.0/24", + "--allow-privileged")); + return command; + } + public void waitUntilDefaultNamespaceCreated() { try { AtomicBoolean started = new AtomicBoolean(false);