@@ -5,8 +5,13 @@ package clients
55import (
66 "io"
77 "os"
8+ "path/filepath"
89 "testing"
910
11+ "github.com/stretchr/testify/assert"
12+ "k8s.io/client-go/tools/clientcmd"
13+ clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
14+
1015 . "github.com/netapp/trident/logging"
1116)
1217
@@ -15,3 +20,245 @@ func TestMain(m *testing.M) {
1520 InitLogOutput (io .Discard )
1621 os .Exit (m .Run ())
1722}
23+
24+ // createValidTempKubeConfig creates a valid temporary kubeconfig file for testing
25+ func createValidTempKubeConfig (t * testing.T ) string {
26+ tempDir := t .TempDir ()
27+ kubeconfigPath := filepath .Join (tempDir , "kubeconfig" )
28+
29+ config := & clientcmdapi.Config {
30+ APIVersion : "v1" ,
31+ Kind : "Config" ,
32+ Clusters : map [string ]* clientcmdapi.Cluster {
33+ "test-cluster" : {
34+ Server : "https://127.0.0.1:6443" ,
35+ InsecureSkipTLSVerify : true ,
36+ },
37+ },
38+ Contexts : map [string ]* clientcmdapi.Context {
39+ "test-context" : {
40+ Cluster : "test-cluster" ,
41+ AuthInfo : "test-user" ,
42+ Namespace : "test-namespace" ,
43+ },
44+ },
45+ CurrentContext : "test-context" ,
46+ AuthInfos : map [string ]* clientcmdapi.AuthInfo {
47+ "test-user" : {
48+ Token : "test-token" ,
49+ },
50+ },
51+ }
52+
53+ err := clientcmd .WriteToFile (* config , kubeconfigPath )
54+ assert .NoError (t , err , "Failed to write kubeconfig file" )
55+
56+ return kubeconfigPath
57+ }
58+
59+ // createInvalidKubeConfig creates an invalid kubeconfig file for testing
60+ func createInvalidKubeConfig (t * testing.T ) string {
61+ tempDir := t .TempDir ()
62+ kubeconfigPath := filepath .Join (tempDir , "bad-kubeconfig" )
63+ err := os .WriteFile (kubeconfigPath , []byte ("invalid yaml content" ), 0644 )
64+ assert .NoError (t , err , "Failed to write bad kubeconfig file" )
65+ return kubeconfigPath
66+ }
67+
68+ // createEmptyKubeConfig creates an empty kubeconfig file for testing
69+ func createEmptyKubeConfig (t * testing.T ) string {
70+ tempDir := t .TempDir ()
71+ kubeconfigPath := filepath .Join (tempDir , "empty-kubeconfig" )
72+ err := os .WriteFile (kubeconfigPath , []byte ("" ), 0644 )
73+ assert .NoError (t , err , "Failed to write empty kubeconfig file" )
74+ return kubeconfigPath
75+ }
76+
77+ func TestCreateK8SClients (t * testing.T ) {
78+ validKubeConfig := createValidTempKubeConfig (t )
79+
80+ tests := []struct {
81+ name string
82+ apiServerIP string
83+ kubeConfigPath string
84+ expectError bool
85+ errorContains string
86+ description string
87+ }{
88+ {
89+ name : "ValidKubeConfigWithInvalidServer" ,
90+ apiServerIP : "https://invalid:6443" ,
91+ kubeConfigPath : validKubeConfig ,
92+ expectError : true ,
93+ description : "Valid kubeconfig but invalid server should fail" ,
94+ },
95+ {
96+ name : "NonExistentKubeConfig" ,
97+ apiServerIP : "" ,
98+ kubeConfigPath : "/non/existent/path" ,
99+ expectError : true ,
100+ description : "Non-existent kubeconfig file should fail" ,
101+ },
102+ {
103+ name : "InClusterConfigOutsideCluster" ,
104+ apiServerIP : "" ,
105+ kubeConfigPath : "" ,
106+ expectError : true ,
107+ description : "In-cluster config outside cluster should fail" ,
108+ },
109+ {
110+ name : "EmptyAPIWithKubeConfig" ,
111+ apiServerIP : "" ,
112+ kubeConfigPath : validKubeConfig ,
113+ expectError : true ,
114+ description : "Empty API with kubeconfig should trigger ex-cluster path" ,
115+ },
116+ {
117+ name : "APIWithEmptyKubeConfig" ,
118+ apiServerIP : "https://test:6443" ,
119+ kubeConfigPath : "" ,
120+ expectError : true ,
121+ description : "API server with empty kubeconfig should trigger in-cluster path" ,
122+ },
123+ {
124+ name : "BothNonEmpty" ,
125+ apiServerIP : "https://test:6443" ,
126+ kubeConfigPath : "/invalid/path" ,
127+ expectError : true ,
128+ description : "Both non-empty should trigger ex-cluster path" ,
129+ },
130+ }
131+
132+ for _ , tt := range tests {
133+ t .Run (tt .name , func (t * testing.T ) {
134+ clients , err := CreateK8SClients (tt .apiServerIP , tt .kubeConfigPath )
135+
136+ if tt .expectError {
137+ assert .Error (t , err , tt .description )
138+ assert .Nil (t , clients , "Clients should be nil on error" )
139+ if tt .errorContains != "" {
140+ assert .Contains (t , err .Error (), tt .errorContains , "Error message should contain expected text" )
141+ }
142+ } else {
143+ assert .NoError (t , err , tt .description )
144+ assert .NotNil (t , clients , "Clients should not be nil on success" )
145+ }
146+ })
147+ }
148+ }
149+
150+ func TestCreateK8SClientsExCluster (t * testing.T ) {
151+ validKubeConfig := createValidTempKubeConfig (t )
152+ invalidKubeConfig := createInvalidKubeConfig (t )
153+ emptyKubeConfig := createEmptyKubeConfig (t )
154+
155+ tests := []struct {
156+ name string
157+ apiServerIP string
158+ kubeConfigPath string
159+ expectError bool
160+ errorContains string
161+ description string
162+ }{
163+ {
164+ name : "InvalidKubeConfigPath" ,
165+ apiServerIP : "" ,
166+ kubeConfigPath : "/invalid/path" ,
167+ expectError : true ,
168+ description : "Invalid kubeconfig path should fail" ,
169+ },
170+ {
171+ name : "ValidConfigWithValidServer" ,
172+ apiServerIP : "https://127.0.0.1:6443" ,
173+ kubeConfigPath : validKubeConfig ,
174+ expectError : true ,
175+ errorContains : "could not initialize Kubernetes client" ,
176+ description : "Valid config should parse but fail at K8S client creation in test environment" ,
177+ },
178+ {
179+ name : "InvalidKubeConfigContent" ,
180+ apiServerIP : "" ,
181+ kubeConfigPath : invalidKubeConfig ,
182+ expectError : true ,
183+ description : "Invalid kubeconfig content should fail" ,
184+ },
185+ {
186+ name : "EmptyKubeConfig" ,
187+ apiServerIP : "" ,
188+ kubeConfigPath : emptyKubeConfig ,
189+ expectError : true ,
190+ description : "Empty kubeconfig should fail" ,
191+ },
192+ {
193+ name : "EmptyAPIServerWithInvalidPath" ,
194+ apiServerIP : "" ,
195+ kubeConfigPath : "/invalid/path" ,
196+ expectError : true ,
197+ description : "Empty API server with invalid path should fail" ,
198+ },
199+ }
200+
201+ for _ , tt := range tests {
202+ t .Run (tt .name , func (t * testing.T ) {
203+ clients , err := createK8SClientsExCluster (tt .apiServerIP , tt .kubeConfigPath )
204+
205+ if tt .expectError {
206+ assert .Error (t , err , tt .description )
207+ if tt .errorContains != "" {
208+ assert .Contains (t , err .Error (), tt .errorContains , "Error message should contain expected text" )
209+ }
210+ // For the valid config case, clients might not be nil if config parsing succeeded
211+ if tt .errorContains != "could not initialize Kubernetes client" {
212+ assert .Nil (t , clients , "Clients should be nil on error" )
213+ }
214+ } else {
215+ assert .NoError (t , err , tt .description )
216+ assert .NotNil (t , clients , "Clients should not be nil on success" )
217+ assert .NotNil (t , clients .KubeConfig , "KubeConfig should not be nil" )
218+ }
219+ })
220+ }
221+ }
222+
223+ func TestCreateK8SClientsInCluster (t * testing.T ) {
224+ // Test in-cluster creation (will fail due to missing namespace file in test environment)
225+ clients , err := createK8SClientsInCluster ()
226+
227+ assert .Error (t , err , "Expected error for in-cluster config outside cluster" )
228+ assert .Nil (t , clients , "Clients should be nil on error" )
229+ }
230+
231+ func TestClientsStruct (t * testing.T ) {
232+ tests := []struct {
233+ name string
234+ namespace string
235+ }{
236+ {
237+ name : "TestNamespace" ,
238+ namespace : "test-namespace" ,
239+ },
240+ {
241+ name : "EmptyNamespace" ,
242+ namespace : "" ,
243+ },
244+ {
245+ name : "DefaultNamespace" ,
246+ namespace : "default" ,
247+ },
248+ }
249+
250+ for _ , tt := range tests {
251+ t .Run (tt .name , func (t * testing.T ) {
252+ clients := & Clients {
253+ Namespace : tt .namespace ,
254+ }
255+
256+ assert .Equal (t , tt .namespace , clients .Namespace , "Namespace should be set correctly" )
257+ assert .Nil (t , clients .KubeClient , "KubeClient should be nil initially" )
258+ assert .Nil (t , clients .CRDClient , "CRDClient should be nil initially" )
259+ assert .Nil (t , clients .TridentCRDClient , "TridentCRDClient should be nil initially" )
260+ assert .Nil (t , clients .SnapshotClient , "SnapshotClient should be nil initially" )
261+ assert .Nil (t , clients .K8SVersion , "K8SVersion should be nil initially" )
262+ })
263+ }
264+ }
0 commit comments