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 0c4fb546555..333193bb8b6 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 @@ -56,6 +56,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.function.Predicate; import java.util.function.UnaryOperator; @@ -235,7 +236,6 @@ public class Config { private Boolean autoConfigure; - @Deprecated private List files = new ArrayList<>(); @JsonIgnore @@ -586,7 +586,7 @@ public Config(String masterUrl, String apiVersion, String namespace, Boolean tru if (Utils.isNotNullOrEmpty(autoOAuthToken)) { this.autoOAuthToken = autoOAuthToken; } - if (contexts != null && !contexts.isEmpty()) { + if (Utils.isNotNullOrEmpty(contexts)) { this.contexts = contexts; } if (Utils.isNotNull(currentContext)) { @@ -716,7 +716,7 @@ public static void configFromSysPropsOrEnvVars(Config config) { } String tlsVersionsVar = Utils.getSystemPropertyOrEnvVar(KUBERNETES_TLS_VERSIONS); - if (tlsVersionsVar != null && !tlsVersionsVar.isEmpty()) { + if (Utils.isNotNullOrEmpty(tlsVersionsVar)) { String[] tlsVersionsSplit = tlsVersionsVar.split(","); TlsVersion[] tlsVersions = new TlsVersion[tlsVersionsSplit.length]; for (int i = 0; i < tlsVersionsSplit.length; i++) { @@ -832,7 +832,7 @@ public static Config fromKubeconfig(String context, String kubeconfigContents, S */ public Config refresh() { final String currentContextName = this.getCurrentContext() != null ? this.getCurrentContext().getName() : null; - if (this.oauthToken != null && !this.oauthToken.isEmpty()) { + if (Utils.isNotNullOrEmpty(this.oauthToken)) { return this; } if (this.autoConfigure) { @@ -856,8 +856,7 @@ private static boolean tryKubeConfig(Config config, String context) { return false; } String[] kubeConfigFilenames = getKubeconfigFilenames(); - if (kubeConfigFilenames == null - || kubeConfigFilenames.length == 0) { + if (Utils.isNullOrEmpty(kubeConfigFilenames)) { return false; } List allFiles = Arrays.stream(kubeConfigFilenames) @@ -869,19 +868,18 @@ private static boolean tryKubeConfig(Config config, String context) { } private static io.fabric8.kubernetes.api.model.Config mergeKubeConfigs(List files) { - if (files == null - || files.isEmpty()) { + if (Utils.isNullOrEmpty(files)) { return null; } return files.stream() - .map(Config::createKubeconfig) - .reduce(null, (merged, additionalConfig) -> { - if (additionalConfig != null) { - return KubeConfigUtils.merge(additionalConfig, merged); - } else { - return merged; - } - }); + .map(Config::createKubeconfig) + .reduce(null, (merged, additionalConfig) -> { + if (additionalConfig != null) { + return KubeConfigUtils.merge(additionalConfig, merged); + } else { + return merged; + } + }); } private static io.fabric8.kubernetes.api.model.Config createKubeconfig(File file) { @@ -889,8 +887,7 @@ private static io.fabric8.kubernetes.api.model.Config createKubeconfig(File file LOGGER.debug("Found for Kubernetes config at: [{}].", file.getPath()); try { String content = getKubeconfigContents(file); - if (content != null - && !content.isEmpty()) { + if (Utils.isNotNullOrEmpty(content)) { kubeConfig = KubeConfigUtils.parseConfigFromString(content); } } catch (KubernetesClientException e) { @@ -908,7 +905,6 @@ public static String getKubeconfigFilename() { String fileName = null; String[] fileNames = getKubeconfigFilenames(); // if system property/env var contains multiple files take the first one based on the environment - // we are running in (eg. : for Linux, ; for Windows) if (fileNames.length >= 1) { fileName = fileNames[0]; if (fileNames.length > 1) { @@ -922,17 +918,15 @@ public static String getKubeconfigFilename() { public static String[] getKubeconfigFilenames() { String[] fileNames = null; String fileName = Utils.getSystemPropertyOrEnvVar(KUBERNETES_KUBECONFIG_FILES); - if (fileName != null - && !fileName.isEmpty()) { + if (Utils.isNotNullOrEmpty(fileName)) { fileNames = fileName.split(File.pathSeparator); } - if (fileNames == null - || fileNames.length == 0) { + if (Utils.isNullOrEmpty(fileNames)) { fileNames = new String[] { DEFAULT_KUBECONFIG_FILE.toString() }; } return Arrays.stream(fileNames) - .filter(filename -> isReadableKubeconfFile(new File(filename))) - .toArray(String[]::new); + .filter(filename -> isReadableKubeconfFile(new File(filename))) + .toArray(String[]::new); } private static boolean isReadableKubeconfFile(File file) { @@ -964,7 +958,7 @@ private static String getKubeconfigContents(File kubeConfigFile) { // It is only used to rewrite relative tls asset paths inside kubeconfig when a file is passed, and in the case that // the kubeconfig references some assets via relative paths. private static boolean loadFromKubeconfig(Config config, String context, String kubeconfigContents) { - if (kubeconfigContents != null && !kubeconfigContents.isEmpty()) { + if (Utils.isNotNullOrEmpty(kubeconfigContents)) { return loadFromKubeconfig(config, context, KubeConfigUtils.parseConfigFromString(kubeconfigContents)); } else { return false; @@ -1116,7 +1110,7 @@ protected static List getAuthenticatorCommandFromExecConfig(ExecConfig e command = shellQuote(command); List args = exec.getArgs(); - if (args != null && !args.isEmpty()) { + if (Utils.isNotNullOrEmpty(args)) { command += " " + args .stream() .map(Config::shellQuote) @@ -1217,7 +1211,7 @@ private static String getSystemEnvVariable(String envVariableName) { protected static String getHomeDir(Predicate directoryExists, UnaryOperator getEnvVar) { String home = getEnvVar.apply("HOME"); - if (home != null && !home.isEmpty() && directoryExists.test(home)) { + if (Utils.isNotNullOrEmpty(home) && directoryExists.test(home)) { return home; } String osName = System.getProperty("os.name").toLowerCase(Locale.ROOT); @@ -1231,7 +1225,7 @@ protected static String getHomeDir(Predicate directoryExists, UnaryOpera } } String userProfile = getEnvVar.apply("USERPROFILE"); - if (userProfile != null && !userProfile.isEmpty() && directoryExists.test(userProfile)) { + if (Utils.isNotNullOrEmpty(userProfile) && directoryExists.test(userProfile)) { return userProfile; } } @@ -1751,8 +1745,7 @@ public void setCurrentContext(NamedContext context) { */ @Deprecated public File getFile() { - if (files != null - && !files.isEmpty()) { + if (Utils.isNotNullOrEmpty(files)) { return files.get(0); } else { return null; @@ -1770,13 +1763,13 @@ public List getFiles() { return files; } - public KubeConfigFile getFile(String username) { - if (username == null - || username.isEmpty()) { + public KubeConfigFile getFileWithAuthInfo(String name) { + if (Utils.isNullOrEmpty(name) + || Utils.isNullOrEmpty(getFiles())) { return null; } - return Arrays.stream(getKubeconfigFilenames()) - .map(File::new) + return getFiles().stream() + .filter(Config::isReadableKubeconfFile) .map(file -> { try { return new KubeConfigFile(file, KubeConfigUtils.parseConfig(file)); @@ -1784,16 +1777,20 @@ public KubeConfigFile getFile(String username) { return null; } }) - .filter(entry -> entry != null - && entry.getConfig() != null - && hasAuthInfo(username, entry.getConfig())) + .filter(Objects::nonNull) + .filter(entry -> hasAuthInfoNamed(name, entry.getConfig())) .findFirst() .orElse(null); } - private boolean hasAuthInfo(String username, io.fabric8.kubernetes.api.model.Config kubeConfig) { + private boolean hasAuthInfoNamed(String username, io.fabric8.kubernetes.api.model.Config kubeConfig) { + if (Utils.isNullOrEmpty(username) + || kubeConfig == null + || kubeConfig.getUsers() == null) { + return false; + } return kubeConfig.getUsers().stream() - .anyMatch(namedAuthInfo -> username.equals(namedAuthInfo.getUser().getUsername())); + .anyMatch(namedAuthInfo -> username.equals(namedAuthInfo.getName())); } public static class KubeConfigFile { diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/ConfigBuilder.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/ConfigBuilder.java index a829b7ac6ed..b214247db85 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/ConfigBuilder.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/ConfigBuilder.java @@ -59,7 +59,7 @@ public Config build() { fluent.getCurrentContext(), fluent.getContexts(), Optional.ofNullable(fluent.getAutoConfigure()).orElse(!disableAutoConfig()), true); buildable.setAuthProvider(fluent.getAuthProvider()); - buildable.setFile(fluent.getFile()); + buildable.setFiles(fluent.getFiles()); return buildable; } } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/ConfigFluent.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/ConfigFluent.java index b2d81528893..91458b3a684 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/ConfigFluent.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/ConfigFluent.java @@ -78,7 +78,7 @@ public void copyInstance(Config instance) { this.withContexts(instance.getContexts()); this.withAutoConfigure(instance.getAutoConfigure()); this.withAuthProvider(instance.getAuthProvider()); - this.withFile(instance.getFile()); + this.withFiles(instance.getFiles()); } } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/internal/KubeConfigUtils.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/internal/KubeConfigUtils.java index 8f293d4f8e3..81f344df975 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/internal/KubeConfigUtils.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/internal/KubeConfigUtils.java @@ -26,6 +26,7 @@ import io.fabric8.kubernetes.api.model.NamedExtension; import io.fabric8.kubernetes.api.model.PreferencesBuilder; import io.fabric8.kubernetes.client.utils.Serialization; +import io.fabric8.kubernetes.client.utils.Utils; import java.io.File; import java.io.FileInputStream; @@ -183,17 +184,16 @@ public static Config merge(Config thisConfig, Config thatConfig) { builder.addAllToExtensions(thisConfig.getExtensions()); } if (!builder.hasCurrentContext() - && thisConfig.getCurrentContext() != null - && !thisConfig.getCurrentContext().isEmpty()) { + && Utils.isNotNullOrEmpty(thisConfig.getCurrentContext())) { builder.withCurrentContext(thisConfig.getCurrentContext()); } Config merged = builder.build(); mergePreferences(thisConfig, merged); return merged; - } - public static void mergePreferences(io.fabric8.kubernetes.api.model.Config source, io.fabric8.kubernetes.api.model.Config destination) { + public static void mergePreferences(io.fabric8.kubernetes.api.model.Config source, + io.fabric8.kubernetes.api.model.Config destination) { if (source.getPreferences() != null) { PreferencesBuilder builder = new PreferencesBuilder(destination.getPreferences()); if (source.getPreferences() != null) { diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtils.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtils.java index 60915905c31..5a40c8c2f5b 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtils.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtils.java @@ -198,10 +198,11 @@ public static OAuthToken persistOAuthToken(Config currentConfig, OAuthToken oAut } private static void persistOAuthTokenToFile(Config currentConfig, String token, Map authProviderConfig) { - if (currentConfig.getFile() != null && currentConfig.getCurrentContext() != null) { + if (currentConfig.getCurrentContext() != null + && currentConfig.getCurrentContext().getContext() != null) { try { final String userName = currentConfig.getCurrentContext().getContext().getUser(); - Config.KubeConfigFile kubeConfigFile = currentConfig.getFile(userName); + Config.KubeConfigFile kubeConfigFile = currentConfig.getFileWithAuthInfo(userName); if (kubeConfigFile == null) { LOGGER.warn("oidc: failure while persisting new tokens into KUBECONFIG: file for user {} not found", userName); return; @@ -242,6 +243,9 @@ private static NamedAuthInfo getOrCreateNamedAuthInfo(String userName, io.fabric } private static void persistOAuthTokenToFile(AuthProviderConfig config, Map authProviderConfig) { + if (config == null) { + return; + } Optional.of(config) .map(AuthProviderConfig::getConfig) .ifPresent(c -> c.putAll(authProviderConfig)); diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/Utils.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/Utils.java index 8c491c1158e..8db382b5c66 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/Utils.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/Utils.java @@ -36,6 +36,7 @@ import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Locale; @@ -291,8 +292,20 @@ public static boolean isNullOrEmpty(String str) { return str == null || str.isEmpty(); } - public static boolean isNotNullOrEmpty(Map map) { - return !(map == null || map.isEmpty()); + public static boolean isNotNullOrEmpty(Map map) { + return !isNullOrEmpty(map); + } + + public static boolean isNullOrEmpty(Map map) { + return map == null || map.isEmpty(); + } + + public static boolean isNotNullOrEmpty(Collection collection) { + return !isNullOrEmpty(collection); + } + + public static boolean isNullOrEmpty(Collection collection) { + return collection == null || collection.isEmpty(); } public static boolean isNotNullOrEmpty(String str) { @@ -300,7 +313,11 @@ public static boolean isNotNullOrEmpty(String str) { } public static boolean isNotNullOrEmpty(String[] array) { - return !(array == null || array.length == 0); + return !isNullOrEmpty(array); + } + + public static boolean isNullOrEmpty(String[] array) { + return array == null || array.length == 0; } public static boolean isNotNull(T... refList) { diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigTest.java index 50733cbb2b8..e3dff01df3a 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigTest.java @@ -17,8 +17,12 @@ import io.fabric8.kubernetes.api.model.ExecConfig; import io.fabric8.kubernetes.api.model.ExecConfigBuilder; +import io.fabric8.kubernetes.api.model.NamedAuthInfo; +import io.fabric8.kubernetes.api.model.NamedCluster; import io.fabric8.kubernetes.api.model.NamedContext; +import io.fabric8.kubernetes.client.Config.KubeConfigFile; import io.fabric8.kubernetes.client.http.TlsVersion; +import io.fabric8.kubernetes.client.internal.KubeConfigUtils; import io.fabric8.kubernetes.client.lib.FileSystem; import io.fabric8.kubernetes.client.utils.Utils; import org.assertj.core.api.InstanceOfAssertFactories; @@ -79,7 +83,7 @@ class ConfigTest { .filePath(ConfigTest.class.getResource("/test-kubeconfig-exec-args-with-spaces")); private static final String TEST_KUBECONFIG_NO_CURRENT_CONTEXT_FILE = Utils - .filePath(ConfigTest.class.getResource("/test-kubeconfig-nocurrentctxt.yml")); + .filePath(ConfigTest.class.getResource("/test-kubeconfig-nocurrentctxt")); private static final String TEST_KUBECONFIG_EXEC_FILE_CERT_AUTH = Utils .filePath(ConfigTest.class.getResource("/test-kubeconfig-exec-cert-auth")); @@ -1215,7 +1219,7 @@ void refresh_whenOAuthTokenSourceSetToUser_thenConfigUnchanged() { } @Test - void build_givenEmptyKubeConfig_whenConfigCreated_thenShouldNotProduceNPE() throws URISyntaxException { + void build_given_emptyKubeConfig_then_shouldNotProduceNPE() throws URISyntaxException { try { // Given System.setProperty("kubeconfig", @@ -1232,16 +1236,13 @@ void build_givenEmptyKubeConfig_whenConfigCreated_thenShouldNotProduceNPE() thro } @Test - void build_givenSeveralKubeConfigs_whenAutoconfigured_and_currentContextInFirstFile_then_shouldUseCurrentContextInFirstFile() + void builder_given_severalKubeConfigsAndCurrentContextInFirstFile_then_shouldUseCurrentContextInFirstFile() throws URISyntaxException { try { // Given System.setProperty(Config.KUBERNETES_KUBECONFIG_FILES, - // only has current-context - getResourceAbsolutePath("/test-kubeconfig-onlycurrentcontext") + File.pathSeparator + - // has all contexts, clusters, users - getResourceAbsolutePath("/test-kubeconfig") - ); + getResourceAbsolutePath("/test-kubeconfig-onlycurrentctx") + File.pathSeparator + + getResourceAbsolutePath("/test-kubeconfig")); // When Config config = new ConfigBuilder().build(); @@ -1256,15 +1257,13 @@ void build_givenSeveralKubeConfigs_whenAutoconfigured_and_currentContextInFirstF } @Test - void build_givenSeveralKubeConfigs_whenAutoconfigured_and_currentContextInSecondFile_then_shouldUseCurrentContextInSecondFile() + void builder_given_severalKubeConfigsAndCurrentContextInSecondFile_then_shouldUseCurrentContextInSecondFile() throws URISyntaxException { try { // Given System.setProperty(Config.KUBERNETES_KUBECONFIG_FILES, - // only has current-context getResourceAbsolutePath("/test-kubeconfig-empty") + File.pathSeparator + - // has all contexts, clusters, users - getResourceAbsolutePath("/test-kubeconfig")); + getResourceAbsolutePath("/test-kubeconfig")); // When Config config = new ConfigBuilder().build(); @@ -1279,10 +1278,89 @@ void build_givenSeveralKubeConfigs_whenAutoconfigured_and_currentContextInSecond } @Test - void getKubeconfigFilenames_given_filenames_defined_in_KUBECONFIG_then_returns_all_filenames() throws URISyntaxException { + void builder_given_severalKubeConfigsWithSameCluster_then_shouldUseFirstCluster() + throws URISyntaxException, IOException { + try { + // Given + String clusterName = "172-28-128-4:8443"; + + String withSecureCluster = getResourceAbsolutePath("/test-ec-kubeconfig-mangled"); + NamedCluster secureCluster = getCluster(withSecureCluster, clusterName); + assertThat(secureCluster).isNotNull(); + assertThat(secureCluster.getCluster().getServer()).isEqualTo("https://bogus.com"); + + String withInsecureCluster = getResourceAbsolutePath("/test-ec-kubeconfig"); + NamedCluster insecureCluster = getCluster(withInsecureCluster, clusterName); + assertThat(insecureCluster).isNotNull(); + assertThat(insecureCluster.getCluster().getServer()).isEqualTo("https://172.28.128.4:8443"); + + System.setProperty(Config.KUBERNETES_KUBECONFIG_FILES, + withSecureCluster + File.pathSeparator + + withInsecureCluster); + + // When + Config config = new ConfigBuilder().build(); + + // Then + // cluster in 1st file is not overriden by identically named cluster in 2nd file + assertThat(config.getMasterUrl()).startsWith("https://bogus.com"); + } finally { + System.clearProperty(Config.KUBERNETES_KUBECONFIG_FILES); + } + } + + private static NamedCluster getCluster(String filePath, String clusterName) throws IOException { + io.fabric8.kubernetes.api.model.Config config = KubeConfigUtils.parseConfig(new File(filePath)); + return config.getClusters().stream() + .filter(cluster -> clusterName.equals(cluster.getName())) + .findFirst() + .orElse(null); + } + + @Test + void builder_given_severalKubeConfigsWithSameUser_then_shouldUseFirstUser() + throws URISyntaxException, IOException { + try { + // Given + String userName = "user/172-28-128-4:8443"; + + String withUserWithToken = getResourceAbsolutePath("/test-ec-kubeconfig-mangled"); + NamedAuthInfo userWithToken = getUser(withUserWithToken, userName); + assertThat(userWithToken).isNotNull(); + assertThat(userWithToken.getUser().getToken()).isEqualTo("token"); + + String withUserWithoutToken = getResourceAbsolutePath("/test-ec-kubeconfig"); + NamedAuthInfo userWithoutToken = getUser(withUserWithoutToken, userName); + assertThat(userWithoutToken).isNotNull(); + assertThat(userWithoutToken.getUser().getToken()).isNull(); + + System.setProperty(Config.KUBERNETES_KUBECONFIG_FILES, + withUserWithToken + File.pathSeparator + + withUserWithoutToken); + + // When + Config config = new ConfigBuilder().build(); + + // Then + // user in 1st file is not overriden by identically named user in 2nd file + assertThat(config.getAutoOAuthToken()).isEqualTo("token"); + } finally { + System.clearProperty(Config.KUBERNETES_KUBECONFIG_FILES); + } + } + + private static NamedAuthInfo getUser(String filePath, String userName) throws IOException { + io.fabric8.kubernetes.api.model.Config config = KubeConfigUtils.parseConfig(new File(filePath)); + return config.getUsers().stream() + .filter(user -> userName.equals(user.getName())) + .findFirst() + .orElse(null); + } + + @Test + void getKubeconfigFilenames_given_severalFilenamesDefinedInKUBECONFIG_then_returnsAllFilenames() throws URISyntaxException { try { // Given - // only has current-context String file1 = getResourceAbsolutePath("/test-kubeconfig-empty"); // has all contexts, clusters, users String file2 = getResourceAbsolutePath("/test-kubeconfig"); @@ -1302,10 +1380,9 @@ void getKubeconfigFilenames_given_filenames_defined_in_KUBECONFIG_then_returns_a } @Test - void getKubeconfigFilenames_given_directory_defined_in_KUBECONFIG_then_does_not_return_it() throws URISyntaxException { + void getKubeconfigFilenames_given_directoryDefinedInKUBECONFIG_then_doesNotReturnIt() throws URISyntaxException { try { // Given - // only has current-context String file1 = new File("/dev/null").getAbsolutePath(); // has all contexts, clusters, users String file2 = getResourceAbsolutePath("/test-kubeconfig"); @@ -1324,24 +1401,44 @@ void getKubeconfigFilenames_given_directory_defined_in_KUBECONFIG_then_does_not_ } } + private String getResourceAbsolutePath(String filename) throws URISyntaxException { + return new File(Objects.requireNonNull(getClass().getResource(filename)).toURI()).getAbsolutePath(); + } + + @Test + void getKubeconfigFilenames_given_KUBECONFNotSet_then_returnsDefault() { + // Given + System.clearProperty(Config.KUBERNETES_KUBECONFIG_FILES); + + // When + String[] filenames = Config.getKubeconfigFilenames(); + + // Then + assertThat(filenames) + .isNotNull() + .containsExactly(Config.DEFAULT_KUBECONFIG_FILE.getAbsolutePath()); + } + @Test - void getKubeconfigFilenames_given_KUBECONF_not_set_then_returns_default() { + void getFilenames_given_KUBECONFNotSet_then_returnsDefault() throws URISyntaxException { + try { // Given - // only has current-context - System.clearProperty(Config.KUBERNETES_KUBECONFIG_FILES); + String fileWithToken = getResourceAbsolutePath("/test-kubeconfig-oidc"); + System.setProperty(Config.KUBERNETES_KUBECONFIG_FILES, + fileWithToken + File.pathSeparator + + Config.DEFAULT_KUBECONFIG_FILE.getAbsolutePath()); + Config config = new ConfigBuilder().build(); // When - String[] filenames = Config.getKubeconfigFilenames(); + KubeConfigFile found = config.getFileWithAuthInfo("mmosley"); // Then - assertThat(filenames) + assertThat(found) .isNotNull() - .hasSize(1) - .containsExactly(Config.DEFAULT_KUBECONFIG_FILE.getAbsolutePath()); - } - - private String getResourceAbsolutePath(String filename) throws URISyntaxException { - return new File(Objects.requireNonNull(getClass().getResource(filename)).toURI()).getAbsolutePath(); + .hasFieldOrPropertyWithValue("absolutePath", fileWithToken); + } finally { + System.clearProperty(Config.KUBERNETES_KUBECONFIG_FILES); + } } } diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtilsBehaviorTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtilsBehaviorTest.java index 1870b8dd910..4615371fdfc 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtilsBehaviorTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtilsBehaviorTest.java @@ -19,6 +19,7 @@ import io.fabric8.kubernetes.api.model.NamedAuthInfo; import io.fabric8.kubernetes.api.model.NamedAuthInfoBuilder; import io.fabric8.kubernetes.api.model.NamedClusterBuilder; +import io.fabric8.kubernetes.api.model.NamedContext; import io.fabric8.kubernetes.api.model.NamedContextBuilder; import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.ConfigBuilder; @@ -112,7 +113,7 @@ void setUp() throws Exception { .build(); Files.write(kubeConfigFile, Serialization.asYaml(kubeConfig).getBytes(StandardCharsets.UTF_8)); originalConfig = new ConfigBuilder(Config.empty()) - .withFile(tempDir.resolve("kube-config").toFile()) + .withFiles(tempDir.resolve("kube-config").toFile()) .build() .refresh(); // Auth provider configuration (minimal) @@ -493,11 +494,12 @@ void skipsInFileWhenOriginalConfigHasNoCurrentContext() { void logsWarningIfReferencedFileIsMissing() { originalConfig.setFile(kubeConfig); originalConfig = new ConfigBuilder(originalConfig) - .withCurrentContext(new NamedContextBuilder().withName("context").build()).build(); + .withCurrentContext(createNamedContext("context", "default-user")) + .build(); persistOAuthToken(originalConfig, oAuthTokenResponse, "fake.token"); assertThat(systemErr.toString()) .contains("oidc: failure while persisting new tokens into KUBECONFIG") - .contains("FileNotFoundException"); + .contains("file for user default-user not found"); } @Nested @@ -505,18 +507,20 @@ void logsWarningIfReferencedFileIsMissing() { class WithValidKubeConfig { @BeforeEach void setUp() throws IOException { - Files.write(kubeConfig.toPath(), ("---" + - "users:\n" + - "- name: user\n").getBytes(StandardCharsets.UTF_8)); + Files.write(kubeConfig.toPath(), ( + "---\n" + + "users:\n" + + "- name: user\n" + + "contexts:\n" + + "- context:\n" + + " name: context\n").getBytes(StandardCharsets.UTF_8)); } @Test void persistsTokenInFile() throws IOException { originalConfig.setFile(kubeConfig); originalConfig = new ConfigBuilder(originalConfig) - .withCurrentContext(new NamedContextBuilder() - .withName("context") - .withNewContext().withUser("user").endContext().build()) + .withCurrentContext(createNamedContext("context", "user")) .build(); persistOAuthToken(originalConfig, oAuthTokenResponse, "fake.token"); assertThat(KubeConfigUtils.parseConfig(kubeConfig)) @@ -555,4 +559,13 @@ void persistsOAuthTokenInFile() throws IOException { } } + + private static NamedContext createNamedContext(String name, String user) { + return new NamedContextBuilder() + .withName(name) + .withNewContext() + .withUser(user) + .endContext() + .build(); + } } diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtilsTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtilsTest.java index e5a7886a061..a00ffd55003 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtilsTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtilsTest.java @@ -40,6 +40,7 @@ import java.util.Base64; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import static io.fabric8.kubernetes.client.http.TestStandardHttpClientFactory.Mode.SINGLETON; import static io.fabric8.kubernetes.client.utils.OpenIDConnectionUtils.CLIENT_ID_KUBECONFIG; @@ -77,10 +78,12 @@ void persistOAuthTokenWithUpdatedToken(@TempDir Path tempDir) throws IOException oAuthTokenResponse.setIdToken("id-token-updated"); oAuthTokenResponse.setRefreshToken("refresh-token-updated"); Path kubeConfig = Files.createTempFile(tempDir, "test", "kubeconfig"); - Files.copy(OpenIDConnectionUtilsTest.class.getResourceAsStream("/test-kubeconfig-oidc"), kubeConfig, - StandardCopyOption.REPLACE_EXISTING); - Config originalConfig = Config.fromKubeconfig(null, new String(Files.readAllBytes(kubeConfig), StandardCharsets.UTF_8), - kubeConfig.toFile().getAbsolutePath()); + Files.copy(Objects.requireNonNull(OpenIDConnectionUtilsTest.class.getResourceAsStream("/test-kubeconfig-oidc")), + kubeConfig, + StandardCopyOption.REPLACE_EXISTING); + Config originalConfig = Config.fromKubeconfig(null, new String(Files.readAllBytes(kubeConfig), + StandardCharsets.UTF_8), + kubeConfig.toFile().getAbsolutePath()); // When OpenIDConnectionUtils.persistOAuthToken(originalConfig, oAuthTokenResponse, null); diff --git a/kubernetes-client-api/src/test/resources/test-ec-kubeconfig-mangled b/kubernetes-client-api/src/test/resources/test-ec-kubeconfig-mangled new file mode 100644 index 00000000000..d0b63ee8bd2 --- /dev/null +++ b/kubernetes-client-api/src/test/resources/test-ec-kubeconfig-mangled @@ -0,0 +1,19 @@ +apiVersion: v1 +clusters: +- cluster: + certificate-authority: testns/ca.pem + server: https://bogus.com + name: 172-28-128-4:8443 +contexts: +- context: + cluster: 172-28-128-4:8443 + namespace: default + user: user/172-28-128-4:8443 + name: default/172-28-128-4:8443/user +current-context: default/172-28-128-4:8443/user +kind: Config +preferences: {} +users: +- name: user/172-28-128-4:8443 + user: + token: token diff --git a/kubernetes-client-api/src/test/resources/test-kubeconfig-nocurrentctxt.yml b/kubernetes-client-api/src/test/resources/test-kubeconfig-nocurrentctxt similarity index 100% rename from kubernetes-client-api/src/test/resources/test-kubeconfig-nocurrentctxt.yml rename to kubernetes-client-api/src/test/resources/test-kubeconfig-nocurrentctxt diff --git a/kubernetes-client-api/src/test/resources/test-kubeconfig-onlycurrentcontext b/kubernetes-client-api/src/test/resources/test-kubeconfig-onlycurrentctx similarity index 100% rename from kubernetes-client-api/src/test/resources/test-kubeconfig-onlycurrentcontext rename to kubernetes-client-api/src/test/resources/test-kubeconfig-onlycurrentctx