blob: ebad36c92b66599a7f2c019ebda6aba82e02ec24 [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"
5)
6
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -07007// Provider structures exist for each tangible provider of OpenStack service.
8// For example, Rackspace, Hewlett-Packard, and NASA might have their own instance of this structure.
9//
10// At a minimum, a provider must expose an authentication endpoint.
11type Provider struct {
12 AuthEndpoint string
13}
14
Samuel A. Falvo II1206f852013-07-15 17:56:51 -070015// ReauthHandlerFunc functions are responsible for somehow performing the task of
16// reauthentication.
Samuel A. Falvo II2f50b142013-07-16 11:38:03 -070017type ReauthHandlerFunc func(AccessProvider) error
Samuel A. Falvo II1206f852013-07-15 17:56:51 -070018
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070019// Context structures encapsulate Gophercloud-global state in a manner which
20// facilitates easier unit testing. As a user of this SDK, you'll never
21// have to use this structure, except when contributing new code to the SDK.
Samuel A. Falvo IIfd78c302013-06-25 16:35:32 -070022type Context struct {
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070023 // providerMap serves as a directory of supported providers.
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070024 providerMap map[string]Provider
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070025
26 // httpClient refers to the current HTTP client interface to use.
27 httpClient *http.Client
Samuel A. Falvo II1206f852013-07-15 17:56:51 -070028
29 // reauthHandler provides the functionality needed to re-authenticate
30 // if that feature is enabled. Note: in order to allow for automatic
31 // re-authentication, the Context object will need to remember your
32 // username, password, and tenant ID as provided in the initial call
33 // to Authenticate(). If you do not desire this, you'll need to handle
34 // reauthentication yourself through other means. Two methods exist:
35 // the first approach is to just handle errors yourself at the application
36 // layer, and the other is through a custom reauthentication handler
37 // set through the WithReauthHandler() method.
38 reauthHandler ReauthHandlerFunc
Samuel A. Falvo IIfd78c302013-06-25 16:35:32 -070039}
40
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070041// TestContext yields a new Context instance, pre-initialized with a barren
42// state suitable for per-unit-test customization. This configuration consists
43// of:
44//
45// * An empty provider map.
46//
47// * 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 -070048func TestContext() *Context {
49 return &Context{
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070050 providerMap: make(map[string]Provider),
Samuel A. Falvo II839428e2013-06-25 18:02:24 -070051 httpClient: &http.Client{},
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -070052 reauthHandler: func(acc AccessProvider) error {
53 return acc.Reauthenticate()
54 },
Samuel A. Falvo IIfd78c302013-06-25 16:35:32 -070055 }
56}
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070057
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070058// UseCustomClient configures the context to use a customized HTTP client
59// instance. By default, TestContext() will return a Context which uses
Samuel A. Falvo IIfca35b72013-07-02 18:30:28 -070060// the net/http package's default client instance.
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -070061func (c *Context) UseCustomClient(hc *http.Client) *Context {
Samuel A. Falvo II839428e2013-06-25 18:02:24 -070062 c.httpClient = hc
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -070063 return c
64}
65
66// RegisterProvider allows a unit test to register a mythical provider convenient for testing.
67// If the provider structure lacks adequate configuration, or the configuration given has some
68// detectable error, an ErrConfiguration error will result.
69func (c *Context) RegisterProvider(name string, p Provider) error {
70 if p.AuthEndpoint == "" {
71 return ErrConfiguration
72 }
73
74 c.providerMap[name] = p
75 return nil
76}
77
78// WithProvider offers convenience for unit tests.
79func (c *Context) WithProvider(name string, p Provider) *Context {
80 err := c.RegisterProvider(name, p)
81 if err != nil {
82 panic(err)
83 }
84 return c
85}
86
87// ProviderByName will locate a provider amongst those previously registered, if it exists.
88// If the named provider has not been registered, an ErrProvider error will result.
89func (c *Context) ProviderByName(name string) (p Provider, err error) {
90 for provider, descriptor := range c.providerMap {
91 if name == provider {
92 return descriptor, nil
93 }
94 }
95 return Provider{}, ErrProvider
96}
97
Samuel A. Falvo II1dd740a2013-07-08 15:48:40 -070098// Instantiates a Cloud Servers API for the provider given.
99func (c *Context) ServersApi(acc AccessProvider, criteria ApiCriteria) (CloudServersProvider, error) {
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -0700100 url := acc.FirstEndpointUrlByCriteria(criteria)
101 if url == "" {
102 return nil, ErrEndpoint
103 }
104
Samuel A. Falvo II1dd740a2013-07-08 15:48:40 -0700105 gcp := &genericServersProvider{
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -0700106 endpoint: url,
107 context: c,
Samuel A. Falvo IIbc0d54a2013-07-08 14:45:21 -0700108 access: acc,
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -0700109 }
110
111 return gcp, nil
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -0700112}
Samuel A. Falvo II1206f852013-07-15 17:56:51 -0700113
114// WithReauthHandler configures the context to handle reauthentication attempts using the supplied
115// funtion. By default, reauthentication happens by invoking Authenticate(), which is unlikely to be
116// useful in a unit test.
117//
118// Do not confuse this function with WithReauth()! Although they work together to support reauthentication,
119// WithReauth() actually contains the decision-making logic to determine when to perform a reauth,
120// while WithReauthHandler() is used to configure what a reauth actually entails.
121func (c *Context) WithReauthHandler(f ReauthHandlerFunc) *Context {
122 c.reauthHandler = f
123 return c
124}