Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / github.com / gophercloud / gophercloud / openstack / utils / choose_version.go
1 package utils
2
3 import (
4         "fmt"
5         "strings"
6
7         "github.com/gophercloud/gophercloud"
8 )
9
10 // Version is a supported API version, corresponding to a vN package within the appropriate service.
11 type Version struct {
12         ID       string
13         Suffix   string
14         Priority int
15 }
16
17 var goodStatus = map[string]bool{
18         "current":   true,
19         "supported": true,
20         "stable":    true,
21 }
22
23 // ChooseVersion queries the base endpoint of an API to choose the most recent non-experimental alternative from a service's
24 // published versions.
25 // It returns the highest-Priority Version among the alternatives that are provided, as well as its corresponding endpoint.
26 func ChooseVersion(client *gophercloud.ProviderClient, recognized []*Version) (*Version, string, error) {
27         type linkResp struct {
28                 Href string `json:"href"`
29                 Rel  string `json:"rel"`
30         }
31
32         type valueResp struct {
33                 ID     string     `json:"id"`
34                 Status string     `json:"status"`
35                 Links  []linkResp `json:"links"`
36         }
37
38         type versionsResp struct {
39                 Values []valueResp `json:"values"`
40         }
41
42         type response struct {
43                 Versions versionsResp `json:"versions"`
44         }
45
46         normalize := func(endpoint string) string {
47                 if !strings.HasSuffix(endpoint, "/") {
48                         return endpoint + "/"
49                 }
50                 return endpoint
51         }
52         identityEndpoint := normalize(client.IdentityEndpoint)
53
54         // If a full endpoint is specified, check version suffixes for a match first.
55         for _, v := range recognized {
56                 if strings.HasSuffix(identityEndpoint, v.Suffix) {
57                         return v, identityEndpoint, nil
58                 }
59         }
60
61         var resp response
62         _, err := client.Request("GET", client.IdentityBase, &gophercloud.RequestOpts{
63                 JSONResponse: &resp,
64                 OkCodes:      []int{200, 300},
65         })
66
67         if err != nil {
68                 return nil, "", err
69         }
70
71         var highest *Version
72         var endpoint string
73
74         for _, value := range resp.Versions.Values {
75                 href := ""
76                 for _, link := range value.Links {
77                         if link.Rel == "self" {
78                                 href = normalize(link.Href)
79                         }
80                 }
81
82                 for _, version := range recognized {
83                         if strings.Contains(value.ID, version.ID) {
84                                 // Prefer a version that exactly matches the provided endpoint.
85                                 if href == identityEndpoint {
86                                         if href == "" {
87                                                 return nil, "", fmt.Errorf("Endpoint missing in version %s response from %s", value.ID, client.IdentityBase)
88                                         }
89                                         return version, href, nil
90                                 }
91
92                                 // Otherwise, find the highest-priority version with a whitelisted status.
93                                 if goodStatus[strings.ToLower(value.Status)] {
94                                         if highest == nil || version.Priority > highest.Priority {
95                                                 highest = version
96                                                 endpoint = href
97                                         }
98                                 }
99                         }
100                 }
101         }
102
103         if highest == nil {
104                 return nil, "", fmt.Errorf("No supported version available from endpoint %s", client.IdentityBase)
105         }
106         if endpoint == "" {
107                 return nil, "", fmt.Errorf("Endpoint missing in version %s response from %s", highest.ID, client.IdentityBase)
108         }
109
110         return highest, endpoint, nil
111 }