change all time fields to have type time.Time (#190)
* add Volume.Unmarshal
* add volumetenants.VolumeExt.Unmarshal
* create servers.Server time.Time fields
* json.Unmarshal can correctly handle time.RFC3339 (Server time fields)
* add v3 Token UnmarshalJSON method
* check for empty string when unmarshaling time
* add Member UnmarshalJSON
* v3 tokens.Token ExtractInto
* v3 trust.Trust UnmarshalJSON
* time.Time fields swift response objects
* time.Time fields for orchestration response objects
* time.Time fields for shared file systems response objects
* if we don't use pointers for the custom time fields, we don't need to check if they're nil
* style guide fixes: 'r' for receiver, 's' for struct
* remove unnecessary pointers from UnmarshalJSON methods
diff --git a/openstack/identity/v3/extensions/trusts/results.go b/openstack/identity/v3/extensions/trusts/results.go
index 3d3c7f2..bdd8e84 100644
--- a/openstack/identity/v3/extensions/trusts/results.go
+++ b/openstack/identity/v3/extensions/trusts/results.go
@@ -1,7 +1,5 @@
package trusts
-import "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
-
type TrusteeUser struct {
ID string `json:"id"`
}
@@ -19,11 +17,6 @@
RedelegationCount int `json:"redelegation_count"`
}
-type Token struct {
- tokens.Token
- Trust Trust `json:"OS-TRUST:trust"`
-}
-
type TokenExt struct {
- Token Token `json:"token"`
+ Trust Trust `json:"OS-TRUST:trust"`
}
diff --git a/openstack/identity/v3/extensions/trusts/testing/fixtures.go b/openstack/identity/v3/extensions/trusts/testing/fixtures.go
index b4106a3..e311526 100644
--- a/openstack/identity/v3/extensions/trusts/testing/fixtures.go
+++ b/openstack/identity/v3/extensions/trusts/testing/fixtures.go
@@ -4,24 +4,13 @@
"fmt"
"net/http"
"testing"
- "time"
- "github.com/gophercloud/gophercloud"
- "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts"
"github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
"github.com/gophercloud/gophercloud/testhelper"
)
// HandleCreateTokenWithTrustID verifies that providing certain AuthOptions and Scope results in an expected JSON structure.
func HandleCreateTokenWithTrustID(t *testing.T, options tokens.AuthOptionsBuilder, requestJSON string) {
- testhelper.SetupHTTP()
- defer testhelper.TeardownHTTP()
-
- client := gophercloud.ServiceClient{
- ProviderClient: &gophercloud.ProviderClient{},
- Endpoint: testhelper.Endpoint(),
- }
-
testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) {
testhelper.TestMethod(t, r, "POST")
testhelper.TestHeader(t, r, "Content-Type", "application/json")
@@ -75,30 +64,4 @@
}
}`)
})
-
- var actual trusts.TokenExt
- err := tokens.Create(&client, options).ExtractInto(&actual)
- if err != nil {
- t.Errorf("Create returned an error: %v", err)
- }
- expected := trusts.TokenExt{
- Token: trusts.Token{
- Token: tokens.Token{
- ExpiresAt: gophercloud.JSONRFC3339Milli(time.Date(2013, 02, 27, 18, 30, 59, 999999000, time.UTC)),
- },
- Trust: trusts.Trust{
- ID: "fe0aef",
- Impersonation: false,
- TrusteeUser: trusts.TrusteeUser{
- ID: "0ca8f6",
- },
- TrustorUser: trusts.TrustorUser{
- ID: "bd263c",
- },
- RedelegatedTrustID: "3ba234",
- RedelegationCount: 2,
- },
- },
- }
- testhelper.AssertDeepEquals(t, expected, actual)
}
diff --git a/openstack/identity/v3/extensions/trusts/testing/requests_test.go b/openstack/identity/v3/extensions/trusts/testing/requests_test.go
index f0e41dc..f8a65ad 100644
--- a/openstack/identity/v3/extensions/trusts/testing/requests_test.go
+++ b/openstack/identity/v3/extensions/trusts/testing/requests_test.go
@@ -2,12 +2,18 @@
import (
"testing"
+ "time"
"github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts"
"github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestCreateUserIDPasswordTrustID(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
ao := trusts.AuthOptsExt{
TrustID: "de0945a",
AuthOptionsBuilder: &tokens.AuthOptions{
@@ -32,4 +38,37 @@
}
}
`)
+
+ var actual struct {
+ tokens.Token
+ trusts.TokenExt
+ }
+ err := tokens.Create(client.ServiceClient(), ao).ExtractInto(&actual)
+ if err != nil {
+ t.Errorf("Create returned an error: %v", err)
+ }
+ expected := struct {
+ tokens.Token
+ trusts.TokenExt
+ }{
+ tokens.Token{
+ ExpiresAt: time.Date(2013, 02, 27, 18, 30, 59, 999999000, time.UTC),
+ },
+ trusts.TokenExt{
+ Trust: trusts.Trust{
+ ID: "fe0aef",
+ Impersonation: false,
+ TrusteeUser: trusts.TrusteeUser{
+ ID: "0ca8f6",
+ },
+ TrustorUser: trusts.TrustorUser{
+ ID: "bd263c",
+ },
+ RedelegatedTrustID: "3ba234",
+ RedelegationCount: 2,
+ },
+ },
+ }
+
+ th.AssertDeepEquals(t, expected, actual)
}
diff --git a/openstack/identity/v3/tokens/results.go b/openstack/identity/v3/tokens/results.go
index 2144a2b..0f1e8c2 100644
--- a/openstack/identity/v3/tokens/results.go
+++ b/openstack/identity/v3/tokens/results.go
@@ -1,7 +1,10 @@
package tokens
-import "errors"
-import "github.com/gophercloud/gophercloud"
+import (
+ "time"
+
+ "github.com/gophercloud/gophercloud"
+)
// Endpoint represents a single API endpoint offered by a service.
// It matches either a public, internal or admin URL.
@@ -35,7 +38,7 @@
// ServiceCatalog provides a view into the service catalog from a previous, successful authentication.
type ServiceCatalog struct {
- Entries []CatalogEntry
+ Entries []CatalogEntry `json:"catalog"`
}
// commonResult is the deferred result of a Create or a Get call.
@@ -51,34 +54,23 @@
// ExtractToken interprets a commonResult as a Token.
func (r commonResult) ExtractToken() (*Token, error) {
- var s struct {
- Token *Token `json:"token"`
- }
-
+ var s Token
err := r.ExtractInto(&s)
if err != nil {
return nil, err
}
- if s.Token == nil {
- return nil, errors.New("'token' missing in JSON response")
- }
-
// Parse the token itself from the stored headers.
- s.Token.ID = r.Header.Get("X-Subject-Token")
+ s.ID = r.Header.Get("X-Subject-Token")
- return s.Token, err
+ return &s, err
}
// ExtractServiceCatalog returns the ServiceCatalog that was generated along with the user's Token.
func (r CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) {
- var s struct {
- Token struct {
- Entries []CatalogEntry `json:"catalog"`
- } `json:"token"`
- }
+ var s ServiceCatalog
err := r.ExtractInto(&s)
- return &ServiceCatalog{Entries: s.Token.Entries}, err
+ return &s, err
}
// CreateResult defers the interpretation of a created token.
@@ -103,5 +95,9 @@
// ID is the issued token.
ID string `json:"id"`
// ExpiresAt is the timestamp at which this token will no longer be accepted.
- ExpiresAt gophercloud.JSONRFC3339Milli `json:"expires_at"`
+ ExpiresAt time.Time `json:"expires_at"`
+}
+
+func (r commonResult) ExtractInto(v interface{}) error {
+ return r.ExtractIntoStructPtr(v, "token")
}
diff --git a/openstack/identity/v3/tokens/testing/requests_test.go b/openstack/identity/v3/tokens/testing/requests_test.go
index 27f3fdc..ddffeb4 100644
--- a/openstack/identity/v3/tokens/testing/requests_test.go
+++ b/openstack/identity/v3/tokens/testing/requests_test.go
@@ -39,10 +39,12 @@
options.Scope = *scope
}
- _, err := tokens.Create(&client, &options).Extract()
- if err != nil {
- t.Errorf("Create returned an error: %v", err)
+ expected := &tokens.Token{
+ ExpiresAt: time.Date(2014, 10, 2, 13, 45, 0, 0, time.UTC),
}
+ actual, err := tokens.Create(&client, &options).Extract()
+ testhelper.AssertNoErr(t, err)
+ testhelper.CheckDeepEquals(t, expected, actual)
}
func authTokenPostErr(t *testing.T, options tokens.AuthOptions, scope *tokens.Scope, includeToken bool, expectedErr error) {
@@ -423,7 +425,7 @@
}
expected, _ := time.Parse(time.UnixDate, "Fri Aug 29 13:10:01 UTC 2014")
- if token.ExpiresAt != gophercloud.JSONRFC3339Milli(expected) {
+ if token.ExpiresAt != expected {
t.Errorf("Expected expiration time %s, but was %s", expected.Format(time.UnixDate), time.Time(token.ExpiresAt).Format(time.UnixDate))
}
}
@@ -526,7 +528,5 @@
options := tokens.AuthOptions{UserID: "me", Password: "squirrel!"}
_, err := tokens.Create(&client, &options).Extract()
- if err == nil {
- t.Error("Create succeeded with no token returned")
- }
+ testhelper.AssertNoErr(t, err)
}