Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package kubectl-gather for openSUSE:Factory 
checked in at 2026-07-31 15:29:40
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kubectl-gather (Old)
 and      /work/SRC/openSUSE:Factory/.kubectl-gather.new.2004 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kubectl-gather"

Fri Jul 31 15:29:40 2026 rev:8 rq:1368471 version:0.14.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/kubectl-gather/kubectl-gather.changes    
2026-07-13 14:26:54.273032491 +0200
+++ /work/SRC/openSUSE:Factory/.kubectl-gather.new.2004/kubectl-gather.changes  
2026-07-31 16:08:40.239274641 +0200
@@ -1,0 +2,12 @@
+Thu Jul 30 05:37:19 UTC 2026 - Johannes Kastl 
<[email protected]>
+
+- Update to version 0.14.0:
+  * Highlights
+    - Support gathering from multiple kubeconfig files via a
+      comma-separated --kubeconfig list.
+      See Using separate kubeconfig files.
+      https://github.com/nirs/kubectl-gather#using-separate-kubeconfig-files
+  * What's Changed
+    - Support multiple kubeconfig files by @nirs in #165
+
+-------------------------------------------------------------------

Old:
----
  kubectl-gather-0.13.1.obscpio

New:
----
  kubectl-gather-0.14.0.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kubectl-gather.spec ++++++
--- /var/tmp/diff_new_pack.bwqvwk/_old  2026-07-31 16:08:40.791293844 +0200
+++ /var/tmp/diff_new_pack.bwqvwk/_new  2026-07-31 16:08:40.795293983 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           kubectl-gather
-Version:        0.13.1
+Version:        0.14.0
 Release:        0
 Summary:        Kubectl plugin to gather data about your cluster
 License:        Apache-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.bwqvwk/_old  2026-07-31 16:08:40.827295096 +0200
+++ /var/tmp/diff_new_pack.bwqvwk/_new  2026-07-31 16:08:40.831295236 +0200
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/nirs/kubectl-gather.git</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">refs/tags/v0.13.1</param>
+    <param name="revision">refs/tags/v0.14.0</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="versionrewrite-pattern">v(.*)</param>
     <param name="changesgenerate">enable</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.bwqvwk/_old  2026-07-31 16:08:40.859296209 +0200
+++ /var/tmp/diff_new_pack.bwqvwk/_new  2026-07-31 16:08:40.863296348 +0200
@@ -3,6 +3,6 @@
                 <param 
name="url">https://github.com/nirs/kubectl-gather</param>
               <param 
name="changesrevision">62c6089cb7cb3552a81b6f74b8394d4b1433fd70</param></service><service
 name="tar_scm">
                 <param 
name="url">https://github.com/nirs/kubectl-gather.git</param>
-              <param 
name="changesrevision">d7c350ae547cc357159abcacb28cb2d9e85f93db</param></service></servicedata>
+              <param 
name="changesrevision">8e26ef87c72fc49d9120a1b1eacc88500928f877</param></service></servicedata>
 (No newline at EOF)
 

++++++ kubectl-gather-0.13.1.obscpio -> kubectl-gather-0.14.0.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kubectl-gather-0.13.1/.golangci.yaml 
new/kubectl-gather-0.14.0/.golangci.yaml
--- old/kubectl-gather-0.13.1/.golangci.yaml    2026-07-13 01:01:21.000000000 
+0200
+++ new/kubectl-gather-0.14.0/.golangci.yaml    2026-07-29 15:34:14.000000000 
+0200
@@ -5,7 +5,6 @@
 linters:
   enable:
     - errcheck
