1515package client
1616
1717import (
18+ stderrors "errors"
1819 "os"
1920 "path/filepath"
2021 "strings"
2122 "sync"
2223 "testing"
24+
25+ "github.com/NVIDIA/aicr/pkg/errors"
2326)
2427
28+ func assertKubeconfigErrorContext (t * testing.T , err error , wantKubeconfig string ) {
29+ t .Helper ()
30+
31+ var structuredErr * errors.StructuredError
32+ if ! stderrors .As (err , & structuredErr ) {
33+ t .Fatalf ("error = %v, want *errors.StructuredError" , err )
34+ }
35+ gotKubeconfig , ok := structuredErr .Context ["kubeconfig" ].(string )
36+ if ! ok {
37+ t .Fatalf ("error context kubeconfig = %v, want string" , structuredErr .Context ["kubeconfig" ])
38+ }
39+ if gotKubeconfig != wantKubeconfig {
40+ t .Errorf ("error context kubeconfig = %q, want %q" , gotKubeconfig , wantKubeconfig )
41+ }
42+ }
43+
2544// TestBuildKubeClient_PathResolution tests the kubeconfig path resolution logic
2645// without attempting to connect to a cluster.
2746func TestBuildKubeClient_PathResolution (t * testing.T ) {
@@ -30,24 +49,30 @@ func TestBuildKubeClient_PathResolution(t *testing.T) {
3049 t .Setenv ("KUBECONFIG" , os .Getenv ("KUBECONFIG" ))
3150
3251 tests := []struct {
33- name string
34- kubeconfigArg string
35- kubeconfigEnv string
36- wantErr bool
37- errorContains string
52+ name string
53+ kubeconfigArg string
54+ kubeconfigEnv string
55+ wantErr bool
56+ errorContains string
57+ wantCode errors.ErrorCode
58+ wantKubeconfig string
3859 }{
3960 {
40- name : "explicit invalid path" ,
41- kubeconfigArg : "/nonexistent/path/to/kubeconfig" ,
42- wantErr : true ,
43- errorContains : "failed to build kube config" ,
61+ name : "explicit invalid path" ,
62+ kubeconfigArg : " /nonexistent/path/to/kubeconfig " ,
63+ wantErr : true ,
64+ errorContains : "failed to build kube config" ,
65+ wantCode : errors .ErrCodeInvalidRequest ,
66+ wantKubeconfig : "/nonexistent/path/to/kubeconfig" ,
4467 },
4568 {
46- name : "env var with invalid path" ,
47- kubeconfigArg : "" ,
48- kubeconfigEnv : "/nonexistent/env/kubeconfig" ,
49- wantErr : true ,
50- errorContains : "failed to build kube config" ,
69+ name : "env var with invalid path" ,
70+ kubeconfigArg : "" ,
71+ kubeconfigEnv : "/nonexistent/env/kubeconfig" ,
72+ wantErr : true ,
73+ errorContains : "failed to build kube config" ,
74+ wantCode : errors .ErrCodeInvalidRequest ,
75+ wantKubeconfig : "/nonexistent/env/kubeconfig" ,
5176 },
5277 }
5378
@@ -72,6 +97,12 @@ func TestBuildKubeClient_PathResolution(t *testing.T) {
7297 t .Errorf ("BuildKubeClient() error = %v, want error containing %q" , err , tt .errorContains )
7398 }
7499 }
100+ if err != nil && tt .wantCode != "" && ! stderrors .Is (err , errors .New (tt .wantCode , "" )) {
101+ t .Errorf ("BuildKubeClient() error = %v, want code %s" , err , tt .wantCode )
102+ }
103+ if err != nil && tt .wantKubeconfig != "" {
104+ assertKubeconfigErrorContext (t , err , tt .wantKubeconfig )
105+ }
75106 })
76107 }
77108}
@@ -117,6 +148,50 @@ func TestBuildKubeClient_ExplicitPath(t *testing.T) {
117148 if ! strings .Contains (err .Error (), "failed to build kube config" ) {
118149 t .Errorf ("BuildKubeClient() error = %v, want error containing 'failed to build kube config'" , err )
119150 }
151+ if ! stderrors .Is (err , errors .New (errors .ErrCodeInvalidRequest , "" )) {
152+ t .Errorf ("BuildKubeClient() error = %v, want ErrCodeInvalidRequest" , err )
153+ }
154+ assertKubeconfigErrorContext (t , err , invalidConfig )
155+ }
156+
157+ // TestBuildKubeClient_InvalidClientConfigReturnsInvalidRequest verifies that a
158+ // kubeconfig which parses successfully but cannot initialize a Kubernetes
159+ // client is still classified as caller input rather than an internal failure.
160+ func TestBuildKubeClient_InvalidClientConfigReturnsInvalidRequest (t * testing.T ) {
161+ kubeconfig := filepath .Join (t .TempDir (), "invalid-client-config" )
162+ content := `apiVersion: v1
163+ kind: Config
164+ clusters:
165+ - name: test
166+ cluster:
167+ server: https://127.0.0.1
168+ certificate-authority-data: bm90IGEgcGVtIGNlcnRpZmljYXRl
169+ contexts:
170+ - name: test
171+ context:
172+ cluster: test
173+ user: test
174+ current-context: test
175+ users:
176+ - name: test
177+ user:
178+ token: test
179+ `
180+ if err := os .WriteFile (kubeconfig , []byte (content ), 0o600 ); err != nil {
181+ t .Fatalf ("failed to write test kubeconfig: %v" , err )
182+ }
183+
184+ _ , _ , err := BuildKubeClient (kubeconfig )
185+ if err == nil {
186+ t .Fatal ("BuildKubeClient() error = nil, want invalid request" )
187+ }
188+ if ! stderrors .Is (err , errors .New (errors .ErrCodeInvalidRequest , "" )) {
189+ t .Errorf ("BuildKubeClient() error = %v, want ErrCodeInvalidRequest" , err )
190+ }
191+ if ! strings .Contains (err .Error (), "failed to create kubernetes client from kubeconfig" ) {
192+ t .Errorf ("BuildKubeClient() error = %v, want client construction failure" , err )
193+ }
194+ assertKubeconfigErrorContext (t , err , kubeconfig )
120195}
121196
122197// TestGetKubeClient_Singleton tests that GetKubeClient returns the same instance.
0 commit comments