github.com/cloudfoundry-community/cloudfoundry-cli@v6.44.1-0.20240130060226-cda5ed8e89a5+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  func IsVersionMet(minVersion string) bool {
    22  	version := matchMajorAPIVersion(minVersion)
    23  	ok, err := versioncheck.IsMinimumAPIVersionMet(version, minVersion)
    24  	Expect(err).ToNot(HaveOccurred())
    25  
    26  	return ok
    27  }
    28  
    29  type UAAVersion struct {
    30  	App struct {
    31  		Version string `json:"version"`
    32  	} `json:"app"`
    33  }
    34  
    35  func (v UAAVersion) Version() string {
    36  	return v.App.Version
    37  }
    38  
    39  func IsUAAVersionAtLeast(minVersion string) bool {
    40  	info := fetchAPIVersion()
    41  	uaaUrl := fmt.Sprintf("%s/info", info.Links.UAA.Href)
    42  	tr := &http.Transport{
    43  		TLSClientConfig: &tls.Config{InsecureSkipVerify: skipSSLValidation()},
    44  	}
    45  	req, err := http.NewRequest("GET", uaaUrl, nil)
    46  	Expect(err).ToNot(HaveOccurred())
    47  	req.Header.Add("Accept", "application/json")
    48  	client := &http.Client{Transport: tr}
    49  	resp, err := client.Do(req)
    50  	Expect(err).ToNot(HaveOccurred())
    51  
    52  	defer resp.Body.Close()
    53  
    54  	if resp.StatusCode == http.StatusOK {
    55  		bodyBytes, err2 := ioutil.ReadAll(resp.Body)
    56  		Expect(err2).ToNot(HaveOccurred())
    57  
    58  		version := &UAAVersion{}
    59  
    60  		err3 := json.Unmarshal(bodyBytes, &version)
    61  		Expect(err3).ToNot(HaveOccurred())
    62  		currentUaaVersion := version.Version()
    63  		ok, err := versioncheck.IsMinimumAPIVersionMet(currentUaaVersion, minVersion)
    64  		Expect(err).ToNot(HaveOccurred())
    65  		return ok
    66  	}
    67  	Expect(resp.StatusCode).To(Equal(http.StatusOK))
    68  	return false
    69  }
    70  
    71  func SkipIfUAAVersionLessThan(version string) {
    72  	if !IsUAAVersionAtLeast(version) {
    73  		Skip(fmt.Sprintf("Test requires UAA version at least %s", version))
    74  	}
    75  }
    76  
    77  func SkipIfUAAVersionAtLeast(version string) {
    78  	if IsUAAVersionAtLeast(version) {
    79  		Skip(fmt.Sprintf("Test requires UAA version less than %s", version))
    80  	}
    81  }
    82  
    83  func matchMajorAPIVersion(minVersion string) string {
    84  	version := GetAPIVersionV2()
    85  	if strings.HasPrefix(minVersion, "3") {
    86  		version = getAPIVersionV3()
    87  	}
    88  	return version
    89  }
    90  
    91  func GetAPIVersionV2() string {
    92  	return fetchAPIVersion().Links.CloudContollerV2.Meta.Version
    93  }
    94  
    95  func SkipIfVersionLessThan(minVersion string) {
    96  	if ignoreAPIVersion() {
    97  		return
    98  	}
    99  
   100  	version := matchMajorAPIVersion(minVersion)
   101  	if !IsVersionMet(minVersion) {
   102  		Skip(fmt.Sprintf("minimum version %s not met by API version %s", minVersion, version))
   103  	}
   104  }
   105  
   106  func SkipIfVersionAtLeast(maxVersion string) {
   107  	version := matchMajorAPIVersion(maxVersion)
   108  
   109  	if IsVersionMet(maxVersion) {
   110  		Skip(fmt.Sprintf("maximum version %s exceeded by API version %s", maxVersion, version))
   111  	}
   112  }
   113  
   114  func ignoreAPIVersion() bool {
   115  	ignoreEnv := os.Getenv("CF_INT_IGNORE_API_VERSION_CHECK")
   116  	if ignoreEnv == "" {
   117  		return false
   118  	}
   119  
   120  	ignoreBool, err := strconv.ParseBool(ignoreEnv)
   121  	return ignoreBool || err != nil
   122  }
   123  
   124  type ccRoot struct {
   125  	Links struct {
   126  		CloudContollerV2 struct {
   127  			Meta struct {
   128  				Version string
   129  			}
   130  		} `json:"cloud_controller_v2"`
   131  
   132  		CloudContollerV3 struct {
   133  			Meta struct {
   134  				Version string
   135  			}
   136  		} `json:"cloud_controller_v3"`
   137  
   138  		UAA struct {
   139  			Href string `json:"href"`
   140  		} `json:"uaa"`
   141  	} `json:"links"`
   142  }
   143  
   144  var cacheLock sync.Mutex
   145  var CcRootCache *ccRoot
   146  
   147  func fetchAPIVersion() ccRoot {
   148  	cacheLock.Lock()
   149  	defer cacheLock.Unlock()
   150  	if CcRootCache == nil {
   151  		session := CF("curl", "/")
   152  		Eventually(session).Should(Exit(0))
   153  		var result ccRoot
   154  		err := json.Unmarshal(session.Out.Contents(), &result)
   155  		Expect(err).ToNot(HaveOccurred())
   156  		CcRootCache = &result
   157  	}
   158  	return *CcRootCache
   159  }
   160  
   161  func getAPIVersionV3() string {
   162  	return fetchAPIVersion().Links.CloudContollerV3.Meta.Version
   163  }
   164  
   165  func SkipIfNoRoutingAPI() {
   166  	// TODO: #161159794 remove this function and check a nicer error message when available
   167  	var response struct {
   168  		RoutingEndpoint string `json:"routing_endpoint"`
   169  	}
   170  	Curl(&response, "/v2/info")
   171  
   172  	if response.RoutingEndpoint == "" {
   173  		Skip("Test requires routing endpoint on /v2/info")
   174  	}
   175  }