package k8s import ( "errors" "os" "path/filepath" "strings" "testing" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" ) func TestNewReturnsErrorWhenNoClusterConfigOrValidKubeconfigExists(t *testing.T) { restore := swapClientTestHooks() defer restore() inClusterConfigFn = func() (*rest.Config, error) { return nil, errors.New("cluster config exploded") } t.Setenv("KUBECONFIG", "/definitely/missing/kubeconfig") client, err := New() if err == nil || client != nil { t.Fatalf("expected New to fail without usable Kubernetes config, got client=%#v err=%v", client, err) } if !strings.Contains(err.Error(), "load kubeconfig") { t.Fatalf("expected kubeconfig load error, got %v", err) } } func TestNewReturnsInClusterErrorWhenNoKubeconfigIsProvided(t *testing.T) { restore := swapClientTestHooks() defer restore() inClusterConfigFn = func() (*rest.Config, error) { return nil, errors.New("cluster config exploded") } t.Setenv("KUBECONFIG", "") client, err := New() if err == nil || client != nil { t.Fatalf("expected in-cluster config error, got client=%#v err=%v", client, err) } if !strings.Contains(err.Error(), "load in-cluster config: cluster config exploded") { t.Fatalf("expected in-cluster config error, got %v", err) } } func TestNewLoadsKubeconfigAndBuildsClientset(t *testing.T) { restore := swapClientTestHooks() defer restore() inClusterConfigFn = func() (*rest.Config, error) { return nil, errors.New("not in cluster") } kubeconfigPath := filepath.Join(t.TempDir(), "config") if err := os.WriteFile(kubeconfigPath, []byte(`apiVersion: v1 kind: Config clusters: - cluster: server: https://127.0.0.1:6443 name: local contexts: - context: cluster: local user: local name: local current-context: local users: - name: local user: token: test-token `), 0o600); err != nil { t.Fatalf("write kubeconfig: %v", err) } t.Setenv("KUBECONFIG", kubeconfigPath) client, err := New() if err != nil { t.Fatalf("expected kubeconfig-backed client construction, got %v", err) } if client == nil || client.Clientset == nil { t.Fatalf("expected populated client, got %#v", client) } if client.Dynamic == nil { t.Fatalf("expected populated dynamic client, got %#v", client) } } func TestNewWrapsClientsetConstructionFailures(t *testing.T) { restore := swapClientTestHooks() defer restore() inClusterConfigFn = func() (*rest.Config, error) { return &rest.Config{Host: "https://127.0.0.1:6443"}, nil } newForConfigFn = func(*rest.Config) (kubernetes.Interface, error) { return nil, errors.New("clientset exploded") } client, err := New() if err == nil || client != nil { t.Fatalf("expected clientset construction error, got client=%#v err=%v", client, err) } if !strings.Contains(err.Error(), "build clientset: clientset exploded") { t.Fatalf("expected wrapped clientset error, got %v", err) } } func TestNewWrapsDynamicClientConstructionFailures(t *testing.T) { restore := swapClientTestHooks() defer restore() inClusterConfigFn = func() (*rest.Config, error) { return &rest.Config{Host: "https://127.0.0.1:6443"}, nil } newDynamicForConfigFn = func(*rest.Config) (dynamic.Interface, error) { return nil, errors.New("dynamic exploded") } client, err := New() if err == nil || client != nil { t.Fatalf("expected dynamic client construction error, got client=%#v err=%v", client, err) } if !strings.Contains(err.Error(), "build dynamic client: dynamic exploded") { t.Fatalf("expected wrapped dynamic client error, got %v", err) } } func swapClientTestHooks() func() { originalInCluster := inClusterConfigFn originalBuildConfig := buildConfigFromFlagsFn originalNewForConfig := newForConfigFn originalNewDynamicForConfig := newDynamicForConfigFn return func() { inClusterConfigFn = originalInCluster buildConfigFromFlagsFn = originalBuildConfig newForConfigFn = originalNewForConfig newDynamicForConfigFn = originalNewDynamicForConfig } }