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 | |
| 62 | chosen, endpoint, err := utils.ChooseVersion(client.IdentityBase, client.IdentityEndpoint, versions) |
| 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 | |
| 99 | client.TokenID = token.ID |
| 100 | client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) { |
| 101 | return os.V2EndpointURL(catalog, opts) |
| 102 | } |
| 103 | |
| 104 | return nil |
| 105 | } |
| 106 | |
| 107 | // NewIdentityV2 creates a ServiceClient that may be used to access the v2 identity service. |
| 108 | func NewIdentityV2(client *gophercloud.ProviderClient) *gophercloud.ServiceClient { |
| 109 | v2Endpoint := client.IdentityBase + "v2.0/" |
| 110 | |
| 111 | return &gophercloud.ServiceClient{ |
Ash Wilson | 13e7dc2 | 2014-10-22 09:26:40 -0400 | [diff] [blame] | 112 | ProviderClient: client, |
| 113 | Endpoint: v2Endpoint, |
Ash Wilson | 9e172e8 | 2014-10-07 16:42:39 -0400 | [diff] [blame] | 114 | } |
Ash Wilson | 54b0382 | 2014-10-07 14:18:41 -0400 | [diff] [blame] | 115 | } |
Jon Perritt | ccc2e94 | 2014-10-15 18:01:21 -0500 | [diff] [blame] | 116 | |
Ash Wilson | 2bc96b7 | 2014-10-20 15:16:10 -0400 | [diff] [blame] | 117 | // NewComputeV2 creates a ServiceClient that may be used to access the v2 compute service. |
| 118 | func NewComputeV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { |
| 119 | eo.ApplyDefaults("compute") |
| 120 | url, err := client.EndpointLocator(eo) |
| 121 | if err != nil { |
| 122 | return nil, err |
| 123 | } |
Ash Wilson | bb3a3fd | 2014-10-22 08:16:31 -0400 | [diff] [blame] | 124 | |
Ash Wilson | 2bc96b7 | 2014-10-20 15:16:10 -0400 | [diff] [blame] | 125 | return &gophercloud.ServiceClient{ |
Ash Wilson | a93ac3f | 2014-10-22 14:33:25 -0400 | [diff] [blame] | 126 | ProviderClient: client, |
| 127 | Endpoint: url, |
Ash Wilson | 2bc96b7 | 2014-10-20 15:16:10 -0400 | [diff] [blame] | 128 | }, nil |
| 129 | } |
Ash Wilson | bb3a3fd | 2014-10-22 08:16:31 -0400 | [diff] [blame] | 130 | |
Jon Perritt | ccc2e94 | 2014-10-15 18:01:21 -0500 | [diff] [blame] | 131 | // NewObjectCDNV1 creates a ServiceClient that may be used with the Rackspace v1 CDN. |
| 132 | func NewObjectCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { |
| 133 | eo.ApplyDefaults("rax:object-cdn") |
| 134 | url, err := client.EndpointLocator(eo) |
| 135 | if err != nil { |
| 136 | return nil, err |
| 137 | } |
Ash Wilson | 13e7dc2 | 2014-10-22 09:26:40 -0400 | [diff] [blame] | 138 | return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil |
Jon Perritt | ccc2e94 | 2014-10-15 18:01:21 -0500 | [diff] [blame] | 139 | } |
| 140 | |
| 141 | // NewObjectStorageV1 creates a ServiceClient that may be used with the Rackspace v1 object storage package. |
| 142 | func NewObjectStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { |
| 143 | return os.NewObjectStorageV1(client, eo) |
| 144 | } |
Jamie Hannaford | f8ef986 | 2014-10-22 12:37:38 +0200 | [diff] [blame] | 145 | |
| 146 | // NewBlockStorageV1 creates a ServiceClient that can be used to access the |
| 147 | // Rackspace Cloud Block Storage v1 API. |
| 148 | func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { |
Jamie Hannaford | 390ff52 | 2014-10-23 14:46:48 +0200 | [diff] [blame] | 149 | eo.ApplyDefaults("volume") |
Jamie Hannaford | f8ef986 | 2014-10-22 12:37:38 +0200 | [diff] [blame] | 150 | url, err := client.EndpointLocator(eo) |
| 151 | if err != nil { |
| 152 | return nil, err |
| 153 | } |
| 154 | |
| 155 | return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil |
| 156 | } |
Jamie Hannaford | 1ede18f | 2014-11-05 12:37:52 +0100 | [diff] [blame] | 157 | |
| 158 | // NewLBV1 creates a ServiceClient that can be used to access the Rackspace |
| 159 | // Cloud Load Balancer v1 API. |
| 160 | func NewLBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { |
| 161 | eo.ApplyDefaults("rax:load-balancer") |
| 162 | url, err := client.EndpointLocator(eo) |
| 163 | if err != nil { |
| 164 | return nil, err |
| 165 | } |
| 166 | return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil |
| 167 | } |
Jon Perritt | 53c8a3a | 2014-11-24 07:46:35 -0700 | [diff] [blame] | 168 | |
| 169 | // NewNetworkV2 creates a ServiceClient that can be used to access the Rackspace |
| 170 | // Networking v2 API. |
| 171 | func NewNetworkV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { |
| 172 | eo.ApplyDefaults("network") |
| 173 | url, err := client.EndpointLocator(eo) |
| 174 | if err != nil { |
| 175 | return nil, err |
| 176 | } |
| 177 | return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil |
| 178 | } |
Jon Perritt | f36970b | 2015-01-16 09:13:45 -0700 | [diff] [blame] | 179 | |
| 180 | // NewCDNV1 creates a ServiceClient that may be used to access the Rackspace v1 |
| 181 | // CDN service. |
| 182 | func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { |
| 183 | eo.ApplyDefaults("rax:cdn") |
| 184 | url, err := client.EndpointLocator(eo) |
| 185 | if err != nil { |
| 186 | return nil, err |
| 187 | } |
| 188 | return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil |
| 189 | } |