blob: a41cc6d95bf6a541c9118162c48e33c95268bdec [file] [log] [blame]
Samuel A. Falvo IIfd78c302013-06-25 16:35:32 -07001package gophercloud
2
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -07003import (
4 "net/http"
Justin Santa Barbara23f2a3a2013-08-31 17:54:59 -07005 "strings"
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -07006)
7
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -07008// Provider structures exist for each tangible provider of OpenStack service.
9// For example, Rackspace, Hewlett-Packard, and NASA might have their own instance of this structure.
10//
11// At a minimum, a provider must expose an authentication endpoint.
12type Provider struct {
13 AuthEndpoint string
14}
15
Samuel A. Falvo II1206f852013-07-15 17:56:51 -070016// ReauthHandlerFunc functions are responsible for somehow performing the task of
17// reauthentication.
Samuel A. Falvo II2f50b142013-07-16 11:38:03 -070018type ReauthHandlerFunc func(AccessProvider) error
Samuel A. Falvo II1206f852013-07-15 17:56:51 -070019
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070020// Context structures encapsulate Gophercloud-global state in a manner which
21// facilitates easier unit testing. As a user of this SDK, you'll never
22// have to use this structure, except when contributing new code to the SDK.
Samuel A. Falvo IIfd78c302013-06-25 16:35:32 -070023type Context struct {
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070024 // providerMap serves as a directory of supported providers.
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070025 providerMap map[string]Provider
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070026
27 // httpClient refers to the current HTTP client interface to use.
28 httpClient *http.Client
Samuel A. Falvo II1206f852013-07-15 17:56:51 -070029
30 // reauthHandler provides the functionality needed to re-authenticate
31 // if that feature is enabled. Note: in order to allow for automatic
32 // re-authentication, the Context object will need to remember your
33 // username, password, and tenant ID as provided in the initial call
34 // to Authenticate(). If you do not desire this, you'll need to handle
35 // reauthentication yourself through other means. Two methods exist:
36 // the first approach is to just handle errors yourself at the application
37 // layer, and the other is through a custom reauthentication handler
38 // set through the WithReauthHandler() method.
39 reauthHandler ReauthHandlerFunc
Samuel A. Falvo IIfd78c302013-06-25 16:35:32 -070040}
41
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070042// TestContext yields a new Context instance, pre-initialized with a barren
43// state suitable for per-unit-test customization. This configuration consists
44// of:
45//
46// * An empty provider map.
47//
48// * An HTTP client built by the net/http package (see http://godoc.org/net/http#Client).
Samuel A. Falvo IIfd78c302013-06-25 16:35:32 -070049func TestContext() *Context {
50 return &Context{
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070051 providerMap: make(map[string]Provider),
Samuel A. Falvo II839428e2013-06-25 18:02:24 -070052 httpClient: &http.Client{},
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -070053 reauthHandler: func(acc AccessProvider) error {
54 return acc.Reauthenticate()
55 },
Samuel A. Falvo IIfd78c302013-06-25 16:35:32 -070056 }
57}
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070058
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070059// UseCustomClient configures the context to use a customized HTTP client
60// instance. By default, TestContext() will return a Context which uses
Samuel A. Falvo IIfca35b72013-07-02 18:30:28 -070061// the net/http package's default client instance.
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -070062func (c *Context) UseCustomClient(hc *http.Client) *Context {
Samuel A. Falvo II839428e2013-06-25 18:02:24 -070063 c.httpClient = hc
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -070064 return c
65}
66
67// RegisterProvider allows a unit test to register a mythical provider convenient for testing.
68// If the provider structure lacks adequate configuration, or the configuration given has some
69// detectable error, an ErrConfiguration error will result.
70func (c *Context) RegisterProvider(name string, p Provider) error {
71 if p.AuthEndpoint == "" {
72 return ErrConfiguration
73 }
74
75 c.providerMap[name] = p
76 return nil
77}
78
79// WithProvider offers convenience for unit tests.
80func (c *Context) WithProvider(name string, p Provider) *Context {
81 err := c.RegisterProvider(name, p)
82 if err != nil {
83 panic(err)
84 }
85 return c
86}
87
88// ProviderByName will locate a provider amongst those previously registered, if it exists.
89// If the named provider has not been registered, an ErrProvider error will result.
Samuel A. Falvo II32d297d2013-10-24 16:45:58 -070090//
91// You may also specify a custom Identity API URL.
92// Any provider name that contains the characters "://", in that order, will be treated as a custom Identity API URL.
93// Custom URLs, important for private cloud deployments, overrides all provider configurations.
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -070094func (c *Context) ProviderByName(name string) (p Provider, err error) {
95 for provider, descriptor := range c.providerMap {
96 if name == provider {
97 return descriptor, nil
98 }
99 }
Justin Santa Barbara23f2a3a2013-08-31 17:54:59 -0700100 if strings.Contains(name, "://") {
Jon Perritt0c1629d2013-12-06 19:51:36 -0600101 p = Provider{
Justin Santa Barbara23f2a3a2013-08-31 17:54:59 -0700102 AuthEndpoint: name,
103 }
104 return p, nil
105 }
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -0700106 return Provider{}, ErrProvider
107}
108
Samuel A. Falvo II1dd740a2013-07-08 15:48:40 -0700109// Instantiates a Cloud Servers API for the provider given.
110func (c *Context) ServersApi(acc AccessProvider, criteria ApiCriteria) (CloudServersProvider, error) {
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -0700111 url := acc.FirstEndpointUrlByCriteria(criteria)
112 if url == "" {
113 return nil, ErrEndpoint
114 }
115
Samuel A. Falvo II1dd740a2013-07-08 15:48:40 -0700116 gcp := &genericServersProvider{
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -0700117 endpoint: url,
118 context: c,
Samuel A. Falvo IIbc0d54a2013-07-08 14:45:21 -0700119 access: acc,
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -0700120 }
121
122 return gcp, nil
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -0700123}
Samuel A. Falvo II1206f852013-07-15 17:56:51 -0700124
125// WithReauthHandler configures the context to handle reauthentication attempts using the supplied
126// funtion. By default, reauthentication happens by invoking Authenticate(), which is unlikely to be
127// useful in a unit test.
128//
129// Do not confuse this function with WithReauth()! Although they work together to support reauthentication,
130// WithReauth() actually contains the decision-making logic to determine when to perform a reauth,
131// while WithReauthHandler() is used to configure what a reauth actually entails.
132func (c *Context) WithReauthHandler(f ReauthHandlerFunc) *Context {
133 c.reauthHandler = f
134 return c
135}