blob: 069d4c9afb4ccf03478cbe663ec7f030d2a777ed [file] [log] [blame]
package gophercloud
import "strings"
// globalContext is the, well, "global context."
// Most of this SDK is written in a manner to facilitate easier testing,
// which doesn't require all the configuration a real-world application would require.
// However, for real-world deployments, applications should be able to rely on a consistent configuration of providers, etc.
var globalContext *Context
// providers is the set of supported providers.
var providers = map[string]Provider{
"rackspace-us": Provider{
AuthEndpoint: "https://identity.api.rackspacecloud.com/v2.0/tokens",
},
"rackspace-uk": Provider{
AuthEndpoint: "https://lon.identity.api.rackspacecloud.com/v2.0/tokens",
},
}
// Initialize the global context to sane configuration.
// The Go runtime ensures this function is called before main(),
// thus guaranteeing proper configuration before your application ever runs.
func init() {
globalContext = TestContext()
for name, descriptor := range providers {
globalContext.RegisterProvider(name, descriptor)
}
}
// Authenticate() grants access to the OpenStack-compatible provider API.
//
// Providers are identified through a unique key string.
// Specifying an unsupported provider will result in an ErrProvider error.
//
// The supplied AuthOptions instance allows the client to specify only those credentials
// relevant for the authentication request. At present, support exists for OpenStack
// Identity V2 API only; support for V3 will become available as soon as documentation for it
// becomes readily available.
//
// For Identity V2 API requirements, you must provide at least the Username and Password
// options. The TenantId field is optional, and defaults to "".
func Authenticate(provider string, options AuthOptions) (*Access, error) {
return globalContext.Authenticate(provider, options)
}
// ApiCriteria provides one or more criteria for the SDK to look for appropriate endpoints.
// Fields left unspecified or otherwise set to their zero-values are assumed to not be
// relevant, and do not participate in the endpoint search.
type ApiCriteria struct {
// Name specifies the desired service catalog entry name.
Name string
// Region specifies the desired endpoint region.
Region string
// VersionId specifies the desired version of the endpoint.
// Note that this field is matched exactly, and is (at present)
// opaque to Gophercloud. Thus, requesting a version 2
// endpoint will _not_ match a version 3 endpoint.
VersionId string
// The UrlChoice field inidicates whether or not gophercloud
// should use the public or internal endpoint URL if a
// candidate endpoint is found.
UrlChoice int
}
// The choices available for UrlChoice. See the ApiCriteria structure for details.
const (
PublicURL = iota
InternalURL
)
// ComputeProvider instances encapsulate a Cloud Servers API, should one exist in the service catalog
// for your provider.
type ComputeProvider interface {
ListServers() ([]Server, error)
}
// AccessProvider instances encapsulate a Keystone authentication interface.
type AccessProvider interface {
// FirstEndpointUrlByCriteria searches through the service catalog for the first
// matching entry endpoint fulfilling the provided criteria. If nothing found,
// return "". Otherwise, return either the public or internal URL for the
// endpoint, depending on both its existence and the setting of the ApiCriteria.UrlChoice
// field.
FirstEndpointUrlByCriteria(ApiCriteria) string
}
// genericCloudProvider structures provide the implementation for generic OpenStack-compatible
// ComputeProvider interfaces.
type genericCloudProvider struct {
// endpoint refers to the provider's API endpoint base URL. This will be used to construct
// and issue queries.
endpoint string
}
func ComputeApi(acc AccessProvider, criteria ApiCriteria) (ComputeProvider, error) {
url := acc.FirstEndpointUrlByCriteria(criteria)
if url == "" {
return nil, ErrEndpoint
}
gcp := &genericCloudProvider{
endpoint: url,
}
return gcp, nil
}
// See AccessProvider interface definition for details.
func (a *Access) FirstEndpointUrlByCriteria(ac ApiCriteria) string {
ep := FindFirstEndpointByCriteria(a.ServiceCatalog, ac)
urls := []string{ep.PublicURL, ep.InternalURL}
return urls[ac.UrlChoice]
}
// Given a set of criteria to match on, locate the first candidate endpoint
// in the provided service catalog.
//
// If nothing found, the result will be a zero-valued EntryEndpoint (all URLs
// set to "").
func FindFirstEndpointByCriteria(entries []CatalogEntry, ac ApiCriteria) EntryEndpoint {
rgn := strings.ToUpper(ac.Region)
for _, entry := range entries {
if (ac.Name != "") && (ac.Name != entry.Name) {
continue
}
for _, endpoint := range entry.Endpoints {
if (ac.Region != "") && (rgn != strings.ToUpper(endpoint.Region)) {
continue
}
if (ac.VersionId != "") && (ac.VersionId != endpoint.VersionId) {
continue
}
return endpoint
}
}
return EntryEndpoint{}
}
// See the ComputeProvider interface for details.
func (gcp *genericCloudProvider) ListServers() ([]Server, error) {
return nil, nil
}
// Server structures provide data about a server running in your provider's cloud.
type Server struct {
Id string
}