blob: e88b2c7d825a8931a43badaa34969c4afbff2033 [file] [log] [blame]
Jamie Hannaford2aaf1a62014-10-16 12:55:50 +02001package tokens
2
3import (
4 "time"
5
6 "github.com/mitchellh/mapstructure"
7 "github.com/rackspace/gophercloud"
8 "github.com/rackspace/gophercloud/openstack/identity/v2/tenants"
9)
10
11// Token provides only the most basic information related to an authentication token.
12type Token struct {
13 // ID provides the primary means of identifying a user to the OpenStack API.
14 // OpenStack defines this field as an opaque value, so do not depend on its content.
15 // It is safe, however, to compare for equality.
16 ID string
17
18 // ExpiresAt provides a timestamp in ISO 8601 format, indicating when the authentication token becomes invalid.
19 // After this point in time, future API requests made using this authentication token will respond with errors.
20 // Either the caller will need to reauthenticate manually, or more preferably, the caller should exploit automatic re-authentication.
21 // See the AuthOptions structure for more details.
22 ExpiresAt time.Time
23
24 // Tenant provides information about the tenant to which this token grants access.
25 Tenant tenants.Tenant
26}
27
28// Endpoint represents a single API endpoint offered by a service.
29// It provides the public and internal URLs, if supported, along with a region specifier, again if provided.
30// The significance of the Region field will depend upon your provider.
31//
32// In addition, the interface offered by the service will have version information associated with it
33// through the VersionId, VersionInfo, and VersionList fields, if provided or supported.
34//
35// In all cases, fields which aren't supported by the provider and service combined will assume a zero-value ("").
36type Endpoint struct {
37 TenantID string `mapstructure:"tenantId"`
38 PublicURL string `mapstructure:"publicURL"`
39 InternalURL string `mapstructure:"internalURL"`
40 AdminURL string `mapstructure:"adminURL"`
41 Region string `mapstructure:"region"`
42 VersionID string `mapstructure:"versionId"`
43 VersionInfo string `mapstructure:"versionInfo"`
44 VersionList string `mapstructure:"versionList"`
45}
46
47// CatalogEntry provides a type-safe interface to an Identity API V2 service catalog listing.
48// Each class of service, such as cloud DNS or block storage services, will have a single
49// CatalogEntry representing it.
50//
51// Note: when looking for the desired service, try, whenever possible, to key off the type field.
52// Otherwise, you'll tie the representation of the service to a specific provider.
53type CatalogEntry struct {
54 // Name will contain the provider-specified name for the service.
55 Name string `mapstructure:"name"`
56
57 // Type will contain a type string if OpenStack defines a type for the service.
58 // Otherwise, for provider-specific services, the provider may assign their own type strings.
59 Type string `mapstructure:"type"`
60
61 // Endpoints will let the caller iterate over all the different endpoints that may exist for
62 // the service.
63 Endpoints []Endpoint `mapstructure:"endpoints"`
64}
65
66// ServiceCatalog provides a view into the service catalog from a previous, successful authentication.
67type ServiceCatalog struct {
68 Entries []CatalogEntry
69}
70
71// CreateResult defers the interpretation of a created token.
72// Use ExtractToken() to interpret it as a Token, or ExtractServiceCatalog() to interpret it as a service catalog.
73type CreateResult struct {
74 gophercloud.CommonResult
75}
76
77// ExtractToken returns the just-created Token from a CreateResult.
78func (result CreateResult) ExtractToken() (*Token, error) {
79 if result.Err != nil {
80 return nil, result.Err
81 }
82
83 var response struct {
84 Access struct {
85 Token struct {
86 Expires string `mapstructure:"expires"`
87 ID string `mapstructure:"id"`
88 Tenant tenants.Tenant `mapstructure:"tenant"`
89 } `mapstructure:"token"`
90 } `mapstructure:"access"`
91 }
92
93 err := mapstructure.Decode(result.Resp, &response)
94 if err != nil {
95 return nil, err
96 }
97
98 expiresTs, err := time.Parse(gophercloud.RFC3339Milli, response.Access.Token.Expires)
99 if err != nil {
100 return nil, err
101 }
102
103 return &Token{
104 ID: response.Access.Token.ID,
105 ExpiresAt: expiresTs,
106 Tenant: response.Access.Token.Tenant,
107 }, nil
108}
109
110// ExtractServiceCatalog returns the ServiceCatalog that was generated along with the user's Token.
111func (result CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) {
112 if result.Err != nil {
113 return nil, result.Err
114 }
115
116 var response struct {
117 Access struct {
118 Entries []CatalogEntry `mapstructure:"serviceCatalog"`
119 } `mapstructure:"access"`
120 }
121
122 err := mapstructure.Decode(result.Resp, &response)
123 if err != nil {
124 return nil, err
125 }
126
127 return &ServiceCatalog{Entries: response.Access.Entries}, nil
128}
129
130// createErr quickly packs an error in a CreateResult.
131func createErr(err error) CreateResult {
132 return CreateResult{gophercloud.CommonResult{Err: err}}
133}