<p>My query is pretty much what the title says, I have a local file say <code>file.txt</code> and I want to copy it into <code>pod1</code>'s container <code>container1</code>.</p>
<p>If I was to do it using kubectl, the appropriate command would be :</p>
<p><code>kubectl cp file.txt pod1:file.txt -c container1</code></p>
<p>However, how do I do it using the Go client of kubectl?</p>
<p>I tried 2 ways but none of them worked :</p>
<pre><code>import (
    &quot;fmt&quot;
    &quot;context&quot;
    &quot;log&quot;
    &quot;os&quot;
    &quot;path/filepath&quot;

    g &quot;github.com/sdslabs/katana/configs&quot;
    v1 &quot;k8s.io/api/core/v1&quot;
    metav1 &quot;k8s.io/apimachinery/pkg/apis/meta/v1&quot;
    &quot;k8s.io/apimachinery/pkg/labels&quot;
    &quot;k8s.io/client-go/kubernetes&quot;
    &quot;k8s.io/client-go/rest&quot;
    &quot;k8s.io/client-go/tools/clientcmd&quot;
    //&quot;k8s.io/kubectl/pkg/cmd/exec&quot;
)

func CopyIntoPod(namespace string, podName string, containerName string, srcPath string, dstPath string) {
    // Create a Kubernetes client
    config, err := GetKubeConfig()
    if err != nil {
        log.Fatal(err)
    }

    client, err := kubernetes.NewForConfig(config)
    if err != nil {
        log.Fatal(err)
    }

    // Build the command to execute
    cmd := []string{&quot;cp&quot;, srcPath, dstPath}

    // Use the PodExecOptions struct to specify the options for the exec request
    options := v1.PodExecOptions{
        Container: containerName,
        Command:   cmd,
        Stdin:     false,
        Stdout:    true,
        Stderr:    true,
        TTY:       false,
    }
    log.Println(&quot;Options set!&quot;)

    // Use the CoreV1Api.Exec method to execute the command inside the container
    req := client.CoreV1().RESTClient().Post().
        Namespace(namespace).
        Name(podName).
        Resource(&quot;pods&quot;).
        SubResource(&quot;exec&quot;).
        VersionedParams(&amp;options, metav1.ParameterCodec)
    log.Println(&quot;Request generated&quot;)
    
    exec, err := req.Stream(context.TODO())
    if err != nil {
        log.Fatal(err)
    }
    defer exec.Close()

    // Read the response from the exec command
    var result []byte
    if _, err := exec.Read(result); err != nil {
        log.Fatal(err)
    }

    fmt.Println(&quot;File copied successfully!&quot;)
}
</code></pre>
<p>This gave me the error message :</p>
<p><code>no kind is registered for the type v1.PodExecOptions in scheme &quot;pkg/runtime/scheme.go:100&quot;</code></p>
<p>I couldn't figure it out, so I tried another way :</p>
<pre><code>type PodExec struct {
    RestConfig *rest.Config
    *kubernetes.Clientset
}

func NewPodExec(config *rest.Config, clientset *kubernetes.Clientset) *PodExec {
    config.APIPath = &quot;/api&quot; // Make sure we target /api and not just /
    config.GroupVersion = &amp;schema.GroupVersion{Version: &quot;v1&quot;} // this targets the core api groups so the url path will be /api/v1
    config.NegotiatedSerializer = serializer.WithoutConversionCodecFactory{CodecFactory: scheme.Codecs}
    return &amp;PodExec{
      RestConfig: config,
      Clientset:  clientset,
    }  
}

