From c6a16dd95fbbb6b44fbf64858a4b8794d1afcdeb Mon Sep 17 00:00:00 2001 From: Rohan Kumar Date: Mon, 19 Aug 2024 15:47:56 +0530 Subject: [PATCH] fix (kubernetes-client-api) : Config should use `proxy-url` in kubeconfig's cluster configuration Set Config's `httpProxy` / `httpsProxy` fields if current context's cluster configuration has `proxy-url` set Signed-off-by: Rohan Kumar --- .../io/fabric8/kubernetes/client/Config.java | 13 +++ .../client/ConfigProxySourceTest.java | 87 ++++++++++++++++--- 2 files changed, 88 insertions(+), 12 deletions(-) diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/Config.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/Config.java index 34260a58748..6efdb3016d4 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/Config.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/Config.java @@ -153,6 +153,7 @@ public class Config { private static final int DEFAULT_WATCH_RECONNECT_INTERVAL = 1000; private static final int DEFAULT_CONNECTION_TIMEOUT = 10 * 1000; private static final String DEFAULT_CLIENT_KEY_PASSPHRASE = "changeit"; + private static final String SOCKS5_PROTOCOL_PREFIX = "socks5://"; private Boolean trustCerts; private Boolean disableHostnameVerification; @@ -926,6 +927,18 @@ private static void mergeKubeConfigContents(Config config, String context, io.fa if (currentAuthInfo != null) { mergeKubeConfigAuthInfo(config, currentCluster, currentAuthInfo); } + String proxyUrl = currentCluster.getProxyUrl(); + if (Utils.isNotNullOrEmpty(proxyUrl)) { + if (proxyUrl.startsWith(SOCKS5_PROTOCOL_PREFIX) && config.getMasterUrl().startsWith(HTTPS_PROTOCOL_PREFIX)) { + config.setHttpsProxy(proxyUrl); + } else if (proxyUrl.startsWith(SOCKS5_PROTOCOL_PREFIX)) { + config.setHttpProxy(proxyUrl); + } else if (proxyUrl.startsWith(HTTP_PROTOCOL_PREFIX)) { + config.setHttpProxy(proxyUrl); + } else if (proxyUrl.startsWith(HTTPS_PROTOCOL_PREFIX)) { + config.setHttpsProxy(proxyUrl); + } + } } } diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigProxySourceTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigProxySourceTest.java index fa1ef152670..f1dd6cbfc27 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigProxySourceTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigProxySourceTest.java @@ -15,13 +15,19 @@ */ package io.fabric8.kubernetes.client; +import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.client.utils.Utils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; @@ -79,7 +85,7 @@ void kubeConfigProxyUrl() { // When + Then assertThat(new ConfigBuilder().build()) .hasFieldOrPropertyWithValue("httpProxy", "http://proxy-via-http-proxy-property:3128") - .hasFieldOrPropertyWithValue("httpsProxy", null); + .hasFieldOrPropertyWithValue("httpsProxy", "socks5://proxy-via-kubeconfig-proxy-url:1080"); } finally { System.clearProperty("kubeconfig"); } @@ -201,7 +207,7 @@ void kubeConfigProxyUrl() { .filePath(ConfigTest.class.getResource("/config-proxy-source/kubeconfig-with-proxy-url"))); // When + Then assertThat(configBuilder.build()) - .hasFieldOrPropertyWithValue("httpsProxy", null) + .hasFieldOrPropertyWithValue("httpsProxy", "socks5://proxy-via-kubeconfig-proxy-url:1080") .hasFieldOrPropertyWithValue("httpProxy", "http://proxy-via-builder:3128"); } finally { System.clearProperty("kubeconfig"); @@ -223,13 +229,70 @@ void tearDown() { System.clearProperty("kubeconfig"); } - @Test - @Disabled("https://github.com/fabric8io/kubernetes-client/issues/6150") - void noOtherConfiguration() { - // When + Then - assertThat(new ConfigBuilder().build()) - .hasFieldOrPropertyWithValue("httpProxy", null) - .hasFieldOrPropertyWithValue("httpsProxy", "socks5://proxy-via-kubeconfig-proxy-url:1080"); + @Nested + @DisplayName("no other proxy configuration") + class NoOtherConfiguration { + @TempDir + private File temporaryFolder; + + @Test + @DisplayName("proxy-url with sock5 scheme, masterUrl with https scheme, then Config sets httpsProxy") + void whenProxyUrlSocks5MasterUrlHttps_thenHttpsProxySetInConfig() { + // When + Then + assertThat(new ConfigBuilder().build()) + .hasFieldOrPropertyWithValue("httpProxy", null) + .hasFieldOrPropertyWithValue("httpsProxy", "socks5://proxy-via-kubeconfig-proxy-url:1080"); + } + + @Test + @DisplayName("proxy-url with http scheme, then Config sets httpProxy") + void whenProxyUrlHttp_thenHttpProxySetInConfig() throws IOException { + // Given + System.setProperty("kubeconfig", + createKubeConfigWithCluster("http://kubernetes-remote-server.example:6443", "http://proxy-server.example:80") + .getAbsolutePath()); + // When + Then + assertThat(new ConfigBuilder().build()) + .hasFieldOrPropertyWithValue("httpProxy", "http://proxy-server.example:80") + .hasFieldOrPropertyWithValue("httpsProxy", null); + } + + @Test + @DisplayName("proxy-url with https scheme, then Config sets httpsProxy") + void whenProxyUrlHttps_thenHttpsProxySetInConfig() throws IOException { + // Given + System.setProperty("kubeconfig", + createKubeConfigWithCluster("https://kubernetes-remote-server.example:6443", "https://proxy-server.example:80") + .getAbsolutePath()); + // When + Then + assertThat(new ConfigBuilder().build()) + .hasFieldOrPropertyWithValue("httpProxy", null) + .hasFieldOrPropertyWithValue("httpsProxy", "https://proxy-server.example:80"); + } + + @Test + @DisplayName("proxy-url with sock5 scheme, masterUrl with http scheme, then Config sets httpProxy") + void whenProxyUrlSocks5AndMasterUrlHttp_thenHttpProxySetInConfig() throws IOException { + // Given + System.setProperty("kubeconfig", + createKubeConfigWithCluster("http://kubernetes-remote-server.example:6443", "socks5://proxy-server.example:1080") + .getAbsolutePath()); + // When + Then + assertThat(new ConfigBuilder().build()) + .hasFieldOrPropertyWithValue("httpProxy", "socks5://proxy-server.example:1080") + .hasFieldOrPropertyWithValue("httpsProxy", null); + } + + private File createKubeConfigWithCluster(String masterUrl, String proxyUrl) throws IOException { + io.fabric8.kubernetes.api.model.Config kubeConfig = Serialization.unmarshal( + ConfigTest.class.getResourceAsStream("/config-proxy-source/kubeconfig-with-proxy-url"), + io.fabric8.kubernetes.api.model.Config.class); + kubeConfig.getClusters().get(0).getCluster().setServer(masterUrl); + kubeConfig.getClusters().get(0).getCluster().setProxyUrl(proxyUrl); + File updatedKubeConfig = new File(temporaryFolder, "kubeconfig"); + Files.write(updatedKubeConfig.toPath(), Serialization.asYaml(kubeConfig).getBytes(StandardCharsets.UTF_8)); + return updatedKubeConfig; + } } @Test @@ -240,7 +303,7 @@ void httpProxySystemProperty() { assertThat(new ConfigBuilder().build()) .hasFieldOrPropertyWithValue("httpProxy", "http://proxy-via-http-proxy-property:3128") - .hasFieldOrPropertyWithValue("httpsProxy", null); + .hasFieldOrPropertyWithValue("httpsProxy", "socks5://proxy-via-kubeconfig-proxy-url:1080"); } finally { System.clearProperty("http.proxy"); } @@ -265,7 +328,7 @@ void allProxySystemProperty() { void httpProxyViaBuilder() { assertThat(new ConfigBuilder().withHttpProxy("http://proxy-via-builder:3128").build()) .hasFieldOrPropertyWithValue("httpProxy", "http://proxy-via-builder:3128") - .hasFieldOrPropertyWithValue("httpsProxy", null); + .hasFieldOrPropertyWithValue("httpsProxy", "socks5://proxy-via-kubeconfig-proxy-url:1080"); } } }