blob: 3903e3964b7979306b09155f05365da25a55a566 [file] [log] [blame]
Ash Wilson1f110512014-10-02 15:43:47 -04001package 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
hzlouchaob7640892015-11-04 21:37:20 +080026
27 // the owner user of token
28 UserName string
29 UserID string
Ash Wilson1f110512014-10-02 15:43:47 -040030}
31
Ash Wilsonab48bbc2014-10-03 09:57:03 -040032// Endpoint represents a single API endpoint offered by a service.
33// It provides the public and internal URLs, if supported, along with a region specifier, again if provided.
34// The significance of the Region field will depend upon your provider.
35//
36// In addition, the interface offered by the service will have version information associated with it
37// through the VersionId, VersionInfo, and VersionList fields, if provided or supported.
38//
39// In all cases, fields which aren't supported by the provider and service combined will assume a zero-value ("").
40type Endpoint struct {
41 TenantID string `mapstructure:"tenantId"`
42 PublicURL string `mapstructure:"publicURL"`
43 InternalURL string `mapstructure:"internalURL"`
44 AdminURL string `mapstructure:"adminURL"`
45 Region string `mapstructure:"region"`
46 VersionID string `mapstructure:"versionId"`
47 VersionInfo string `mapstructure:"versionInfo"`
48 VersionList string `mapstructure:"versionList"`
49}
50
51// CatalogEntry provides a type-safe interface to an Identity API V2 service catalog listing.
52// Each class of service, such as cloud DNS or block storage services, will have a single
53// CatalogEntry representing it.
54//
55// Note: when looking for the desired service, try, whenever possible, to key off the type field.
56// Otherwise, you'll tie the representation of the service to a specific provider.
57type CatalogEntry struct {
58 // Name will contain the provider-specified name for the service.
59 Name string `mapstructure:"name"`
60
61 // Type will contain a type string if OpenStack defines a type for the service.
62 // Otherwise, for provider-specific services, the provider may assign their own type strings.
63 Type string `mapstructure:"type"`
64
65 // Endpoints will let the caller iterate over all the different endpoints that may exist for
66 // the service.
67 Endpoints []Endpoint `mapstructure:"endpoints"`
68}
69
70// ServiceCatalog provides a view into the service catalog from a previous, successful authentication.
71type ServiceCatalog struct {
72 Entries []CatalogEntry
73}
74
Ash Wilson1f110512014-10-02 15:43:47 -040075// CreateResult defers the interpretation of a created token.
76// Use ExtractToken() to interpret it as a Token, or ExtractServiceCatalog() to interpret it as a service catalog.
77type CreateResult struct {
Ash Wilsonf548aad2014-10-20 08:35:34 -040078 gophercloud.Result
Ash Wilson1f110512014-10-02 15:43:47 -040079}
80
hzlouchaof6e29262015-10-27 12:51:08 +080081// GetResult is the deferred response from a Get call.
82type GetResult struct {
hzlouchaob7640892015-11-04 21:37:20 +080083 gophercloud.Result
hzlouchaof6e29262015-10-27 12:51:08 +080084}
85
Ash Wilson1f110512014-10-02 15:43:47 -040086// ExtractToken returns the just-created Token from a CreateResult.
87func (result CreateResult) ExtractToken() (*Token, error) {
Ash Wilson27d29e22014-10-03 11:57:14 -040088 if result.Err != nil {
89 return nil, result.Err
90 }
91
Ash Wilson1f110512014-10-02 15:43:47 -040092 var response struct {
93 Access struct {
94 Token struct {
95 Expires string `mapstructure:"expires"`
96 ID string `mapstructure:"id"`
97 Tenant tenants.Tenant `mapstructure:"tenant"`
98 } `mapstructure:"token"`
99 } `mapstructure:"access"`
100 }
101
Ash Wilsond3dc2542014-10-20 10:10:48 -0400102 err := mapstructure.Decode(result.Body, &response)
Ash Wilson1f110512014-10-02 15:43:47 -0400103 if err != nil {
104 return nil, err
105 }
106
107 expiresTs, err := time.Parse(gophercloud.RFC3339Milli, response.Access.Token.Expires)
108 if err != nil {
109 return nil, err
110 }
111
112 return &Token{
113 ID: response.Access.Token.ID,
114 ExpiresAt: expiresTs,
115 Tenant: response.Access.Token.Tenant,
116 }, nil
117}
118
Ash Wilsonab48bbc2014-10-03 09:57:03 -0400119// ExtractServiceCatalog returns the ServiceCatalog that was generated along with the user's Token.
120func (result CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) {
Ash Wilson27d29e22014-10-03 11:57:14 -0400121 if result.Err != nil {
122 return nil, result.Err
123 }
124
Ash Wilsonab48bbc2014-10-03 09:57:03 -0400125 var response struct {
126 Access struct {
127 Entries []CatalogEntry `mapstructure:"serviceCatalog"`
128 } `mapstructure:"access"`
129 }
130
Ash Wilsond3dc2542014-10-20 10:10:48 -0400131 err := mapstructure.Decode(result.Body, &response)
Ash Wilsonab48bbc2014-10-03 09:57:03 -0400132 if err != nil {
133 return nil, err
134 }
135
136 return &ServiceCatalog{Entries: response.Access.Entries}, nil
137}
138
Ash Wilson1f110512014-10-02 15:43:47 -0400139// createErr quickly packs an error in a CreateResult.
140func createErr(err error) CreateResult {
Ash Wilsonf548aad2014-10-20 08:35:34 -0400141 return CreateResult{gophercloud.Result{Err: err}}
Ash Wilson1f110512014-10-02 15:43:47 -0400142}
hzlouchaob7640892015-11-04 21:37:20 +0800143
144// ExtractToken returns the Token from a GetResult.
145func (result GetResult) ExtractToken() (*Token, error) {
146 if result.Err != nil {
147 return nil, result.Err
148 }
149
150 var response struct {
151 Access struct {
152 Token struct {
153 Expires string `mapstructure:"expires"`
154 ID string `mapstructure:"id"`
155 } `mapstructure:"token"`
156 User struct {
157 ID string `mapstructure:"id"`
158 Name string `mapstructure:"name"`
159 } `mapstructure:"user"`
160 } `mapstructure:"access"`
161 }
162
163 err := mapstructure.Decode(result.Body, &response)
164 if err != nil {
165 return nil, err
166 }
167
168 expiresTs, err := time.Parse(gophercloud.RFC3339Milli, response.Access.Token.Expires)
169 if err != nil {
170 return nil, err
171 }
172
173 return &Token{
174 ID: response.Access.Token.ID,
175 ExpiresAt: expiresTs,
176 UserID: response.Access.User.ID,
177 UserName: response.Access.User.Name,
178 }, nil
179}