github.com/interconnectedcloud/qdr-operator@v0.0.0-20210826174505-576d2b33dac7/test/e2e/framework/util.go (about) 1 /* 2 Copyright 2019 The Interconnectedcloud Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package framework 18 19 import ( 20 "fmt" 21 "sort" 22 23 "k8s.io/apimachinery/pkg/util/uuid" 24 clientset "k8s.io/client-go/kubernetes" 25 restclient "k8s.io/client-go/rest" 26 "k8s.io/client-go/tools/clientcmd" 27 clientcmdapi "k8s.io/client-go/tools/clientcmd/api" 28 29 e2elog "github.com/interconnectedcloud/qdr-operator/test/e2e/framework/log" 30 31 "github.com/onsi/gomega" 32 ) 33 34 var ( 35 RunID = uuid.NewUUID() 36 ) 37 38 // RestclientConfig returns a config holds the information needed to build connection to kubernetes clusters. 39 func RestclientConfig(kubeContext string) (*clientcmdapi.Config, error) { 40 //e2elog.Logf(">>> kubeConfig: %s", TestContext.KubeConfig) 41 if TestContext.KubeConfig == "" { 42 return nil, fmt.Errorf("KubeConfig must be specified to load client config") 43 } 44 c, err := clientcmd.LoadFromFile(TestContext.KubeConfig) 45 if err != nil { 46 return nil, fmt.Errorf("error loading KubeConfig: %v", err.Error()) 47 } 48 if kubeContext != "" { 49 //e2elog.Logf(">>> kubeContext: %s", kubeContext) 50 c.CurrentContext = kubeContext 51 } 52 return c, nil 53 } 54 55 // LoadConfig returns a config for a rest client. 56 func LoadConfig() (*restclient.Config, error) { 57 c, err := RestclientConfig(TestContext.KubeContext) 58 if err != nil { 59 if TestContext.KubeConfig == "" { 60 return restclient.InClusterConfig() 61 } 62 return nil, err 63 } 64 65 return clientcmd.NewDefaultClientConfig(*c, &clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: TestContext.Host}}).ClientConfig() 66 } 67 68 // LoadClientset returns clientset for connecting to kubernetes clusters. 69 func LoadClientset() (*clientset.Clientset, error) { 70 config, err := LoadConfig() 71 if err != nil { 72 return nil, fmt.Errorf("error creating client: %v", err.Error()) 73 } 74 return clientset.NewForConfig(config) 75 } 76 77 // ExpectError expects an error happens, otherwise an exception raises 78 func ExpectError(err error, explain ...interface{}) { 79 gomega.Expect(err).To(gomega.HaveOccurred(), explain...) 80 } 81 82 // ExpectNoError checks if "err" is set, and if so, fails assertion while logging the error. 83 func ExpectNoError(err error, explain ...interface{}) { 84 ExpectNoErrorWithOffset(1, err, explain...) 85 } 86 87 // ExpectNoErrorWithOffset checks if "err" is set, and if so, fails assertion while logging the error at "offset" levels above its caller 88 // (for example, for call chain f -> g -> ExpectNoErrorWithOffset(1, ...) error would be logged for "f"). 89 func ExpectNoErrorWithOffset(offset int, err error, explain ...interface{}) { 90 if err != nil { 91 e2elog.Logf("Unexpected error occurred: %v", err) 92 } 93 gomega.ExpectWithOffset(1+offset, err).NotTo(gomega.HaveOccurred(), explain...) 94 } 95 96 // ExpectNoErrorWithRetries checks if an error occurs with the given retry count. 97 func ExpectNoErrorWithRetries(fn func() error, maxRetries int, explain ...interface{}) { 98 var err error 99 for i := 0; i < maxRetries; i++ { 100 err = fn() 101 if err == nil { 102 return 103 } 104 e2elog.Logf("(Attempt %d of %d) Unexpected error occurred: %v", i+1, maxRetries, err) 105 } 106 gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred(), explain...) 107 } 108 109 // ContainsAll can be used to compare two sorted slices and validate 110 // both are not nil and all elements from given model are present on 111 // the target instance. 112 func ContainsAll(model, target []interface{}) bool { 113 if model == nil || target == nil { 114 return false 115 } 116 117 if len(model) > len(target) { 118 return false 119 } 120 121 ti := 0 122 for _, vm := range model { 123 found := false 124 for i := ti; i < len(target); i++ { 125 if vm == target[i] { 126 found = true 127 if ti == i { 128 ti++ 129 } else { 130 ti = i 131 } 132 break 133 } 134 } 135 136 if !found { 137 return false 138 } 139 } 140 141 return true 142 } 143 144 // FromInts returns an interface array with sorted elements from int array 145 func FromInts(m []int) []interface{} { 146 res := make([]interface{}, len(m)) 147 for i, v := range m { 148 res[i] = v 149 } 150 sort.Slice(res, func(i1, i2 int) bool { 151 return res[i1].(int) < res[i2].(int) 152 }) 153 return res 154 } 155 156 // FromStrings returns an interface array with sorted elements from string array 157 func FromStrings(m []string) []interface{} { 158 res := make([]interface{}, len(m)) 159 for i, v := range m { 160 res[i] = v 161 } 162 sort.Slice(res, func(i1, i2 int) bool { 163 return res[i1].(string) < res[i2].(string) 164 }) 165 return res 166 }