-
Notifications
You must be signed in to change notification settings - Fork 21
fix: create lazy OpenShift context to avoid check timeouts (#865) #866
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,10 @@ open class OSClientAdapter(client: OpenShiftClient, private val kubeClient: Kube | |
ClientConfig(kubeClient.configuration) | ||
} | ||
|
||
override fun toOpenShift(): OSClientAdapter { | ||
return this | ||
} | ||
|
||
override fun isOpenShift(): Boolean { | ||
return true | ||
} | ||
|
@@ -52,17 +56,33 @@ open class KubeClientAdapter(client: KubernetesClient) : | |
override fun isOpenShift(): Boolean { | ||
return false | ||
} | ||
|
||
override fun toOpenShift(): OSClientAdapter { | ||
val kubeClient = get() | ||
val osClient = kubeClient.adapt(NamespacedOpenShiftClient::class.java) | ||
return OSClientAdapter(osClient, kubeClient) | ||
} | ||
} | ||
|
||
abstract class ClientAdapter<C : KubernetesClient>(private val fabric8Client: C) { | ||
|
||
companion object Factory { | ||
|
||
const val TIMEOUT_CONNECTION = 5000 | ||
const val TIMEOUT_REQUEST = 5000 | ||
const val LIMIT_RECONNECT = 2 | ||
|
||
fun create( | ||
namespace: String? = null, | ||
context: String? = null, | ||
clientBuilder: KubernetesClientBuilder? = null, | ||
createConfig: (context: String?) -> Config = { context -> Config.autoConfigure(context) }, | ||
createConfig: (context: String?) -> Config = { context -> | ||
val config = Config.autoConfigure(context) | ||
config.connectionTimeout = TIMEOUT_CONNECTION | ||
config.requestTimeout = TIMEOUT_REQUEST | ||
config.watchReconnectLimit = LIMIT_RECONNECT | ||
config | ||
}, | ||
externalTrustManagerProvider: ((toIntegrate: List<X509ExtendedTrustManager>) -> X509TrustManager)? = null | ||
): ClientAdapter<out KubernetesClient> { | ||
KubeConfigEnvValue.copyToSystem() | ||
|
@@ -76,12 +96,14 @@ abstract class ClientAdapter<C : KubernetesClient>(private val fabric8Client: C) | |
setSslContext(httpClientBuilder, config, trustManager) | ||
} | ||
.build() | ||
return if (ClusterHelper.isOpenShift(kubeClient)) { | ||
val osClient = kubeClient.adapt(NamespacedOpenShiftClient::class.java) | ||
OSClientAdapter(osClient, kubeClient) | ||
} else { | ||
KubeClientAdapter(kubeClient) | ||
} | ||
/** | ||
* Always create kubernetes client. | ||
* Upgrade existing client to OpenShift only async bcs checking if cluster is OpenShift is costly | ||
* and may timeout if cluster is not reachable. | ||
* @see [issue 865](https://github.com/redhat-developer/intellij-kubernetes/issues/865) | ||
* @see ClientAdapter.toOpenShift | ||
**/ | ||
return KubeClientAdapter(kubeClient) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is the core of the fix: dont check if the cluster is OpenShift and create a Kubernetes- or OpenShift client. This check is costly and may timeout if the cluster is not reachable. |
||
} | ||
|
||
private fun setSslContext( | ||
|
@@ -114,6 +136,8 @@ abstract class ClientAdapter<C : KubernetesClient>(private val fabric8Client: C) | |
ClientConfig(fabric8Client.configuration) | ||
} | ||
|
||
abstract fun toOpenShift(): OSClientAdapter | ||
|
||
abstract fun isOpenShift(): Boolean | ||
|
||
fun get(): C { | ||
|
@@ -145,6 +169,10 @@ abstract class ClientAdapter<C : KubernetesClient>(private val fabric8Client: C) | |
} | ||
} | ||
|
||
fun canAdaptToOpenShift(): Boolean { | ||
return ClusterHelper.isOpenShift(fabric8Client) | ||
} | ||
|
||
open fun close() { | ||
clients.values.forEach{ it.close() } | ||
fabric8Client.close() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ import com.redhat.devtools.intellij.kubernetes.model.IResourceModelObservable | |
import com.redhat.devtools.intellij.kubernetes.model.client.ClientAdapter | ||
import com.redhat.devtools.intellij.kubernetes.model.client.KubeClientAdapter | ||
import com.redhat.devtools.intellij.kubernetes.model.client.OSClientAdapter | ||
import com.redhat.devtools.intellij.kubernetes.model.resource.IResourceOperator | ||
import com.redhat.devtools.intellij.kubernetes.model.resource.ResourceKind | ||
import com.redhat.devtools.intellij.kubernetes.model.resource.kubernetes.KubernetesReplicas.Replicator | ||
import io.fabric8.kubernetes.api.model.GenericKubernetesResource | ||
|
@@ -23,30 +24,29 @@ import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinition | |
import io.fabric8.kubernetes.client.KubernetesClient | ||
import io.fabric8.kubernetes.client.Watch | ||
import io.fabric8.kubernetes.client.Watcher | ||
import io.fabric8.openshift.api.model.Project | ||
import io.fabric8.openshift.client.OpenShiftClient | ||
import java.net.URL | ||
|
||
interface IActiveContext<N: HasMetadata, C: KubernetesClient>: IContext { | ||
|
||
companion object Factory { | ||
fun create( | ||
fun createLazyOpenShift( | ||
client: ClientAdapter<out KubernetesClient>, | ||
observable: IResourceModelObservable | ||
modelChange: IResourceModelObservable | ||
): IActiveContext<out HasMetadata, out KubernetesClient>? { | ||
val currentContext = client.config.currentContext ?: return null | ||
return if (client.isOpenShift()) { | ||
OpenShiftContext( | ||
currentContext, | ||
observable, | ||
client as OSClientAdapter | ||
) | ||
} else { | ||
KubernetesContext( | ||
currentContext, | ||
observable, | ||
client as KubeClientAdapter | ||
) | ||
} | ||
return LazyOpenShiftContext(currentContext, modelChange, client as KubeClientAdapter) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is the core of the fix: dont check if the cluster is OpenShift and create a Kubernetes- or OpenShift context. This check is costly and may timeout if the cluster is not reachable. |
||
} | ||
|
||
fun createOpenShift( | ||
client: OSClientAdapter, | ||
modelChange: IResourceModelObservable | ||
): IActiveContext<Project, OpenShiftClient>? { | ||
val currentContext = client.config.currentContext ?: return null | ||
return OpenShiftContext(currentContext, modelChange, client) | ||
} | ||
|
||
} | ||
|
||
/** | ||
|
@@ -65,6 +65,8 @@ interface IActiveContext<N: HasMetadata, C: KubernetesClient>: IContext { | |
} | ||
} | ||
|
||
val namespaceKind : ResourceKind<out HasMetadata> | ||
|
||
/** | ||
* The master url for this context. This is the url of the cluster for this context. | ||
*/ | ||
|
@@ -75,6 +77,16 @@ interface IActiveContext<N: HasMetadata, C: KubernetesClient>: IContext { | |
*/ | ||
val version: ClusterInfo | ||
|
||
/** | ||
* Returns the list of internal [IResourceOperator]s that are available in this context. | ||
* [IResourceOperator]s that are contributed by registrations to the extension point are not included. | ||
* | ||
* @return the list of [IResourceOperator]s that are available in this context. | ||
* @see IResourceOperator | ||
* @see com.redhat.devtools.intellij.kubernetes.model.context.ActiveContext.getExtensionResourceOperators | ||
*/ | ||
fun getInternalResourceOperators(): List<IResourceOperator<out HasMetadata>> | ||
|
||
/** | ||
* Returns {@code true} if this context is an OpenShift context. This is true for context with an OpenShift cluster. | ||
*/ | ||
|
@@ -129,7 +141,7 @@ interface IActiveContext<N: HasMetadata, C: KubernetesClient>: IContext { | |
fun getAllResources(definition: CustomResourceDefinition): Collection<GenericKubernetesResource> | ||
|
||
/** | ||
* Returns the latest version of the given resource from cluster. Returns `null` if none was found. | ||
* Returns the latest version of the given resource from the cluster. Returns `null` if none was found. | ||
* | ||
* @param resource which is to be requested from cluster | ||
* | ||
|
@@ -265,7 +277,7 @@ interface IActiveContext<N: HasMetadata, C: KubernetesClient>: IContext { | |
/** | ||
* Notifies the context that the given resource was replaced in the cluster. | ||
* Replaces the resource with the given new version if it exists. | ||
* Does nothing otherwiese. | ||
* Does nothing otherwise. | ||
* | ||
* | ||
* @param resource the new (version) of the resource | ||
|
@@ -279,7 +291,7 @@ interface IActiveContext<N: HasMetadata, C: KubernetesClient>: IContext { | |
* | ||
* @return the url of the Dashboard for this context | ||
*/ | ||
fun getDashboardUrl(): String | ||
fun getDashboardUrl(): String? | ||
|
||
/** | ||
* Closes and disposes this context. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an aspect of the fix: impose timeouts for connecting, requesting and reconnecting.