func (p *PodExec) PodCopyFile(src string, dst string, containername string, podNamespace string) (*bytes.Buffer, *bytes.Buffer, *bytes.Buffer, error) {
    ioStreams, in, out, errOut := genericclioptions.NewTestIOStreams()
    copyOptions := cp.NewCopyOptions(ioStreams)
    copyOptions.Clientset = p.Clientset
    copyOptions.ClientConfig = p.RestConfig
    copyOptions.Container = containername
    copyOptions.Namespace = podNamespace
    err := copyOptions.Run()
    if err != nil {
        return nil, nil, nil, fmt.Errorf(&quot;could not run copy operation: %v&quot;, err)
    }
    return in, out, errOut, nil
}
</code></pre>
<p>However, there were some issues with the <code>copyOptions.Run()</code> command, it tried to look for <code>o.args[0] and o.args[0]</code> inside copyOptions but <code>o</code> is not imported so it couldn't be modified.</p>
<p>Context : <a href="https://pkg.go.dev/k8s.io/kubectl/pkg/cmd/cp#CopyOptions.Run" rel="nofollow noreferrer">https://pkg.go.dev/k8s.io/kubectl/pkg/cmd/cp#CopyOptions.Run</a></p>
<p>So, now I'm really lost and confused. Any help would be appreciated. Thanks.</p>
<p>Edit : I did think of a viable method where we can just call <code>cmd.exec()</code> and run the <code>kubectl cp</code> command directly but it seems kinda hacky and I'm not sure whether it would work, any thoughts?</p>

<p>Here's how I finally managed to do it :</p>
<pre><code>package main

import (
    &quot;context&quot;
    &quot;fmt&quot;
    &quot;os&quot;
    &quot;path/filepath&quot;

    &quot;k8s.io/client-go/kubernetes&quot;
    &quot;k8s.io/client-go/kubernetes/scheme&quot;
    corev1 &quot;k8s.io/api/core/v1&quot;
    &quot;k8s.io/client-go/tools/clientcmd&quot;
    &quot;k8s.io/client-go/util/homedir&quot;
    metav1 &quot;k8s.io/apimachinery/pkg/apis/meta/v1&quot;
    &quot;k8s.io/client-go/tools/remotecommand&quot;
)

func CopyIntoPod(podName string, namespace string, containerName string, srcPath string, dstPath string) {
    // Get the default kubeconfig file
    kubeConfig := filepath.Join(homedir.HomeDir(), &quot;.kube&quot;, &quot;config&quot;)

    // Create a config object using the kubeconfig file
    config, err := clientcmd.BuildConfigFromFlags(&quot;&quot;, kubeConfig)
    if err != nil {
        fmt.Printf(&quot;Error creating config: %s\n&quot;, err)
        return
    }

    // Create a Kubernetes client
    client, err := kubernetes.NewForConfig(config)
    if err != nil {
        fmt.Printf(&quot;Error creating client: %s\n&quot;, err)
        return
    }

    // Open the file to copy
    localFile, err := os.Open(srcPath)
    if err != nil {
        fmt.Printf(&quot;Error opening local file: %s\n&quot;, err)
        return
    }
    defer localFile.Close()

    pod, err := client.CoreV1().Pods(namespace).Get(context.TODO(), podName, metav1.GetOptions{})
    if err != nil {
        fmt.Printf(&quot;Error getting pod: %s\n&quot;, err)
        return
    }

    // Find the container in the pod
    var container *corev1.Container
    for _, c := range pod.Spec.Containers {
        if c.Name == containerName {
            container = &amp;c
            break
        }
    }

    if container == nil {
        fmt.Printf(&quot;Container not found in pod\n&quot;)
        return
    }

    // Create a stream to the container
    req := client.CoreV1().RESTClient().Post().
        Resource(&quot;pods&quot;).
        Name(podName).
        Namespace(namespace).
        SubResource(&quot;exec&quot;).
        Param(&quot;container&quot;, containerName)   

    req.VersionedParams(&amp;corev1.PodExecOptions{
        Container: containerName,
        Command:   []string{&quot;bash&quot;, &quot;-c&quot;, &quot;cat &gt; &quot; + dstPath},
        Stdin:     true,
        Stdout:    true,
        Stderr:    true,
    }, scheme.ParameterCodec)

    exec, err := remotecommand.NewSPDYExecutor(config, &quot;POST&quot;, req.URL())
    if err != nil {
        fmt.Printf(&quot;Error creating executor: %s\n&quot;, err)
        return
    }

    // Create a stream to the container
    err = exec.StreamWithContext(context.TODO(), remotecommand.StreamOptions{
        Stdin:  localFile,
        Stdout: os.Stdout,
        Stderr: os.Stderr,
        Tty:    false,
    })
    if err != nil {
        fmt.Printf(&quot;Error streaming: %s\n&quot;, err)
        return
    }

    fmt.Println(&quot;File copied successfully&quot;)
}
</code></pre>
