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  }