Skip to content
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

Exception while execute cmd in pod #4319

Closed
fbi007130 opened this issue Aug 5, 2022 · 4 comments
Closed

Exception while execute cmd in pod #4319

fbi007130 opened this issue Aug 5, 2022 · 4 comments
Labels

Comments

@fbi007130
Copy link

Describe the bug

I follow the guild by https://github.com/fabric8io/kubernetes-client/blob/master/kubernetes-examples/src/main/java/io/fabric8/kubernetes/examples/ExecuteCommandOnPodExample.java to execute cmd in my pod.But there is a exception.
Exception
`Exception in thread "main" io.fabric8.kubernetes.client.KubernetesClientException: An error has occurred.
at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:103)
at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:97)
at io.fabric8.kubernetes.client.utils.Utils.waitUntilReady(Utils.java:174)
at io.fabric8.kubernetes.client.utils.Utils.waitUntilReadyOrFail(Utils.java:184)
at io.fabric8.kubernetes.client.dsl.internal.core.v1.PodOperationsImpl.exec(PodOperationsImpl.java:286)
at mypackage.common.step.ExecuteCommandOnPodExample.execCmd(ExecuteCommandOnPodExample.java:64)
at mypackage.common.step.ExecuteCommandOnPodExample.execCommandOnPod(ExecuteCommandOnPodExample.java:43)
at mypackage.common.step.ExecuteCommandOnPodExample.main(ExecuteCommandOnPodExample.java:102)
Caused by: io.fabric8.kubernetes.client.http.WebSocketHandshakeException
at io.fabric8.kubernetes.client.okhttp.OkHttpWebSocketImpl$BuilderImpl$1.onFailure(OkHttpWebSocketImpl.java:71)
at okhttp3.internal.ws.RealWebSocket.failWebSocket(RealWebSocket.java:571)
at okhttp3.internal.ws.RealWebSocket$2.onResponse(RealWebSocket.java:198)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:203)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at java.base/java.lang.Thread.run(Thread.java:831)
Suppressed: java.lang.Throwable: waiting here
at io.fabric8.kubernetes.client.utils.Utils.waitUntilReady(Utils.java:173)
at io.fabric8.kubernetes.client.utils.Utils.waitUntilReadyOrFail(Utils.java:184)
at io.fabric8.kubernetes.client.dsl.internal.core.v1.PodOperationsImpl.exec(PodOperationsImpl.java:286)
at mypackage.common.step.ExecuteCommandOnPodExample.execCmd(ExecuteCommandOnPodExample.java:64)
at mypackage.common.step.ExecuteCommandOnPodExample.execCommandOnPod(ExecuteCommandOnPodExample.java:43)
at mypackage.common.step.ExecuteCommandOnPodExample.main(ExecuteCommandOnPodExample.java:102)
Caused by: java.net.ProtocolException: Expected HTTP 101 response but was '400 Bad Request'
at okhttp3.internal.ws.RealWebSocket.checkResponse(RealWebSocket.java:229)
at okhttp3.internal.ws.RealWebSocket$2.onResponse(RealWebSocket.java:196)
... 5 more
null

Process finished with exit code 1
`

Code:
`package mypackage.common.step;

import mypackage.common.util.K8SClient;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.ConfigBuilder;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
import io.fabric8.kubernetes.client.dsl.ExecListener;
import io.fabric8.kubernetes.client.dsl.ExecWatch;
//import lombok.SneakyThrows;

import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

@SuppressWarnings("java:S106")
public class ExecuteCommandOnPodExample implements AutoCloseable {
//It is my client which is success in get pod and etc.
private final KubernetesClient client= K8SClient.getFabricClient();

public ExecuteCommandOnPodExample() {

// Config config = new ConfigBuilder().build();
// this.client = new KubernetesClientBuilder().withConfig(config).build();
}

@Override
public void close() {

// client.close();
}

// @SneakyThrows
public String execCommandOnPod(String podName, String namespace, String... cmd) {
Pod pod = client.pods().inNamespace(namespace).withName(podName).get();
System.out.printf("Running command: [%s] on pod [%s] in namespace [%s]%n",
Arrays.toString(cmd), pod.getMetadata().getName(), namespace);

    CompletableFuture<String> data = new CompletableFuture<>();
    String result=null;
    try (ExecWatch execWatch = execCmd(pod, data, cmd)) {
        result = data.get(10, TimeUnit.SECONDS);
    } catch (ExecutionException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (TimeoutException e) {
        e.printStackTrace();
    }finally {
   }
    return result;
}

private ExecWatch execCmd(Pod pod, CompletableFuture<String> data, String... command) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    return client.pods()
            .inNamespace(pod.getMetadata().getNamespace())
            .withName(pod.getMetadata().getName())
            .writingOutput(baos)
            .writingError(baos)
            .usingListener(new SimpleListener(data, baos))
            .exec(command);
}

static class SimpleListener implements ExecListener {

    private CompletableFuture<String> data;
    private ByteArrayOutputStream baos;

    public SimpleListener(CompletableFuture<String> data, ByteArrayOutputStream baos) {
        this.data = data;
        this.baos = baos;
    }

    @Override
    public void onOpen() {
        System.out.println("Reading data... ");
    }

    @Override
    public void onFailure(Throwable t, Response failureResponse) {
        System.err.println(t.getMessage());
        data.completeExceptionally(t);
    }

    @Override
    public void onClose(int code, String reason) {
        System.out.println("Exit with: " + code + " and with reason: " + reason);
        data.complete(baos.toString());
    }
}

public static void main(String[] args) {

    final String pod = "pod-name-is-valid";
    final String namespace = "namespace-is-valid";
    final String command = "df -h";

    try (ExecuteCommandOnPodExample example = new ExecuteCommandOnPodExample()) {
        String cmdOutput = example.execCommandOnPod(pod, namespace, command.split(" "));
        System.out.println(cmdOutput);
    }

}

}`

Fabric8 Kubernetes Client version

6.0.0

Steps to reproduce

complie the code and execute it.

Expected behavior

execute cmd in the pod.

Runtime

Kubernetes (vanilla)

Kubernetes API Server version

1.23

Environment

Linux

Fabric8 Kubernetes Client Logs

No response

Additional context

There are two container in the pod and default container has been set.

@shawkins
Copy link
Contributor

shawkins commented Aug 5, 2022

There are two container in the pod

This is the root issue, when there are multiple containers it looks like the exec call needs the container name. If you add inContainer(xxx) to the execCmd, it should work.

and default container has been set

What mechanism are you using for that?

I see that kubectl will default to the first container if none is provided.

Looking this example over, it's also probably time to revamp it to use the exit code logic instead.

@fbi007130
Copy link
Author

Thanks,it seems work while the inContainerner was add.
I has try it before issue raised,and it was not worked.The reason is parameter name in the method is 'id' but not 'name',so I just put the container id in it.Thanks.

@fbi007130
Copy link
Author

I try to recur the request in curl, a message was return.If the message also print in console,I think is very helpful.
{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"a container name must be specified for pod podnamehere choose one of: [istio-init istio-proxy bbbp]","reason":"BadRequest","code":400}
In my log of code ,there is no response body print.

@shawkins
Copy link
Contributor

shawkins commented Aug 8, 2022

In my log of code ,there is no response body print.

OkHttp is not passing that in the exception. You'd probably have to enable debug/trace logging at the okhttp level.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants