Merge pull request #301 from pquerna/add_reset_api_key
[RFR] Add ResetAPIKey for Users
diff --git a/auth_options.go b/auth_options.go
index bc0ef65..19ce5d4 100644
--- a/auth_options.go
+++ b/auth_options.go
@@ -1,20 +1,28 @@
package gophercloud
-// AuthOptions allows anyone calling Authenticate to supply the required access
-// credentials. Its fields are the union of those recognized by each identity
-// implementation and provider.
+/*
+AuthOptions stores information needed to authenticate to an OpenStack cluster.
+You can populate one manually, or use a provider's AuthOptionsFromEnv() function
+to read relevant information from the standard environment variables. Pass one
+to a provider's AuthenticatedClient function to authenticate and obtain a
+ProviderClient representing an active session on that provider.
+
+Its fields are the union of those recognized by each identity implementation and
+provider.
+*/
type AuthOptions struct {
// IdentityEndpoint specifies the HTTP endpoint that is required to work with
- // the Identity API of the appropriate version. Required by the identity
- // services, but often populated by a provider Client.
+ // the Identity API of the appropriate version. While it's ultimately needed by
+ // all of the identity services, it will often be populated by a provider-level
+ // function.
IdentityEndpoint string
// Username is required if using Identity V2 API. Consult with your provider's
// control panel to discover your account's username. In Identity V3, either
- // UserID or a combination of Username and DomainID or DomainName.
+ // UserID or a combination of Username and DomainID or DomainName are needed.
Username, UserID string
- // Exactly one of Password or ApiKey is required for the Identity V2 and V3
+ // Exactly one of Password or APIKey is required for the Identity V2 and V3
// APIs. Consult with your provider's control panel to discover your account's
// preferred method of authentication.
Password, APIKey string
@@ -25,7 +33,7 @@
// The TenantID and TenantName fields are optional for the Identity V2 API.
// Some providers allow you to specify a TenantName instead of the TenantId.
- // Some require both. Your provider's authentication policies will determine
+ // Some require both. Your provider's authentication policies will determine
// how these fields influence authentication.
TenantID, TenantName string
@@ -34,5 +42,7 @@
// re-authenticate automatically if/when your token expires. If you set it to
// false, it will not cache these settings, but re-authentication will not be
// possible. This setting defaults to false.
+ //
+ // This setting is speculative and is currently not respected!
AllowReauth bool
}
diff --git a/auth_results.go b/auth_results.go
index 1a1faa5..856a233 100644
--- a/auth_results.go
+++ b/auth_results.go
@@ -2,10 +2,9 @@
import "time"
-// AuthResults encapsulates the raw results from an authentication request. As OpenStack allows
-// extensions to influence the structure returned in ways that Gophercloud cannot predict at
-// compile-time, you should use type-safe accessors to work with the data represented by this type,
-// such as ServiceCatalog and TokenID.
+// AuthResults [deprecated] is a leftover type from the v0.x days. It was
+// intended to describe common functionality among identity service results, but
+// is not actually used anywhere.
type AuthResults interface {
// TokenID returns the token's ID value from the authentication response.
TokenID() (string, error)
diff --git a/doc.go b/doc.go
new file mode 100644
index 0000000..fb81a9d
--- /dev/null
+++ b/doc.go
@@ -0,0 +1,67 @@
+/*
+Package gophercloud provides a multi-vendor interface to OpenStack-compatible
+clouds. The library has a three-level hierarchy: providers, services, and
+resources.
+
+Provider structs represent the service providers that offer and manage a
+collection of services. Examples of providers include: OpenStack, Rackspace,
+HP. These are defined like so:
+
+ opts := gophercloud.AuthOptions{
+ IdentityEndpoint: "https://my-openstack.com:5000/v2.0",
+ Username: "{username}",
+ Password: "{password}",
+ TenantID: "{tenant_id}",
+ }
+
+ provider, err := openstack.AuthenticatedClient(opts)
+
+Service structs are specific to a provider and handle all of the logic and
+operations for a particular OpenStack service. Examples of services include:
+Compute, Object Storage, Block Storage. In order to define one, you need to
+pass in the parent provider, like so:
+
+ opts := gophercloud.EndpointOpts{Region: "RegionOne"}
+
+ client := openstack.NewComputeV2(provider, opts)
+
+Resource structs are the domain models that services make use of in order
+to work with and represent the state of API resources:
+
+ server, err := servers.Get(client, "{serverId}").Extract()
+
+Intermediate Result structs are returned for API operations, which allow
+generic access to the HTTP headers, response body, and any errors associated
+with the network transaction. To turn a result into a usable resource struct,
+you must call the Extract method which is chained to the response, or an
+Extract function from an applicable extension:
+
+ result := servers.Get(client, "{serverId}")
+
+ // Attempt to extract the disk configuration from the OS-DCF disk config
+ // extension:
+ config, err := diskconfig.ExtractGet(result)
+
+All requests that enumerate a collection return a Pager struct that is used to
+iterate through the results one page at a time. Use the EachPage method on that
+Pager to handle each successive Page in a closure, then use the appropriate
+extraction method from that request's package to interpret that Page as a slice
+of results:
+
+ err := servers.List(client, nil).EachPage(func (page pagination.Page) (bool, error) {
+ s, err := servers.ExtractServers(page)
+ if err != nil {
+ return false, err
+ }
+
+ // Handle the []servers.Server slice.
+
+ // Return "false" or an error to prematurely stop fetching new pages.
+ return true, nil
+ })
+
+This top-level package contains utility functions and data types that are used
+throughout the provider and service packages. Of particular note for end users
+are the AuthOptions and EndpointOpts structs.
+*/
+package gophercloud
diff --git a/endpoint_search.go b/endpoint_search.go
index b6f6b48..5189431 100644
--- a/endpoint_search.go
+++ b/endpoint_search.go
@@ -3,58 +3,85 @@
import "errors"
var (
- // ErrServiceNotFound is returned when no service matches the EndpointOpts.
+ // ErrServiceNotFound is returned when no service in a service catalog matches
+ // the provided EndpointOpts. This is generally returned by provider service
+ // factory methods like "NewComputeV2()" and can mean that a service is not
+ // enabled for your account.
ErrServiceNotFound = errors.New("No suitable service could be found in the service catalog.")
- // ErrEndpointNotFound is returned when no available endpoints match the provided EndpointOpts.
+ // ErrEndpointNotFound is returned when no available endpoints match the
+ // provided EndpointOpts. This is also generally returned by provider service
+ // factory methods, and usually indicates that a region was specified
+ // incorrectly.
ErrEndpointNotFound = errors.New("No suitable endpoint could be found in the service catalog.")
)
-// Availability indicates whether a specific service endpoint is accessible.
-// Identity v2 lists these as different kinds of URLs ("adminURL",
-// "internalURL", and "publicURL"), while v3 lists them as "Interfaces".
+// Availability indicates to whom a specific service endpoint is accessible:
+// the internet at large, internal networks only, or only to administrators.
+// Different identity services use different terminology for these. Identity v2
+// lists them as different kinds of URLs within the service catalog ("adminURL",
+// "internalURL", and "publicURL"), while v3 lists them as "Interfaces" in an
+// endpoint's response.
type Availability string
const (
- // AvailabilityAdmin makes an endpoint only available to administrators.
+ // AvailabilityAdmin indicates that an endpoint is only available to
+ // administrators.
AvailabilityAdmin Availability = "admin"
- // AvailabilityPublic makes an endpoint available to everyone.
+ // AvailabilityPublic indicates that an endpoint is available to everyone on
+ // the internet.
AvailabilityPublic Availability = "public"
- // AvailabilityInternal makes an endpoint only available within the cluster.
+ // AvailabilityInternal indicates that an endpoint is only available within
+ // the cluster's internal network.
AvailabilityInternal Availability = "internal"
)
-// EndpointOpts contains options for finding an endpoint for an Openstack client.
+// EndpointOpts specifies search criteria used by queries against an
+// OpenStack service catalog. The options must contain enough information to
+// unambiguously identify one, and only one, endpoint within the catalog.
+//
+// Usually, these are passed to service client factory functions in a provider
+// package, like "rackspace.NewComputeV2()".
type EndpointOpts struct {
- // Type is the service type for the client (e.g., "compute", "object-store").
- // Required.
+ // Type [required] is the service type for the client (e.g., "compute",
+ // "object-store"). Generally, this will be supplied by the service client
+ // function, but a user-given value will be honored if provided.
Type string
- // Name is the service name for the client (e.g., "nova") as it appears in
- // the service catalog. Services can have the same Type but a different Name,
- // which is why both Type and Name are sometimes needed. Optional.
+ // Name [optional] is the service name for the client (e.g., "nova") as it
+ // appears in the service catalog. Services can have the same Type but a
+ // different Name, which is why both Type and Name are sometimes needed.
Name string
- // Region is the geographic region in which the service resides. Required only
- // for services that span multiple regions.
+ // Region [required] is the geographic region in which the endpoint resides,
+ // generally specifying which datacenter should house your resources.
+ // Required only for services that span multiple regions.
Region string
- // Availability is the visibility of the endpoint to be returned. Valid types
- // are: AvailabilityPublic, AvailabilityInternal, or AvailabilityAdmin.
- // Availability is not required, and defaults to AvailabilityPublic.
- // Not all providers or services offer all Availability options.
+ // Availability [optional] is the visibility of the endpoint to be returned.
+ // Valid types include the constants AvailabilityPublic, AvailabilityInternal,
+ // or AvailabilityAdmin from this package.
+ //
+ // Availability is not required, and defaults to AvailabilityPublic. Not all
+ // providers or services offer all Availability options.
Availability Availability
}
-// EndpointLocator is a function that describes how to locate a single endpoint
-// from a service catalog for a specific ProviderClient. It should be set
-// during ProviderClient authentication and used to discover related ServiceClients.
+/*
+EndpointLocator is an internal function to be used by provider implementations.
+
+It provides an implementation that locates a single endpoint from a service
+catalog for a specific ProviderClient based on user-provided EndpointOpts. The
+provider then uses it to discover related ServiceClients.
+*/
type EndpointLocator func(EndpointOpts) (string, error)
-// ApplyDefaults sets EndpointOpts fields if not already set. Currently,
-// EndpointOpts.Availability defaults to the public endpoint.
+// ApplyDefaults is an internal method to be used by provider implementations.
+//
+// It sets EndpointOpts fields if not already set, including a default type.
+// Currently, EndpointOpts.Availability defaults to the public endpoint.
func (eo *EndpointOpts) ApplyDefaults(t string) {
if eo.Type == "" {
eo.Type = t
diff --git a/package.go b/package.go
deleted file mode 100644
index e8c2e82..0000000
--- a/package.go
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-Package gophercloud provides a multi-vendor interface to OpenStack-compatible
-clouds. The library has a three-level hierarchy: providers, services, and
-resources.
-
-Provider structs represent the service providers that offer and manage a
-collection of services. Examples of providers include: OpenStack, Rackspace,
-HP. These are defined like so:
-
- opts := gophercloud.AuthOptions{
- IdentityEndpoint: "https://my-openstack.com:5000/v2.0",
- Username: "{username}",
- Password: "{password}",
- TenantID: "{tenant_id}",
- }
-
- provider, err := openstack.AuthenticatedClient(opts)
-
-Service structs are specific to a provider and handle all of the logic and
-operations for a particular OpenStack service. Examples of services include:
-Compute, Object Storage, Block Storage. In order to define one, you need to
-pass in the parent provider, like so:
-
- opts := gophercloud.EndpointOpts{Region: "RegionOne"}
-
- client := openstack.NewComputeV2(provider, opts)
-
-Resource structs are the domain models that services make use of in order
-to work with and represent the state of API resources:
-
- server, err := servers.Get(client, "{serverId}").Extract()
-
-Another convention is to return Result structs for API operations, which allow
-you to access the HTTP headers, response body, and associated errors with the
-network transaction. To get a resource struct, you then call the Extract
-method which is chained to the response.
-*/
-package gophercloud
diff --git a/params.go b/params.go
index 5fe3c2c..7b79166 100644
--- a/params.go
+++ b/params.go
@@ -9,11 +9,15 @@
"time"
)
-// MaybeString takes a string that might be a zero-value, and either returns a
-// pointer to its address or a nil value (i.e. empty pointer). This is useful
-// for converting zero values in options structs when the end-user hasn't
-// defined values. Those zero values need to be nil in order for the JSON
-// serialization to ignore them.
+/*
+MaybeString is an internal function to be used by request methods in individual
+resource packages.
+
+It takes a string that might be a zero value and returns either a pointer to its
+address or nil. This is useful for allowing users to conveniently omit values
+from an options struct by leaving them zeroed, but still pass nil to the JSON
+serializer so they'll be omitted from the request body.
+*/
func MaybeString(original string) *string {
if original != "" {
return &original
@@ -21,8 +25,14 @@
return nil
}
-// MaybeInt takes an int that might be a zero-value, and either returns a
-// pointer to its address or a nil value (i.e. empty pointer).
+/*
+MaybeInt is an internal function to be used by request methods in individual
+resource packages.
+
+Like MaybeString, it accepts an int that may or may not be a zero value, and
+returns either a pointer to its address or nil. It's intended to hint that the
+JSON serializer should omit its field.
+*/
func MaybeInt(original int) *int {
if original != 0 {
return &original
@@ -61,19 +71,26 @@
}
/*
-BuildQueryString accepts a generic structure and parses it URL struct. It
-converts field names into query names based on "q" tags. So for example, this
-type:
+BuildQueryString is an internal function to be used by request methods in
+individual resource packages.
- struct {
+It accepts a tagged structure and expands it into a URL struct. Field names are
+converted into query parameters based on a "q" tag. For example:
+
+ type struct Something {
Bar string `q:"x_bar"`
Baz int `q:"lorem_ipsum"`
- }{
- Bar: "XXX",
- Baz: "YYY",
}
-will be converted into ?x_bar=XXX&lorem_ipsum=YYYY
+ instance := Something{
+ Bar: "AAA",
+ Baz: "BBB",
+ }
+
+will be converted into "?x_bar=AAA&lorem_ipsum=BBB".
+
+The struct's fields may be strings, integers, or boolean values. Fields left at
+their type's zero value will be omittted from the query.
*/
func BuildQueryString(opts interface{}) (*url.URL, error) {
optsValue := reflect.ValueOf(opts)
@@ -132,9 +149,34 @@
return nil, fmt.Errorf("Options type is not a struct.")
}
-// BuildHeaders accepts a generic structure and parses it into a string map. It
-// converts field names into header names based on "h" tags, and field values
-// into header values by a simple one-to-one mapping.
+/*
+BuildHeaders is an internal function to be used by request methods in
+individual resource packages.
+
+It accepts a arbitrary tagged structure and produces a string map that's
+suitable for use as the HTTP headers of an outgoing request. Field names are
+mapped to header names based in "h" tags.
+
+ type struct Something {
+ Bar string `h:"x_bar"`
+ Baz int `h:"lorem_ipsum"`
+ }
+
+ instance := Something{
+ Bar: "AAA",
+ Baz: "BBB",
+ }
+
+will be converted into:
+
+ map[string]string{
+ "x_bar": "AAA",
+ "lorem_ipsum": "BBB",
+ }
+
+Untagged fields and fields left at their zero values are skipped. Integers,
+booleans and string values are supported.
+*/
func BuildHeaders(opts interface{}) (map[string]string, error) {
optsValue := reflect.ValueOf(opts)
if optsValue.Kind() == reflect.Ptr {
diff --git a/results.go b/results.go
index f480bc7..3fd5029 100644
--- a/results.go
+++ b/results.go
@@ -5,21 +5,37 @@
"net/http"
)
-// Result acts as a base struct that other results can embed.
+/*
+Result is an internal type to be used by individual resource packages, but its
+methods will be available on a wide variety of user-facing embedding types.
+
+It acts as a base struct that other Result types, returned from request
+functions, can embed for convenience. All Results capture basic information
+from the HTTP transaction that was performed, including the response body,
+HTTP headers, and any errors that happened.
+
+Generally, each Result type will have an Extract method that can be used to
+further interpret the result's payload in a specific context. Extensions or
+providers can then provide additional extraction functions to pull out
+provider- or extension-specific information as well.
+*/
type Result struct {
- // Body is the payload of the HTTP response from the server. In most cases, this will be the
- // deserialized JSON structure.
+ // Body is the payload of the HTTP response from the server. In most cases,
+ // this will be the deserialized JSON structure.
Body interface{}
// Header contains the HTTP header structure from the original response.
Header http.Header
- // Err is an error that occurred during the operation. It's deferred until extraction to make
- // it easier to chain operations.
+ // Err is an error that occurred during the operation. It's deferred until
+ // extraction to make it easier to chain the Extract call.
Err error
}
-// PrettyPrintJSON creates a string containing the full response body as pretty-printed JSON.
+// PrettyPrintJSON creates a string containing the full response body as
+// pretty-printed JSON. It's useful for capturing test fixtures and for
+// debugging extraction bugs. If you include its output in an issue related to
+// a buggy extraction function, we will all love you forever.
func (r Result) PrettyPrintJSON() string {
pretty, err := json.MarshalIndent(r.Body, "", " ")
if err != nil {
@@ -28,44 +44,67 @@
return string(pretty)
}
-// ErrResult represents results that only contain a potential error and
-// nothing else. Usually if the operation executed successfully, the Err field
-// will be nil; otherwise it will be stocked with a relevant error.
+// ErrResult is an internal type to be used by individual resource packages, but
+// its methods will be available on a wide variety of user-facing embedding
+// types.
+//
+// It represents results that only contain a potential error and
+// nothing else. Usually, if the operation executed successfully, the Err field
+// will be nil; otherwise it will be stocked with a relevant error. Use the
+// ExtractErr method
+// to cleanly pull it out.
type ErrResult struct {
Result
}
-// ExtractErr is a function that extracts error information from a result.
+// ExtractErr is a function that extracts error information, or nil, from a result.
func (r ErrResult) ExtractErr() error {
return r.Err
}
-// HeaderResult represents a result that only contains an `error` (possibly nil)
-// and an http.Header. This is used, for example, by the `objectstorage` packages
-// in `openstack`, because most of the operations don't return response bodies.
+/*
+HeaderResult is an internal type to be used by individual resource packages, but
+its methods will be available on a wide variety of user-facing embedding types.
+
+It represents a result that only contains an error (possibly nil) and an
+http.Header. This is used, for example, by the objectstorage packages in
+openstack, because most of the operations don't return response bodies, but do
+have relevant information in headers.
+*/
type HeaderResult struct {
Result
}
// ExtractHeader will return the http.Header and error from the HeaderResult.
-// Usage: header, err := objects.Create(client, "my_container", objects.CreateOpts{}).ExtractHeader()
+//
+// header, err := objects.Create(client, "my_container", objects.CreateOpts{}).ExtractHeader()
func (hr HeaderResult) ExtractHeader() (http.Header, error) {
return hr.Header, hr.Err
}
-// RFC3339Milli describes a time format used by API responses.
+// RFC3339Milli describes a common time format used by some API responses.
const RFC3339Milli = "2006-01-02T15:04:05.999999Z"
-// Link represents a structure that enables paginated collections how to
-// traverse backward or forward. The "Rel" field is usually either "next".
+/*
+Link is an internal type to be used in packages of collection resources that are
+paginated in a certain way.
+
+It's a response substructure common to many paginated collection results that is
+used to point to related pages. Usually, the one we care about is the one with
+Rel field set to "next".
+*/
type Link struct {
Href string `mapstructure:"href"`
Rel string `mapstructure:"rel"`
}
-// ExtractNextURL attempts to extract the next URL from a JSON structure. It
-// follows the common convention of nesting back and next URLs in a "links"
-// JSON array.
+/*
+ExtractNextURL is an internal function useful for packages of collection
+resources that are paginated in a certain way.
+
+It attempts attempts to extract the "next" URL from slice of Link structs, or
+"" if no such URL is present.
+*/
func ExtractNextURL(links []Link) (string, error) {
var url string
diff --git a/util.go b/util.go
index 101fd39..fbd9fe9 100644
--- a/util.go
+++ b/util.go
@@ -7,7 +7,9 @@
)
// WaitFor polls a predicate function, once per second, up to a timeout limit.
-// It usually does this to wait for the resource to transition to a certain state.
+// It usually does this to wait for a resource to transition to a certain state.
+// Resource packages will wrap this in a more convenient function that's
+// specific to a certain resource, but it can also be useful on its own.
func WaitFor(timeout int, predicate func() (bool, error)) error {
start := time.Now().Second()
for {
@@ -30,7 +32,10 @@
}
}
-// NormalizeURL ensures that each endpoint URL has a closing `/`, as expected by ServiceClient.
+// NormalizeURL is an internal function to be used by provider clients.
+//
+// It ensures that each endpoint URL has a closing `/`, as expected by
+// ServiceClient's methods.
func NormalizeURL(url string) string {
if !strings.HasSuffix(url, "/") {
return url + "/"