KubeConfig.runExec doesn't work with kubeconfig exec command
Closed this issue · 6 comments
Describe the bug
This issue occurs with any kubeconfig file which uses an exec
command to get user credentials.
When instantiating the ApiClient
class through ClientBuilder.kubeconfig
and a kubeconfig file built with KubeConfig.loadKubeConfig
, the following error occurs:
java.lang.NullPointerException: Cannot invoke "java.io.File.toPath()" because "this.file" is null
at io.kubernetes.client.util.KubeConfig.runExec (KubeConfig.java:333)
at io.kubernetes.client.util.KubeConfig.getCredentialsViaExecCredential (KubeConfig.java:291)
at io.kubernetes.client.util.KubeConfig.getCredentials (KubeConfig.java:239)
at io.kubernetes.client.util.credentials.KubeconfigAuthentication.<init> (KubeconfigAuthentication.java:59)
at io.kubernetes.client.util.ClientBuilder.kubeconfig (ClientBuilder.java:300)
at io.kubernetes.client.examples.KubeConfigFileClientExample.main (KubeConfigFileClientExample.java:43)
at org.codehaus.mojo.exec.ExecJavaMojo.lambda$execute$0 (ExecJavaMojo.java:283)
at java.lang.Thread.run (Thread.java:833)
It seems that the KubeConfig.runExec
method expects the kubeconfig to be provided as a file rather than a KubeConfig
object.
The KubeConfigFileClientExample.java
example can be fixed with the following changes:
diff --git a/examples/examples-release-20/src/main/java/io/kubernetes/client/examples/KubeConfigFileClientExample.java b/examples/examples-release-20/src/main/java/io/kubernetes/client/examples/KubeConfigFileClientExample.java
index 7a0ba4dcf..bb62b7365 100644
--- a/examples/examples-release-20/src/main/java/io/kubernetes/client/examples/KubeConfigFileClientExample.java
+++ b/examples/examples-release-20/src/main/java/io/kubernetes/client/examples/KubeConfigFileClientExample.java
@@ -22,6 +22,7 @@ import io.kubernetes.client.util.ClientBuilder;
import io.kubernetes.client.util.KubeConfig;
import java.io.FileReader;
import java.io.IOException;
+import java.nio.file.Paths;
/**
* A simple example of how to use the Java API from an application outside a kubernetes cluster
@@ -37,10 +38,12 @@ public class KubeConfigFileClientExample {
// file path to your KubeConfig
String kubeConfigPath = System.getenv("HOME") + "/.kube/config";
+ KubeConfig kubeconfig = KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath));
+ kubeconfig.setFile(Paths.get(kubeConfigPath).toFile());
// loading the out-of-cluster config, a kubeconfig from file-system
ApiClient client =
- ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))).build();
+ ClientBuilder.kubeconfig(kubeconfig).build();
// set the global default api-client to the in-cluster one from above
Configuration.setDefaultApiClient(client);
Client Version
20
Kubernetes Version
1.28.6
Java Version
17
To Reproduce
Generate a kubeconfig file in $HOME/.kube/config
which uses an exec
command to get user credentials.
cd examples/examples-release-20
mvn -X clean install exec:java -Dexec.mainClass="io.kubernetes.client.examples.KubeConfigFileClientExample"
Expected behavior
Everything works fine
KubeConfig
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: REDACTED
server: REDACTED
tls-server-name: REDACTED
name: REDACTED
contexts:
- context:
cluster: REDACTED
extensions:
- extension: sandbox
name: teleport.kube.name
user: REDACTED
name: REDACTED
current-context: REDACTED
kind: Config
preferences: {}
users:
- name: REDACTED
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- kube
- credentials
- --kube-cluster=sandbox
- --teleport-cluster=REDACTED
- --proxy=REDACTED
command: tsh
env: null
provideClusterInfo: false
Server (please complete the following information):
- OS: Linux
- Environment: system
- Cloud: Azure
Additional context
Ah yes, I see the problem. I think in cases where the file for the kubeconfig isn't present, we should just use the current working directory.
In this case the kubeconfig file is not even in the current directory, it’s located in its default location ($HOME/.kube/config
).
Wouldn’t it be best to just use the data loaded into the KubeConfig object instead? I don’t know Java very well, but from what I understand of the code, it seems that the required information is present in the object.
Since we have the contexts and the users, I guess it should be possible to extract the exec
command from the user of the current context. WDYT?
I looked at the code and I don't think that the kubeconfig you supplied could have triggered this exception.
The code is here:
And in order to throw that exception, your command
needs to have a slash in it (/
or \
) but in your example above, there's no slash it's just tsh
I think that there actually is a bug here, but to debug properly I need the correct kubeconfig which you used.
And in order to throw that exception, your
command
needs to have a slash in it (/
or\
) but in your example above, there's no slash it's justtsh
I think that there actually is a bug here, but to debug properly I need the correct kubeconfig which you used.
That's my bad, I copied the kubeconfig example on the three issues I opened at once and since I did multiple tests to try to make each of them work, I kept the command as tsh
but in fact it's an absolute path from my root.
I don't think the real path is super relevant but it's something like that: /nix/store/xyz-tsh/bin/tsh
.
Sorry about that and thanks for the quick fix! If you wish me to, I can test the fix tomorrow and let you know.
The Kubernetes project currently lacks enough contributors to adequately respond to all issues.
This bot triages un-triaged issues according to the following rules:
- After 90d of inactivity,
lifecycle/stale
is applied - After 30d of inactivity since
lifecycle/stale
was applied,lifecycle/rotten
is applied - After 30d of inactivity since
lifecycle/rotten
was applied, the issue is closed
You can:
- Mark this issue as fresh with
/remove-lifecycle stale
- Close this issue with
/close
- Offer to help out with Issue Triage
Please send feedback to sig-contributor-experience at kubernetes/community.
/lifecycle stale
Fixed by #3244