Samuel A. Falvo II | 8a549ef | 2014-01-24 15:20:54 -0800 | [diff] [blame] | 1 | package identity |
| 2 | |
| 3 | import "github.com/mitchellh/mapstructure" |
| 4 | |
Samuel A. Falvo II | 2b96321 | 2014-02-09 02:12:30 -0800 | [diff] [blame] | 5 | // ServiceCatalog provides a view into the service catalog from a previous, successful authentication. |
| 6 | // OpenStack extensions may alter the structure of the service catalog in ways unpredictable to Go at compile-time, |
| 7 | // so this structure serves as a convenient anchor for type-safe accessors and methods. |
| 8 | type ServiceCatalog struct { |
Samuel A. Falvo II | 8a549ef | 2014-01-24 15:20:54 -0800 | [diff] [blame] | 9 | serviceDescriptions []interface{} |
| 10 | } |
| 11 | |
Samuel A. Falvo II | 2b96321 | 2014-02-09 02:12:30 -0800 | [diff] [blame] | 12 | // CatalogEntry provides a type-safe interface to an Identity API V2 service |
| 13 | // catalog listing. Each class of service, such as cloud DNS or block storage |
| 14 | // services, will have a single CatalogEntry representing it. |
| 15 | // |
| 16 | // Name will contain the provider-specified name for the service. |
| 17 | // |
| 18 | // If OpenStack defines a type for the service, this field will contain that |
| 19 | // type string. Otherwise, for provider-specific services, the provider may |
| 20 | // assign their own type strings. |
| 21 | // |
| 22 | // Endpoints will let the caller iterate over all the different endpoints that |
| 23 | // may exist for the service. |
| 24 | // |
| 25 | // Note: when looking for the desired service, try, whenever possible, to key |
| 26 | // off the type field. Otherwise, you'll tie the representation of the service |
| 27 | // to a specific provider. |
Samuel A. Falvo II | 8a549ef | 2014-01-24 15:20:54 -0800 | [diff] [blame] | 28 | type CatalogEntry struct { |
Samuel A. Falvo II | 0262e97 | 2014-01-24 16:06:56 -0800 | [diff] [blame] | 29 | Name string |
| 30 | Type string |
Samuel A. Falvo II | 8a549ef | 2014-01-24 15:20:54 -0800 | [diff] [blame] | 31 | Endpoints []Endpoint |
| 32 | } |
| 33 | |
Samuel A. Falvo II | 2b96321 | 2014-02-09 02:12:30 -0800 | [diff] [blame] | 34 | // Endpoint represents a single API endpoint offered by a service. |
| 35 | // It provides the public and internal URLs, if supported, along with a region specifier, again if provided. |
| 36 | // The significance of the Region field will depend upon your provider. |
| 37 | // |
| 38 | // In addition, the interface offered by the service will have version information associated with it |
| 39 | // through the VersionId, VersionInfo, and VersionList fields, if provided or supported. |
| 40 | // |
| 41 | // In all cases, fields which aren't supported by the provider and service combined will assume a zero-value (""). |
Samuel A. Falvo II | 8a549ef | 2014-01-24 15:20:54 -0800 | [diff] [blame] | 42 | type Endpoint struct { |
Samuel A. Falvo II | 0262e97 | 2014-01-24 16:06:56 -0800 | [diff] [blame] | 43 | TenantId string |
| 44 | PublicURL string |
Samuel A. Falvo II | 8a549ef | 2014-01-24 15:20:54 -0800 | [diff] [blame] | 45 | InternalURL string |
Samuel A. Falvo II | 0262e97 | 2014-01-24 16:06:56 -0800 | [diff] [blame] | 46 | Region string |
| 47 | VersionId string |
Samuel A. Falvo II | 8a549ef | 2014-01-24 15:20:54 -0800 | [diff] [blame] | 48 | VersionInfo string |
| 49 | VersionList string |
| 50 | } |
| 51 | |
Samuel A. Falvo II | 2b96321 | 2014-02-09 02:12:30 -0800 | [diff] [blame] | 52 | // GetServiceCatalog acquires the service catalog from a successful authentication's results. |
| 53 | func GetServiceCatalog(ar AuthResults) (*ServiceCatalog, error) { |
Samuel A. Falvo II | 8a549ef | 2014-01-24 15:20:54 -0800 | [diff] [blame] | 54 | access := ar["access"].(map[string]interface{}) |
| 55 | sds := access["serviceCatalog"].([]interface{}) |
Samuel A. Falvo II | 2b96321 | 2014-02-09 02:12:30 -0800 | [diff] [blame] | 56 | sc := &ServiceCatalog{ |
Samuel A. Falvo II | 8a549ef | 2014-01-24 15:20:54 -0800 | [diff] [blame] | 57 | serviceDescriptions: sds, |
| 58 | } |
| 59 | return sc, nil |
| 60 | } |
| 61 | |
Samuel A. Falvo II | 2b96321 | 2014-02-09 02:12:30 -0800 | [diff] [blame] | 62 | // NumberOfServices yields the number of services the caller may use. Note |
| 63 | // that this does not necessarily equal the number of endpoints available for |
| 64 | // use. |
| 65 | func (sc *ServiceCatalog) NumberOfServices() int { |
Samuel A. Falvo II | 8a549ef | 2014-01-24 15:20:54 -0800 | [diff] [blame] | 66 | return len(sc.serviceDescriptions) |
| 67 | } |
| 68 | |
Samuel A. Falvo II | 2b96321 | 2014-02-09 02:12:30 -0800 | [diff] [blame] | 69 | // CatalogEntries returns a slice of service catalog entries. |
| 70 | // Each entry corresponds to a specific class of service offered by the API provider. |
| 71 | // See the CatalogEntry structure for more details. |
| 72 | func (sc *ServiceCatalog) CatalogEntries() ([]CatalogEntry, error) { |
Samuel A. Falvo II | 8a549ef | 2014-01-24 15:20:54 -0800 | [diff] [blame] | 73 | var err error |
| 74 | ces := make([]CatalogEntry, sc.NumberOfServices()) |
| 75 | for i, sd := range sc.serviceDescriptions { |
| 76 | d := sd.(map[string]interface{}) |
| 77 | eps, err := parseEndpoints(d["endpoints"].([]interface{})) |
| 78 | if err != nil { |
| 79 | return ces, err |
| 80 | } |
| 81 | ces[i] = CatalogEntry{ |
Samuel A. Falvo II | 0262e97 | 2014-01-24 16:06:56 -0800 | [diff] [blame] | 82 | Name: d["name"].(string), |
| 83 | Type: d["type"].(string), |
Samuel A. Falvo II | 8a549ef | 2014-01-24 15:20:54 -0800 | [diff] [blame] | 84 | Endpoints: eps, |
| 85 | } |
| 86 | } |
| 87 | return ces, err |
| 88 | } |
| 89 | |
| 90 | func parseEndpoints(eps []interface{}) ([]Endpoint, error) { |
| 91 | var err error |
| 92 | result := make([]Endpoint, len(eps)) |
| 93 | for i, ep := range eps { |
| 94 | e := Endpoint{} |
| 95 | err = mapstructure.Decode(ep, &e) |
| 96 | if err != nil { |
| 97 | return result, err |
| 98 | } |
| 99 | result[i] = e |
| 100 | } |
| 101 | return result, err |
| 102 | } |