Ash Wilson | 54b0382 | 2014-10-07 14:18:41 -0400 | [diff] [blame] | 1 | package rackspace |
| 2 | |
| 3 | import ( |
Ash Wilson | 9e172e8 | 2014-10-07 16:42:39 -0400 | [diff] [blame] | 4 | "fmt" |
Ash Wilson | 54b0382 | 2014-10-07 14:18:41 -0400 | [diff] [blame] | 5 | |
| 6 | "github.com/rackspace/gophercloud" |
| 7 | os "github.com/rackspace/gophercloud/openstack" |
Ash Wilson | 9e172e8 | 2014-10-07 16:42:39 -0400 | [diff] [blame] | 8 | "github.com/rackspace/gophercloud/openstack/utils" |
| 9 | tokens2 "github.com/rackspace/gophercloud/rackspace/identity/v2/tokens" |
Ash Wilson | 54b0382 | 2014-10-07 14:18:41 -0400 | [diff] [blame] | 10 | ) |
| 11 | |
| 12 | const ( |
| 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 Wilson | 9e172e8 | 2014-10-07 16:42:39 -0400 | [diff] [blame] | 20 | const ( |
| 21 | v20 = "v2.0" |
| 22 | ) |
| 23 | |
Ash Wilson | 54b0382 | 2014-10-07 14:18:41 -0400 | [diff] [blame] | 24 | // 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. |
| 30 | func NewClient(endpoint string) (*gophercloud.ProviderClient, error) { |
Ash Wilson | 0d86a3e | 2014-10-09 11:00:21 -0400 | [diff] [blame] | 31 | if endpoint == "" { |
| 32 | return os.NewClient(RackspaceUSIdentity) |
| 33 | } |
Ash Wilson | 54b0382 | 2014-10-07 14:18:41 -0400 | [diff] [blame] | 34 | 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. |
| 42 | func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) { |
Ash Wilson | 9e172e8 | 2014-10-07 16:42:39 -0400 | [diff] [blame] | 43 | client, err := NewClient(options.IdentityEndpoint) |
Ash Wilson | 54b0382 | 2014-10-07 14:18:41 -0400 | [diff] [blame] | 44 | if err != nil { |
| 45 | return nil, err |
| 46 | } |
| 47 | |
Ash Wilson | 9e172e8 | 2014-10-07 16:42:39 -0400 | [diff] [blame] | 48 | 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. |
| 57 | func 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 Wilson | 2491b4c | 2015-02-12 16:13:39 -0500 | [diff] [blame] | 62 | chosen, endpoint, err := utils.ChooseVersion(client, versions) |
Ash Wilson | 9e172e8 | 2014-10-07 16:42:39 -0400 | [diff] [blame] | 63 | 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 Wilson | bab89ef | 2014-10-09 11:00:38 -0400 | [diff] [blame] | 76 | // AuthenticateV2 explicitly authenticates with v2 of the identity service. |
| 77 | func AuthenticateV2(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error { |
| 78 | return v2auth(client, "", options) |
| 79 | } |
| 80 | |
Ash Wilson | 9e172e8 | 2014-10-07 16:42:39 -0400 | [diff] [blame] | 81 | func 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 Perritt | f4052c6 | 2015-02-14 09:48:18 -0700 | [diff] [blame] | 99 | if options.AllowReauth { |
Jon Perritt | 6fe7c40 | 2015-02-17 12:24:53 -0700 | [diff] [blame] | 100 | client.ReauthFunc = func() error { |
| 101 | return AuthenticateV2(client, options) |
| 102 | } |
Jon Perritt | f4052c6 | 2015-02-14 09:48:18 -0700 | [diff] [blame] | 103 | } |
Ash Wilson | 9e172e8 | 2014-10-07 16:42:39 -0400 | [diff] [blame] | 104 | 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. |
| 113 | func NewIdentityV2(client *gophercloud.ProviderClient) *gophercloud.ServiceClient { |
| 114 | v2Endpoint := client.IdentityBase + "v2.0/" |
| 115 | |
| 116 | return &gophercloud.ServiceClient{ |
Ash Wilson | 13e7dc2 | 2014-10-22 09:26:40 -0400 | [diff] [blame] | 117 | ProviderClient: client, |
| 118 | Endpoint: v2Endpoint, |
Ash Wilson | 9e172e8 | 2014-10-07 16:42:39 -0400 | [diff] [blame] | 119 | } |
Ash Wilson | 54b0382 | 2014-10-07 14:18:41 -0400 | [diff] [blame] | 120 | } |
Jon Perritt | ccc2e94 | 2014-10-15 18:01:21 -0500 | [diff] [blame] | 121 | |
Ash Wilson | 2bc96b7 | 2014-10-20 15:16:10 -0400 | [diff] [blame] | 122 | // NewComputeV2 creates a ServiceClient that may be used to access the v2 compute service. |
| 123 | func 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 Wilson | bb3a3fd | 2014-10-22 08:16:31 -0400 | [diff] [blame] | 129 | |
Ash Wilson | 2bc96b7 | 2014-10-20 15:16:10 -0400 | [diff] [blame] | 130 | return &gophercloud.ServiceClient{ |
Ash Wilson | a93ac3f | 2014-10-22 14:33:25 -0400 | [diff] [blame] | 131 | ProviderClient: client, |
| 132 | Endpoint: url, |
Ash Wilson | 2bc96b7 | 2014-10-20 15:16:10 -0400 | [diff] [blame] | 133 | }, nil |
| 134 | } |
Ash Wilson | bb3a3fd | 2014-10-22 08:16:31 -0400 | [diff] [blame] | 135 | |
Jon Perritt | ccc2e94 | 2014-10-15 18:01:21 -0500 | [diff] [blame] | 136 | // NewObjectCDNV1 creates a ServiceClient that may be used with the Rackspace v1 CDN. |
| 137 | func 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 Wilson | 13e7dc2 | 2014-10-22 09:26:40 -0400 | [diff] [blame] | 143 | return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil |
Jon Perritt | ccc2e94 | 2014-10-15 18:01:21 -0500 | [diff] [blame] | 144 | } |
| 145 | |
| 146 | // NewObjectStorageV1 creates a ServiceClient that may be used with the Rackspace v1 object storage package. |
| 147 | func NewObjectStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { |
| 148 | return os.NewObjectStorageV1(client, eo) |
| 149 | } |
Jamie Hannaford | f8ef986 | 2014-10-22 12:37:38 +0200 | [diff] [blame] | 150 | |
| 151 | // NewBlockStorageV1 creates a ServiceClient that can be used to access the |
| 152 | // Rackspace Cloud Block Storage v1 API. |
| 153 | func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { |
Jamie Hannaford | 390ff52 | 2014-10-23 14:46:48 +0200 | [diff] [blame] | 154 | eo.ApplyDefaults("volume") |
Jamie Hannaford | f8ef986 | 2014-10-22 12:37:38 +0200 | [diff] [blame] | 155 | 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 Hannaford | 1ede18f | 2014-11-05 12:37:52 +0100 | [diff] [blame] | 162 | |
| 163 | // NewLBV1 creates a ServiceClient that can be used to access the Rackspace |
| 164 | // Cloud Load Balancer v1 API. |
| 165 | func 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 Perritt | 53c8a3a | 2014-11-24 07:46:35 -0700 | [diff] [blame] | 173 | |
| 174 | // NewNetworkV2 creates a ServiceClient that can be used to access the Rackspace |
| 175 | // Networking v2 API. |
| 176 | func 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 Perritt | f36970b | 2015-01-16 09:13:45 -0700 | [diff] [blame] | 184 | |
| 185 | // NewCDNV1 creates a ServiceClient that may be used to access the Rackspace v1 |
| 186 | // CDN service. |
| 187 | func 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 Perritt | f76605e | 2015-02-09 16:33:35 -0700 | [diff] [blame] | 195 | |
| 196 | // NewOrchestrationV1 creates a ServiceClient that may be used to access the v1 orchestration service. |
| 197 | func 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 Perritt | 3353473 | 2015-03-16 10:23:22 -0600 | [diff] [blame] | 205 | |
| 206 | // NewRackConnectV3 creates a ServiceClient that may be used to access the v3 RackConnect service. |
| 207 | func 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 Hannaford | 05d200d | 2015-02-20 14:49:05 +0100 | [diff] [blame] | 215 | |
Jamie Hannaford | 75e8cc4 | 2015-11-16 14:09:25 +0100 | [diff] [blame] | 216 | // NewDBV1 creates a ServiceClient that may be used to access the v1 DB service. |
Jamie Hannaford | 05d200d | 2015-02-20 14:49:05 +0100 | [diff] [blame] | 217 | func NewDBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { |
Jamie Hannaford | 42a5c6f | 2015-03-02 15:24:07 +0100 | [diff] [blame] | 218 | eo.ApplyDefaults("rax:database") |
Jamie Hannaford | 05d200d | 2015-02-20 14:49:05 +0100 | [diff] [blame] | 219 | url, err := client.EndpointLocator(eo) |
| 220 | if err != nil { |
| 221 | return nil, err |
| 222 | } |
| 223 | return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil |
| 224 | } |