I have a controller with one function to execute commands in the pods (same namespace as the operator). I'm able to see the output while controller is started locally, when the same controller runs on the cluster (as pod) it gives an empty output, even if the commend looks to be executed correctly.
The function is implemented as method as initially I passed the namespace via reconciler object.
func (r *BPReconciler) ExecCmdPod(config *restclient.Config, podName string, containerName string, podNamespace string, cmd []string) (string, error) {
log := ctrl.Log.WithName("Execute command ")
log.Info("Executing command inside container", "Pod Name:", podName, "Container Name:", containerName)
//NewForConfig creates a new Clientset for the given config. func NewForConfig(c *rest.Config) (*Clientset, error)
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
fmt.Printf("Error creating clientset: %s\n", err)
}
//build the request URL which will be used by Executor
request := clientset.CoreV1().RESTClient().Post().Resource("pods").Name(podName).Namespace(podNamespace).SubResource("exec") // .Param("container", containerName)
//https://pkg.go.dev/k8s.io/api/core/v1#PodExecOptions
option := &corev1.PodExecOptions{
Command: cmd,
Stdin: true,
Stdout: true,
Stderr: true,
TTY: true,
Container: containerName,
}
request.VersionedParams(
option,
scheme.ParameterCodec,
)
// return Executor https://pkg.go.dev/k8s.io/client-go/tools/remotecommand#Executor
exec, err := remotecommand.NewSPDYExecutor(config, "POST", request.URL())
if err != nil {
fmt.Printf("Error creating executor: %s\n", err)
}
var execOut bytes.Buffer
var execErr bytes.Buffer
w := io.MultiWriter(os.Stdout, &execOut)
err = exec.StreamWithContext(context.TODO(), remotecommand.StreamOptions{
Stdin: os.Stdin,
Stdout: w,
Stderr: &execErr,
Tty: true,
})
if err != nil {
log.Info("There was an error")
fmt.Println(err)
fmt.Println("Error output:", execErr.String())
return "", err
}
if execErr.Len() > 0 {
log.Info("There was an errorExec")
return "", fmt.Errorf("stderr: %v", execErr.String())
}
if err == nil {
log.Info("Command executed successfully")
}
return execOut.String(), nil
}
I tried already to play with several options of Stdin/Stdout but couldn't get that working. My last idea was the RBAC, but I have all what is required I believe:
//+kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch;delete;deletecollection
//+kubebuilder:rbac:groups=core,resources=pods/exec,verbs=create
//+kubebuilder:rbac:groups=core,resources=pods/log,verbs=get;list
I even tried with:
//+kubebuilder:rbac:groups=*,resources=*,verbs=*
Any idea what could be wrong here?