summaryrefslogtreecommitdiff
path: root/vendor/github.com/microsoft/azure-devops-go-api/azuredevops/versionnegotiation.go
blob: f1a2a2f33a95196827ba8a6f054eadefbe90a502 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package azuredevops

import "strconv"

func negotiateRequestVersion(location *ApiResourceLocation, apiVersion string) (string, error) {
	if apiVersion == "" {
		// if no api-version is sent to the server, the server will decide the version. The server uses the latest
		// released version if the endpoint has been released, otherwise it will use the latest preview version.
		return apiVersion, nil
	}

	matches := apiVersionRegEx.FindStringSubmatch(apiVersion)
	if len(matches) == 0 && matches[0] != "" {
		return apiVersion, &InvalidApiVersion{apiVersion}
	}

	requestedApiVersion, err := NewVersion(matches[1])
	if err != nil {
		return apiVersion, err
	}
	locationMinVersion, err := NewVersion(*location.MinVersion)
	if err != nil {
		return apiVersion, err
	}
	if locationMinVersion.CompareTo(*requestedApiVersion) > 0 {
		// Client is older than the server. The server no longer supports this
		// resource (deprecated).
		return apiVersion, nil
	} else {
		locationMaxVersion, err := NewVersion(*location.MaxVersion)
		if err != nil {
			return apiVersion, err
		}
		if locationMaxVersion.CompareTo(*requestedApiVersion) < 0 {
			// Client is newer than the server. Negotiate down to the latest version
			// on the server
			negotiatedVersion := string(*location.MaxVersion)
			if *location.ReleasedVersion < *location.MaxVersion {
				negotiatedVersion += "-preview"
			}
			return negotiatedVersion, nil
		} else {
			// We can send at the requested api version. Make sure the resource version
			// is not bigger than what the server supports
			negotiatedVersion := matches[1]
			if len(matches) > 3 && matches[3] != "" { // matches '-preview'
				negotiatedVersion += "-preview"
				if len(matches) > 5 && matches[5] != "" { // has a resource version
					requestedResourceVersion, _ := strconv.Atoi(matches[5])
					if *location.ResourceVersion < requestedResourceVersion {
						negotiatedVersion += "." + strconv.Itoa(*location.ResourceVersion)
					} else {
						negotiatedVersion += "." + matches[5]
					}
				}
			} else {
				// requesting released version, ensure server supports a released version, and if not append '-preview'
				locationReleasedVersion, err := NewVersion(*location.ReleasedVersion)
				if err != nil {
					return apiVersion, err
				}
				if (locationReleasedVersion.Major == 0 && locationReleasedVersion.Minor == 0) || locationReleasedVersion.CompareTo(*requestedApiVersion) < 0 {
					negotiatedVersion += "-preview"
				}
			}
			return negotiatedVersion, nil
		}
	}
}