-    - goconst
     - nolintlint
     # TODO: enable after fixing issues
     #- gocritic
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kubectl-gather-0.13.1/README.md 
new/kubectl-gather-0.14.0/README.md
--- old/kubectl-gather-0.13.1/README.md 2026-07-13 01:01:21.000000000 +0200
+++ new/kubectl-gather-0.14.0/README.md 2026-07-29 15:34:14.000000000 +0200
@@ -200,6 +200,69 @@
         └── ceph-volume.log
 ```
 
+## Using separate kubeconfig files
+
+When working with multiple clusters you often get a separate kubeconfig
+file per cluster, exported from CI or another system. These files
+typically have duplicate entries and use the same generic names (e.g.
+"admin" for every context and user), so they cannot be merged with
+standard tools.
+
+To gather from separate kubeconfig files, pass them all to
+`--kubeconfig`:
+
+```
+$ kubectl gather --kubeconfig ocp/hub.yaml,ocp/c1.yaml,ocp/c2.yaml -d gather.dr
+2026-05-06T00:15:32.100+0300   INFO    gather  Using cluster "hub" from 
kubeconfig "ocp/hub.yaml"
+2026-05-06T00:15:32.101+0300   INFO    gather  Using cluster "c1" from 
kubeconfig "ocp/c1.yaml"
+2026-05-06T00:15:32.102+0300   INFO    gather  Using cluster "c2" from 
kubeconfig "ocp/c2.yaml"
+2026-05-06T00:15:32.102+0300   INFO    gather  Gathering from all namespaces
+2026-05-06T00:15:32.102+0300   INFO    gather  Gathering from cluster "hub"
+2026-05-06T00:15:32.102+0300   INFO    gather  Gathering from cluster "c1"
+2026-05-06T00:15:32.102+0300   INFO    gather  Gathering from cluster "c2"
+...
+```
+
+When using multiple kubeconfig files, each file provides one cluster.
+The cluster name is derived from the filename (without directory and
+extension), and the actual context names inside the files (e.g. "admin")
+are not used for naming. The gathered data is stored in one directory
+per cluster:
+
+```
+$ tree -L 2 gather.dr/
+gather.dr/
+├── c1
+│   ├── cluster
+│   └── namespaces
+├── c2
+│   ├── cluster
+│   └── namespaces
+├── gather.log
+└── hub
+    ├── cluster
+    └── namespaces
+```
+
+File names must be unique across all specified kubeconfig files, even
+if the files are in different directories.
+
+The cluster name is always derived from the filename, even for a single
+file:
+
+```
+$ kubectl gather --kubeconfig hub.yaml -d gather.one
+2026-05-06T00:15:32.100+0300   INFO    gather  Using cluster "hub" from 
kubeconfig "hub.yaml"
+2026-05-06T00:15:32.100+0300   INFO    gather  Gathering from all namespaces
+2026-05-06T00:15:32.100+0300   INFO    gather  Gathering from cluster "hub"
+...
+```
+
+Use `--contexts` to select specific contexts from a kubeconfig file.
+
+`kubectl gather` never modifies the provided kubeconfig files or the
+default kubeconfig (`~/.kube/config`).
+
 ## Gathering data for specific namespaces
 
 When debugging a problem, it is useful to gather data for specific
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kubectl-gather-0.13.1/cmd/config.go 
new/kubectl-gather-0.14.0/cmd/config.go
--- old/kubectl-gather-0.13.1/cmd/config.go     2026-07-13 01:01:21.000000000 
+0200
+++ new/kubectl-gather-0.14.0/cmd/config.go     1970-01-01 01:00:00.000000000 
+0100
@@ -1,82 +0,0 @@
-// SPDX-FileCopyrightText: The kubectl-gather authors
-// SPDX-License-Identifier: Apache-2.0
-
-package cmd
-
-import (
-       "fmt"
-       "os"
-
-       "k8s.io/client-go/rest"
-       "k8s.io/client-go/tools/clientcmd"
-       "k8s.io/client-go/tools/clientcmd/api"
-)
-
-type clusterConfig struct {
-       Config  *rest.Config
-       Context string
-}
-
-func loadClusterConfigs(contexts []string, kubeconfig string) 
([]*clusterConfig, error) {
-       if len(contexts) == 0 {
-               restConfig, err := rest.InClusterConfig()
-               if err != rest.ErrNotInCluster {
-                       if err != nil {
-                               return nil, err
-                       }
-
-                       log.Infof("Using in cluster config")
-                       return []*clusterConfig{{Config: restConfig}}, nil
-               }
-
-               log.Debugf("Not running in cluster")
-       }
-
-       config, err := loadKubeconfig(kubeconfig)
-       if err != nil {
-               return nil, err
-       }
-
-       if len(contexts) == 0 {
-               if config.CurrentContext == "" {
-                       return nil, fmt.Errorf("no context specified and 
current context not set")
-               }
-
-               log.Infof("Using current context %q", config.CurrentContext)
-               contexts = []string{config.CurrentContext}
-       }
-
-       var configs []*clusterConfig
-
-       for _, context := range contexts {
-               restConfig, err := clientcmd.NewNonInteractiveClientConfig(
-                       *config, context, nil, nil).ClientConfig()
-               if err != nil {
-                       return nil, err
-               }
-
-               configs = append(configs, &clusterConfig{Config: restConfig, 
Context: context})
-       }
-
-       return configs, nil
-}
-
-func loadKubeconfig(kubeconfig string) (*api.Config, error) {
-       if kubeconfig == "" {
-               kubeconfig = defaultKubeconfig()
-       }
-       log.Infof("Using kubeconfig %q", kubeconfig)
-       config, err := clientcmd.LoadFromFile(kubeconfig)
-       if err != nil {
-               return nil, err
-       }
-       return config, nil
-}
-
-func defaultKubeconfig() string {
-       env := os.Getenv("KUBECONFIG")
-       if env != "" {
-               return env
-       }
-       return clientcmd.RecommendedHomeFile
-}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kubectl-gather-0.13.1/cmd/local.go 
new/kubectl-gather-0.14.0/cmd/local.go
--- old/kubectl-gather-0.13.1/cmd/local.go      2026-07-13 01:01:21.000000000 
+0200
+++ new/kubectl-gather-0.14.0/cmd/local.go      2026-07-29 15:34:14.000000000 
+0200
@@ -9,6 +9,7 @@
        "time"
 
        "github.com/nirs/kubectl-gather/pkg/gather"
+       "github.com/nirs/kubectl-gather/pkg/kubeconfig"
 )
 
 type result struct {
@@ -16,7 +17,7 @@
        Err   error
 }
 
-func localGather(clusterConfigs []*clusterConfig) {
+func localGather(clusterConfigs []*kubeconfig.Config) {
        start := time.Now()
 
        wg := sync.WaitGroup{}
@@ -25,30 +26,30 @@
        for i := range clusterConfigs {
                clusterConfig := clusterConfigs[i]
 
-               if clusterConfig.Context != "" {
-                       log.Infof("Gathering from cluster %q", 
clusterConfig.Context)
+               if clusterConfig.Name != "" {
+                       log.Infof("Gathering from cluster %q", 
clusterConfig.Name)
                } else {
-                       log.Info("Gathering on cluster")
+                       log.Info("Gathering in cluster")
                }
                start := time.Now()
 
-               directory := filepath.Join(directory, clusterConfig.Context)
+               clusterDir := filepath.Join(directory, clusterConfig.Name)
 
                options := gather.Options{
-                       Kubeconfig: kubeconfig,
+                       Kubeconfig: clusterConfig.Kubeconfig,
                        Context:    clusterConfig.Context,
                        Namespaces: namespaces,
                        Addons:     addons,
                        Cluster:    cluster,
                        Salt:       parsedSalt,
-                       Log:        log.Named(clusterConfig.Context),
+                       Log:        log.Named(clusterConfig.Name),
                }
 
                wg.Add(1)
                go func() {
                        defer wg.Done()
 
-                       g, err := gather.New(clusterConfig.Config, directory, 
options)
+                       g, err := gather.New(clusterConfig.Config, clusterDir, 
options)
                        if err != nil {
                                results <- result{Err: err}
                                return
@@ -61,11 +62,11 @@
                        }
 
                        elapsed := time.Since(start).Seconds()
-                       if clusterConfig.Context != "" {
+                       if clusterConfig.Name != "" {
                                log.Infof("Gathered %d resources from cluster 
%q in %.3f seconds",
-                                       g.Count(), clusterConfig.Context, 
elapsed)
+                                       g.Count(), clusterConfig.Name, elapsed)
                        } else {
-                               log.Infof("Gathered %d resources on cluster in 
%.3f seconds",
+                               log.Infof("Gathered %d resources in %.3f 
seconds",
                                        g.Count(), elapsed)
                        }
                }()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kubectl-gather-0.13.1/cmd/remote.go 
new/kubectl-gather-0.14.0/cmd/remote.go
--- old/kubectl-gather-0.13.1/cmd/remote.go     2026-07-13 01:01:21.000000000 
+0200
+++ new/kubectl-gather-0.14.0/cmd/remote.go     2026-07-29 15:34:14.000000000 
+0200
@@ -13,9 +13,10 @@
        "time"
 
        "github.com/nirs/kubectl-gather/pkg/gather"
+       "github.com/nirs/kubectl-gather/pkg/kubeconfig"
 )
 
-func remoteGather(clusterConfigs []*clusterConfig) {
+func remoteGather(clusterConfigs []*kubeconfig.Config) {
        start := time.Now()
 
        wg := sync.WaitGroup{}
@@ -23,12 +24,12 @@
 
        for i := range clusterConfigs {
                clusterConfig := clusterConfigs[i]
-               directory := filepath.Join(directory, clusterConfig.Context)
+               clusterDir := filepath.Join(directory, clusterConfig.Name)
 
                wg.Add(1)
                go func() {
                        defer wg.Done()
-                       if err := runMustGather(clusterConfig.Context, 
directory); err != nil {
+                       if err := runMustGather(clusterConfig, clusterDir); err 
!= nil {
                                errors <- err
                        }
                }()
@@ -45,13 +46,13 @@
                len(clusterConfigs), time.Since(start).Seconds())
 }
 
-func runMustGather(context string, directory string) error {
-       log.Infof("Gathering on remote cluster %q", context)
+func runMustGather(config *kubeconfig.Config, directory string) error {
+       log.Infof("Gathering on remote cluster %q", config.Name)
        start := time.Now()
 
        var stderr bytes.Buffer
 
-       cmd := mustGatherCommand(context, directory)
+       cmd := mustGatherCommand(config, directory)
        cmd.Stderr = &stderr
 
        log.Debugf("Running command: %s", cmd)
@@ -61,21 +62,23 @@
 
        elapsed := time.Since(start).Seconds()
        log.Infof("Gathered on remote cluster %q in %.3f seconds",
-               context, elapsed)
+               config.Name, elapsed)
 
        return nil
 }
 
-func mustGatherCommand(context string, directory string) *exec.Cmd {
+func mustGatherCommand(config *kubeconfig.Config, directory string) *exec.Cmd {
        args := []string{
                "adm",
                "must-gather",
                "--image=" + gather.Image,
-               "--context=" + context,
                "--dest-dir=" + directory,
        }
-       if kubeconfig != "" {
-               args = append(args, "--kubeconfig="+kubeconfig)
+       if config.Context != "" {
+               args = append(args, "--context="+config.Context)
+       }
+       if config.Kubeconfig != "" {
+               args = append(args, "--kubeconfig="+config.Kubeconfig)
        }
 
        var remoteArgs []string
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kubectl-gather-0.13.1/cmd/root.go 
new/kubectl-gather-0.14.0/cmd/root.go
--- old/kubectl-gather-0.13.1/cmd/root.go       2026-07-13 01:01:21.000000000 
+0200
+++ new/kubectl-gather-0.14.0/cmd/root.go       2026-07-29 15:34:14.000000000 
+0200
@@ -19,10 +19,11 @@
        "sigs.k8s.io/yaml"
 
        "github.com/nirs/kubectl-gather/pkg/gather"
+       "github.com/nirs/kubectl-gather/pkg/kubeconfig"
 )
 
 var directory string
-var kubeconfig string
+var kubeconfigs []string
 var contexts []string
 var namespaces []string
 var addons []string
@@ -39,6 +40,9 @@
   # store it in gather.{timestamp}.
   kubectl gather --kubeconfig my-kubeconfig
 
+  # Gather from multiple clusters, each with its own kubeconfig file.
+  kubectl gather --kubeconfig ocp/hub.yaml,ocp/c1.yaml,ocp/c2.yaml
+
   # Gather data from all namespaces in clusters "dr1", "dr2" and "hub" and 
store
   # it in "gather.local/", using default kubeconfig (~/.kube/config).
   kubectl gather --contexts dr1,dr2,hub --directory gather.local
@@ -87,8 +91,8 @@
        // Don't set default kubeconfig, so kubeconfig is empty unless the user
        // specified the option. This is required to allow running remote 
commands
        // using in-cluster config.
-       rootCmd.Flags().StringVar(&kubeconfig, "kubeconfig", "",
-               "the kubeconfig file to use")
+       rootCmd.Flags().StringSliceVar(&kubeconfigs, "kubeconfig", nil,
+               "comma separated list of kubeconfig files to use")
 
        rootCmd.Flags().StringSliceVar(&contexts, "contexts", nil,
                "comma separated list of contexts to gather data from")
@@ -140,10 +144,24 @@
                log.Fatal(err)
        }
 
-       clusterConfigs, err := loadClusterConfigs(contexts, kubeconfig)
+       clusterConfigs, err := kubeconfig.Load(contexts, kubeconfigs)
        if err != nil {
                log.Fatal(err)
        }
+       if len(kubeconfigs) > 0 {
+               for _, c := range clusterConfigs {
+                       log.Infof("Using cluster %q from kubeconfig %q", 
c.Name, c.Kubeconfig)
+               }
+       } else if len(contexts) > 0 {
+               log.Infof("Using kubeconfig %q", clusterConfigs[0].Kubeconfig)
+       } else {
+               if clusterConfigs[0].Name == "" {
+                       log.Infof("Using in cluster config")
+               } else {
+                       log.Infof("Using kubeconfig %q", 
clusterConfigs[0].Kubeconfig)
+                       log.Infof("Using current context %q", 
clusterConfigs[0].Name)
+               }
+       }
 
        if cmd.Flags().Changed("salt") {
                log.Infof("Using user-provided salt %q", salt)
@@ -179,6 +197,10 @@
 }
 
 func validateOptions(cmd *cobra.Command) error {
+       if len(contexts) > 0 && len(kubeconfigs) > 1 {
+               return fmt.Errorf("--contexts cannot be used with multiple 
--kubeconfig files")
+       }
+
        if salt != "" {
                var err error
                parsedSalt, err = validateSalt(salt)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kubectl-gather-0.13.1/e2e/gather_test.go 
new/kubectl-gather-0.14.0/e2e/gather_test.go
--- old/kubectl-gather-0.13.1/e2e/gather_test.go        2026-07-13 
01:01:21.000000000 +0200
+++ new/kubectl-gather-0.14.0/e2e/gather_test.go        2026-07-29 
15:34:14.000000000 +0200
@@ -3,6 +3,7 @@
 package e2e
 
 import (
+       "os"
        "os/exec"
        "path/filepath"
        "strings"
@@ -151,6 +152,50 @@
        validateGatherAll(t, validate.New(outputDir).WithDataRoot(dataRoot))
 }
 
+func TestGatherMultipleKubeconfigs(dt *testing.T) {
+       t := test.WithLog(dt)
+       outputDir := "out/test-gather-multi-kubeconfig"
+
+       kubeconfigs := exportKubeconfigs(t)
+
+       cmd := exec.Command(
+               kubectlGather,
+               "--kubeconfig", strings.Join(kubeconfigs, ","),
+               "--directory", outputDir,
+       )
+       if err := commands.Run(cmd, t.Log); err != nil {
+               t.Errorf("kubectl-gather failed: %s", err)
+       }
+
+       validateGatherAll(t, validate.New(outputDir))
+}
+
+func TestGatherMultipleKubeconfigsRemote(dt *testing.T) {
+       t := test.WithLog(dt)
+       if _, err := exec.LookPath("oc"); err != nil {
+               t.Skip("oc not found, skipping remote test")
+       }
+
+       outputDir := "out/test-gather-multi-kubeconfig-remote"
+
+       kubeconfigs := exportKubeconfigs(t)
+
+       cmd := exec.Command(
+               kubectlGather,
+               "--kubeconfig", strings.Join(kubeconfigs, ","),
+               "--remote",
+               "--directory", outputDir,
+       )
+       if err := commands.Run(cmd, t.Log); err != nil {
+               t.Fatalf("kubectl-gather --remote failed: %s", err)
+       }
+
+       dataRoot := findDataRoot(t, filepath.Join(outputDir, clusters.C1))
+       t.Debugf("Data root: %s", dataRoot)
+
+       validateGatherAll(t, validate.New(outputDir).WithDataRoot(dataRoot))
+}
+
 func TestGatherClusterFalse(dt *testing.T) {
        t := test.WithLog(dt)
        outputDir := "out/test-gather-cluster-false"
@@ -525,6 +570,36 @@
 
 // Test helpers
 
+// exportKubeconfigs exports a separate kubeconfig file for each cluster,
+// simulating the multi-kubeconfig workflow where each file was exported from a
+// different system. Files are named after the cluster (e.g. "c1.yaml") so the
+// derived cluster name matches the expected directory layout.
+func exportKubeconfigs(t *test.T) []string {
+       t.Helper()
+
+       dir := t.TempDir()
+
+       var paths []string
+       for _, name := range clusters.Names {
+               path := filepath.Join(dir, name+".yaml")
+               cmd := exec.Command(
+                       "kubectl", "config", "view",
+                       "--minify",
+                       "--flatten",
+                       "--context", name,
+               )
+               out, err := cmd.Output()
+               if err != nil {
+                       t.Fatalf("failed to export kubeconfig for context %q: 
%s", name, err)
+               }
+               if err := os.WriteFile(path, out, 0600); err != nil {
+                       t.Fatal(err)
+               }
+               paths = append(paths, path)
+       }
+       return paths
+}
+
 func validateGatherAll(t *test.T, v *validate.Validator) {
        t.Helper()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kubectl-gather-0.13.1/pkg/kubeconfig/kubeconfig.go 
new/kubectl-gather-0.14.0/pkg/kubeconfig/kubeconfig.go
--- old/kubectl-gather-0.13.1/pkg/kubeconfig/kubeconfig.go      1970-01-01 
01:00:00.000000000 +0100
+++ new/kubectl-gather-0.14.0/pkg/kubeconfig/kubeconfig.go      2026-07-29 
15:34:14.000000000 +0200
@@ -0,0 +1,256 @@
+// SPDX-FileCopyrightText: The kubectl-gather authors
+// SPDX-License-Identifier: Apache-2.0
+
+// Package kubeconfig loads cluster configurations for kubectl-gather.
+//
+// The returned [Config] values vary by mode:
+//
+//     Mode                     Name                  Context
+//     In-cluster               ""                    ""
+//     Current context          see below             ""
+//     Explicit --contexts      sanitized context     context
+//     Multiple kubeconfigs     sanitized filename    ""
+//
+// Name is used for the output directory and logging. It is always
+// sanitized for cross-platform filesystem compatibility (no ":", "\",
+// "/", ".", or leading/trailing "-"). Empty Name means in-cluster mode
+// (data goes directly to the gather directory).
+//
+// Context is passed to child processes as --context. Empty Context means
+// use the file's current-context implicitly — no --context flag is passed.
+//
+// # Naming for current context (no --contexts specified)
+//
+// When gathering the current context, Name is chosen by checking whether
+// the context name is already filesystem-safe. If sanitizeName(context)
+// equals the original context, the context name is used — this gives
+// meaningful names for minikube/kind clusters (e.g. "dr1", "hub"). If
+// the context name requires sanitization (common with OpenShift contexts
+// like "admin/api-cluster.example.com:6443/system:admin"), the kubeconfig
+// filename is used instead as a shorter, predictable alternative.
+//
+// Examples:
+//
+//     kubectl gather --kubeconfig hub.yaml
+//       (current-context: "admin/api-hub:6443/system:admin")
+//       → Name="hub" (context is not clean, use filename), Context=""
+//
+//     kubectl gather
+//       (default ~/.kube/config, current-context: "dr1")
+//       → Name="dr1" (context is clean, use it), Context=""
+//
+//     kubectl gather --contexts dr1,dr2
+//       → Name="dr1", Context="dr1"
+//       → Name="dr2", Context="dr2"
+//
+//     kubectl gather --kubeconfig hub.yaml,c1.yaml,c2.yaml
+//       → Name="hub", Context=""
+//       → Name="c1", Context=""
+//       → Name="c2", Context=""
+package kubeconfig
+
+import (
+       "fmt"
+       "os"
+       "path/filepath"
+       "strings"
+
+       "k8s.io/client-go/rest"
+       "k8s.io/client-go/tools/clientcmd"
+)
+
+// Config holds the connection information and metadata for a single cluster.
+type Config struct {
+       // Config is the Kubernetes REST client configuration for API access.
+       Config *rest.Config
+
+       // Name is the cluster name for output directory and logging (empty for 
in-cluster).
+       Name string
+
+       // Context is the context name for child processes (empty to use 
current-context).
+       Context string
+
+       // Kubeconfig is the file path for child processes.
+       Kubeconfig string
+}
+
+// Load loads cluster configurations based on the provided flags. It routes to
+// the appropriate loading strategy:
+//   - contexts specified: load the given contexts from a single kubeconfig
+//   - kubeconfigs specified: load current-context from each file
+//   - neither: try in-cluster config, fallback to default kubeconfig
+func Load(contexts, kubeconfigs []string) ([]*Config, error) {
+       if len(contexts) > 0 && len(kubeconfigs) > 1 {
+               return nil, fmt.Errorf("contexts cannot be used with multiple 
kubeconfig files")
+       }
+
+       if len(contexts) > 0 {
+               var kc string
+               if len(kubeconfigs) == 1 {
+                       kc = kubeconfigs[0]
+               }
+               return loadContexts(contexts, kc)
+       }
+
+       if len(kubeconfigs) > 0 {
+               return loadKubeconfigs(kubeconfigs)
+       }
+
+       configs, err := loadInCluster()
+       if err == nil {
+               return configs, nil
+       }
+       if err != rest.ErrNotInCluster {
+               return nil, err
+       }
+
+       return loadCurrentContext()
+}
+
+func loadInCluster() ([]*Config, error) {
+       restConfig, err := rest.InClusterConfig()
+       if err != nil {
+               return nil, err
+       }
+       return []*Config{{Config: restConfig}}, nil
+}
+
+// loadContexts loads explicit contexts from a single kubeconfig file.
+func loadContexts(contexts []string, kubeconfig string) ([]*Config, error) {
+       if kubeconfig == "" {
+               kubeconfig = defaultKubeconfig()
+       }
+
+       config, err := clientcmd.LoadFromFile(kubeconfig)
+       if err != nil {
+               return nil, err
+       }
+
+       var configs []*Config
+       hosts := make(map[string]string) // host -> context
+       for _, context := range contexts {
+               restConfig, err := clientcmd.NewNonInteractiveClientConfig(
+                       *config, context, nil, nil).ClientConfig()
+               if err != nil {
+                       return nil, err
+               }
+               if prev, ok := hosts[restConfig.Host]; ok {
+                       return nil, fmt.Errorf("duplicate cluster %q from 
contexts %q and %q", restConfig.Host, prev, context)
+               }
+               hosts[restConfig.Host] = context
+               configs = append(configs, &Config{
+                       Config:     restConfig,
+                       Name:       sanitizeName(context),
+                       Context:    context,
+                       Kubeconfig: kubeconfig,
+               })
+       }
+       return configs, nil
+}
+
+// loadCurrentContext loads the current-context from the default kubeconfig.
+func loadCurrentContext() ([]*Config, error) {
+       kubeconfig := defaultKubeconfig()
+
+       config, err := clientcmd.LoadFromFile(kubeconfig)
+       if err != nil {
+               return nil, err
+       }
+       if config.CurrentContext == "" {
+               return nil, fmt.Errorf("no context specified and current 
context not set")
+       }
+
+       name := config.CurrentContext
+       if sanitizeName(name) != name {
+               name = nameFromFilename(kubeconfig)
+       }
+
+       restConfig, err := clientcmd.NewNonInteractiveClientConfig(
+               *config, config.CurrentContext, nil, nil).ClientConfig()
+       if err != nil {
+               return nil, err
+       }
+       return []*Config{{
+               Config:     restConfig,
+               Name:       name,
+               Kubeconfig: kubeconfig,
+       }}, nil
+}
+
+// loadKubeconfigs loads each kubeconfig file independently, using 
current-context
+// from each file. The cluster name is derived from the filename (without
+// directory and extension). Context is left empty since each file's
+// current-context is used implicitly. No merging or renaming is done.
+func loadKubeconfigs(kubeconfigs []string) ([]*Config, error) {
+       names := make(map[string]string) // derived name -> file path
+       hosts := make(map[string]string) // host -> file path
+       var configs []*Config
+
+       for _, path := range kubeconfigs {
+               name := nameFromFilename(path)
+
+               if prev, ok := names[name]; ok {
+                       return nil, fmt.Errorf("duplicate cluster name %q from 
files %q and %q", name, prev, path)
+               }
+               names[name] = path
+
+               config, err := clientcmd.LoadFromFile(path)
+               if err != nil {
+                       return nil, fmt.Errorf("loading %q: %w", path, err)
+               }
+
+               context := config.CurrentContext
+               if context == "" {
+                       return nil, fmt.Errorf("file %q: current-context not 
set", path)
+               }
+
+               restConfig, err := clientcmd.NewNonInteractiveClientConfig(
+                       *config, context, nil, nil).ClientConfig()
+               if err != nil {
+                       return nil, fmt.Errorf("file %q: %w", path, err)
+               }
+
+               if prev, ok := hosts[restConfig.Host]; ok {
+                       return nil, fmt.Errorf("duplicate cluster %q from files 
%q and %q", restConfig.Host, prev, path)
+               }
+               hosts[restConfig.Host] = path
+
+               configs = append(configs, &Config{
+                       Config:     restConfig,
+                       Name:       name,
+                       Kubeconfig: path,
+               })
+       }
+
+       return configs, nil
+}
+
+// defaultKubeconfig returns the kubeconfig path from the KUBECONFIG 
environment
+// variable or the default location.
+func defaultKubeconfig() string {
+       env := os.Getenv("KUBECONFIG")
+       if env != "" {
+               return env
+       }
+       return clientcmd.RecommendedHomeFile
+}
+
+// nameFromFilename extracts a cluster name from a kubeconfig file path by 
taking the
+// filename without directory and extension, and sanitizing for cross-platform 
use.
+func nameFromFilename(path string) string {
+       basename := filepath.Base(path)
+       name := strings.TrimSuffix(basename, filepath.Ext(basename))
+       return sanitizeName(name)
+}
+
+// sanitizeName replaces characters that are problematic in file paths to
+// ensure the name works as a directory component on any platform.
+func sanitizeName(name string) string {
+       name = strings.NewReplacer(
+               ":", "-", // invalid on Windows
+               "\\", "-", // path separator on Windows
+               "/", "-", // path separator on Unix
+               ".", "-", // hidden directory prefix, confusing in paths
+       ).Replace(name)
+       return strings.Trim(name, "-")
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kubectl-gather-0.13.1/pkg/kubeconfig/kubeconfig_test.go 
new/kubectl-gather-0.14.0/pkg/kubeconfig/kubeconfig_test.go
--- old/kubectl-gather-0.13.1/pkg/kubeconfig/kubeconfig_test.go 1970-01-01 
01:00:00.000000000 +0100
+++ new/kubectl-gather-0.14.0/pkg/kubeconfig/kubeconfig_test.go 2026-07-29 
15:34:14.000000000 +0200
@@ -0,0 +1,607 @@
+// SPDX-FileCopyrightText: The kubectl-gather authors
+// SPDX-License-Identifier: Apache-2.0
+
+package kubeconfig
+
+import (
+       "os"
+       "path/filepath"
+       "testing"
+)
+
+// In-cluster config is tested via e2e since rest.InClusterConfig() requires
+// service account files on disk.
+
+type expectedConfig struct {
+       Name       string
+       Context    string
+       Kubeconfig string
+       Host       string
+}
+
+// kubectl gather (KUBECONFIG=hub.yaml, no --kubeconfig flag)
+// Name derived from filename since current context is not filesystem-safe.
+func TestLoadDefaultKubeconfigUnsafeContext(t *testing.T) {
+       dir := t.TempDir()
+       hubPath := writeKubeconfig(t, dir, "hub.yaml", `
+apiVersion: v1
+kind: Config
+current-context: admin/api-hub-example-com:6443/system:admin
+clusters:
+- cluster:
+    server: https://hub.example.com:6443
+  name: hub-cluster
+contexts:
+- context:
+    cluster: hub-cluster
+    user: admin
+  name: admin/api-hub-example-com:6443/system:admin
+users:
+- name: admin
+  user:
+    token: token1
+`)
+       t.Setenv("KUBECONFIG", hubPath)
+
+       configs, err := Load(nil, nil)
+       if err != nil {
+               t.Fatal(err)
+       }
+       checkConfigs(t, configs, []expectedConfig{
+               {
+                       Name:       "hub",
+                       Host:       "https://hub.example.com:6443";,
+                       Kubeconfig: hubPath,
+               },
+       })
+}
+
+// Name is the current context since it is already filesystem-safe.
+// Context is empty to use the current context.
+func TestLoadDefaultKubeconfigSafeContext(t *testing.T) {
+       dir := t.TempDir()
+       configPath := writeKubeconfig(t, dir, "config", `
+apiVersion: v1
+kind: Config
+current-context: minikube
+clusters:
+- cluster:
+    server: https://192.168.49.2:8443
+  name: minikube
+contexts:
+- context:
+    cluster: minikube
+    user: minikube
+  name: minikube
+users:
+- name: minikube
+  user:
+    token: token1
+`)
+       t.Setenv("KUBECONFIG", configPath)
+
+       configs, err := Load(nil, nil)
+       if err != nil {
+               t.Fatal(err)
+       }
+       checkConfigs(t, configs, []expectedConfig{
+               {
+                       Name:       "minikube",
+                       Host:       "https://192.168.49.2:8443";,
+                       Kubeconfig: configPath,
+               },
+       })
+}
+
+// kubectl gather --contexts ...
+// Name is the sanitized context name. Context is the raw value for child 
processes.
+func TestLoadFromContexts(t *testing.T) {
+       // OCP clusters: context names are auto-generated and need sanitization.
+       t.Run("openshift", func(t *testing.T) {
+               dir := t.TempDir()
+               configPath := writeKubeconfig(t, dir, "config", `
+apiVersion: v1
+kind: Config
+current-context: admin/api-hub-example-com:6443/system:admin
+clusters:
+- cluster:
+    server: https://hub.example.com:6443
+  name: hub-cluster
+- cluster:
+    server: https://dr1.example.com:6443
+  name: dr1-cluster
+- cluster:
+    server: https://dr2.example.com:6443
+  name: dr2-cluster
+contexts:
+- context:
+    cluster: hub-cluster
+    user: admin
+  name: admin/api-hub-example-com:6443/system:admin
+- context:
+    cluster: dr1-cluster
+    user: admin
+  name: admin/api-dr1-example-com:6443/system:admin
+- context:
+    cluster: dr2-cluster
+    user: admin
+  name: admin/api-dr2-example-com:6443/system:admin
+users:
+- name: admin
+  user:
+    token: token1
+`)
+               t.Setenv("KUBECONFIG", configPath)
+
+               contexts := []string{
+                       "admin/api-hub-example-com:6443/system:admin",
+                       "admin/api-dr1-example-com:6443/system:admin",
+                       "admin/api-dr2-example-com:6443/system:admin",
+               }
+               configs, err := Load(contexts, nil)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               checkConfigs(t, configs, []expectedConfig{
+                       {
+                               Name:       
"admin-api-hub-example-com-6443-system-admin",
+                               Context:    
"admin/api-hub-example-com:6443/system:admin",
+                               Host:       "https://hub.example.com:6443";,
+                               Kubeconfig: configPath,
+                       },
+                       {
+                               Name:       
"admin-api-dr1-example-com-6443-system-admin",
+                               Context:    
"admin/api-dr1-example-com:6443/system:admin",
+                               Host:       "https://dr1.example.com:6443";,
+                               Kubeconfig: configPath,
+                       },
+                       {
+                               Name:       
"admin-api-dr2-example-com-6443-system-admin",
+                               Context:    
"admin/api-dr2-example-com:6443/system:admin",
+                               Host:       "https://dr2.example.com:6443";,
+                               Kubeconfig: configPath,
+                       },
+               })
+       })
+
+       // Minikube/drenv clusters: context names are clean and used as-is.
+       t.Run("drenv", func(t *testing.T) {
+               dir := t.TempDir()
+               configPath := writeKubeconfig(t, dir, "config", `
+apiVersion: v1
+kind: Config
+current-context: hub
+clusters:
+- cluster:
+    server: https://hub.example.com:6443
+  name: hub-cluster
+- cluster:
+    server: https://dr1.example.com:6443
+  name: dr1-cluster
+- cluster:
+    server: https://dr2.example.com:6443
+  name: dr2-cluster
+contexts:
+- context:
+    cluster: hub-cluster
+    user: admin
+  name: hub
+- context:
+    cluster: dr1-cluster
+    user: admin
+  name: dr1
+- context:
+    cluster: dr2-cluster
+    user: admin
+  name: dr2
+users:
+- name: admin
+  user:
+    token: token1
+`)
+
+               configs, err := Load([]string{"hub", "dr1", "dr2"}, 
[]string{configPath})
+               if err != nil {
+                       t.Fatal(err)
+               }
+               checkConfigs(t, configs, []expectedConfig{
+                       {
+                               Name:       "hub",
+                               Context:    "hub",
+                               Host:       "https://hub.example.com:6443";,
+                               Kubeconfig: configPath,
+                       },
+                       {
+                               Name:       "dr1",
+                               Context:    "dr1",
+                               Host:       "https://dr1.example.com:6443";,
+                               Kubeconfig: configPath,
+                       },
+                       {
+                               Name:       "dr2",
+                               Context:    "dr2",
+                               Host:       "https://dr2.example.com:6443";,
+                               Kubeconfig: configPath,
+                       },
+               })
+       })
+}
+
+// kubectl gather --kubeconfig hub.yaml,spoke1.yaml
+// Name derived from filename. Context is empty to use each file's current 
context.
+func TestLoadFromMultipleKubeconfigs(t *testing.T) {
+       dir := t.TempDir()
+
+       hubPath := writeKubeconfig(t, dir, "hub.yaml", `
+apiVersion: v1
+kind: Config
+current-context: admin
+clusters:
+- cluster:
+    server: https://hub.example.com:6443
+  name: hub-cluster
+contexts:
+- context:
+    cluster: hub-cluster
+    user: admin
+  name: admin
+users:
+- name: admin
+  user:
+    token: token1
+`)
+
+       spoke1Path := writeKubeconfig(t, dir, "spoke1.yaml", `
+apiVersion: v1
+kind: Config
+current-context: admin
+clusters:
+- cluster:
+    server: https://spoke1.example.com:6443
+  name: spoke-cluster
+contexts:
+- context:
+    cluster: spoke-cluster
+    user: admin
+  name: admin
+users:
+- name: admin
+  user:
+    token: token2
+`)
+
+       configs, err := Load(nil, []string{hubPath, spoke1Path})
+       if err != nil {
+               t.Fatal(err)
+       }
+       checkConfigs(t, configs, []expectedConfig{
+               {
+                       Name:       "hub",
+                       Host:       "https://hub.example.com:6443";,
+                       Kubeconfig: hubPath,
+               },
+               {
+                       Name:       "spoke1",
+                       Host:       "https://spoke1.example.com:6443";,
+                       Kubeconfig: spoke1Path,
+               },
+       })
+}
+
+// kubectl gather --kubeconfig cluster1.yaml
+// Name derived from filename. Uses current-context to select the right cluster
+// from a file with stale entries.
+func TestLoadFromKubeconfigSafeContext(t *testing.T) {
+       dir := t.TempDir()
+
+       cluster1Path := writeKubeconfig(t, dir, "cluster1.yaml", `
+apiVersion: v1
+kind: Config
+current-context: admin
+clusters:
+- cluster:
+    server: https://current.example.com:6443
+  name: current-cluster
+- cluster:
+    server: https://old.example.com:6443
+  name: old-cluster
+contexts:
+- context:
+    cluster: current-cluster
+    user: admin
+  name: admin
+- context:
+    cluster: old-cluster
+    user: old-admin
+  name: old-admin
+users:
+- name: admin
+  user:
+    token: current-token
+- name: old-admin
+  user:
+    token: old-token
+`)
+
+       configs, err := Load(nil, []string{cluster1Path})
+       if err != nil {
+               t.Fatal(err)
+       }
+       checkConfigs(t, configs, []expectedConfig{
+               {
+                       Name:       "cluster1",
+                       Host:       "https://current.example.com:6443";,
+                       Kubeconfig: cluster1Path,
+               },
+       })
+}
+
+// kubectl gather --kubeconfig hub.yaml
+// Name derived from filename since current context is not filesystem-safe.
+func TestLoadFromKubeconfigUnsafeContext(t *testing.T) {
+       dir := t.TempDir()
+       hubPath := writeKubeconfig(t, dir, "hub.yaml", `
+apiVersion: v1
+kind: Config
+current-context: admin/api-hub-example-com:6443/system:admin
+clusters:
+- cluster:
+    server: https://hub.example.com:6443
+  name: hub-cluster
+contexts:
+- context:
+    cluster: hub-cluster
+    user: admin
+  name: admin/api-hub-example-com:6443/system:admin
+users:
+- name: admin
+  user:
+    token: token1
+`)
+
+       configs, err := Load(nil, []string{hubPath})
+       if err != nil {
+               t.Fatal(err)
+       }
+       checkConfigs(t, configs, []expectedConfig{
+               {
+                       Name:       "hub",
+                       Host:       "https://hub.example.com:6443";,
+                       Kubeconfig: hubPath,
+               },
+       })
+}
+
+// TestDeriveName verifies that names derived from filenames are sanitized to 
safe directory names.
+func TestDeriveNameFromFilename(t *testing.T) {
+       tests := []struct {
+               path string
+               want string
+       }{
+               {"ocp/hub.yaml", "hub"},
+               {"ocp/hub.yml", "hub"},
+               {"/home/user/configs/my-cluster.kubeconfig", "my-cluster"},
+               {"cluster:6443.yaml", "cluster-6443"},
+               {"plain", "plain"},
+               {".hidden.yaml", "hidden"},
+               {"my.cluster.yaml", "my-cluster"},
+       }
+       for _, tt := range tests {
+               got := nameFromFilename(tt.path)
+               if got != tt.want {
+                       t.Errorf("nameFromFilename(%q) = %q, want %q", tt.path, 
got, tt.want)
+               }
+       }
+}
+
+// --- negative cases ---
+
+// kubectl gather --contexts admin,viewer
+// Error: both contexts point to the same cluster.
+func TestLoadFromContextsDuplicateHost(t *testing.T) {
+       dir := t.TempDir()
+       configPath := writeKubeconfig(t, dir, "config", `
+apiVersion: v1
+kind: Config
+current-context: admin
+clusters:
+- cluster:
+    server: https://hub.example.com:6443
+  name: hub
+contexts:
+- context:
+    cluster: hub
+    user: admin
+  name: admin
+- context:
+    cluster: hub
+    user: viewer
+  name: viewer
+users:
+- name: admin
+  user:
+    token: admin-token
+- name: viewer
+  user:
+    token: viewer-token
+`)
+
+       _, err := Load([]string{"admin", "viewer"}, []string{configPath})
+       if err == nil {
+               t.Fatal("expected error for duplicate host, got nil")
+       }
+}
+
+// kubectl gather --kubeconfig my-kubeconfig
+// Error: current-context not set and no --contexts specified.
+func TestLoadFromKubconfigsNoCurrentContext(t *testing.T) {
+       dir := t.TempDir()
+       configPath := writeKubeconfig(t, dir, "config", `
+apiVersion: v1
+kind: Config
+clusters:
+- cluster:
+    server: https://example.com:6443
+  name: cluster
+contexts:
+- context:
+    cluster: cluster
+    user: admin
+  name: ctx
+users:
+- name: admin
+  user:
+    token: token
+`)
+
+       _, err := Load(nil, []string{configPath})
+       if err == nil {
+               t.Fatal("expected error for missing current-context, got nil")
+       }
+}
+
+// kubectl gather --kubeconfig dir1/cluster.yaml,dir2/cluster.yaml
+// Error: duplicate basenames.
+func TestLoadFromKubeconfigsDuplicateBasenames(t *testing.T) {
+       dir1 := t.TempDir()
+       dir2 := t.TempDir()
+
+       content := `
+apiVersion: v1
+kind: Config
+current-context: admin
+clusters:
+- cluster:
+    server: https://example.com:6443
+  name: cluster
+contexts:
+- context:
+    cluster: cluster
+    user: admin
+  name: admin
+users:
+- name: admin
+  user:
+    token: token
+`
+       cluster1Path := writeKubeconfig(t, dir1, "cluster.yaml", content)
+       cluster2Path := writeKubeconfig(t, dir2, "cluster.yaml", content)
+
+       _, err := Load(nil, []string{cluster1Path, cluster2Path})
+       if err == nil {
+               t.Fatal("expected error for duplicate basenames, got nil")
+       }
+}
+
+// kubectl gather --kubeconfig .hidden.yaml,hidden.yaml
+// Error: names collide after sanitization.
+func TestLoadFromKubeconfigsSanitizedCollision(t *testing.T) {
+       dir := t.TempDir()
+
+       content := `
+apiVersion: v1
+kind: Config
+current-context: admin
+clusters:
+- cluster:
+    server: https://example.com:6443
+  name: cluster
+contexts:
+- context:
+    cluster: cluster
+    user: admin
+  name: admin
+users:
+- name: admin
+  user:
+    token: token
+`
+       hiddenPath := writeKubeconfig(t, dir, ".hidden.yaml", content)
+       plainPath := writeKubeconfig(t, dir, "hidden.yaml", content)
+
+       _, err := Load(nil, []string{hiddenPath, plainPath})
+       if err == nil {
+               t.Fatal("expected error for sanitized name collision, got nil")
+       }
+}
+
+// kubectl gather --kubeconfig hub.yaml,hub-backup.yaml
+// Error: both files point to the same cluster.
+func TestLoadFromKubeconfigsDuplicateHost(t *testing.T) {
+       dir := t.TempDir()
+
+       hub1Path := writeKubeconfig(t, dir, "hub.yaml", `
+apiVersion: v1
+kind: Config
+current-context: admin
+clusters:
+- cluster:
+    server: https://hub.example.com:6443
+  name: hub
+contexts:
+- context:
+    cluster: hub
+    user: admin
+  name: admin
+users:
+- name: admin
+  user:
+    token: token1
+`)
+
+       hub2Path := writeKubeconfig(t, dir, "hub-backup.yaml", `
+apiVersion: v1
+kind: Config
+current-context: admin
+clusters:
+- cluster:
+    server: https://hub.example.com:6443
+  name: hub
+contexts:
+- context:
+    cluster: hub
+    user: admin
+  name: admin
+users:
+- name: admin
+  user:
+    token: token2
+`)
+
+       _, err := Load(nil, []string{hub1Path, hub2Path})
+       if err == nil {
+               t.Fatal("expected error for duplicate host, got nil")
+       }
+}
+
+// --- helpers ---
+
+func checkConfigs(t *testing.T, got []*Config, want []expectedConfig) {
+       t.Helper()
+       if len(got) != len(want) {
+               t.Fatalf("expected %d configs, got %d", len(want), len(got))
+       }
+       for i, w := range want {
+               if got[i].Name != w.Name {
+                       t.Errorf("configs[%d].Name = %q, want %q", i, 
got[i].Name, w.Name)
+               }
+               if got[i].Context != w.Context {
+                       t.Errorf("configs[%d].Context = %q, want %q", i, 
got[i].Context, w.Context)
+               }
+               if got[i].Kubeconfig != w.Kubeconfig {
+                       t.Errorf("configs[%d].Kubeconfig = %q, want %q", i, 
got[i].Kubeconfig, w.Kubeconfig)
+               }
+               if got[i].Config.Host != w.Host {
+                       t.Errorf("configs[%d].Config.Host = %q, want %q", i, 
got[i].Config.Host, w.Host)
+               }
+       }
+}
+
+func writeKubeconfig(t *testing.T, dir, filename, content string) string {
+       t.Helper()
+       path := filepath.Join(dir, filename)
+       if err := os.WriteFile(path, []byte(content), 0600); err != nil {
+               t.Fatal(err)
+       }
+       return path
+}

++++++ kubectl-gather.obsinfo ++++++
--- /var/tmp/diff_new_pack.bwqvwk/_old  2026-07-31 16:08:41.083304002 +0200
+++ /var/tmp/diff_new_pack.bwqvwk/_new  2026-07-31 16:08:41.091304280 +0200
@@ -1,5 +1,5 @@
 name: kubectl-gather
-version: 0.13.1
-mtime: 1783897281
-commit: d7c350ae547cc357159abcacb28cb2d9e85f93db
+version: 0.14.0
+mtime: 1785332054
+commit: 8e26ef87c72fc49d9120a1b1eacc88500928f877
 

++++++ vendor.tar.gz ++++++

Reply via email to