Re-implement basic identity API for v0.2.0.
diff --git a/openstack/identity/extensions.go b/openstack/identity/extensions.go
index 4a861ff..cfd8f24 100644
--- a/openstack/identity/extensions.go
+++ b/openstack/identity/extensions.go
@@ -1,14 +1,18 @@
package identity
import (
- "fmt"
"github.com/mitchellh/mapstructure"
)
-var (
- ErrNotFound = fmt.Errorf("Identity extension not found")
-)
-
+// ExtensionDetails provides the details offered by the OpenStack Identity V2 extensions API
+// for a named extension.
+//
+// Name provides the name, presumably the same as that used to query the API with.
+//
+// Updated provides, in a sense, the version of the extension supported. It gives the timestamp
+// of the most recent extension deployment.
+//
+// Description provides a more customer-oriented description of the extension.
type ExtensionDetails struct {
Name string
Namespace string
@@ -16,37 +20,71 @@
Description string
}
-// ExtensionsDesc structures are returned by the Extensions() function for valid input.
-// This structure implements the ExtensionInquisitor interface.
-type ExtensionsDesc struct {
- extensions []interface{}
-}
+// ExtensionsResult encapsulates the raw data returned by a call to
+// GetExtensions(). As OpenStack extensions may freely alter the response
+// bodies of structures returned to the client, you may only safely access the
+// data provided through separate, type-safe accessors or methods.
+type ExtensionsResult map[string]interface{}
-func Extensions(m map[string]interface{}) *ExtensionsDesc {
- return &ExtensionsDesc{extensions: m["extensions"].([]interface{})}
-}
-
-func extensionIndexByAlias(e *ExtensionsDesc, alias string) (int, error) {
- for i, ee := range e.extensions {
- extensionRecord := ee.(map[string]interface{})
- if extensionRecord["alias"] == alias {
- return i, nil
- }
+// IsExtensionAvailable returns true if and only if the provider supports the named extension.
+func (er ExtensionsResult) IsExtensionAvailable(alias string) bool {
+ e, err := extensions(er)
+ if err != nil {
+ return false
}
- return 0, ErrNotFound
-}
-
-func (e *ExtensionsDesc) IsExtensionAvailable(alias string) bool {
- _, err := extensionIndexByAlias(e, alias)
+ _, err = extensionIndexByAlias(e, alias)
return err == nil
}
-func (e *ExtensionsDesc) ExtensionDetailsByAlias(alias string) (*ExtensionDetails, error) {
+// ExtensionDetailsByAlias returns more detail than the mere presence of an extension by the provider.
+// See the ExtensionDetails structure.
+func (er ExtensionsResult) ExtensionDetailsByAlias(alias string) (*ExtensionDetails, error) {
+ e, err := extensions(er)
+ if err != nil {
+ return nil, err
+ }
i, err := extensionIndexByAlias(e, alias)
if err != nil {
return nil, err
}
ed := &ExtensionDetails{}
- err = mapstructure.Decode(e.extensions[i], ed)
+ err = mapstructure.Decode(e[i], ed)
return ed, err
}
+
+func extensionIndexByAlias(records []interface{}, alias string) (int, error) {
+ for i, er := range records {
+ extensionRecord := er.(map[string]interface{})
+ if extensionRecord["alias"] == alias {
+ return i, nil
+ }
+ }
+ return 0, ErrNotImplemented
+}
+
+func extensions(er ExtensionsResult) ([]interface{}, error) {
+ e, ok := er["extensions"]
+ if !ok {
+ return nil, ErrNotImplemented
+ }
+ return e.([]interface{}), nil
+}
+
+// Aliases returns the set of extension handles, or "aliases" as OpenStack calls them.
+// These are not the names of the extensions, but rather opaque, symbolic monikers for their corresponding extension.
+// Use the ExtensionDetailsByAlias() method to query more information for an extension if desired.
+func (er ExtensionsResult) Aliases() ([]string, error) {
+ e, err := extensions(er)
+ if err != nil {
+ return nil, err
+ }
+ aliases := make([]string, len(e))
+ for i, ex := range e {
+ ext := ex.(map[string]interface{})
+ extn, ok := ext["alias"]
+ if ok {
+ aliases[i] = extn.(string)
+ }
+ }
+ return aliases, nil
+}