diff --git a/.github/workflows/IJ.yml b/.github/workflows/IJ.yml index eedb4c1..b744750 100644 --- a/.github/workflows/IJ.yml +++ b/.github/workflows/IJ.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - IJ: [2022.3, 2023.1, 2023.2, 2023.3, 2024.1, 2024.2] + IJ: [2022.3, 2023.1, 2023.2, 2023.3, 2024.1, 2024.2, 2024.3] steps: - uses: actions/checkout@v4 diff --git a/build.gradle.kts b/build.gradle.kts index 62268ae..cae1134 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,4 @@ +import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType import org.jetbrains.intellij.platform.gradle.TestFrameworkType import org.jetbrains.intellij.platform.gradle.models.ProductRelease @@ -59,9 +60,8 @@ dependencies { // for unit tests testImplementation(libs.junit) testImplementation(libs.assertj.core) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.opentest4j) // known issue: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-faq.html#missing-opentest4j-dependency-in-test-framework - } tasks { @@ -73,6 +73,9 @@ tasks { useJUnit() systemProperty("tools.dl.path", temporaryDir) jvmArgs("-Djava.awt.headless=true") + testLogging { + exceptionFormat = TestExceptionFormat.FULL + } } withType { diff --git a/gradle.properties b/gradle.properties index 41901dc..8a12932 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ nexusUser=invalid nexusPassword=invalid # IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension -ideaVersion=2024.2 +ideaVersion=2024.3 # Gradle Releases -> https://github.com/gradle/gradle/releases gradleVersion=8.5 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 46c3e72..840dd27 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,13 +1,13 @@ [versions] # libraries junit = "4.13.2" -kubernetes-client = "6.12.0" +kubernetes-client = "7.0.0" jackson-core = "2.17.0" commons-lang3 = "3.12.0" commons-exec = "1.3" common-lang = "3.9.4" assertj-core = "3.22.0" -mockito-inline = "4.5.1" +mockito-core = "5.14.2" opentest4j = "1.3.0" # plugins @@ -22,7 +22,7 @@ kubernetes-httpclient-okhttp = { group = "io.fabric8", name = "kubernetes-httpcl jackson-core = { group = "com.fasterxml.jackson.core", name = "jackson-core", version.ref = "jackson-core" } commons-lang3 = { group = "org.apache.commons", name = "commons-lang3", version.ref = "commons-lang3" } assertj-core = { group = "org.assertj", name = "assertj-core", version.ref = "assertj-core" } -mockito-inline = { group = "org.mockito", name = "mockito-inline", version.ref = "mockito-inline" } +mockito-core = { group = "org.mockito", name = "mockito-core", version.ref = "mockito-core" } commons-exec = { group = "org.apache.commons", name = "commons-exec", version.ref = "commons-exec" } common-lang = { group = "com.twelvemonkeys.common", name = "common-lang", version.ref = "common-lang" } opentest4j = { group = "org.opentest4j", name = "opentest4j", version.ref = "opentest4j" } diff --git a/src/main/java/com/redhat/devtools/intellij/common/kubernetes/ClusterHelper.java b/src/main/java/com/redhat/devtools/intellij/common/kubernetes/ClusterHelper.java index d2ebe8c..20fb95c 100644 --- a/src/main/java/com/redhat/devtools/intellij/common/kubernetes/ClusterHelper.java +++ b/src/main/java/com/redhat/devtools/intellij/common/kubernetes/ClusterHelper.java @@ -16,8 +16,6 @@ import io.fabric8.kubernetes.client.VersionInfo; import io.fabric8.openshift.client.OpenShiftClient; -import java.net.HttpURLConnection; - public class ClusterHelper { private ClusterHelper() { @@ -25,36 +23,26 @@ private ClusterHelper() { } public static boolean isOpenShift(KubernetesClient client) { - return client.hasApiGroup(OpenShiftClient.BASE_API_GROUP, false); + try { + return client != null + && client.hasApiGroup(OpenShiftClient.BASE_API_GROUP, false); + } catch (KubernetesClientException e) { + return false; + } } public static ClusterInfo getClusterInfo(KubernetesClient client) { - if (client instanceof OpenShiftClient) { - return new ClusterInfo( - getKubernetesVersion((OpenShiftClient) client), - true, - getOpenShiftVersion((OpenShiftClient) client)); - - } else if (client.adapt(OpenShiftClient.class) != null && client.adapt(OpenShiftClient.class).isSupported()){ + OpenShiftClient openShiftClient = getOpenShiftClient(client); + if (openShiftClient != null) { return new ClusterInfo( getKubernetesVersion(client), true, - getOpenShiftVersion(client)); + getOpenShiftVersion(openShiftClient)); } else { return new ClusterInfo( getKubernetesVersion(client), false, ""); - - } - } - - private static String getKubernetesVersion(OpenShiftClient client) { - try { - KubernetesClient kclient = new KubernetesClientBuilder().withConfig(client.getConfiguration()).build(); - return getKubernetesVersion(kclient); - } catch (KubernetesClientException e) { - return null; } } @@ -63,18 +51,23 @@ private static String getKubernetesVersion(KubernetesClient client) { return version != null ? version.getGitVersion() : ""; } - private static String getOpenShiftVersion(KubernetesClient client) { - try { - OpenShiftClient oclient = client.adapt(OpenShiftClient.class); - return getOpenShiftVersion(oclient); - } catch (KubernetesClientException e) { + private static OpenShiftClient getOpenShiftClient(KubernetesClient client) { + if (client instanceof OpenShiftClient) { + return (OpenShiftClient) client; + } else if (isOpenShift(client)) { + return client.adapt(OpenShiftClient.class); + } else { return null; } } private static String getOpenShiftVersion(OpenShiftClient client) { VersionInfo version = client.getVersion(); - return version != null && version.getMajor() != null ? getVersion(version.getMajor(), version.getMinor()) : ""; + if (version != null && version.getMajor() != null) { + return getVersion(version.getMajor(), version.getMinor()); + } else { + return ""; + } } private static String getVersion(String major, String minor) { diff --git a/src/main/java/com/redhat/devtools/intellij/common/utils/ConfigHelper.java b/src/main/java/com/redhat/devtools/intellij/common/utils/ConfigHelper.java index 2dfe8ec..0bacc85 100644 --- a/src/main/java/com/redhat/devtools/intellij/common/utils/ConfigHelper.java +++ b/src/main/java/com/redhat/devtools/intellij/common/utils/ConfigHelper.java @@ -10,190 +10,246 @@ ******************************************************************************/ package com.redhat.devtools.intellij.common.utils; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import io.fabric8.kubernetes.api.model.AuthInfo; -import io.fabric8.kubernetes.api.model.AuthProviderConfig; -import io.fabric8.kubernetes.api.model.Config; -import io.fabric8.kubernetes.api.model.ConfigBuilder; import io.fabric8.kubernetes.api.model.Context; import io.fabric8.kubernetes.api.model.NamedContext; -import io.fabric8.kubernetes.client.internal.KubeConfigUtils; +import io.fabric8.kubernetes.client.Config; -import java.io.File; -import java.io.IOException; -import java.net.URL; import java.util.Collection; -import java.util.Map; import java.util.Objects; public class ConfigHelper { - private static final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - public static String getKubeConfigPath() { - return io.fabric8.kubernetes.client.Config.getKubeconfigFilename(); - } - - public static void saveKubeConfig(Config config) throws IOException { - mapper.writeValue(new File(getKubeConfigPath()), config); - } - - public static Config safeLoadKubeConfig() { - try { - return loadKubeConfig(); - } catch (IOException e) { - return null; - } - } - - public static Config loadKubeConfig() throws IOException { - return loadKubeConfig(getKubeConfigPath()); + /** + * Returns {@code true} if the given {@link io.fabric8.kubernetes.client.Config}s are equal. + * They are considered equal if they're equal in + * + * + * @param thisConfig the first config to compare + * @param thatConfig the second config to compare + * @return true if both configs are equal in context, contexts and token + * + * @see #areEqualCurrentContext(Config, Config) + * @see #areEqualCluster(Config, Config) + * @see #areEqualAuthInfo(Config, Config) + */ + public static boolean areEqual(Config thisConfig, Config thatConfig) { + return areEqualCurrentContext(thisConfig, thatConfig) + && areEqualCluster(thisConfig, thatConfig) + && areEqualAuthInfo(thisConfig, thatConfig); } - public static Config loadKubeConfig(String path) throws IOException { - File f = new File(path); - if (f.exists()) { - return KubeConfigUtils.parseConfig(f); - } else { - return new ConfigBuilder().build(); + /** + * Returns {@code true} if the given {@link io.fabric8.kubernetes.client.Config}s are equal in current context. + * They are considered equal if they're equal in + * + * + * @param thisConfig the first config to compare + * @param thatConfig the second config to compare + * @return true if both configs are equal in context, existing contexts and token + * + * @see Config#getCurrentContext() + * @see #areEqualContext(NamedContext, NamedContext) + */ + public static boolean areEqualCurrentContext(Config thisConfig, Config thatConfig) { + if (thisConfig == null) { + return thatConfig == null; + } else if (thatConfig == null) { + return false; } - } - public static boolean isKubeConfigParsable() { - return isKubeConfigParsable(new File(getKubeConfigPath())); + return areEqualContext(thisConfig.getCurrentContext(), thatConfig.getCurrentContext()); } - public static boolean isKubeConfigParsable(File kubeConfig) { - try { - mapper.readValue(kubeConfig, Config.class); - return true; - } catch (IOException e) { + /** + * Returns {@code true} if both given {@link NamedContext} are equal in + * + * + * @param thisContext the first context to compare + * @param thatContext the second context to compare + * @return true if both contexts are equal + * + * @see #areEqualContext(Context, Context) + * @see NamedContext + * @see Context + */ + public static boolean areEqualContext(NamedContext thisContext, NamedContext thatContext) { + if (thisContext == null) { + return thatContext == null; + } else if (thatContext == null) { return false; } - } - public static ToolsConfig loadToolsConfig() throws IOException { - return loadToolsConfig(ConfigHelper.class.getResource("/tools.json")); - } - - public static ToolsConfig loadToolsConfig(URL url) throws IOException { - try { - return mapper.readValue(url, ToolsConfig.class); - } catch (IOException e) { - throw new IOException("Could not load tools config at " + url.toString() + ": " + e.getMessage(), e); - } + return Objects.equals(thisContext.getName(), thatContext.getName()) + && areEqualContext(thisContext.getContext(), thatContext.getContext()); } - public static NamedContext getCurrentContext() { - try { - Config config = loadKubeConfig(); - return getCurrentContext(config); - } catch (IOException e) { - return null; + /** + * Returns {@code true} if both given {@link Context} are equal. + * They are considered equal if they're equal in + * + * + * @param thisContext the first context to compare + * @param thatContext the second context to compare + * @return true if both contexts are equal + * + * @see NamedContext + * @see Context + */ + private static boolean areEqualContext(Context thisContext, Context thatContext) { + if (thisContext == null) { + return thatContext == null; + } else if (thatContext == null) { + return false; } - } - public static NamedContext getCurrentContext(Config config) { - if (config == null) { - return null; - } - return KubeConfigUtils.getCurrentContext(config); + return Objects.equals(thisContext.getCluster(), thatContext.getCluster()) + && Objects.equals(thisContext.getUser(), thatContext.getUser()) + && Objects.equals(thisContext.getNamespace(), thatContext.getNamespace()); } - public static String getCurrentContextName(Config config) { - String current = null; - NamedContext currentContext = getCurrentContext(config); - if (currentContext != null - && currentContext.getName() != null) { - current = currentContext.getName(); + /** + * Returns {@code true} if both given {@link Config} are equal in + * + * + * @param thisConfig the first config to compare + * @param thatConfig the second config to compare + * @return true if both configs are equal in master url, trust certs, proxies and auth info + * + * @see Config + */ + public static boolean areEqualCluster(Config thisConfig, Config thatConfig) { + if (thisConfig == null) { + return thatConfig == null; + } else if (thatConfig == null) { + return false; } - return current; - } - public static String getCurrentContextName() { - try { - return getCurrentContextName(loadKubeConfig()); - } catch (IOException e) { - return null; - } + return Objects.equals(thisConfig.getMasterUrl(), thatConfig.getMasterUrl()) + && areEqualTrustCerts(thisConfig, thatConfig) + && areEqualProxy(thisConfig, thatConfig) + && areEqualAuthInfo(thisConfig, thatConfig); } /** - * Returns {@code true} if the given {@link io.fabric8.kubernetes.api.model.Config} and - * the new {@link io.fabric8.kubernetes.api.model.Config} are equal. They are considered equal if they're - * equal in + * Returns {@code true} if both given {@link Config} are equal in * * - * @param kubeConfig the (file) config to compare - * @param newKubeConfig the (client, runtime) config to compare - * @return true if both configs are equal in context, contexts and token + * @param thisConfig the first config to compare + * @param thatConfig the second config to compare + * @return true if both configs are equal in http- & https-proxy, proxy username & password + * + * @see Config */ - public static boolean areEqualCurrentContext(Config kubeConfig, Config newKubeConfig) { - if (newKubeConfig == null) { - return kubeConfig == null; - } else if (kubeConfig == null) { + private static boolean areEqualProxy(Config thisConfig, Config thatConfig) { + if (thisConfig == null) { + return thatConfig == null; + } else if (thatConfig == null) { return false; } - return areEqual(KubeConfigUtils.getCurrentContext(newKubeConfig), KubeConfigUtils.getCurrentContext(kubeConfig)) - && areEqualToken(kubeConfig, newKubeConfig); + + return Objects.equals(thisConfig.getHttpProxy(), thatConfig.getHttpProxy()) + && Objects.equals(thisConfig.getHttpsProxy(), thatConfig.getHttpsProxy()) + && Objects.equals(thisConfig.getProxyUsername(), thatConfig.getProxyUsername()) + && Objects.equals(thisConfig.getProxyPassword(), thatConfig.getProxyPassword()); } /** - * Returns {@code true} if the given {@link io.fabric8.kubernetes.api.model.Config} and - * (client runtime) {@link io.fabric8.kubernetes.client.Config} are equal. They are considered equal if they're - * equal in + * Returns {@code true} if both given {@link Config} are equal in * * - * @param kubeConfig the (file) config to compare - * @param clientConfig the (client, runtime) config to compare - * @return true if both configs are equal in context, contexts and token + * @param thisConfig the first config to compare + * @param thatConfig the second config to compare + * @return true if both configs are equal in trusting certs, disabling hostname verification, ca cert data & file + * + * @see Config */ - public static boolean areEqual(Config kubeConfig, io.fabric8.kubernetes.client.Config clientConfig) { - if (clientConfig == null) { - return kubeConfig == null; - } else if (kubeConfig == null) { + private static boolean areEqualTrustCerts(Config thisConfig, Config thatConfig) { + if (thisConfig == null) { + return thatConfig == null; + } else if (thatConfig == null) { return false; } - return areEqual(clientConfig.getCurrentContext(), KubeConfigUtils.getCurrentContext(kubeConfig)) - && areEqual(clientConfig.getContexts(), kubeConfig.getContexts()) - && areEqualToken(kubeConfig, clientConfig); + + return thisConfig.isTrustCerts() == thatConfig.isTrustCerts() + && thisConfig.isDisableHostnameVerification() == thatConfig.isDisableHostnameVerification() + && Objects.equals(thisConfig.getCaCertData(), thatConfig.getCaCertData()) + && Objects.equals(thisConfig.getCaCertFile(), thatConfig.getCaCertFile()); } /** - * Returns {@code true} if the given {@link io.fabric8.kubernetes.api.model.Config} and - * (client runtime) {@link io.fabric8.kubernetes.client.Config} are equal. They are considered equal if they're - * equal in + * Returns {@code true} if both given {@link Config} are equal in auth info * * - * @param thisConfig the first (file) config to compare - * @param thatConfig the second (file) config to compare - * @return true if both configs are equal in context, contexts and token + * @param thisConfig the first config to compare + * @param thatConfig the second config to compare + * @return true if both configs are equal in client cert file/data, key file/data/algo, username, password + * proxies and token + * + * @see Config */ - public static boolean areEqual(Config thisConfig, Config thatConfig) { + public static boolean areEqualAuthInfo(Config thisConfig, Config thatConfig) { if (thisConfig == null) { return thatConfig == null; } else if (thatConfig == null) { return false; } - return areEqual(KubeConfigUtils.getCurrentContext(thisConfig), KubeConfigUtils.getCurrentContext(thatConfig)) - && areEqual(thisConfig.getContexts(), thatConfig.getContexts()) - && areEqualToken(getAuthInfo(thisConfig), getAuthInfo(thatConfig)); + + return Objects.equals(thisConfig.getClientCertFile(), thatConfig.getClientCertFile()) + && Objects.equals(thisConfig.getClientCertData(), thatConfig.getClientCertData()) + && Objects.equals(thisConfig.getClientKeyFile(), thatConfig.getClientKeyFile()) + && Objects.equals(thisConfig.getClientKeyData(), thatConfig.getClientKeyData()) + && Objects.equals(thisConfig.getClientKeyAlgo(), thatConfig.getClientKeyAlgo()) + && Objects.equals(thisConfig.getUsername(), thatConfig.getUsername()) + && Objects.equals(thisConfig.getPassword(), thatConfig.getPassword()) + && areEqualProxy(thisConfig, thatConfig) + && areEqualToken(thisConfig, thatConfig); } /** - * Returns {@code true} if both given contexts are equal. They are considered equal if they're equal in + * Returns {@code true} if both given {@link Config} are equal in contexts. + * They are considered equal if they're equal in the number of contexts are these are equal individually. * * - * @param thisContext the first context to compare - * @param thatContext the second context to compare + * @param thisConfig the first context to compare + * @param thatConfig the second context to compare * @return true if both contexts are equal * * @see NamedContext * @see Context + * + * @see Config#getContexts() */ - public static boolean areEqual(NamedContext thisContext, NamedContext thatContext) { - if (thisContext == null) { - return thatContext == null; - } else if (thatContext == null) { - return false; - } - if (!Objects.equals(thisContext.getName(), thatContext.getName())) { - return false; - } - - return areEqual(thisContext.getContext(), thatContext.getContext()); + public static boolean areEqualContexts(Config thisConfig, Config thatConfig) { + return areEqualContexts(thisConfig.getContexts(), thatConfig.getContexts()); } - private static boolean areEqual(Context thisContext, Context thatContext) { - if (thisContext == null) { - return thatContext == null; - } else if (thatContext == null) { - return false; - } - - if (!Objects.equals(thisContext.getCluster(), thatContext.getCluster())){ - return false; - } else if (!Objects.equals(thisContext.getNamespace(), thatContext.getNamespace())){ - return false; - } else { - return Objects.equals(thisContext.getUser(), thatContext.getUser()); - } - } - - public static boolean areEqual(Collection these, Collection those) { + /** + * Returns {@code true} if both given {@link Config} are equal in contexts. + * They are considered equal if they're equal in the number of contexts are these are equal individually. + *
    + *
  • cluster
  • + *
  • user
  • + *
  • current namespace
  • + *
  • extensions
  • + *
+ * + * @param these the contexts to compare + * @param those the other contexts to compare to + * @return true if both collections of contexts are equal + * + * @see NamedContext + * @see Context + */ + private static boolean areEqualContexts(Collection these, Collection those) { if (these == null) { return those == null; } else if (those == null) { @@ -245,7 +295,7 @@ public static boolean areEqual(Collection these, Collection contains(namedContext, those)); + .allMatch(namedContext -> contains(namedContext, those)); } private static boolean contains(NamedContext namedContext, Collection namedContexts) { @@ -254,122 +304,25 @@ private static boolean contains(NamedContext namedContext, Collection areEqual(namedContext, named)); - } - - /** - * Returns {@code true} if the token in the given (kubernetes file) {@link io.fabric8.kubernetes.api.model.Config} - * and (client runtime) {@link io.fabric8.kubernetes.client.Config} are equal. - * Returns {@code false} otherwise. - * - * @param kubeConfig the (kube config) auth info that contains the token - * @param clientConfig the (client) config that contains the token - * @return true if both tokens are equal, false otherwise - */ - public static boolean areEqualToken(Config kubeConfig, io.fabric8.kubernetes.client.Config clientConfig) { - return areEqualToken(getAuthInfo(kubeConfig), clientConfig); - } - - /** - * Returns {@code true} if the token in the given (kubernetes file) {@link io.fabric8.kubernetes.api.model.Config} - * and the one in the new Kubernetes file {@link io.fabric8.kubernetes.api.model.Config} are equal. - * Returns {@code false} otherwise. - * - * @param kubeConfig the (kube config) auth info that contains the token - * @param newKubeConfig the (client) config that contains the token - * @return true if both tokens are equal, false otherwise - */ - public static boolean areEqualToken(Config kubeConfig, Config newKubeConfig) { - return areEqualToken(getAuthInfo(kubeConfig), getAuthInfo(newKubeConfig)); - } - - private static AuthInfo getAuthInfo(Config kubeConfig) { - NamedContext current = KubeConfigUtils.getCurrentContext(kubeConfig); - if (current == null) { - return null; - } - return KubeConfigUtils.getUserAuthInfo(kubeConfig, current.getContext()); + .anyMatch(named -> areEqualContext(namedContext, named)); } /** - * Returns {@code true} if the token in the given {@link AuthInfo} (that's retrieved from the kube config file) - * and {@link Config} (that's contains the runtime settings that the kubernetes-client is using) are equal. + * Returns {@code true} if the (authentication) token in the given {@link io.fabric8.kubernetes.client.Config} + * and the one in the other config are equal. * Returns {@code false} otherwise. * - * @param authInfo the (kube config) auth info that contains the token - * @param clientConfig the (client) config that contains the token + * @param thisConfig the config to compare the active token of + * @param thatConfig the other config to compare the active token of * @return true if both tokens are equal, false otherwise */ - public static boolean areEqualToken(AuthInfo authInfo, io.fabric8.kubernetes.client.Config clientConfig) { - String kubeConfigToken = getToken(authInfo); - if (clientConfig == null - || clientConfig.getOauthToken() == null) { - return kubeConfigToken == null; - } - return clientConfig.getOauthToken().equals(kubeConfigToken); - } - - /** - * Returns {@code true} if the token in the given {@link AuthInfo} (that's retrieved from the kube config file) - * and the new {@link AuthInfo} (that's retrieved from the new kube config file) are equal. - * Returns {@code false} otherwise. - * - * @param authInfo the (kube config) auth info that contains the token - * @param newAuthInfo the new (kube config) auth that contains the token - * @return true if both tokens are equal, false otherwise - */ - public static boolean areEqualToken(AuthInfo authInfo, AuthInfo newAuthInfo) { - String configToken = getToken(authInfo); - String newConfigToken = getToken(newAuthInfo); - if (configToken == null) { - return newConfigToken == null; - } else if (newConfigToken == null) { + public static boolean areEqualToken(Config thisConfig, Config thatConfig) { + if (thisConfig == null) { + return thatConfig == null; + } else if (thatConfig == null) { return false; } - return configToken.equals(newConfigToken); + return Objects.equals(thisConfig.getAutoOAuthToken(), thatConfig.getAutoOAuthToken()); } - - /** - * Returns the token for the given {@code AuthInfo}. Returns {@code null} if it was not found. - * The token is searched in the auth provider in the following - * properties, respecting the given order of precedence: - *
    - *
  • "access-token"
  • - *
  • "id-token"
  • - *
- * @param authInfo the auth info to retrieve the token from - * @return the token that was found or null - */ - private static String getToken(AuthInfo authInfo){ - if (authInfo == null) { - return null; - } - if (authInfo.getToken() != null) { - return authInfo.getToken(); - } - AuthProviderConfig authProviderConfig = authInfo.getAuthProvider(); - if (authProviderConfig == null) { - return null; - } - Map config = authProviderConfig.getConfig(); - if (config == null - || config.isEmpty()) { - return null; - } - // GKE token - String accessToken = config.get("access-token"); - if (accessToken != null - && !accessToken.isEmpty()) { - return accessToken; - } - // OpenID Connect token - String idToken = config.get("id-token"); - if (idToken != null - && !idToken.isEmpty()) { - return idToken; - } - return null; - } - } diff --git a/src/main/java/com/redhat/devtools/intellij/common/utils/ConfigWatcher.java b/src/main/java/com/redhat/devtools/intellij/common/utils/ConfigWatcher.java index f796983..c142252 100644 --- a/src/main/java/com/redhat/devtools/intellij/common/utils/ConfigWatcher.java +++ b/src/main/java/com/redhat/devtools/intellij/common/utils/ConfigWatcher.java @@ -11,8 +11,7 @@ package com.redhat.devtools.intellij.common.utils; import com.intellij.openapi.diagnostic.Logger; -import io.fabric8.kubernetes.api.model.Config; -import io.fabric8.kubernetes.client.internal.KubeConfigUtils; +import io.fabric8.kubernetes.client.Config; import java.io.IOException; import java.nio.file.FileSystems; @@ -38,22 +37,14 @@ public class ConfigWatcher implements Runnable { private WatchService service; public interface Listener { - void onUpdate(ConfigWatcher source, Config config); + void onUpdate(Config updatedConfig); } - public ConfigWatcher(String config, Listener listener) { - this(Paths.get(config), listener); + public ConfigWatcher(Listener listener) { + this(Config.getKubeconfigFilenames().stream().map(Paths::get).toList(), listener, new HighSensitivityRegistrar()); } - public ConfigWatcher(Path config, Listener listener) { - this(List.of(config), listener); - } - - public ConfigWatcher(List configs, Listener listener) { - this(configs, listener, new HighSensitivityRegistrar()); - } - - public ConfigWatcher(List configs, Listener listener, HighSensitivityRegistrar registrar) { + protected ConfigWatcher(List configs, Listener listener, HighSensitivityRegistrar registrar) { this.configs = configs; this.listener = listener; this.registrar = registrar; @@ -61,7 +52,7 @@ public ConfigWatcher(List configs, Listener listener, HighSensitivityRegis @Override public void run() { - watch((Config config) -> listener.onUpdate(this, config)); + watch(listener::onUpdate); } public void close() throws IOException { @@ -70,11 +61,11 @@ public void close() throws IOException { } } - private void watch(Consumer consumer) { + private void watch(Consumer listener) { try (WatchService service = createWatchService()) { Collection watchedDirectories = getWatchedDirectories(); watchedDirectories.forEach(directory -> - new ConfigDirectoryWatch(directory, consumer, service, registrar).start() + new ConfigDirectoryWatch(directory, listener, service, registrar).start() ); } catch (IOException e) { String configPaths = configs.stream() @@ -106,11 +97,11 @@ private class ConfigDirectoryWatch { private final Path directory; private final WatchService service; private final HighSensitivityRegistrar registrar; - private final Consumer consumer; + private final Consumer listener; - private ConfigDirectoryWatch(Path directory, Consumer consumer, WatchService service, HighSensitivityRegistrar registrar) { + private ConfigDirectoryWatch(Path directory, Consumer listener, WatchService service, HighSensitivityRegistrar registrar) { this.directory = directory; - this.consumer = consumer; + this.listener = listener; this.service = service; this.registrar = registrar; } @@ -118,7 +109,7 @@ private ConfigDirectoryWatch(Path directory, Consumer consumer, WatchSer private void start() { try { register(directory, service, registrar); - watch(consumer, service); + watch(listener, service); } catch (InterruptedException e) { LOG.warn("Watching " + directory + " was interrupted", e); } catch (IOException e) { @@ -136,56 +127,34 @@ private void register(Path path, WatchService service, HighSensitivityRegistrar service); } - private void watch(Consumer consumer, WatchService service) throws InterruptedException { + private void watch(Consumer listener, WatchService service) throws InterruptedException { for (WatchKey key = service.take(); key != null; key = service.take()) { key.pollEvents().forEach((event) -> { Path changed = getAbsolutePath(directory, (Path) event.context()); - if (isConfigPath(changed)) { - consumer.accept(loadConfig(changed)); - } + notifyListener(listener, changed); }); key.reset(); } } + private void notifyListener(Consumer listener, Path changed) { + if (isConfigPath(changed)) { + try { + var config = Config.autoConfigure(null); + listener.accept(config); + } catch (Exception e) { + LOG.warn("Loading config at '" + changed + "' failed.", e); + } + } + } + protected boolean isConfigPath(Path path) { return configs != null && configs.contains(path); } - /** - * Returns {@link Config} for the given path if the kube config file - *
    - *
  • exists and
  • - *
  • is not empty and
  • - *
  • is valid yaml
  • - *
- * Returns {@code null} otherwise. - * - * @param path the path to the kube config - * @return returns true if the kube config that the event points to exists, is not empty and is valid yaml - */ - private Config loadConfig(Path path) { - // TODO: replace by Config#getKubeConfigFiles once kubernetes-client 7.0 is available - if (path == null) { - return null; - } - try { - if (Files.exists(path) - && Files.size(path) > 0) { - return KubeConfigUtils.parseConfig(path.toFile()); - } - } catch (Exception e) { - // only catch - LOG.warn("Could not load kube config at " + path.toAbsolutePath(), e); - } - return null; - } - private Path getAbsolutePath(Path directory, Path relativePath) { return directory.resolve(relativePath); } - } - } diff --git a/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java b/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java index fdfeaff..e9e55f5 100644 --- a/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java +++ b/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java @@ -134,7 +134,7 @@ public static DownloadHelper getInstance() { */ private CompletableFuture downloadIfRequiredAsyncInner(String toolName, URL url) throws IOException { CompletableFuture result = new CompletableFuture<>(); - ToolsConfig config = ConfigHelper.loadToolsConfig(url); + ToolsConfig config = ToolsConfigHelper.loadToolsConfig(url); ToolsConfig.Tool tool = config.getTools().get(toolName); if (tool == null) { throw new IOException("Tool " + toolName + " not found in config file " + url); diff --git a/src/main/java/com/redhat/devtools/intellij/common/utils/ToolsConfigHelper.java b/src/main/java/com/redhat/devtools/intellij/common/utils/ToolsConfigHelper.java new file mode 100644 index 0000000..4f963eb --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/common/utils/ToolsConfigHelper.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2024 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v20.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.redhat.devtools.intellij.common.utils; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; + +import java.io.IOException; +import java.net.URL; + +/** + * Util methods that deal with tool (oc, kubectl, odo, etc.) configs. + */ +public class ToolsConfigHelper { + private static final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); + + static ToolsConfig loadToolsConfig(URL url) throws IOException { + try { + return mapper.readValue(url, ToolsConfig.class); + } catch (IOException e) { + throw new IOException("Could not load tools config at " + url.toString() + ": " + e.getMessage(), e); + } + } +} diff --git a/src/test/java/com/redhat/devtools/intellij/common/kubernetes/ClusterHelperTest.java b/src/test/java/com/redhat/devtools/intellij/common/kubernetes/ClusterHelperTest.java index 8faa975..efe3950 100644 --- a/src/test/java/com/redhat/devtools/intellij/common/kubernetes/ClusterHelperTest.java +++ b/src/test/java/com/redhat/devtools/intellij/common/kubernetes/ClusterHelperTest.java @@ -38,15 +38,19 @@ public void testKubernetesCluster() { @Test public void testOCP4NormalUserCluster() { + // given OpenShiftClient oclient = mock(OpenShiftClient.class); when(oclient.getVersion()).thenReturn(null); - when(oclient.isSupported()).thenReturn(true); VersionInfo versionInfo = mock(VersionInfo.class); when(versionInfo.getGitVersion()).thenReturn("1.20.0"); + KubernetesClient client = mock(KubernetesClient.class); when(client.adapt(OpenShiftClient.class)).thenReturn(oclient); + when(client.hasApiGroup(OpenShiftClient.BASE_API_GROUP, false)).thenReturn(true); when(client.getKubernetesVersion()).thenReturn(versionInfo); + // when ClusterInfo info = ClusterHelper.getClusterInfo(client); + // then assertEquals("1.20.0", info.getKubernetesVersion()); assertTrue(info.isOpenshift()); assertEquals("", info.getOpenshiftVersion()); @@ -54,18 +58,22 @@ public void testOCP4NormalUserCluster() { @Test public void testOCP3OrOCP4AdminUserCluster() { + // given + OpenShiftClient oclient = mock(OpenShiftClient.class); VersionInfo oversionInfo = mock(VersionInfo.class); when(oversionInfo.getMajor()).thenReturn("4"); when(oversionInfo.getMinor()).thenReturn("7.0"); - OpenShiftClient oclient = mock(OpenShiftClient.class); when(oclient.getVersion()).thenReturn(oversionInfo); - when(oclient.isSupported()).thenReturn(true); - VersionInfo versionInfo = mock(VersionInfo.class); - when(versionInfo.getGitVersion()).thenReturn("1.20.0"); + KubernetesClient client = mock(KubernetesClient.class); when(client.adapt(OpenShiftClient.class)).thenReturn(oclient); + when(client.hasApiGroup(OpenShiftClient.BASE_API_GROUP, false)).thenReturn(true); + VersionInfo versionInfo = mock(VersionInfo.class); + when(versionInfo.getGitVersion()).thenReturn("1.20.0"); when(client.getKubernetesVersion()).thenReturn(versionInfo); + // when ClusterInfo info = ClusterHelper.getClusterInfo(client); + // then assertEquals("1.20.0", info.getKubernetesVersion()); assertTrue(info.isOpenshift()); assertEquals("4.7.0", info.getOpenshiftVersion()); diff --git a/src/test/java/com/redhat/devtools/intellij/common/utils/ConfigHelperTest.java b/src/test/java/com/redhat/devtools/intellij/common/utils/ConfigHelperTest.java index 7a13e5d..48f1e6d 100644 --- a/src/test/java/com/redhat/devtools/intellij/common/utils/ConfigHelperTest.java +++ b/src/test/java/com/redhat/devtools/intellij/common/utils/ConfigHelperTest.java @@ -10,22 +10,13 @@ ******************************************************************************/ package com.redhat.devtools.intellij.common.utils; -import io.fabric8.kubernetes.api.model.AuthInfo; -import io.fabric8.kubernetes.api.model.AuthProviderConfig; import io.fabric8.kubernetes.api.model.Context; -import io.fabric8.kubernetes.api.model.NamedAuthInfo; -import io.fabric8.kubernetes.api.model.NamedAuthInfoBuilder; import io.fabric8.kubernetes.api.model.NamedContext; import io.fabric8.kubernetes.client.Config; import org.junit.Test; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; @@ -40,538 +31,260 @@ public class ConfigHelperTest { "namespace1", "papa smurf"), "papa smurfs context"); - private static final NamedAuthInfo user1 = new NamedAuthInfo( - ctx1.getContext().getUser(), - authInfo(null, authProviderConfig("token1"))); private static final NamedContext ctx2 = new NamedContext( new Context("cluster2", null, "namespace2", "grumpy smurf"), "grumpy smurfs context"); - private static final NamedAuthInfo user2 = new NamedAuthInfo( - ctx2.getContext().getUser(), - authInfo(null, authProviderConfig("token2"))); private static final NamedContext ctx3 = new NamedContext( new Context("cluster3", null, "namespace3", "smurfette"), "smurfettes context"); - private static final NamedAuthInfo user3 = new NamedAuthInfo( - ctx3.getContext().getUser(), - authInfo(null, authProviderConfig("token3"))); private static final NamedContext ctx4 = new NamedContext( new Context("cluster4", null, "namespace4", "jokey smurf"), "jokey smurfs context"); - private static final NamedAuthInfo user4 = new NamedAuthInfo( - ctx4.getContext().getUser(), - authInfo(null, authProviderConfig("token4"))); private static final NamedContext ctx5 = new NamedContext( new Context("cluster2", null, "namespace2", "azrael"), "azraels context"); - private static final NamedAuthInfo user5 = new NamedAuthInfo( - ctx5.getContext().getUser(), - authInfo("token1", null)); - - private static final List allUsers = Arrays.asList(user1, user2, user3, user4, user5); - private static final List allContexts = Arrays.asList(ctx1, ctx2, ctx3, ctx5); // ctx4 not included + private static final List allContextsButCtx4 = Arrays.asList(ctx1, ctx2, ctx3, ctx5); // ctx4 not included @Test - public void identical_namedContexts_should_be_equal() { + public void areEqualCurrentContext_returns_true_given_identical_current_contexts() { // given + Config config1 = clientConfig(ctx1); + Config config2 = clientConfig(ctx1); // when - boolean equal = ConfigHelper.areEqual(ctx1, clone(ctx1)); + boolean equal = ConfigHelper.areEqualCurrentContext(config1, config2); // then assertThat(equal).isTrue(); } @Test - public void null_namedContexts_should_not_be_equal_to_non_null_namedContext() { + public void areEqualCurrentContext_returns_false_given_one_config_has_no_current_context_and_the_other_has() { // given + Config config1 = clientConfig((NamedContext) null); + Config config2 = clientConfig(ctx1); // when - boolean equal = ConfigHelper.areEqual(ctx1, null); + boolean equal = ConfigHelper.areEqualCurrentContext(config1, config2); // then assertThat(equal).isFalse(); } @Test - public void non_null_namedContexts_should_not_be_equal_to_null_namedContext() { - // given - // when - boolean equal = ConfigHelper.areEqual(null, ctx1); - // then - assertThat(equal).isFalse(); - } - - @Test - public void namedContexts_with_different_cluster_should_NOT_be_equal() { + public void areEqualCurrentContext_returns_false_given_current_contexts_differ_in_cluster() { // given + Config config1 = clientConfig(ctx1); NamedContext differentCluster = clone(ctx1); differentCluster.getContext().setCluster("imperial fleet"); + Config config2 = clientConfig(differentCluster); // when - boolean equal = ConfigHelper.areEqual(ctx1, differentCluster); + boolean equal = ConfigHelper.areEqualCurrentContext(config1, config2); // then assertThat(equal).isFalse(); } @Test - public void namedContexts_with_different_namespace_should_NOT_be_equal() { + public void areEqualCurrentContext_returns_false_given_current_contexts_differ_in_namespace() { // given + Config config1 = clientConfig(ctx1); NamedContext differentNamespace = clone(ctx1); differentNamespace.getContext().setNamespace("stormtroopers"); + Config config2 = clientConfig(differentNamespace); // when - boolean equal = ConfigHelper.areEqual(ctx1, differentNamespace); + boolean equal = ConfigHelper.areEqualCurrentContext(config1, config2); // then assertThat(equal).isFalse(); } @Test - public void namedContexts_with_different_user_should_NOT_be_equal() { + public void areEqualCurrentContext_returns_false_given_current_contexts_differ_in_user() { // given + Config config1 = clientConfig(ctx1); NamedContext differentUser = clone(ctx1); differentUser.getContext().setUser("lord vader"); + Config config2 = clientConfig(differentUser); // when - boolean equal = ConfigHelper.areEqual(ctx1, differentUser); + boolean equal = ConfigHelper.areEqualCurrentContext(config1, config2); // then assertThat(equal).isFalse(); } @Test - public void namedContexts_with_different_name_should_NOT_be_equal() { + public void areEqualCurrentContext_returns_false_given_current_contexts_differ_in_name() { // given + Config config1 = clientConfig(ctx1); NamedContext differentName = clone(ctx1); - differentName.setName("imperial fleet"); + differentName.setName("r2d2"); + Config config2 = clientConfig(differentName); // when - boolean equal = ConfigHelper.areEqual(ctx1, differentName); + boolean equal = ConfigHelper.areEqualCurrentContext(config1, config2); // then assertThat(equal).isFalse(); } @Test - public void namedContexts_with_same_members_should_be_equal() { + public void areEqualContexts_returns_true_given_contexts_with_same_members() { // given + Config config1 = clientConfig(allContextsButCtx4); + List sameMembers = clone(allContextsButCtx4); + Config config2 = clientConfig(sameMembers); // when - boolean equal = ConfigHelper.areEqual( - Arrays.asList(ctx1, ctx2), - Arrays.asList(clone(ctx1), clone(ctx2))); + boolean equal = ConfigHelper.areEqualContexts(config1, config2); // then assertThat(equal).isTrue(); } @Test - public void namedContexts_with_additional_member_should_NOT_be_equal() { + public void areEqualContexts_returns_false_given_config_is_missing_one_context() { // given - + Config config1 = clientConfig(allContextsButCtx4); + List isMissingOneContext = clone(allContextsButCtx4); + isMissingOneContext.remove(isMissingOneContext.size() - 1); + Config config2 = clientConfig(isMissingOneContext); // when - boolean equal = ConfigHelper.areEqual( - Arrays.asList(ctx1, ctx2), - Arrays.asList(clone(ctx1), clone(ctx2), ctx3)); + boolean equal = ConfigHelper.areEqualContexts(config1, config2); // then assertThat(equal).isFalse(); } @Test - public void namedContexts_with_different_members_should_NOT_be_equal() { + public void areEqualContexts_returns_false_given_config_has_additional_context() { // given - List additionalMember = clone(allContexts); - additionalMember.add(ctx4); + Config config1 = clientConfig(allContextsButCtx4); + List hasAdditionalCtx4 = clone(allContextsButCtx4); + hasAdditionalCtx4.add(ctx4); + Config config2 = clientConfig(hasAdditionalCtx4); // when - boolean equal = ConfigHelper.areEqual( - allContexts, - additionalMember); + boolean equal = ConfigHelper.areEqualContexts(config1, config2); // then assertThat(equal).isFalse(); } @Test - public void authInfo_with_same_provider_token_should_be_equal() { + public void areEqualAuthInfo_returns_false_given_contexts_differ_in_username() { // given - String token = "gargamel"; - AuthInfo authInfo = authInfo(null, authProviderConfig("id-token", token)); - Config config = clientConfig(token); + Config config1 = clientConfig("yoda", null); + Config config2 = clientConfig("obiwan", null); // when - boolean equal = ConfigHelper.areEqualToken(authInfo, config); - // then - assertThat(equal).isTrue(); - } - - @Test - public void authInfo_with_same_authinfo_token_should_be_equal() { - // given - String token = "token42"; - AuthInfo authInfo = authInfo(token, null); - Config config = clientConfig(token); - // when - boolean equal = ConfigHelper.areEqualToken(authInfo, config); - // then - assertThat(equal).isTrue(); - } - - @Test - public void authInfo_with_different_provider_token_should_NOT_be_equal() { - // given - AuthInfo authInfo = authInfo(null, authProviderConfig("id-token", "gargamel")); - Config config = clientConfig("azrael"); - // when - boolean equal = ConfigHelper.areEqualToken(authInfo, config); + boolean equal = ConfigHelper.areEqualAuthInfo(config1, config2); // then assertThat(equal).isFalse(); } @Test - public void authInfo_with_same_provider_token_in_access_token_should_be_equal() { - // given - String token = "gargamel"; - AuthInfo authInfo = authInfo(null, authProviderConfig("access-token", token)); - Config config = clientConfig(token); - // when - boolean equal = ConfigHelper.areEqualToken(authInfo, config); - // then - assertThat(equal).isTrue(); - } - - @Test - public void two_authInfos_with_same_provider_token_should_be_equal() { - // given - String token = "gargamel"; - AuthInfo authInfo = authInfo(null, authProviderConfig("id-token", token)); - AuthInfo newAuthInfo = authInfo(null, authProviderConfig("id-token", token)); - // when - boolean equal = ConfigHelper.areEqualToken(authInfo, newAuthInfo); - // then - assertThat(equal).isTrue(); - } - - @Test - public void two_authInfos_with_same_authinfo_token_should_be_equal() { + public void areEqualAuthInfo_returns_false_given_contexts_differ_in_password() { // given - String token = "token42"; - AuthInfo authInfo = authInfo(token, null); - AuthInfo newAuthInfo = authInfo(token, null); + Config config1 = clientConfig("yoda", "the force"); + Config config2 = clientConfig("yoda", "the light saber"); // when - boolean equal = ConfigHelper.areEqualToken(authInfo, newAuthInfo); - // then - assertThat(equal).isTrue(); - } - - @Test - public void two_authInfos_with_different_provider_token_should_NOT_be_equal() { - // given - AuthInfo authInfo = authInfo(null, authProviderConfig("id-token", "gargamel")); - AuthInfo newAuthInfo = authInfo(null, authProviderConfig("id-token", "azrael")); - // when - boolean equal = ConfigHelper.areEqualToken(authInfo, newAuthInfo); + boolean equal = ConfigHelper.areEqualAuthInfo(config1, config2); // then assertThat(equal).isFalse(); } @Test - public void two_authInfos_with_same_provider_token_in_access_token_should_be_equal() { + public void areEqualToken_returns_true_given_contexts_have_same_token() { // given - String token = "gargamel"; - AuthInfo authInfo = authInfo(null, authProviderConfig("access-token", token)); - AuthInfo newAuthInfo = authInfo(null, authProviderConfig("access-token", token)); + Config config1 = clientConfig("R2-D2"); + Config config2 = clientConfig("R2-D2"); // when - boolean equal = ConfigHelper.areEqualToken(authInfo, newAuthInfo); + boolean equal = ConfigHelper.areEqualToken(config1, config2); // then assertThat(equal).isTrue(); } @Test - public void kubeConfig1_and_kubeConfig2_are_equal_if_same_in_currentContext_contexts_and_provider_token() { - // given - io.fabric8.kubernetes.api.model.Config kubeConfig1 = kubeConfig( - ctx2, - allContexts, - allUsers); - io.fabric8.kubernetes.api.model.Config kubeConfig2 = kubeConfig( - clone(ctx2), - clone(allContexts), - clone(allUsers)); - // when - boolean equal = ConfigHelper.areEqual(kubeConfig1, kubeConfig2); - // then - assertThat(equal).isTrue(); - } - - @Test - public void kubeConfig1_and_kubeConfig2_are_NOT_equal_if_NOT_same_in_currentContext() { - // given - io.fabric8.kubernetes.api.model.Config kubeConfig1 = kubeConfig( - ctx2, - allContexts, - allUsers); - io.fabric8.kubernetes.api.model.Config kubeConfig2 = kubeConfig( - clone(ctx3), - clone(allContexts), - clone(allUsers)); - // when - boolean equal = ConfigHelper.areEqual(kubeConfig1, kubeConfig2); - // then - assertThat(equal).isFalse(); - } - - @Test - public void kubeConfig1_and_kubeConfig2_are_NOT_equal_if_contexts_has_additional_member() { - // given - List allContextsWithAddition = new ArrayList<>(allContexts); - allContextsWithAddition.add(ctx4); - io.fabric8.kubernetes.api.model.Config kubeConfig1 = kubeConfig( - ctx2, - allContextsWithAddition, - allUsers); - io.fabric8.kubernetes.api.model.Config kubeConfig2 = kubeConfig( - clone(ctx2), - clone(allContexts), - clone(allUsers)); - // when - boolean equal = ConfigHelper.areEqual(kubeConfig1, kubeConfig2); - // then - assertThat(equal).isFalse(); - } - - @Test - public void kubeConfig1_and_kubeConfig2_are_NOT_equal_if_token_is_different() { - // given - io.fabric8.kubernetes.api.model.Config kubeConfig1 = kubeConfig( - ctx2, - allContexts, - allUsers); - - String currentUserName = ctx2.getContext().getUser(); - NamedAuthInfo currentUser = allUsers.stream() - .filter(user -> user.getName().equals(currentUserName)) - .findFirst() - .get(); - NamedAuthInfo currentUserClone = clone(currentUser); - List allUsersClone = clone(allUsers); - int index = allUsersClone.indexOf(currentUserClone); - allUsersClone.set(index, currentUserClone); - currentUserClone.getUser().setToken("token 42"); - io.fabric8.kubernetes.api.model.Config kubeConfig2 = kubeConfig( - clone(ctx2), - clone(allContexts), - allUsersClone); - // when - boolean equal = ConfigHelper.areEqual(kubeConfig1, kubeConfig2); - // then - assertThat(equal).isFalse(); - } - - @Test - public void kubeConfig1_and_kubeConfig2_are_NOT_equal_if_kubeConfig2_has_no_current_context() { + public void areEqualToken_returns_false_given_contexts_differ_in_token() { // given - io.fabric8.kubernetes.api.model.Config kubeConfig1 = kubeConfig( - ctx2, - allContexts, - allUsers); - io.fabric8.kubernetes.api.model.Config kubeConfig2 = kubeConfig( - null, // no current context - allContexts, - allUsers); + Config config1 = clientConfig("R2-D2"); + Config config2 = clientConfig("C-3PO"); // when - boolean equal = ConfigHelper.areEqual(kubeConfig1, kubeConfig2); + boolean equal = ConfigHelper.areEqualToken(config1, config2); // then assertThat(equal).isFalse(); } @Test - public void kubeConfig_and_clientConfig_are_equal_if_same_in_currentContext_contexts_and_provider_token() { + public void areEqual_returns_true_given_both_context_have_same_token_current_ctx_and_contexts() { // given - io.fabric8.kubernetes.api.model.Config kubeConfig = kubeConfig( - ctx2, - allContexts, - allUsers); - io.fabric8.kubernetes.client.Config clientConfig = clientConfig( - getUser(ctx2, allUsers), - clone(ctx2), - clone(allContexts)); + Config config1 = clientConfig("C3-PO", ctx2, allContextsButCtx4); + Config config2 = clientConfig("C3-PO", clone(ctx2), clone(allContextsButCtx4)); // when - boolean equal = ConfigHelper.areEqual(kubeConfig, clientConfig); + boolean equal = ConfigHelper.areEqual(config1, config2); // then assertThat(equal).isTrue(); } @Test - public void kubeConfig_and_clientConfig_are_equal_if_same_in_currentContext_contexts_and_authinfo_token() { + public void areEqual_returns_false_given_one_context_has_different_token() { // given - io.fabric8.kubernetes.api.model.Config kubeConfig = kubeConfig( - ctx5, - allContexts, - allUsers); - io.fabric8.kubernetes.client.Config clientConfig = clientConfig( - getUser(ctx5, allUsers), - clone(ctx5), - clone(allContexts)); + Config config1 = clientConfig("C3-PO", ctx2, allContextsButCtx4); + Config config2 = clientConfig("R2-D2", clone(ctx2), clone(allContextsButCtx4)); // when - boolean equal = ConfigHelper.areEqual(kubeConfig, clientConfig); - // then - assertThat(equal).isTrue(); - } - - @Test - public void kubeConfig_and_clientConfig_are_NOT_equal_if_NOT_same_in_currentContext() { - // given - io.fabric8.kubernetes.api.model.Config kubeConfig = kubeConfig( - ctx2, - allContexts, - allUsers); - io.fabric8.kubernetes.client.Config clientConfig = clientConfig( - getUser(ctx3, allUsers), - clone(ctx3), - clone(allContexts)); - // when - boolean equal = ConfigHelper.areEqual(kubeConfig, clientConfig); + boolean equal = ConfigHelper.areEqual(config1, config2); // then assertThat(equal).isFalse(); } @Test - public void kubeConfig_and_clientConfig_are_NOT_equal_if_contexts_has_additional_member() { + public void areEqual_returns_false_given_one_context_has_different_current_context() { // given - List allContextsWithAddition = new ArrayList<>(allContexts); - allContextsWithAddition.add(ctx4); - io.fabric8.kubernetes.api.model.Config kubeConfig = kubeConfig( - ctx2, - allContextsWithAddition, - allUsers); - io.fabric8.kubernetes.client.Config clientConfig = clientConfig( - getUser(ctx2, allUsers), - clone(ctx2), - allContexts); + Config config1 = clientConfig("C3-PO", ctx2, allContextsButCtx4); + Config config2 = clientConfig("C3-PO", ctx3, clone(allContextsButCtx4)); // when - boolean equal = ConfigHelper.areEqual(kubeConfig, clientConfig); + boolean equal = ConfigHelper.areEqual(config1, config2); // then assertThat(equal).isFalse(); } @Test - public void kubeConfig_and_clientConfig_are_NOT_equal_if_token_is_different() { - // given - io.fabric8.kubernetes.api.model.Config kubeConfig = kubeConfig( - ctx2, - allContexts, - allUsers); - io.fabric8.kubernetes.client.Config clientConfig = clientConfig( - "token 42", - clone(ctx2), - allContexts); - // when - boolean equal = ConfigHelper.areEqual(kubeConfig, clientConfig); - // then - assertThat(equal).isFalse(); - } - - @Test - public void kubeConfig_and_clientConfig_are_NOT_equal_if_kubeConfig_has_no_current_context() { - // given - io.fabric8.kubernetes.api.model.Config kubeConfig = kubeConfig( - null, // no current context - allContexts, - allUsers); - io.fabric8.kubernetes.client.Config clientConfig = clientConfig( - "token 42", - clone(ctx2), - allContexts); - // when - boolean equal = ConfigHelper.areEqual(kubeConfig, clientConfig); - // then - assertThat(equal).isFalse(); - } - - @Test - public void getCurrentContext_should_return_current_context() { - // given - NamedContext currentContext = ctx3; - io.fabric8.kubernetes.api.model.Config kubeConfig = kubeConfig( - currentContext, - allContexts, - allUsers); - // when - NamedContext currentFoundInFile = ConfigHelper.getCurrentContext(kubeConfig); - // then - assertThat(currentFoundInFile).isEqualTo(currentContext); - } - - @Test - public void getCurrentContext_should_return_null_if_there_is_no_current_context() { + public void areEqual_returns_true_even_if_one_context_has_additional_context() { // given - io.fabric8.kubernetes.api.model.Config kubeConfig = kubeConfig( - null, - allContexts, - allUsers); + Config config1 = clientConfig("C3-PO", ctx2, allContextsButCtx4); + List hasAdditionalContext = clone(allContextsButCtx4); + hasAdditionalContext.add(ctx4); + Config config2 = clientConfig("C3-PO", clone(ctx2), hasAdditionalContext); // when - NamedContext currentFoundInFile = ConfigHelper.getCurrentContext(kubeConfig); - // then - assertThat(currentFoundInFile).isNull(); - } - - @Test - public void getCurrentContextName_should_return_name_of_current_context() { - // given - NamedContext currentContext = ctx3; - io.fabric8.kubernetes.api.model.Config kubeConfig = kubeConfig( - currentContext, - allContexts, - allUsers); - // when - String currentContextName = ConfigHelper.getCurrentContextName(kubeConfig); - // then - assertThat(currentContextName).isEqualTo(currentContext.getName()); - } - - @Test - public void getCurrentContextName_should_return_null_if_there_is_no_current_context() { - // given - io.fabric8.kubernetes.api.model.Config kubeConfig = kubeConfig( - null, - allContexts, - allUsers); - // when - String currentContext = ConfigHelper.getCurrentContextName(kubeConfig); - // then - assertThat(currentContext).isNull(); - } - - private static AuthInfo authInfo(String token, AuthProviderConfig config) { - AuthInfo authInfo = new AuthInfo(); - authInfo.setAuthProvider(config); - authInfo.setToken(token); - return authInfo; + boolean equal = ConfigHelper.areEqual(config1, config2); + // then different number of members doesn't matter, only current context matters + assertThat(equal).isTrue(); } - private static AuthProviderConfig authProviderConfig(String tokenValue) { - return authProviderConfig("id-config", tokenValue); + private static Config clientConfig(String token) { + return clientConfig(token, null, null); } - private static AuthProviderConfig authProviderConfig(String tokenKey, String tokenValue) { - AuthProviderConfig authProviderConfig = new AuthProviderConfig(); - Map config = new HashMap<>(); - config.put(tokenKey, tokenValue); - authProviderConfig.setConfig(config); - return authProviderConfig; + private static Config clientConfig(String username, String password) { + Config config = clientConfig(null, null, null); + doReturn(username) + .when(config).getUsername(); + doReturn(password) + .when(config).getPassword(); + return config; } - private static Config clientConfig(String token) { - return clientConfig(token, null, Collections.emptyList()); + private static Config clientConfig(NamedContext currentContext) { + return clientConfig(null, currentContext, null); } - private static Config clientConfig(NamedAuthInfo user, NamedContext currentContext, List contexts) { - return clientConfig(user.getUser().getToken(), currentContext, contexts); + private static Config clientConfig(List contexts) { + return clientConfig(null, null, contexts); } private static Config clientConfig(String token, NamedContext currentContext, List contexts) { Config config = mock(Config.class); doReturn(token) - .when(config).getOauthToken(); + .when(config).getAutoOAuthToken(); doReturn(currentContext) .when(config).getCurrentContext(); doReturn(contexts) @@ -579,20 +292,6 @@ private static Config clientConfig(String token, NamedContext currentContext, Li return config; } - private static io.fabric8.kubernetes.api.model.Config kubeConfig( - NamedContext currentContext, - List contexts, - List users) { - io.fabric8.kubernetes.api.model.Config config = mock(io.fabric8.kubernetes.api.model.Config.class); - doReturn(currentContext == null? null : currentContext.getName()) - .when(config).getCurrentContext(); - doReturn(contexts) - .when(config).getContexts(); - doReturn(users) - .when(config).getUsers(); - return config; - } - private static List clone(List namedContexts) { return namedContexts.stream() .map(ConfigHelperTest::clone) @@ -608,21 +307,4 @@ private static NamedContext clone(NamedContext namedContext) { context.getUser()), namedContext.getName()); } - - private static NamedAuthInfo clone(NamedAuthInfo user) { - return new NamedAuthInfoBuilder(user).build(); - } - - private static List clone(Collection users) { - return users.stream() - .map(user -> new NamedAuthInfoBuilder(user).build()) - .collect(Collectors.toList()); - } - - private static NamedAuthInfo getUser(NamedContext context, Collection users) { - return users.stream() - .filter(user -> user.getName() == context.getContext().getUser()) - .findAny() - .orElse(null); - } } diff --git a/src/test/java/com/redhat/devtools/intellij/common/utils/ConfigWatcherTest.java b/src/test/java/com/redhat/devtools/intellij/common/utils/ConfigWatcherTest.java index b425802..5bd7af8 100644 --- a/src/test/java/com/redhat/devtools/intellij/common/utils/ConfigWatcherTest.java +++ b/src/test/java/com/redhat/devtools/intellij/common/utils/ConfigWatcherTest.java @@ -10,7 +10,7 @@ ******************************************************************************/ package com.redhat.devtools.intellij.common.utils; -import io.fabric8.kubernetes.api.model.Config; +import io.fabric8.kubernetes.client.Config; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; @@ -157,7 +157,7 @@ private static class ReportingListener implements ConfigWatcher.Listener { private boolean called = false; @Override - public void onUpdate(ConfigWatcher source, Config config) { + public void onUpdate(Config updatedConfig) { this.called = true; } diff --git a/src/test/java/com/redhat/devtools/intellij/common/utils/ToolsConfigTest.java b/src/test/java/com/redhat/devtools/intellij/common/utils/ToolsConfigTest.java index b52d0d8..49c529d 100644 --- a/src/test/java/com/redhat/devtools/intellij/common/utils/ToolsConfigTest.java +++ b/src/test/java/com/redhat/devtools/intellij/common/utils/ToolsConfigTest.java @@ -24,7 +24,7 @@ public class ToolsConfigTest { @BeforeClass public static void init() throws IOException { - config = ConfigHelper.loadToolsConfig(ToolsConfig.class.getResource("/tkn-test.json")); + config = ToolsConfigHelper.loadToolsConfig(ToolsConfig.class.getResource("/tkn-test.json")); } @Test