<p>How can I get the current namespace of an out-of-cluster Go Kubernetes client using the client-go library?</p>
<p>I am using this code example: <a href="https://github.com/kubernetes/client-go/blob/master/examples/out-of-cluster-client-configuration/main.go" rel="nofollow noreferrer">https://github.com/kubernetes/client-go/blob/master/examples/out-of-cluster-client-configuration/main.go</a> for out-cluster client.</p>
<p>Here is an extract of my KUBECONFIG which might help in clarifying:</p>
<pre><code>- context:
    cluster: kind-kind
    namespace: mynamespace
    user: kind-kind
  name: kind-kind
current-context: kind-kind
</code></pre>
<p>I'd like to find an easy way to retrieve <code>mynamespace</code>.</p>

Fabrice Jammes
<p>There is no such thing as &quot;current namespace&quot;.</p>
<p>All namespaces exist at the same time and you can access them all at the same time. The idea of the &quot;current namespace&quot; comes from additional plugins like <a href="https://github.com/ahmetb/kubectx" rel="nofollow noreferrer">kubens</a> mostly. The reality is, that it is just a detail to the kube context for the given cluster as explained <a href="https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/" rel="nofollow noreferrer">here</a> where you can for example specify which set of credential/user combination to access a given namespace. As well as a default namespace to execute commands against via <code>kubectl</code> if you don't specify a namespace at all, as you can read <a href="https://kubernetes.io/docs/reference/config-api/kubeconfig.v1/#Context" rel="nofollow noreferrer">in the documentation</a>. Thus the object of type <code>config</code> also does not have the capability to hold any information about that as you can read <a href="https://pkg.go.dev/k8s.io/client-go/rest@v0.27.4#Config" rel="nofollow noreferrer">here</a></p>
<p>With tools like <code>kubens</code> that allow you to &quot;persist&quot; which namespace you want to execute commands against by default, you get some extra options but they still need to store that state, which they do in state files for each cluster like <code>.kube/kubens/test</code>.</p>
<p>In the code example you posted, you can also see that a namespace is actually specified via the variable <code>namespace</code>, that is set to <code>default</code> <a href="https://github.com/kubernetes/client-go/blob/master/examples/out-of-cluster-client-configuration/main.go#L72" rel="nofollow noreferrer">here</a></p>
<p>You can alternatively try to specify the namespace via flag like</p>
<pre class="lang-golang prettyprint-override"><code>func main() {
    var kubeconfig *string
    var namespace *string
    if home := homedir.HomeDir(); home != &quot;&quot; {
        kubeconfig = flag.String(&quot;kubeconfig&quot;, filepath.Join(home, &quot;.kube&quot;, &quot;config&quot;), &quot;(optional) absolute path to the kubeconfig file&quot;)
    } else {
        kubeconfig = flag.String(&quot;kubeconfig&quot;, &quot;&quot;, &quot;absolute path to the kubeconfig file&quot;)
    }
    namespace = flag.String(&quot;namespace&quot;, &quot;default&quot;, &quot;namespace to execute commands against&quot;)
    flag.Parse()

    // use the current context in kubeconfig
    config, err := clientcmd.BuildConfigFromFlags(&quot;&quot;, *kubeconfig)
    if err != nil {
        panic(err.Error())
    }

    // create the clientset
    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        panic(err.Error())
    }
    for {
        pods, err := clientset.CoreV1().Pods(&quot;&quot;).List(context.TODO(), metav1.ListOptions{})
        if err != nil {
            panic(err.Error())
        }
        fmt.Printf(&quot;There are %d pods in the cluster\n&quot;, len(pods.Items))

        // Examples for error handling:
        // - Use helper functions like e.g. errors.IsNotFound()
        // - And/or cast to StatusError and use its properties like e.g. ErrStatus.Message
        
        pod := &quot;example-xxxxx&quot;
        _, err = clientset.CoreV1().Pods(*namespace).Get(context.TODO(), pod, metav1.GetOptions{})
        if errors.IsNotFound(err) {
            fmt.Printf(&quot;Pod %s in namespace %s not found\n&quot;, pod, *namespace)
        } else if statusError, isStatus := err.(*errors.StatusError); isStatus {
            fmt.Printf(&quot;Error getting pod %s in namespace %s: %v\n&quot;,
                pod, *namespace, statusError.ErrStatus.Message)
        } else if err != nil {
            panic(err.Error())
        } else {
            fmt.Printf(&quot;Found pod %s in namespace %s\n&quot;, pod, *namespace)
        }

        time.Sleep(10 * time.Second)
    }
}

</code></pre>
<p>If you want to replicate a similar behaviour, to what kubens does, you can store the namespace in a file and read it from there, if nothing else is passed as flag, and switch to <code>default</code> if the files doesn't exist, i.e. you never accessed the cluster:</p>
<pre class="lang-golang prettyprint-override"><code>func main() {
    var kubeconfig *string
    var namespace *string
    if home := homedir.HomeDir(); home != &quot;&quot; {
        kubeconfig = flag.String(&quot;kubeconfig&quot;, filepath.Join(home, &quot;.kube&quot;, &quot;config&quot;), &quot;(optional) absolute path to the kubeconfig file&quot;)
    } else {
        kubeconfig = flag.String(&quot;kubeconfig&quot;, &quot;&quot;, &quot;absolute path to the kubeconfig file&quot;)
    }
    namespace = flag.String(&quot;namespace&quot;, &quot;&quot;, &quot;namespace to execute commands against&quot;)
    flag.Parse()

    // use the current context in kubeconfig
    config, err := clientcmd.BuildConfigFromFlags(&quot;&quot;, *kubeconfig)
    if err != nil {
        panic(err.Error())
    }

    // create the clientset
    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        panic(err.Error())
    }

    // write to file if namespace is given as flag
    if *namespace != &quot;&quot; {
        dat := []byte(*namespace)
        err := os.WriteFile(config.ServerName, dat, 0644)
        if err != nil {
            panic(err.Error())
        }
    }
    // read from file if namespace is not given as flag, otherwise use default
    if *namespace == &quot;&quot; {
        _, doesNotExist := os.Stat(config.ServerName)
        if doesNotExist == nil {
            dat, err := os.ReadFile(config.ServerName)
            if err != nil {
                panic(err.Error())
            }
            *namespace = string(dat)
        }
        if doesNotExist != nil {
            *namespace = &quot;default&quot;
        }

    }

</code></pre>
