blob: a8f413ed986fbe8d82aae2596d464e64a2a750b5 [file] [log] [blame]
Ash Wilson54b03822014-10-07 14:18:41 -04001package rackspace
2
3import (
Ash Wilson9e172e82014-10-07 16:42:39 -04004 "fmt"
Ash Wilson54b03822014-10-07 14:18:41 -04005
6 "github.com/rackspace/gophercloud"
7 os "github.com/rackspace/gophercloud/openstack"
Ash Wilson9e172e82014-10-07 16:42:39 -04008 "github.com/rackspace/gophercloud/openstack/utils"
9 tokens2 "github.com/rackspace/gophercloud/rackspace/identity/v2/tokens"
Ash Wilson54b03822014-10-07 14:18:41 -040010)
11
12const (
13 // RackspaceUSIdentity is an identity endpoint located in the United States.
14 RackspaceUSIdentity = "https://identity.api.rackspacecloud.com/v2.0/"
15
16 // RackspaceUKIdentity is an identity endpoint located in the UK.
17 RackspaceUKIdentity = "https://lon.identity.api.rackspacecloud.com/v2.0/"
18)
19
Ash Wilson9e172e82014-10-07 16:42:39 -040020const (
21 v20 = "v2.0"
22)
23
Ash Wilson54b03822014-10-07 14:18:41 -040024// NewClient creates a client that's prepared to communicate with the Rackspace API, but is not
25// yet authenticated. Most users will probably prefer using the AuthenticatedClient function
26// instead.
27//
28// Provide the base URL of the identity endpoint you wish to authenticate against as "endpoint".
29// Often, this will be either RackspaceUSIdentity or RackspaceUKIdentity.
30func NewClient(endpoint string) (*gophercloud.ProviderClient, error) {
Ash Wilson0d86a3e2014-10-09 11:00:21 -040031 if endpoint == "" {
32 return os.NewClient(RackspaceUSIdentity)
33 }
Ash Wilson54b03822014-10-07 14:18:41 -040034 return os.NewClient(endpoint)
35}
36
37// AuthenticatedClient logs in to Rackspace with the provided credentials and constructs a
38// ProviderClient that's ready to operate.
39//
40// If the provided AuthOptions does not specify an explicit IdentityEndpoint, it will default to
41// the canonical, production Rackspace US identity endpoint.
42func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) {
Ash Wilson9e172e82014-10-07 16:42:39 -040043 client, err := NewClient(options.IdentityEndpoint)
Ash Wilson54b03822014-10-07 14:18:41 -040044 if err != nil {
45 return nil, err
46 }
47
Ash Wilson9e172e82014-10-07 16:42:39 -040048 err = Authenticate(client, options)
49 if err != nil {
50 return nil, err
51 }
52 return client, nil
53}
54
55// Authenticate or re-authenticate against the most recent identity service supported at the
56// provided endpoint.
57func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
58 versions := []*utils.Version{
59 &utils.Version{ID: v20, Priority: 20, Suffix: "/v2.0/"},
60 }
61
Ash Wilson2491b4c2015-02-12 16:13:39 -050062 chosen, endpoint, err := utils.ChooseVersion(client, versions)
Ash Wilson9e172e82014-10-07 16:42:39 -040063 if err != nil {
64 return err
65 }
66
67 switch chosen.ID {
68 case v20:
69 return v2auth(client, endpoint, options)
70 default:
71 // The switch statement must be out of date from the versions list.
72 return fmt.Errorf("Unrecognized identity version: %s", chosen.ID)
73 }
74}
75
Ash Wilsonbab89ef2014-10-09 11:00:38 -040076// AuthenticateV2 explicitly authenticates with v2 of the identity service.
77func AuthenticateV2(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
78 return v2auth(client, "", options)
79}
80
Ash Wilson9e172e82014-10-07 16:42:39 -040081func v2auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions) error {
82 v2Client := NewIdentityV2(client)
83 if endpoint != "" {
84 v2Client.Endpoint = endpoint
85 }
86
87 result := tokens2.Create(v2Client, tokens2.WrapOptions(options))
88
89 token, err := result.ExtractToken()
90 if err != nil {
91 return err
92 }
93
94 catalog, err := result.ExtractServiceCatalog()
95 if err != nil {
96 return err
97 }
98
Jon Perrittf4052c62015-02-14 09:48:18 -070099 if options.AllowReauth {
Jon Perritt6fe7c402015-02-17 12:24:53 -0700100 client.ReauthFunc = func() error {
101 return AuthenticateV2(client, options)
102 }
Jon Perrittf4052c62015-02-14 09:48:18 -0700103 }
Ash Wilson9e172e82014-10-07 16:42:39 -0400104 client.TokenID = token.ID
105 client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
106 return os.V2EndpointURL(catalog, opts)
107 }
108
109 return nil
110}
111
112// NewIdentityV2 creates a ServiceClient that may be used to access the v2 identity service.
113func NewIdentityV2(client *gophercloud.ProviderClient) *gophercloud.ServiceClient {
114 v2Endpoint := client.IdentityBase + "v2.0/"
115
116 return &gophercloud.ServiceClient{
Ash Wilson13e7dc22014-10-22 09:26:40 -0400117 ProviderClient: client,
118 Endpoint: v2Endpoint,
Ash Wilson9e172e82014-10-07 16:42:39 -0400119 }
Ash Wilson54b03822014-10-07 14:18:41 -0400120}
Jon Perrittccc2e942014-10-15 18:01:21 -0500121
Ash Wilson2bc96b72014-10-20 15:16:10 -0400122// NewComputeV2 creates a ServiceClient that may be used to access the v2 compute service.
123func NewComputeV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
124 eo.ApplyDefaults("compute")
125 url, err := client.EndpointLocator(eo)
126 if err != nil {
127 return nil, err
128 }
Ash Wilsonbb3a3fd2014-10-22 08:16:31 -0400129
Ash Wilson2bc96b72014-10-20 15:16:10 -0400130 return &gophercloud.ServiceClient{
Ash Wilsona93ac3f2014-10-22 14:33:25 -0400131 ProviderClient: client,
132 Endpoint: url,
Ash Wilson2bc96b72014-10-20 15:16:10 -0400133 }, nil
134}
Ash Wilsonbb3a3fd2014-10-22 08:16:31 -0400135
Jon Perrittccc2e942014-10-15 18:01:21 -0500136// NewObjectCDNV1 creates a ServiceClient that may be used with the Rackspace v1 CDN.
137func NewObjectCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
138 eo.ApplyDefaults("rax:object-cdn")
139 url, err := client.EndpointLocator(eo)
140 if err != nil {
141 return nil, err
142 }
Ash Wilson13e7dc22014-10-22 09:26:40 -0400143 return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
Jon Perrittccc2e942014-10-15 18:01:21 -0500144}
145
146// NewObjectStorageV1 creates a ServiceClient that may be used with the Rackspace v1 object storage package.
147func NewObjectStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
148 return os.NewObjectStorageV1(client, eo)
149}
Jamie Hannafordf8ef9862014-10-22 12:37:38 +0200150
151// NewBlockStorageV1 creates a ServiceClient that can be used to access the
152// Rackspace Cloud Block Storage v1 API.
153func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
Jamie Hannaford390ff522014-10-23 14:46:48 +0200154 eo.ApplyDefaults("volume")
Jamie Hannafordf8ef9862014-10-22 12:37:38 +0200155 url, err := client.EndpointLocator(eo)
156 if err != nil {
157 return nil, err
158 }
159
160 return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
161}
Jamie Hannaford1ede18f2014-11-05 12:37:52 +0100162
163// NewLBV1 creates a ServiceClient that can be used to access the Rackspace
164// Cloud Load Balancer v1 API.
165func NewLBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
166 eo.ApplyDefaults("rax:load-balancer")
167 url, err := client.EndpointLocator(eo)
168 if err != nil {
169 return nil, err
170 }
171 return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
172}
Jon Perritt53c8a3a2014-11-24 07:46:35 -0700173
174// NewNetworkV2 creates a ServiceClient that can be used to access the Rackspace
175// Networking v2 API.
176func NewNetworkV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
177 eo.ApplyDefaults("network")
178 url, err := client.EndpointLocator(eo)
179 if err != nil {
180 return nil, err
181 }
182 return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
183}
Jon Perrittf36970b2015-01-16 09:13:45 -0700184
185// NewCDNV1 creates a ServiceClient that may be used to access the Rackspace v1
186// CDN service.
187func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
188 eo.ApplyDefaults("rax:cdn")
189 url, err := client.EndpointLocator(eo)
190 if err != nil {
191 return nil, err
192 }
193 return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
194}
Jon Perrittf76605e2015-02-09 16:33:35 -0700195
196// NewOrchestrationV1 creates a ServiceClient that may be used to access the v1 orchestration service.
197func NewOrchestrationV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
198 eo.ApplyDefaults("orchestration")
199 url, err := client.EndpointLocator(eo)
200 if err != nil {
201 return nil, err
202 }
203 return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
204}
Jon Perritt33534732015-03-16 10:23:22 -0600205
206// NewRackConnectV3 creates a ServiceClient that may be used to access the v3 RackConnect service.
207func NewRackConnectV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
208 eo.ApplyDefaults("rax:rackconnect")
209 url, err := client.EndpointLocator(eo)
210 if err != nil {
211 return nil, err
212 }
213 return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
214}
Jamie Hannaford05d200d2015-02-20 14:49:05 +0100215
Jamie Hannaford75e8cc42015-11-16 14:09:25 +0100216// NewDBV1 creates a ServiceClient that may be used to access the v1 DB service.
Jamie Hannaford05d200d2015-02-20 14:49:05 +0100217func NewDBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
Jamie Hannaford42a5c6f2015-03-02 15:24:07 +0100218 eo.ApplyDefaults("rax:database")
Jamie Hannaford05d200d2015-02-20 14:49:05 +0100219 url, err := client.EndpointLocator(eo)
220 if err != nil {
221 return nil, err
222 }
223 return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
224}