github.com/kiali/kiali@v1.84.0/kubernetes/testing.go (about) 1 package kubernetes 2 3 import ( 4 "fmt" 5 "os" 6 "testing" 7 "time" 8 9 "k8s.io/apimachinery/pkg/runtime" 10 "k8s.io/client-go/rest" 11 12 "github.com/kiali/kiali/config" 13 ) 14 15 // ReadFile reads a file's contents and calls t.Fatal if any error occurs. 16 func ReadFile(t *testing.T, path string) []byte { 17 t.Helper() 18 contents, err := os.ReadFile(path) 19 if err != nil { 20 t.Fatalf("Error while reading file: %s. Err: %s", path, err) 21 } 22 return contents 23 } 24 25 // SetConfig sets the global config for a test and restores it after the test. 26 func SetConfig(t *testing.T, newConfig config.Config) { 27 oldConfig := config.Get() 28 t.Cleanup(func() { 29 config.Set(oldConfig) 30 }) 31 config.Set(&newConfig) 32 } 33 34 // NewTestingClientFactory creates a client factory and a temporary token file. 35 // Without this token file, the client factory will try to read the token from 36 // the default path at /var/run/secrets/... which probably doesn't exist and 37 // we probably don't want to use it even if it does. 38 // This sets globals so it is NOT safe to use in parallel tests. 39 // It really should just be used for internal client factory tests 40 // since it has side effects with globals and local files/env vars. 41 // If you need a test client factory outside this package, use the mock implementation. 42 func NewTestingClientFactory(t *testing.T) *clientFactory { 43 t.Helper() 44 45 // Reset global vars after test 46 originalToken := KialiTokenForHomeCluster 47 originalPath := DefaultServiceAccountPath 48 t.Cleanup(func() { 49 KialiTokenForHomeCluster = originalToken 50 DefaultServiceAccountPath = originalPath 51 }) 52 53 DefaultServiceAccountPath = fmt.Sprintf("%s/kiali-testing-token-%s", t.TempDir(), time.Now()) 54 if err := os.WriteFile(DefaultServiceAccountPath, []byte("test-token"), 0o644); err != nil { 55 t.Fatalf("Unable to create token file for testing. Err: %s", err) 56 } 57 58 clientConfig := rest.Config{} 59 client, err := newClientFactory(&clientConfig) 60 if err != nil { 61 t.Fatalf("Error creating client factory: %v", err) 62 } 63 64 // Override global client factory for test 65 factory = client 66 67 // Reset after test is over 68 t.Cleanup(func() { 69 factory = nil 70 }) 71 72 return client 73 } 74 75 func createTestRemoteClusterSecretFile(t *testing.T, parentDir string, name string, content string) string { 76 childDir := fmt.Sprintf("%s/%s", parentDir, name) 77 filename := fmt.Sprintf("%s/%s", childDir, name) 78 if err := os.MkdirAll(childDir, 0o777); err != nil { 79 t.Fatalf("Failed to create tmp remote cluster secret dir [%v]: %v", childDir, err) 80 } 81 f, err := os.Create(filename) 82 if err != nil { 83 t.Fatalf("Failed to create tmp remote cluster secret file [%v]: %v", filename, err) 84 } 85 defer f.Close() 86 if _, err2 := f.WriteString(content); err2 != nil { 87 t.Fatalf("Failed to write tmp remote cluster secret file [%v]: %v", filename, err2) 88 } 89 90 return filename 91 } 92 93 // Helper function to create a test remote cluster secret file from a RemoteSecret. 94 // It will cleanup after itself when the test is done. 95 func createTestRemoteClusterSecret(t *testing.T, cluster string, contents string) string { 96 t.Helper() 97 // create a mock volume mount directory where the test remote cluster secret content will go 98 originalRemoteClusterSecretsDir := RemoteClusterSecretsDir 99 t.Cleanup(func() { 100 RemoteClusterSecretsDir = originalRemoteClusterSecretsDir 101 }) 102 RemoteClusterSecretsDir = t.TempDir() 103 104 return createTestRemoteClusterSecretFile(t, RemoteClusterSecretsDir, cluster, contents) 105 } 106 107 // ToRuntimeObjects takes a slice of something that implements runtime.Object 108 // and returns a new slice of the objects as the interface runtime.Object(s). 109 // Useful for testing where the fake client accepts variadic args and you first 110 // need to convert to a slice of the interface like: 111 // 112 // namespaces := []*corev1.Namespace{ns} 113 // client := FakeClient(namespaces...) 114 // 115 // This only works if you first use this function to convert the slice. 116 func ToRuntimeObjects[T runtime.Object](objs []T) []runtime.Object { 117 var retObjs []runtime.Object 118 for _, obj := range objs { 119 o := obj 120 retObjs = append(retObjs, o) 121 } 122 return retObjs 123 }