github.com/loafoe/cli@v7.1.0+incompatible/integration/helpers/version.go (about) 1 package helpers 2 3 import ( 4 "crypto/tls" 5 "encoding/json" 6 "fmt" 7 "io/ioutil" 8 "net/http" 9 "os" 10 "strconv" 11 "strings" 12 "sync" 13 14 "code.cloudfoundry.org/cli/actor/versioncheck" 15 16 . "github.com/onsi/ginkgo" 17 . "github.com/onsi/gomega" 18 . "github.com/onsi/gomega/gexec" 19 ) 20 21 // IsVersionMet verifies the targeted API meets the minimum required version 22 func IsVersionMet(minVersion string) bool { 23 version := matchMajorAPIVersion(minVersion) 24 ok, err := versioncheck.IsMinimumAPIVersionMet(version, minVersion) 25 Expect(err).ToNot(HaveOccurred()) 26 27 return ok 28 } 29 30 // UAAVersion a struct representation of the UAA version 31 type UAAVersion struct { 32 App struct { 33 Version string `json:"version"` 34 } `json:"app"` 35 } 36 37 // Version returns the version of the targeted UAA 38 func (v UAAVersion) Version() string { 39 return v.App.Version 40 } 41 42 // IsUAAVersionAtLeast returns true if the UAA version >= minVersion, false otherwise. 43 func IsUAAVersionAtLeast(minVersion string) bool { 44 info := fetchAPIVersion() 45 uaaUrl := fmt.Sprintf("%s/info", info.Links.UAA.Href) 46 tr := &http.Transport{ 47 TLSClientConfig: &tls.Config{InsecureSkipVerify: SkipSSLValidation()}, 48 } 49 req, err := http.NewRequest("GET", uaaUrl, nil) 50 Expect(err).ToNot(HaveOccurred()) 51 req.Header.Add("Accept", "application/json") 52 client := &http.Client{Transport: tr} 53 resp, err := client.Do(req) 54 Expect(err).ToNot(HaveOccurred()) 55 56 defer resp.Body.Close() 57 58 if resp.StatusCode == http.StatusOK { 59 bodyBytes, err2 := ioutil.ReadAll(resp.Body) 60 Expect(err2).ToNot(HaveOccurred()) 61 62 version := &UAAVersion{} 63 64 err3 := json.Unmarshal(bodyBytes, &version) 65 Expect(err3).ToNot(HaveOccurred()) 66 currentUaaVersion := version.Version() 67 ok, err := versioncheck.IsMinimumAPIVersionMet(currentUaaVersion, minVersion) 68 Expect(err).ToNot(HaveOccurred()) 69 return ok 70 } 71 Expect(resp.StatusCode).To(Equal(http.StatusOK)) 72 return false 73 } 74 75 // SkipIfUAAVersionLessThan is used to skip tests if the UAA version is < the specified version 76 func SkipIfUAAVersionLessThan(version string) { 77 if !IsUAAVersionAtLeast(version) { 78 Skip(fmt.Sprintf("Test requires UAA version at least %s", version)) 79 } 80 } 81 82 // SkipIfUAAVersionAtLeast is used to skip tests if the UAA varsion >= the specified version. 83 func SkipIfUAAVersionAtLeast(version string) { 84 if IsUAAVersionAtLeast(version) { 85 Skip(fmt.Sprintf("Test requires UAA version less than %s", version)) 86 } 87 } 88 89 func matchMajorAPIVersion(minVersion string) string { 90 version := GetAPIVersionV2() 91 if strings.HasPrefix(minVersion, "3") { 92 version = getAPIVersionV3() 93 } 94 return version 95 } 96 97 // GetAPIVersionV2 returns the V2 api version of the targeted API 98 func GetAPIVersionV2() string { 99 return fetchAPIVersion().Links.CloudContollerV2.Meta.Version 100 } 101 102 // SkipIfVersionLessThan is used to skip tests if the the API version < the specified version. If 103 // minVersion contains the prefix 3 then the v3 version is checked, otherwise the v2 version is used. 104 func SkipIfVersionLessThan(minVersion string) { 105 if ignoreAPIVersion() { 106 return 107 } 108 109 version := matchMajorAPIVersion(minVersion) 110 if !IsVersionMet(minVersion) { 111 Skip(fmt.Sprintf("minimum version %s not met by API version %s", minVersion, version)) 112 } 113 } 114 115 // SkipIfVersionLessThan is used to skip tests if the the API version >= the specified version. If 116 // maxVersion contains the prefix 3 then the v3 version is checked, otherwise the v2 version is used. 117 func SkipIfVersionAtLeast(maxVersion string) { 118 version := matchMajorAPIVersion(maxVersion) 119 120 if IsVersionMet(maxVersion) { 121 Skip(fmt.Sprintf("maximum version %s exceeded by API version %s", maxVersion, version)) 122 } 123 } 124 125 func ignoreAPIVersion() bool { 126 ignoreEnv := os.Getenv("CF_INT_IGNORE_API_VERSION_CHECK") 127 if ignoreEnv == "" { 128 return false 129 } 130 131 ignoreBool, err := strconv.ParseBool(ignoreEnv) 132 return ignoreBool || err != nil 133 } 134 135 type ccRoot struct { 136 Links struct { 137 CloudContollerV2 struct { 138 Meta struct { 139 Version string 140 } 141 } `json:"cloud_controller_v2"` 142 143 CloudContollerV3 struct { 144 Meta struct { 145 Version string 146 } 147 } `json:"cloud_controller_v3"` 148 149 UAA struct { 150 Href string `json:"href"` 151 } `json:"uaa"` 152 } `json:"links"` 153 } 154 155 var cacheLock sync.Mutex 156 157 // CcRootCache is a pointer to a cache of the CC root response 158 var CcRootCache *ccRoot 159 160 func fetchAPIVersion() ccRoot { 161 cacheLock.Lock() 162 defer cacheLock.Unlock() 163 if CcRootCache == nil { 164 session := CF("curl", "/") 165 Eventually(session).Should(Exit(0)) 166 var result ccRoot 167 err := json.Unmarshal(session.Out.Contents(), &result) 168 Expect(err).ToNot(HaveOccurred()) 169 CcRootCache = &result 170 } 171 return *CcRootCache 172 } 173 174 func getAPIVersionV3() string { 175 return fetchAPIVersion().Links.CloudContollerV3.Meta.Version 176 } 177 178 // SkipIfNoRoutingAPI is used to skip tests if the routing API is not present 179 func SkipIfNoRoutingAPI() { 180 // TODO: #161159794 remove this function and check a nicer error message when available 181 var response struct { 182 RoutingEndpoint string `json:"routing_endpoint"` 183 } 184 Curl(&response, "/v2/info") 185 186 if response.RoutingEndpoint == "" { 187 Skip("Test requires routing endpoint on /v2/info") 188 } 189 }