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/blockstorage/extensions/volumetenants/results.go b/openstack/blockstorage/extensions/volumetenants/results.go
index 0d4c670..b7d51c7 100644
--- a/openstack/blockstorage/extensions/volumetenants/results.go
+++ b/openstack/blockstorage/extensions/volumetenants/results.go
@@ -1,7 +1,12 @@
package volumetenants
-// An extension to the base Volume object
+// VolumeExt is an extension to the base Volume object
type VolumeExt struct {
// TenantID is the id of the project that owns the volume.
TenantID string `json:"os-vol-tenant-attr:tenant_id"`
}
+
+// UnmarshalJSON to override default
+func (r *VolumeExt) UnmarshalJSON(b []byte) error {
+ return nil
+}
diff --git a/openstack/blockstorage/v2/volumes/results.go b/openstack/blockstorage/v2/volumes/results.go
index 41fbf5c..674ec34 100644
--- a/openstack/blockstorage/v2/volumes/results.go
+++ b/openstack/blockstorage/v2/volumes/results.go
@@ -1,18 +1,38 @@
package volumes
import (
+ "encoding/json"
+ "time"
+
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)
type Attachment struct {
- AttachedAt gophercloud.JSONRFC3339MilliNoZ `json:"attached_at"`
- AttachmentID string `json:"attachment_id"`
- Device string `json:"device"`
- HostName string `json:"host_name"`
- ID string `json:"id"`
- ServerID string `json:"server_id"`
- VolumeID string `json:"volume_id"`
+ AttachedAt time.Time `json:"-"`
+ AttachmentID string `json:"attachment_id"`
+ Device string `json:"device"`
+ HostName string `json:"host_name"`
+ ID string `json:"id"`
+ ServerID string `json:"server_id"`
+ VolumeID string `json:"volume_id"`
+}
+
+func (r *Attachment) UnmarshalJSON(b []byte) error {
+ type tmp Attachment
+ var s struct {
+ tmp
+ AttachedAt gophercloud.JSONRFC3339MilliNoZ `json:"attached_at"`
+ }
+ err := json.Unmarshal(b, &s)
+ if err != nil {
+ return err
+ }
+ *r = Attachment(s.tmp)
+
+ r.AttachedAt = time.Time(s.AttachedAt)
+
+ return err
}
// Volume contains all the information associated with an OpenStack Volume.
@@ -26,9 +46,9 @@
// AvailabilityZone is which availability zone the volume is in.
AvailabilityZone string `json:"availability_zone"`
// The date when this volume was created.
- CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
+ CreatedAt time.Time `json:"-"`
// The date when this volume was last updated
- UpdatedAt gophercloud.JSONRFC3339MilliNoZ `json:"updated_at"`
+ UpdatedAt time.Time `json:"-"`
// Instances onto which the volume is attached.
Attachments []Attachment `json:"attachments"`
// Human-readable display name for the volume.
@@ -57,6 +77,25 @@
Multiattach bool `json:"multiattach"`
}
+func (r *Volume) UnmarshalJSON(b []byte) error {
+ type tmp Volume
+ var s struct {
+ tmp
+ CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
+ UpdatedAt gophercloud.JSONRFC3339MilliNoZ `json:"updated_at"`
+ }
+ err := json.Unmarshal(b, &s)
+ if err != nil {
+ return err
+ }
+ *r = Volume(s.tmp)
+
+ r.CreatedAt = time.Time(s.CreatedAt)
+ r.UpdatedAt = time.Time(s.UpdatedAt)
+
+ return err
+}
+
// VolumePage is a pagination.pager that is returned from a call to the List function.
type VolumePage struct {
pagination.SinglePageBase
diff --git a/openstack/blockstorage/v2/volumes/testing/requests_test.go b/openstack/blockstorage/v2/volumes/testing/requests_test.go
index fd3dbcb..0a18544 100644
--- a/openstack/blockstorage/v2/volumes/testing/requests_test.go
+++ b/openstack/blockstorage/v2/volumes/testing/requests_test.go
@@ -4,7 +4,6 @@
"testing"
"time"
- "github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumetenants"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
"github.com/gophercloud/gophercloud/pagination"
@@ -35,7 +34,7 @@
Attachments: []volumes.Attachment{{
ServerID: "83ec2e3b-4321-422b-8706-a84185f52a0a",
AttachmentID: "05551600-a936-4d4a-ba42-79a037c1-c91a",
- AttachedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2016, 8, 6, 14, 48, 20, 0, time.UTC)),
+ AttachedAt: time.Date(2016, 8, 6, 14, 48, 20, 0, time.UTC),
HostName: "foobar",
VolumeID: "d6cacb1a-8b59-4c88-ad90-d70ebb82bb75",
Device: "/dev/vdc",
@@ -44,7 +43,7 @@
AvailabilityZone: "nova",
Bootable: "false",
ConsistencyGroupID: "",
- CreatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2015, 9, 17, 3, 35, 3, 0, time.UTC)),
+ CreatedAt: time.Date(2015, 9, 17, 3, 35, 3, 0, time.UTC),
Description: "",
Encrypted: false,
Metadata: map[string]string{"foo": "bar"},
@@ -67,7 +66,7 @@
AvailabilityZone: "nova",
Bootable: "false",
ConsistencyGroupID: "",
- CreatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2015, 9, 17, 3, 32, 29, 0, time.UTC)),
+ CreatedAt: time.Date(2015, 9, 17, 3, 32, 29, 0, time.UTC),
Description: "",
Encrypted: false,
Metadata: map[string]string{},
@@ -134,7 +133,7 @@
Attachments: []volumes.Attachment{{
ServerID: "83ec2e3b-4321-422b-8706-a84185f52a0a",
AttachmentID: "05551600-a936-4d4a-ba42-79a037c1-c91a",
- AttachedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2016, 8, 6, 14, 48, 20, 0, time.UTC)),
+ AttachedAt: time.Date(2016, 8, 6, 14, 48, 20, 0, time.UTC),
HostName: "foobar",
VolumeID: "d6cacb1a-8b59-4c88-ad90-d70ebb82bb75",
Device: "/dev/vdc",
@@ -143,7 +142,7 @@
AvailabilityZone: "nova",
Bootable: "false",
ConsistencyGroupID: "",
- CreatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2015, 9, 17, 3, 35, 3, 0, time.UTC)),
+ CreatedAt: time.Date(2015, 9, 17, 3, 35, 3, 0, time.UTC),
Description: "",
Encrypted: false,
Metadata: map[string]string{"foo": "bar"},
@@ -166,7 +165,7 @@
AvailabilityZone: "nova",
Bootable: "false",
ConsistencyGroupID: "",
- CreatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2015, 9, 17, 3, 32, 29, 0, time.UTC)),
+ CreatedAt: time.Date(2015, 9, 17, 3, 32, 29, 0, time.UTC),
Description: "",
Encrypted: false,
Metadata: map[string]string{},
diff --git a/openstack/compute/v2/servers/results.go b/openstack/compute/v2/servers/results.go
index a23923a..c121a6b 100644
--- a/openstack/compute/v2/servers/results.go
+++ b/openstack/compute/v2/servers/results.go
@@ -7,6 +7,7 @@
"fmt"
"net/url"
"path"
+ "time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
@@ -101,12 +102,12 @@
}
// ExtractImageID gets the ID of the newly created server image from the header
-func (res CreateImageResult) ExtractImageID() (string, error) {
- if res.Err != nil {
- return "", res.Err
+func (r CreateImageResult) ExtractImageID() (string, error) {
+ if r.Err != nil {
+ return "", r.Err
}
// Get the image id from the header
- u, err := url.ParseRequestURI(res.Header.Get("Location"))
+ u, err := url.ParseRequestURI(r.Header.Get("Location"))
if err != nil {
return "", err
}
@@ -137,26 +138,27 @@
// Name contains the human-readable name for the server.
Name string `json:"name"`
// Updated and Created contain ISO-8601 timestamps of when the state of the server last changed, and when it was created.
- Updated string
- Created string
- HostID string
+ Updated time.Time `json:"updated"`
+ Created time.Time `json:"created"`
+ HostID string `json:"hostid"`
// Status contains the current operational status of the server, such as IN_PROGRESS or ACTIVE.
- Status string
+ Status string `json:"status"`
// Progress ranges from 0..100.
// A request made against the server completes only once Progress reaches 100.
- Progress int
+ Progress int `json:"progress"`
// AccessIPv4 and AccessIPv6 contain the IP addresses of the server, suitable for remote access for administration.
- AccessIPv4, AccessIPv6 string
+ AccessIPv4 string `json:"accessIPv4"`
+ AccessIPv6 string `json:"accessIPv6"`
// Image refers to a JSON object, which itself indicates the OS image used to deploy the server.
- Image map[string]interface{}
+ Image map[string]interface{} `json:"-"`
// Flavor refers to a JSON object, which itself indicates the hardware configuration of the deployed server.
- Flavor map[string]interface{}
+ Flavor map[string]interface{} `json:"flavor"`
// Addresses includes a list of all IP addresses assigned to the server, keyed by pool.
- Addresses map[string]interface{}
+ Addresses map[string]interface{} `json:"addresses"`
// Metadata includes a list of all user-specified key-value pairs attached to the server.
- Metadata map[string]string
+ Metadata map[string]string `json:"metadata"`
// Links includes HTTP references to the itself, useful for passing along to other APIs that might want a server reference.
- Links []interface{}
+ Links []interface{} `json:"links"`
// KeyName indicates which public key was injected into the server on launch.
KeyName string `json:"key_name"`
// AdminPass will generally be empty (""). However, it will contain the administrative password chosen when provisioning a new server without a set AdminPass setting in the first place.
@@ -166,30 +168,30 @@
SecurityGroups []map[string]interface{} `json:"security_groups"`
}
-func (s *Server) UnmarshalJSON(b []byte) error {
+func (r *Server) UnmarshalJSON(b []byte) error {
type tmp Server
- var server *struct {
+ var s struct {
tmp
- Image interface{}
+ Image interface{} `json:"image"`
}
- err := json.Unmarshal(b, &server)
+ err := json.Unmarshal(b, &s)
if err != nil {
return err
}
- *s = Server(server.tmp)
+ *r = Server(s.tmp)
- switch t := server.Image.(type) {
+ switch t := s.Image.(type) {
case map[string]interface{}:
- s.Image = t
+ r.Image = t
case string:
switch t {
case "":
- s.Image = nil
+ r.Image = nil
}
}
- return nil
+ return err
}
// ServerPage abstracts the raw results of making a List() request against the API.
@@ -200,17 +202,17 @@
}
// IsEmpty returns true if a page contains no Server results.
-func (page ServerPage) IsEmpty() (bool, error) {
- servers, err := ExtractServers(page)
- return len(servers) == 0, err
+func (r ServerPage) IsEmpty() (bool, error) {
+ s, err := ExtractServers(r)
+ return len(s) == 0, err
}
// NextPageURL uses the response's embedded link reference to navigate to the next page of results.
-func (page ServerPage) NextPageURL() (string, error) {
+func (r ServerPage) NextPageURL() (string, error) {
var s struct {
Links []gophercloud.Link `json:"servers_links"`
}
- err := page.ExtractInto(&s)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
diff --git a/openstack/compute/v2/servers/testing/fixtures.go b/openstack/compute/v2/servers/testing/fixtures.go
index adedb46..40d5ed2 100644
--- a/openstack/compute/v2/servers/testing/fixtures.go
+++ b/openstack/compute/v2/servers/testing/fixtures.go
@@ -4,6 +4,7 @@
"fmt"
"net/http"
"testing"
+ "time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
@@ -304,10 +305,12 @@
`
var (
+ herpTimeCreated, _ = time.Parse(time.RFC3339, "2014-09-25T13:10:02Z")
+ herpTimeUpdated, _ = time.Parse(time.RFC3339, "2014-09-25T13:10:10Z")
// ServerHerp is a Server struct that should correspond to the first result in ServerListBody.
ServerHerp = servers.Server{
Status: "ACTIVE",
- Updated: "2014-09-25T13:10:10Z",
+ Updated: herpTimeUpdated,
HostID: "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
Addresses: map[string]interface{}{
"private": []interface{}{
@@ -350,7 +353,7 @@
ID: "ef079b0c-e610-4dfb-b1aa-b49f07ac48e5",
UserID: "9349aff8be7545ac9d2f1d00999a23cd",
Name: "herp",
- Created: "2014-09-25T13:10:02Z",
+ Created: herpTimeCreated,
TenantID: "fcad67a6189847c4aecfa3c81a05783b",
Metadata: map[string]string{},
SecurityGroups: []map[string]interface{}{
@@ -360,10 +363,12 @@
},
}
+ derpTimeCreated, _ = time.Parse(time.RFC3339, "2014-09-25T13:04:41Z")
+ derpTimeUpdated, _ = time.Parse(time.RFC3339, "2014-09-25T13:04:49Z")
// ServerDerp is a Server struct that should correspond to the second server in ServerListBody.
ServerDerp = servers.Server{
Status: "ACTIVE",
- Updated: "2014-09-25T13:04:49Z",
+ Updated: derpTimeUpdated,
HostID: "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
Addresses: map[string]interface{}{
"private": []interface{}{
@@ -406,7 +411,7 @@
ID: "9e5476bd-a4ec-4653-93d6-72c93aa682ba",
UserID: "9349aff8be7545ac9d2f1d00999a23cd",
Name: "derp",
- Created: "2014-09-25T13:04:41Z",
+ Created: derpTimeCreated,
TenantID: "fcad67a6189847c4aecfa3c81a05783b",
Metadata: map[string]string{},
SecurityGroups: []map[string]interface{}{
@@ -416,10 +421,12 @@
},
}
+ merpTimeCreated, _ = time.Parse(time.RFC3339, "2014-09-25T13:04:41Z")
+ merpTimeUpdated, _ = time.Parse(time.RFC3339, "2014-09-25T13:04:49Z")
// ServerMerp is a Server struct that should correspond to the second server in ServerListBody.
ServerMerp = servers.Server{
Status: "ACTIVE",
- Updated: "2014-09-25T13:04:49Z",
+ Updated: merpTimeUpdated,
HostID: "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
Addresses: map[string]interface{}{
"private": []interface{}{
@@ -454,7 +461,7 @@
ID: "9e5476bd-a4ec-4653-93d6-72c93aa682bb",
UserID: "9349aff8be7545ac9d2f1d00999a23cd",
Name: "merp",
- Created: "2014-09-25T13:04:41Z",
+ Created: merpTimeCreated,
TenantID: "fcad67a6189847c4aecfa3c81a05783b",
Metadata: map[string]string{},
SecurityGroups: []map[string]interface{}{
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)
}
diff --git a/openstack/imageservice/v2/images/results.go b/openstack/imageservice/v2/images/results.go
index 653c68c..ae674de 100644
--- a/openstack/imageservice/v2/images/results.go
+++ b/openstack/imageservice/v2/images/results.go
@@ -66,10 +66,10 @@
Properties map[string]string `json:"properties"`
// CreatedAt is the date when the image has been created.
- CreatedAt time.Time `json:"-"`
+ CreatedAt time.Time `json:"created_at"`
// UpdatedAt is the date when the last change has been made to the image or it's properties.
- UpdatedAt time.Time `json:"-"`
+ UpdatedAt time.Time `json:"updated_at"`
// File is the trailing path after the glance endpoint that represent the location
// of the image or the path to retrieve it.
@@ -79,36 +79,29 @@
Schema string `json:"schema"`
}
-func (s *Image) UnmarshalJSON(b []byte) error {
+func (r *Image) UnmarshalJSON(b []byte) error {
type tmp Image
- var p *struct {
+ var s struct {
tmp
SizeBytes interface{} `json:"size"`
- CreatedAt string `json:"created_at"`
- UpdatedAt string `json:"updated_at"`
}
- err := json.Unmarshal(b, &p)
+ err := json.Unmarshal(b, &s)
if err != nil {
return err
}
- *s = Image(p.tmp)
+ *r = Image(s.tmp)
- switch t := p.SizeBytes.(type) {
+ switch t := s.SizeBytes.(type) {
case nil:
return nil
case float32:
- s.SizeBytes = int64(t)
+ r.SizeBytes = int64(t)
case float64:
- s.SizeBytes = int64(t)
+ r.SizeBytes = int64(t)
default:
return fmt.Errorf("Unknown type for SizeBytes: %v (value: %v)", reflect.TypeOf(t), t)
}
- s.CreatedAt, err = time.Parse(time.RFC3339, p.CreatedAt)
- if err != nil {
- return err
- }
- s.UpdatedAt, err = time.Parse(time.RFC3339, p.UpdatedAt)
return err
}
diff --git a/openstack/imageservice/v2/members/results.go b/openstack/imageservice/v2/members/results.go
index 1d2a9c0..d3cc1ce 100644
--- a/openstack/imageservice/v2/members/results.go
+++ b/openstack/imageservice/v2/members/results.go
@@ -1,7 +1,6 @@
package members
import (
- "encoding/json"
"time"
"github.com/gophercloud/gophercloud"
@@ -10,33 +9,12 @@
// Member model
type Member struct {
- CreatedAt time.Time `json:"-"`
+ CreatedAt time.Time `json:"created_at"`
ImageID string `json:"image_id"`
MemberID string `json:"member_id"`
Schema string `json:"schema"`
Status string `json:"status"`
- UpdatedAt time.Time `json:"-"`
-}
-
-func (s *Member) UnmarshalJSON(b []byte) error {
- type tmp Member
- var p *struct {
- tmp
- CreatedAt string `json:"created_at"`
- UpdatedAt string `json:"updated_at"`
- }
- err := json.Unmarshal(b, &p)
- if err != nil {
- return err
- }
-
- *s = Member(p.tmp)
- s.CreatedAt, err = time.Parse(time.RFC3339, p.CreatedAt)
- if err != nil {
- return err
- }
- s.UpdatedAt, err = time.Parse(time.RFC3339, p.UpdatedAt)
- return err
+ UpdatedAt time.Time `json:"updated_at"`
}
// Extract Member model from request if possible
diff --git a/openstack/objectstorage/v1/accounts/results.go b/openstack/objectstorage/v1/accounts/results.go
index 216414b..9bc8340 100644
--- a/openstack/objectstorage/v1/accounts/results.go
+++ b/openstack/objectstorage/v1/accounts/results.go
@@ -2,9 +2,9 @@
import (
"encoding/json"
- "fmt"
"strconv"
"strings"
+ "time"
"github.com/gophercloud/gophercloud"
)
@@ -16,117 +16,124 @@
// UpdateHeader represents the headers returned in the response from an Update request.
type UpdateHeader struct {
- ContentLength int64 `json:"-"`
- ContentType string `json:"Content-Type"`
- TransID string `json:"X-Trans-Id"`
- Date gophercloud.JSONRFC1123 `json:"Date"`
+ ContentLength int64 `json:"-"`
+ ContentType string `json:"Content-Type"`
+ TransID string `json:"X-Trans-Id"`
+ Date time.Time `json:"-"`
}
-func (h *UpdateHeader) UnmarshalJSON(b []byte) error {
+func (r *UpdateHeader) UnmarshalJSON(b []byte) error {
type tmp UpdateHeader
- var updateHeader *struct {
+ var s struct {
tmp
- ContentLength string `json:"Content-Length"`
+ ContentLength string `json:"Content-Length"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
}
- err := json.Unmarshal(b, &updateHeader)
+ err := json.Unmarshal(b, &s)
if err != nil {
return err
}
- *h = UpdateHeader(updateHeader.tmp)
+ *r = UpdateHeader(s.tmp)
- switch updateHeader.ContentLength {
+ switch s.ContentLength {
case "":
- h.ContentLength = 0
+ r.ContentLength = 0
default:
- h.ContentLength, err = strconv.ParseInt(updateHeader.ContentLength, 10, 64)
+ r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
if err != nil {
return err
}
}
- return nil
+ r.Date = time.Time(s.Date)
+
+ return err
}
// Extract will return a struct of headers returned from a call to Get. To obtain
// a map of headers, call the ExtractHeader method on the GetResult.
-func (ur UpdateResult) Extract() (*UpdateHeader, error) {
- var uh *UpdateHeader
- err := ur.ExtractInto(&uh)
- return uh, err
+func (r UpdateResult) Extract() (*UpdateHeader, error) {
+ var s *UpdateHeader
+ err := r.ExtractInto(&s)
+ return s, err
}
// GetHeader represents the headers returned in the response from a Get request.
type GetHeader struct {
- BytesUsed int64 `json:"-"`
- ContainerCount int64 `json:"-"`
- ContentLength int64 `json:"-"`
- ObjectCount int64 `json:"-"`
- ContentType string `json:"Content-Type"`
- TransID string `json:"X-Trans-Id"`
- TempURLKey string `json:"X-Account-Meta-Temp-URL-Key"`
- TempURLKey2 string `json:"X-Account-Meta-Temp-URL-Key-2"`
- Date gophercloud.JSONRFC1123 `json:"Date"`
+ BytesUsed int64 `json:"-"`
+ ContainerCount int64 `json:"-"`
+ ContentLength int64 `json:"-"`
+ ObjectCount int64 `json:"-"`
+ ContentType string `json:"Content-Type"`
+ TransID string `json:"X-Trans-Id"`
+ TempURLKey string `json:"X-Account-Meta-Temp-URL-Key"`
+ TempURLKey2 string `json:"X-Account-Meta-Temp-URL-Key-2"`
+ Date time.Time `json:"-"`
}
-func (h *GetHeader) UnmarshalJSON(b []byte) error {
+func (r *GetHeader) UnmarshalJSON(b []byte) error {
type tmp GetHeader
- var getHeader *struct {
+ var s struct {
tmp
BytesUsed string `json:"X-Account-Bytes-Used"`
ContentLength string `json:"Content-Length"`
ContainerCount string `json:"X-Account-Container-Count"`
ObjectCount string `json:"X-Account-Object-Count"`
+ Date string `json:"Date"`
}
- err := json.Unmarshal(b, &getHeader)
+ err := json.Unmarshal(b, &s)
if err != nil {
return err
}
- *h = GetHeader(getHeader.tmp)
+ *r = GetHeader(s.tmp)
- switch getHeader.BytesUsed {
+ switch s.BytesUsed {
case "":
- h.BytesUsed = 0
+ r.BytesUsed = 0
default:
- h.BytesUsed, err = strconv.ParseInt(getHeader.BytesUsed, 10, 64)
+ r.BytesUsed, err = strconv.ParseInt(s.BytesUsed, 10, 64)
if err != nil {
return err
}
}
- fmt.Println("getHeader: ", getHeader.ContentLength)
- switch getHeader.ContentLength {
+ switch s.ContentLength {
case "":
- h.ContentLength = 0
+ r.ContentLength = 0
default:
- h.ContentLength, err = strconv.ParseInt(getHeader.ContentLength, 10, 64)
+ r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
if err != nil {
return err
}
}
- switch getHeader.ObjectCount {
+ switch s.ObjectCount {
case "":
- h.ObjectCount = 0
+ r.ObjectCount = 0
default:
- h.ObjectCount, err = strconv.ParseInt(getHeader.ObjectCount, 10, 64)
+ r.ObjectCount, err = strconv.ParseInt(s.ObjectCount, 10, 64)
if err != nil {
return err
}
}
- switch getHeader.ContainerCount {
+ switch s.ContainerCount {
case "":
- h.ContainerCount = 0
+ r.ContainerCount = 0
default:
- h.ContainerCount, err = strconv.ParseInt(getHeader.ContainerCount, 10, 64)
+ r.ContainerCount, err = strconv.ParseInt(s.ContainerCount, 10, 64)
if err != nil {
return err
}
}
- return nil
+ if s.Date != "" {
+ r.Date, err = time.Parse(time.RFC1123, s.Date)
+ }
+
+ return err
}
// GetResult is returned from a call to the Get function.
@@ -142,7 +149,7 @@
return s, err
}
-// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
+// ExtractMetadata is a function that takes a GetResult (of type *htts.Response)
// and returns the custom metatdata associated with the account.
func (r GetResult) ExtractMetadata() (map[string]string, error) {
if r.Err != nil {
diff --git a/openstack/objectstorage/v1/accounts/testing/requests_test.go b/openstack/objectstorage/v1/accounts/testing/requests_test.go
index dc5d9de..97852f1 100644
--- a/openstack/objectstorage/v1/accounts/testing/requests_test.go
+++ b/openstack/objectstorage/v1/accounts/testing/requests_test.go
@@ -4,7 +4,6 @@
"testing"
"time"
- "github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts"
th "github.com/gophercloud/gophercloud/testhelper"
fake "github.com/gophercloud/gophercloud/testhelper/client"
@@ -24,7 +23,7 @@
th.AssertNoErr(t, res.Err)
expected := &accounts.UpdateHeader{
- Date: gophercloud.JSONRFC1123(time.Date(2014, time.January, 17, 16, 9, 56, 0, loc)), // Fri, 17 Jan 2014 16:09:56 GMT
+ Date: time.Date(2014, time.January, 17, 16, 9, 56, 0, loc), // Fri, 17 Jan 2014 16:09:56 GMT
}
actual, err := res.Extract()
th.AssertNoErr(t, err)
@@ -48,7 +47,7 @@
ContainerCount: 2,
ObjectCount: 5,
BytesUsed: 14,
- Date: gophercloud.JSONRFC1123(time.Date(2014, time.January, 17, 16, 9, 56, 0, loc)), // Fri, 17 Jan 2014 16:09:56 GMT
+ Date: time.Date(2014, time.January, 17, 16, 9, 56, 0, loc), // Fri, 17 Jan 2014 16:09:56 GMT
}
actual, err := res.Extract()
th.AssertNoErr(t, err)
diff --git a/openstack/objectstorage/v1/containers/results.go b/openstack/objectstorage/v1/containers/results.go
index ebe6eba..8c11b8c 100644
--- a/openstack/objectstorage/v1/containers/results.go
+++ b/openstack/objectstorage/v1/containers/results.go
@@ -5,6 +5,7 @@
"fmt"
"strconv"
"strings"
+ "time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
@@ -88,69 +89,72 @@
// GetHeader represents the headers returned in the response from a Get request.
type GetHeader struct {
- AcceptRanges string `json:"Accept-Ranges"`
- BytesUsed int64 `json:"-"`
- ContentLength int64 `json:"-"`
- ContentType string `json:"Content-Type"`
- Date gophercloud.JSONRFC1123 `json:"Date"`
- ObjectCount int64 `json:"-"`
- Read []string `json:"-"`
- TransID string `json:"X-Trans-Id"`
- VersionsLocation string `json:"X-Versions-Location"`
- Write []string `json:"-"`
+ AcceptRanges string `json:"Accept-Ranges"`
+ BytesUsed int64 `json:"-"`
+ ContentLength int64 `json:"-"`
+ ContentType string `json:"Content-Type"`
+ Date time.Time `json:"-"`
+ ObjectCount int64 `json:"-"`
+ Read []string `json:"-"`
+ TransID string `json:"X-Trans-Id"`
+ VersionsLocation string `json:"X-Versions-Location"`
+ Write []string `json:"-"`
}
-func (h *GetHeader) UnmarshalJSON(b []byte) error {
+func (r *GetHeader) UnmarshalJSON(b []byte) error {
type tmp GetHeader
- var getHeader *struct {
+ var s struct {
tmp
- BytesUsed string `json:"X-Container-Bytes-Used"`
- ContentLength string `json:"Content-Length"`
- ObjectCount string `json:"X-Container-Object-Count"`
- Write string `json:"X-Container-Write"`
- Read string `json:"X-Container-Read"`
+ BytesUsed string `json:"X-Container-Bytes-Used"`
+ ContentLength string `json:"Content-Length"`
+ ObjectCount string `json:"X-Container-Object-Count"`
+ Write string `json:"X-Container-Write"`
+ Read string `json:"X-Container-Read"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
}
- err := json.Unmarshal(b, &getHeader)
+ err := json.Unmarshal(b, &s)
if err != nil {
return err
}
- *h = GetHeader(getHeader.tmp)
+ *r = GetHeader(s.tmp)
- switch getHeader.BytesUsed {
+ switch s.BytesUsed {
case "":
- h.BytesUsed = 0
+ r.BytesUsed = 0
default:
- h.BytesUsed, err = strconv.ParseInt(getHeader.BytesUsed, 10, 64)
+ r.BytesUsed, err = strconv.ParseInt(s.BytesUsed, 10, 64)
if err != nil {
return err
}
}
- switch getHeader.ContentLength {
+ switch s.ContentLength {
case "":
- h.ContentLength = 0
+ r.ContentLength = 0
default:
- h.ContentLength, err = strconv.ParseInt(getHeader.ContentLength, 10, 64)
+ r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
if err != nil {
return err
}
}
- switch getHeader.ObjectCount {
+ switch s.ObjectCount {
case "":
- h.ObjectCount = 0
+ r.ObjectCount = 0
default:
- h.ObjectCount, err = strconv.ParseInt(getHeader.ObjectCount, 10, 64)
+ r.ObjectCount, err = strconv.ParseInt(s.ObjectCount, 10, 64)
if err != nil {
return err
}
}
- h.Read = strings.Split(getHeader.Read, ",")
- h.Write = strings.Split(getHeader.Write, ",")
+ r.Read = strings.Split(s.Read, ",")
+ r.Write = strings.Split(s.Write, ",")
- return nil
+ r.Date = time.Time(s.Date)
+
+ return err
}
// GetResult represents the result of a get operation.
@@ -166,7 +170,7 @@
return s, err
}
-// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
+// ExtractMetadata is a function that takes a GetResult (of type *stts.Response)
// and returns the custom metadata associated with the container.
func (r GetResult) ExtractMetadata() (map[string]string, error) {
if r.Err != nil {
@@ -184,36 +188,39 @@
// CreateHeader represents the headers returned in the response from a Create request.
type CreateHeader struct {
- ContentLength int64 `json:"-"`
- ContentType string `json:"Content-Type"`
- Date gophercloud.JSONRFC1123 `json:"Date"`
- TransID string `json:"X-Trans-Id"`
+ ContentLength int64 `json:"-"`
+ ContentType string `json:"Content-Type"`
+ Date time.Time `json:"-"`
+ TransID string `json:"X-Trans-Id"`
}
-func (h *CreateHeader) UnmarshalJSON(b []byte) error {
+func (r *CreateHeader) UnmarshalJSON(b []byte) error {
type tmp CreateHeader
- var header *struct {
+ var s struct {
tmp
- ContentLength string `json:"Content-Length"`
+ ContentLength string `json:"Content-Length"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
}
- err := json.Unmarshal(b, &header)
+ err := json.Unmarshal(b, &s)
if err != nil {
return err
}
- *h = CreateHeader(header.tmp)
+ *r = CreateHeader(s.tmp)
- switch header.ContentLength {
+ switch s.ContentLength {
case "":
- h.ContentLength = 0
+ r.ContentLength = 0
default:
- h.ContentLength, err = strconv.ParseInt(header.ContentLength, 10, 64)
+ r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
if err != nil {
return err
}
}
- return nil
+ r.Date = time.Time(s.Date)
+
+ return err
}
// CreateResult represents the result of a create operation. To extract the
@@ -233,36 +240,39 @@
// UpdateHeader represents the headers returned in the response from a Update request.
type UpdateHeader struct {
- ContentLength int64 `json:"-"`
- ContentType string `json:"Content-Type"`
- Date gophercloud.JSONRFC1123 `json:"Date"`
- TransID string `json:"X-Trans-Id"`
+ ContentLength int64 `json:"-"`
+ ContentType string `json:"Content-Type"`
+ Date time.Time `json:"-"`
+ TransID string `json:"X-Trans-Id"`
}
-func (h *UpdateHeader) UnmarshalJSON(b []byte) error {
+func (r *UpdateHeader) UnmarshalJSON(b []byte) error {
type tmp UpdateHeader
- var header *struct {
+ var s struct {
tmp
- ContentLength string `json:"Content-Length"`
+ ContentLength string `json:"Content-Length"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
}
- err := json.Unmarshal(b, &header)
+ err := json.Unmarshal(b, &s)
if err != nil {
return err
}
- *h = UpdateHeader(header.tmp)
+ *r = UpdateHeader(s.tmp)
- switch header.ContentLength {
+ switch s.ContentLength {
case "":
- h.ContentLength = 0
+ r.ContentLength = 0
default:
- h.ContentLength, err = strconv.ParseInt(header.ContentLength, 10, 64)
+ r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
if err != nil {
return err
}
}
- return nil
+ r.Date = time.Time(s.Date)
+
+ return err
}
// UpdateResult represents the result of an update operation. To extract the
@@ -282,36 +292,39 @@
// DeleteHeader represents the headers returned in the response from a Delete request.
type DeleteHeader struct {
- ContentLength int64 `json:"-"`
- ContentType string `json:"Content-Type"`
- Date gophercloud.JSONRFC1123 `json:"Date"`
- TransID string `json:"X-Trans-Id"`
+ ContentLength int64 `json:"-"`
+ ContentType string `json:"Content-Type"`
+ Date time.Time `json:"-"`
+ TransID string `json:"X-Trans-Id"`
}
-func (h *DeleteHeader) UnmarshalJSON(b []byte) error {
+func (r *DeleteHeader) UnmarshalJSON(b []byte) error {
type tmp DeleteHeader
- var header *struct {
+ var s struct {
tmp
- ContentLength string `json:"Content-Length"`
+ ContentLength string `json:"Content-Length"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
}
- err := json.Unmarshal(b, &header)
+ err := json.Unmarshal(b, &s)
if err != nil {
return err
}
- *h = DeleteHeader(header.tmp)
+ *r = DeleteHeader(s.tmp)
- switch header.ContentLength {
+ switch s.ContentLength {
case "":
- h.ContentLength = 0
+ r.ContentLength = 0
default:
- h.ContentLength, err = strconv.ParseInt(header.ContentLength, 10, 64)
+ r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
if err != nil {
return err
}
}
- return nil
+ r.Date = time.Time(s.Date)
+
+ return err
}
// DeleteResult represents the result of a delete operation. To extract the
diff --git a/openstack/objectstorage/v1/containers/testing/requests_test.go b/openstack/objectstorage/v1/containers/testing/requests_test.go
index abac922..bb0c784 100644
--- a/openstack/objectstorage/v1/containers/testing/requests_test.go
+++ b/openstack/objectstorage/v1/containers/testing/requests_test.go
@@ -4,7 +4,6 @@
"testing"
"time"
- "github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers"
"github.com/gophercloud/gophercloud/pagination"
th "github.com/gophercloud/gophercloud/testhelper"
@@ -93,7 +92,7 @@
expected := &containers.CreateHeader{
ContentLength: 0,
ContentType: "text/html; charset=UTF-8",
- Date: gophercloud.JSONRFC1123(time.Date(2016, time.August, 17, 19, 25, 43, 0, loc)), //Wed, 17 Aug 2016 19:25:43 GMT
+ Date: time.Date(2016, time.August, 17, 19, 25, 43, 0, loc), //Wed, 17 Aug 2016 19:25:43 GMT
TransID: "tx554ed59667a64c61866f1-0058b4ba37",
}
actual, err := res.Extract()
@@ -133,7 +132,7 @@
AcceptRanges: "bytes",
BytesUsed: 100,
ContentType: "application/json; charset=utf-8",
- Date: gophercloud.JSONRFC1123(time.Date(2016, time.August, 17, 19, 25, 43, 0, loc)), //Wed, 17 Aug 2016 19:25:43 GMT
+ Date: time.Date(2016, time.August, 17, 19, 25, 43, 0, loc), //Wed, 17 Aug 2016 19:25:43 GMT
ObjectCount: 4,
Read: []string{"test"},
TransID: "tx554ed59667a64c61866f1-0057b4ba37",
diff --git a/openstack/objectstorage/v1/objects/results.go b/openstack/objectstorage/v1/objects/results.go
index 4f7020c..0dcdbe2 100644
--- a/openstack/objectstorage/v1/objects/results.go
+++ b/openstack/objectstorage/v1/objects/results.go
@@ -7,6 +7,7 @@
"io/ioutil"
"strconv"
"strings"
+ "time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
@@ -23,15 +24,34 @@
// Hash represents the MD5 checksum value of the object's content.
Hash string `json:"hash"`
- // LastModified is the RFC3339Milli time the object was last modified, represented
- // as a string. For any given object (obj), this value may be parsed to a time.Time:
- // lastModified, err := time.Parse(gophercloud.RFC3339Milli, obj.LastModified)
- LastModified gophercloud.JSONRFC3339MilliNoZ `json:"last_modified"`
+ // LastModified is the time the object was last modified, represented
+ // as a string.
+ LastModified time.Time `json:"-"`
// Name is the unique name for the object.
Name string `json:"name"`
}
+func (r *Object) UnmarshalJSON(b []byte) error {
+ type tmp Object
+ var s *struct {
+ tmp
+ LastModified gophercloud.JSONRFC3339MilliNoZ `json:"last_modified"`
+ }
+
+ err := json.Unmarshal(b, &s)
+ if err != nil {
+ return err
+ }
+
+ *r = Object(s.tmp)
+
+ r.LastModified = time.Time(s.LastModified)
+
+ return nil
+
+}
+
// ObjectPage is a single page of objects that is returned from a call to the
// List function.
type ObjectPage struct {
@@ -100,43 +120,50 @@
// DownloadHeader represents the headers returned in the response from a Download request.
type DownloadHeader struct {
- AcceptRanges string `json:"Accept-Ranges"`
- ContentDisposition string `json:"Content-Disposition"`
- ContentEncoding string `json:"Content-Encoding"`
- ContentLength int64 `json:"-"`
- ContentType string `json:"Content-Type"`
- Date gophercloud.JSONRFC1123 `json:"Date"`
- DeleteAt gophercloud.JSONUnix `json:"X-Delete-At"`
- ETag string `json:"Etag"`
- LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
- ObjectManifest string `json:"X-Object-Manifest"`
- StaticLargeObject bool `json:"X-Static-Large-Object"`
- TransID string `json:"X-Trans-Id"`
+ AcceptRanges string `json:"Accept-Ranges"`
+ ContentDisposition string `json:"Content-Disposition"`
+ ContentEncoding string `json:"Content-Encoding"`
+ ContentLength int64 `json:"-"`
+ ContentType string `json:"Content-Type"`
+ Date time.Time `json:"-"`
+ DeleteAt time.Time `json:"-"`
+ ETag string `json:"Etag"`
+ LastModified time.Time `json:"-"`
+ ObjectManifest string `json:"X-Object-Manifest"`
+ StaticLargeObject bool `json:"X-Static-Large-Object"`
+ TransID string `json:"X-Trans-Id"`
}
-func (h *DownloadHeader) UnmarshalJSON(b []byte) error {
+func (r *DownloadHeader) UnmarshalJSON(b []byte) error {
type tmp DownloadHeader
- var hTmp *struct {
+ var s struct {
tmp
- ContentLength string `json:"Content-Length"`
+ ContentLength string `json:"Content-Length"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ DeleteAt gophercloud.JSONUnix `json:"X-Delete-At"`
+ LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
}
- err := json.Unmarshal(b, &hTmp)
+ err := json.Unmarshal(b, &s)
if err != nil {
return err
}
- *h = DownloadHeader(hTmp.tmp)
+ *r = DownloadHeader(s.tmp)
- switch hTmp.ContentLength {
+ switch s.ContentLength {
case "":
- h.ContentLength = 0
+ r.ContentLength = 0
default:
- h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+ r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
if err != nil {
return err
}
}
+ r.Date = time.Time(s.Date)
+ r.DeleteAt = time.Time(s.DeleteAt)
+ r.LastModified = time.Time(s.LastModified)
+
return nil
}
@@ -174,42 +201,49 @@
// GetHeader represents the headers returned in the response from a Get request.
type GetHeader struct {
- ContentDisposition string `json:"Content-Disposition"`
- ContentEncoding string `json:"Content-Encoding"`
- ContentLength int64 `json:"Content-Length"`
- ContentType string `json:"Content-Type"`
- Date gophercloud.JSONRFC1123 `json:"Date"`
- DeleteAt gophercloud.JSONUnix `json:"X-Delete-At"`
- ETag string `json:"Etag"`
- LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
- ObjectManifest string `json:"X-Object-Manifest"`
- StaticLargeObject bool `json:"X-Static-Large-Object"`
- TransID string `json:"X-Trans-Id"`
+ ContentDisposition string `json:"Content-Disposition"`
+ ContentEncoding string `json:"Content-Encoding"`
+ ContentLength int64 `json:"-"`
+ ContentType string `json:"Content-Type"`
+ Date time.Time `json:"-"`
+ DeleteAt time.Time `json:"-"`
+ ETag string `json:"Etag"`
+ LastModified time.Time `json:"-"`
+ ObjectManifest string `json:"X-Object-Manifest"`
+ StaticLargeObject bool `json:"X-Static-Large-Object"`
+ TransID string `json:"X-Trans-Id"`
}
-func (h *GetHeader) UnmarshalJSON(b []byte) error {
+func (r *GetHeader) UnmarshalJSON(b []byte) error {
type tmp GetHeader
- var hTmp *struct {
+ var s struct {
tmp
- ContentLength string `json:"Content-Length"`
+ ContentLength string `json:"Content-Length"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ DeleteAt gophercloud.JSONUnix `json:"X-Delete-At"`
+ LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
}
- err := json.Unmarshal(b, &hTmp)
+ err := json.Unmarshal(b, &s)
if err != nil {
return err
}
- *h = GetHeader(hTmp.tmp)
+ *r = GetHeader(s.tmp)
- switch hTmp.ContentLength {
+ switch s.ContentLength {
case "":
- h.ContentLength = 0
+ r.ContentLength = 0
default:
- h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+ r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
if err != nil {
return err
}
}
+ r.Date = time.Time(s.Date)
+ r.DeleteAt = time.Time(s.DeleteAt)
+ r.LastModified = time.Time(s.LastModified)
+
return nil
}
@@ -244,37 +278,42 @@
// CreateHeader represents the headers returned in the response from a Create request.
type CreateHeader struct {
- ContentLength int64 `json:"Content-Length"`
- ContentType string `json:"Content-Type"`
- Date gophercloud.JSONRFC1123 `json:"Date"`
- ETag string `json:"Etag"`
- LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
- TransID string `json:"X-Trans-Id"`
+ ContentLength int64 `json:"-"`
+ ContentType string `json:"Content-Type"`
+ Date time.Time `json:"-"`
+ ETag string `json:"Etag"`
+ LastModified time.Time `json:"-"`
+ TransID string `json:"X-Trans-Id"`
}
-func (h *CreateHeader) UnmarshalJSON(b []byte) error {
+func (r *CreateHeader) UnmarshalJSON(b []byte) error {
type tmp CreateHeader
- var hTmp *struct {
+ var s struct {
tmp
- ContentLength string `json:"Content-Length"`
+ ContentLength string `json:"Content-Length"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
}
- err := json.Unmarshal(b, &hTmp)
+ err := json.Unmarshal(b, &s)
if err != nil {
return err
}
- *h = CreateHeader(hTmp.tmp)
+ *r = CreateHeader(s.tmp)
- switch hTmp.ContentLength {
+ switch s.ContentLength {
case "":
- h.ContentLength = 0
+ r.ContentLength = 0
default:
- h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+ r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
if err != nil {
return err
}
}
+ r.Date = time.Time(s.Date)
+ r.LastModified = time.Time(s.LastModified)
+
return nil
}
@@ -297,35 +336,38 @@
// UpdateHeader represents the headers returned in the response from a Update request.
type UpdateHeader struct {
- ContentLength int64 `json:"Content-Length"`
- ContentType string `json:"Content-Type"`
- Date gophercloud.JSONRFC1123 `json:"Date"`
- TransID string `json:"X-Trans-Id"`
+ ContentLength int64 `json:"-"`
+ ContentType string `json:"Content-Type"`
+ Date time.Time `json:"-"`
+ TransID string `json:"X-Trans-Id"`
}
-func (h *UpdateHeader) UnmarshalJSON(b []byte) error {
+func (r *UpdateHeader) UnmarshalJSON(b []byte) error {
type tmp UpdateHeader
- var hTmp *struct {
+ var s struct {
tmp
- ContentLength string `json:"Content-Length"`
+ ContentLength string `json:"Content-Length"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
}
- err := json.Unmarshal(b, &hTmp)
+ err := json.Unmarshal(b, &s)
if err != nil {
return err
}
- *h = UpdateHeader(hTmp.tmp)
+ *r = UpdateHeader(s.tmp)
- switch hTmp.ContentLength {
+ switch s.ContentLength {
case "":
- h.ContentLength = 0
+ r.ContentLength = 0
default:
- h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+ r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
if err != nil {
return err
}
}
+ r.Date = time.Time(s.Date)
+
return nil
}
@@ -344,35 +386,38 @@
// DeleteHeader represents the headers returned in the response from a Delete request.
type DeleteHeader struct {
- ContentLength int64 `json:"Content-Length"`
- ContentType string `json:"Content-Type"`
- Date gophercloud.JSONRFC1123 `json:"Date"`
- TransID string `json:"X-Trans-Id"`
+ ContentLength int64 `json:"Content-Length"`
+ ContentType string `json:"Content-Type"`
+ Date time.Time `json:"-"`
+ TransID string `json:"X-Trans-Id"`
}
-func (h *DeleteHeader) UnmarshalJSON(b []byte) error {
+func (r *DeleteHeader) UnmarshalJSON(b []byte) error {
type tmp DeleteHeader
- var hTmp *struct {
+ var s struct {
tmp
- ContentLength string `json:"Content-Length"`
+ ContentLength string `json:"Content-Length"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
}
- err := json.Unmarshal(b, &hTmp)
+ err := json.Unmarshal(b, &s)
if err != nil {
return err
}
- *h = DeleteHeader(hTmp.tmp)
+ *r = DeleteHeader(s.tmp)
- switch hTmp.ContentLength {
+ switch s.ContentLength {
case "":
- h.ContentLength = 0
+ r.ContentLength = 0
default:
- h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+ r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
if err != nil {
return err
}
}
+ r.Date = time.Time(s.Date)
+
return nil
}
@@ -391,39 +436,46 @@
// CopyHeader represents the headers returned in the response from a Copy request.
type CopyHeader struct {
- ContentLength int64 `json:"Content-Length"`
- ContentType string `json:"Content-Type"`
- CopiedFrom string `json:"X-Copied-From"`
- CopiedFromLastModified gophercloud.JSONRFC1123 `json:"X-Copied-From-Last-Modified"`
- Date gophercloud.JSONRFC1123 `json:"Date"`
- ETag string `json:"Etag"`
- LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
- TransID string `json:"X-Trans-Id"`
+ ContentLength int64 `json:"-"`
+ ContentType string `json:"Content-Type"`
+ CopiedFrom string `json:"X-Copied-From"`
+ CopiedFromLastModified time.Time `json:"-"`
+ Date time.Time `json:"-"`
+ ETag string `json:"Etag"`
+ LastModified time.Time `json:"-"`
+ TransID string `json:"X-Trans-Id"`
}
-func (h *CopyHeader) UnmarshalJSON(b []byte) error {
+func (r *CopyHeader) UnmarshalJSON(b []byte) error {
type tmp CopyHeader
- var hTmp *struct {
+ var s struct {
tmp
- ContentLength string `json:"Content-Length"`
+ ContentLength string `json:"Content-Length"`
+ CopiedFromLastModified gophercloud.JSONRFC1123 `json:"X-Copied-From-Last-Modified"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
}
- err := json.Unmarshal(b, &hTmp)
+ err := json.Unmarshal(b, &s)
if err != nil {
return err
}
- *h = CopyHeader(hTmp.tmp)
+ *r = CopyHeader(s.tmp)
- switch hTmp.ContentLength {
+ switch s.ContentLength {
case "":
- h.ContentLength = 0
+ r.ContentLength = 0
default:
- h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+ r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
if err != nil {
return err
}
}
+ r.Date = time.Time(s.Date)
+ r.CopiedFromLastModified = time.Time(s.CopiedFromLastModified)
+ r.LastModified = time.Time(s.LastModified)
+
return nil
}
diff --git a/openstack/objectstorage/v1/objects/testing/fixtures.go b/openstack/objectstorage/v1/objects/testing/fixtures.go
index 53f03f5..08faab8 100644
--- a/openstack/objectstorage/v1/objects/testing/fixtures.go
+++ b/openstack/objectstorage/v1/objects/testing/fixtures.go
@@ -8,7 +8,6 @@
"testing"
"time"
- "github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects"
th "github.com/gophercloud/gophercloud/testhelper"
fake "github.com/gophercloud/gophercloud/testhelper/client"
@@ -32,14 +31,14 @@
var ExpectedListInfo = []objects.Object{
{
Hash: "451e372e48e0f6b1114fa0724aa79fa1",
- LastModified: gophercloud.JSONRFC3339MilliNoZ(time.Date(2016, time.August, 17, 22, 11, 58, 602650000, time.UTC)), //"2016-08-17T22:11:58.602650"
+ LastModified: time.Date(2016, time.August, 17, 22, 11, 58, 602650000, time.UTC), //"2016-08-17T22:11:58.602650"
Bytes: 14,
Name: "goodbye",
ContentType: "application/octet-stream",
},
{
Hash: "451e372e48e0f6b1114fa0724aa79fa1",
- LastModified: gophercloud.JSONRFC3339MilliNoZ(time.Date(2016, time.August, 17, 22, 11, 58, 602650000, time.UTC)),
+ LastModified: time.Date(2016, time.August, 17, 22, 11, 58, 602650000, time.UTC),
Bytes: 14,
Name: "hello",
ContentType: "application/octet-stream",
diff --git a/openstack/objectstorage/v1/objects/testing/requests_test.go b/openstack/objectstorage/v1/objects/testing/requests_test.go
index 21f8e9d..4f26632 100644
--- a/openstack/objectstorage/v1/objects/testing/requests_test.go
+++ b/openstack/objectstorage/v1/objects/testing/requests_test.go
@@ -7,7 +7,6 @@
"testing"
"time"
- "github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects"
"github.com/gophercloud/gophercloud/pagination"
th "github.com/gophercloud/gophercloud/testhelper"
@@ -47,7 +46,7 @@
expected := &objects.DownloadHeader{
ContentLength: 36,
ContentType: "text/plain; charset=utf-8",
- Date: gophercloud.JSONRFC1123(time.Date(2009, time.November, 10, 23, 0, 0, 0, loc)),
+ Date: time.Date(2009, time.November, 10, 23, 0, 0, 0, loc),
}
actual, err := response.Extract()
th.AssertNoErr(t, err)
diff --git a/openstack/orchestration/v1/stackevents/results.go b/openstack/orchestration/v1/stackevents/results.go
index 6c7f183..46fb0ff 100644
--- a/openstack/orchestration/v1/stackevents/results.go
+++ b/openstack/orchestration/v1/stackevents/results.go
@@ -1,6 +1,9 @@
package stackevents
import (
+ "encoding/json"
+ "time"
+
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)
@@ -10,7 +13,7 @@
// The name of the resource for which the event occurred.
ResourceName string `json:"resource_name"`
// The time the event occurred.
- Time gophercloud.JSONRFC3339NoZ `json:"event_time"`
+ Time time.Time `json:"-"`
// The URLs to the event.
Links []gophercloud.Link `json:"links"`
// The logical ID of the stack resource.
@@ -27,6 +30,24 @@
ResourceProperties map[string]interface{} `json:"resource_properties"`
}
+func (r *Event) UnmarshalJSON(b []byte) error {
+ type tmp Event
+ var s struct {
+ tmp
+ Time gophercloud.JSONRFC3339NoZ `json:"event_time"`
+ }
+ err := json.Unmarshal(b, &s)
+ if err != nil {
+ return err
+ }
+
+ *r = Event(s.tmp)
+
+ r.Time = time.Time(s.Time)
+
+ return nil
+}
+
// FindResult represents the result of a Find operation.
type FindResult struct {
gophercloud.Result
diff --git a/openstack/orchestration/v1/stackevents/testing/fixtures.go b/openstack/orchestration/v1/stackevents/testing/fixtures.go
index a7af025..a40e8d4 100644
--- a/openstack/orchestration/v1/stackevents/testing/fixtures.go
+++ b/openstack/orchestration/v1/stackevents/testing/fixtures.go
@@ -16,7 +16,7 @@
var FindExpected = []stackevents.Event{
{
ResourceName: "hello_world",
- Time: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC)),
+ Time: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
Links: []gophercloud.Link{
{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a",
@@ -39,7 +39,7 @@
},
{
ResourceName: "hello_world",
- Time: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC)),
+ Time: time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC),
Links: []gophercloud.Link{
{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18",
@@ -133,7 +133,7 @@
var ListExpected = []stackevents.Event{
{
ResourceName: "hello_world",
- Time: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC)),
+ Time: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
Links: []gophercloud.Link{
{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a",
@@ -156,7 +156,7 @@
},
{
ResourceName: "hello_world",
- Time: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC)),
+ Time: time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC),
Links: []gophercloud.Link{
{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18",
@@ -258,7 +258,7 @@
var ListResourceEventsExpected = []stackevents.Event{
{
ResourceName: "hello_world",
- Time: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC)),
+ Time: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
Links: []gophercloud.Link{
{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a",
@@ -281,7 +281,7 @@
},
{
ResourceName: "hello_world",
- Time: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC)),
+ Time: time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC),
Links: []gophercloud.Link{
{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18",
@@ -382,7 +382,7 @@
// GetExpected represents the expected object from a Get request.
var GetExpected = &stackevents.Event{
ResourceName: "hello_world",
- Time: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC)),
+ Time: time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC),
Links: []gophercloud.Link{
{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18",
diff --git a/openstack/orchestration/v1/stackresources/results.go b/openstack/orchestration/v1/stackresources/results.go
index bd3e29f..59c02a3 100644
--- a/openstack/orchestration/v1/stackresources/results.go
+++ b/openstack/orchestration/v1/stackresources/results.go
@@ -2,6 +2,7 @@
import (
"encoding/json"
+ "time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
@@ -9,18 +10,37 @@
// Resource represents a stack resource.
type Resource struct {
- Attributes map[string]interface{} `json:"attributes"`
- CreationTime gophercloud.JSONRFC3339NoZ `json:"creation_time"`
- Description string `json:"description"`
- Links []gophercloud.Link `json:"links"`
- LogicalID string `json:"logical_resource_id"`
- Name string `json:"resource_name"`
- PhysicalID string `json:"physical_resource_id"`
- RequiredBy []interface{} `json:"required_by"`
- Status string `json:"resource_status"`
- StatusReason string `json:"resource_status_reason"`
- Type string `json:"resource_type"`
- UpdatedTime gophercloud.JSONRFC3339NoZ `json:"updated_time"`
+ Attributes map[string]interface{} `json:"attributes"`
+ CreationTime time.Time `json:"-"`
+ Description string `json:"description"`
+ Links []gophercloud.Link `json:"links"`
+ LogicalID string `json:"logical_resource_id"`
+ Name string `json:"resource_name"`
+ PhysicalID string `json:"physical_resource_id"`
+ RequiredBy []interface{} `json:"required_by"`
+ Status string `json:"resource_status"`
+ StatusReason string `json:"resource_status_reason"`
+ Type string `json:"resource_type"`
+ UpdatedTime time.Time `json:"-"`
+}
+
+func (r *Resource) UnmarshalJSON(b []byte) error {
+ type tmp Resource
+ var s struct {
+ tmp
+ CreationTime gophercloud.JSONRFC3339NoZ `json:"creation_time"`
+ UpdatedTime gophercloud.JSONRFC3339NoZ `json:"updated_time"`
+ }
+ err := json.Unmarshal(b, &s)
+ if err != nil {
+ return err
+ }
+ *r = Resource(s.tmp)
+
+ r.CreationTime = time.Time(s.CreationTime)
+ r.UpdatedTime = time.Time(s.UpdatedTime)
+
+ return nil
}
// FindResult represents the result of a Find operation.
diff --git a/openstack/orchestration/v1/stackresources/testing/fixtures.go b/openstack/orchestration/v1/stackresources/testing/fixtures.go
index adcd4c6..e890337 100644
--- a/openstack/orchestration/v1/stackresources/testing/fixtures.go
+++ b/openstack/orchestration/v1/stackresources/testing/fixtures.go
@@ -28,8 +28,8 @@
},
LogicalID: "hello_world",
StatusReason: "state changed",
- UpdatedTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC)),
- CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 10, 0, time.UTC)),
+ UpdatedTime: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
+ CreationTime: time.Date(2015, 2, 5, 21, 33, 10, 0, time.UTC),
RequiredBy: []interface{}{},
Status: "CREATE_IN_PROGRESS",
PhysicalID: "49181cd6-169a-4130-9455-31185bbfc5bf",
@@ -99,8 +99,8 @@
},
LogicalID: "hello_world",
StatusReason: "state changed",
- UpdatedTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC)),
- CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 10, 0, time.UTC)),
+ UpdatedTime: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
+ CreationTime: time.Date(2015, 2, 5, 21, 33, 10, 0, time.UTC),
RequiredBy: []interface{}{},
Status: "CREATE_IN_PROGRESS",
PhysicalID: "49181cd6-169a-4130-9455-31185bbfc5bf",
@@ -177,7 +177,7 @@
LogicalID: "wordpress_instance",
Attributes: map[string]interface{}{"SXSW": "atx"},
StatusReason: "state changed",
- UpdatedTime: gophercloud.JSONRFC3339NoZ(time.Date(2014, 12, 10, 18, 34, 35, 0, time.UTC)),
+ UpdatedTime: time.Date(2014, 12, 10, 18, 34, 35, 0, time.UTC),
RequiredBy: []interface{}{},
Status: "CREATE_COMPLETE",
PhysicalID: "00e3a2fe-c65d-403c-9483-4db9930dd194",
diff --git a/openstack/orchestration/v1/stacks/results.go b/openstack/orchestration/v1/stacks/results.go
index 6b6f3a3..8df5419 100644
--- a/openstack/orchestration/v1/stacks/results.go
+++ b/openstack/orchestration/v1/stacks/results.go
@@ -2,6 +2,7 @@
import (
"encoding/json"
+ "time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
@@ -47,15 +48,34 @@
// ListedStack represents an element in the slice extracted from a List operation.
type ListedStack struct {
- CreationTime gophercloud.JSONRFC3339NoZ `json:"creation_time"`
- Description string `json:"description"`
- ID string `json:"id"`
- Links []gophercloud.Link `json:"links"`
- Name string `json:"stack_name"`
- Status string `json:"stack_status"`
- StatusReason string `json:"stack_status_reason"`
- Tags []string `json:"tags"`
- UpdatedTime gophercloud.JSONRFC3339NoZ `json:"updated_time"`
+ CreationTime time.Time `json:"-"`
+ Description string `json:"description"`
+ ID string `json:"id"`
+ Links []gophercloud.Link `json:"links"`
+ Name string `json:"stack_name"`
+ Status string `json:"stack_status"`
+ StatusReason string `json:"stack_status_reason"`
+ Tags []string `json:"tags"`
+ UpdatedTime time.Time `json:"-"`
+}
+
+func (r *ListedStack) UnmarshalJSON(b []byte) error {
+ type tmp ListedStack
+ var s struct {
+ tmp
+ CreationTime gophercloud.JSONRFC3339NoZ `json:"creation_time"`
+ UpdatedTime gophercloud.JSONRFC3339NoZ `json:"updated_time"`
+ }
+ err := json.Unmarshal(b, &s)
+ if err != nil {
+ return err
+ }
+ *r = ListedStack(s.tmp)
+
+ r.CreationTime = time.Time(s.CreationTime)
+ r.UpdatedTime = time.Time(s.UpdatedTime)
+
+ return nil
}
// ExtractStacks extracts and returns a slice of ListedStack. It is used while iterating
@@ -70,22 +90,41 @@
// RetrievedStack represents the object extracted from a Get operation.
type RetrievedStack struct {
- Capabilities []interface{} `json:"capabilities"`
- CreationTime gophercloud.JSONRFC3339NoZ `json:"creation_time"`
- Description string `json:"description"`
- DisableRollback bool `json:"disable_rollback"`
- ID string `json:"id"`
- Links []gophercloud.Link `json:"links"`
- NotificationTopics []interface{} `json:"notification_topics"`
- Outputs []map[string]interface{} `json:"outputs"`
- Parameters map[string]string `json:"parameters"`
- Name string `json:"stack_name"`
- Status string `json:"stack_status"`
- StatusReason string `json:"stack_status_reason"`
- Tags []string `json:"tags"`
- TemplateDescription string `json:"template_description"`
- Timeout int `json:"timeout_mins"`
- UpdatedTime gophercloud.JSONRFC3339NoZ `json:"updated_time"`
+ Capabilities []interface{} `json:"capabilities"`
+ CreationTime time.Time `json:"-"`
+ Description string `json:"description"`
+ DisableRollback bool `json:"disable_rollback"`
+ ID string `json:"id"`
+ Links []gophercloud.Link `json:"links"`
+ NotificationTopics []interface{} `json:"notification_topics"`
+ Outputs []map[string]interface{} `json:"outputs"`
+ Parameters map[string]string `json:"parameters"`
+ Name string `json:"stack_name"`
+ Status string `json:"stack_status"`
+ StatusReason string `json:"stack_status_reason"`
+ Tags []string `json:"tags"`
+ TemplateDescription string `json:"template_description"`
+ Timeout int `json:"timeout_mins"`
+ UpdatedTime time.Time `json:"-"`
+}
+
+func (r *RetrievedStack) UnmarshalJSON(b []byte) error {
+ type tmp RetrievedStack
+ var s struct {
+ tmp
+ CreationTime gophercloud.JSONRFC3339NoZ `json:"creation_time"`
+ UpdatedTime gophercloud.JSONRFC3339NoZ `json:"updated_time"`
+ }
+ err := json.Unmarshal(b, &s)
+ if err != nil {
+ return err
+ }
+ *r = RetrievedStack(s.tmp)
+
+ r.CreationTime = time.Time(s.CreationTime)
+ r.UpdatedTime = time.Time(s.UpdatedTime)
+
+ return nil
}
// GetResult represents the result of a Get operation.
@@ -115,19 +154,38 @@
// PreviewedStack represents the result of a Preview operation.
type PreviewedStack struct {
- Capabilities []interface{} `json:"capabilities"`
- CreationTime gophercloud.JSONRFC3339NoZ `json:"creation_time"`
- Description string `json:"description"`
- DisableRollback bool `json:"disable_rollback"`
- ID string `json:"id"`
- Links []gophercloud.Link `json:"links"`
- Name string `json:"stack_name"`
- NotificationTopics []interface{} `json:"notification_topics"`
- Parameters map[string]string `json:"parameters"`
- Resources []interface{} `json:"resources"`
- TemplateDescription string `json:"template_description"`
- Timeout int `json:"timeout_mins"`
- UpdatedTime gophercloud.JSONRFC3339NoZ `json:"updated_time"`
+ Capabilities []interface{} `json:"capabilities"`
+ CreationTime time.Time `json:"-"`
+ Description string `json:"description"`
+ DisableRollback bool `json:"disable_rollback"`
+ ID string `json:"id"`
+ Links []gophercloud.Link `json:"links"`
+ Name string `json:"stack_name"`
+ NotificationTopics []interface{} `json:"notification_topics"`
+ Parameters map[string]string `json:"parameters"`
+ Resources []interface{} `json:"resources"`
+ TemplateDescription string `json:"template_description"`
+ Timeout int `json:"timeout_mins"`
+ UpdatedTime time.Time `json:"-"`
+}
+
+func (r *PreviewedStack) UnmarshalJSON(b []byte) error {
+ type tmp PreviewedStack
+ var s struct {
+ tmp
+ CreationTime gophercloud.JSONRFC3339NoZ `json:"creation_time"`
+ UpdatedTime gophercloud.JSONRFC3339NoZ `json:"updated_time"`
+ }
+ err := json.Unmarshal(b, &s)
+ if err != nil {
+ return err
+ }
+ *r = PreviewedStack(s.tmp)
+
+ r.CreationTime = time.Time(s.CreationTime)
+ r.UpdatedTime = time.Time(s.UpdatedTime)
+
+ return nil
}
// PreviewResult represents the result of a Preview operation.
diff --git a/openstack/orchestration/v1/stacks/testing/fixtures.go b/openstack/orchestration/v1/stacks/testing/fixtures.go
index 2afbed2..f3e3b57 100644
--- a/openstack/orchestration/v1/stacks/testing/fixtures.go
+++ b/openstack/orchestration/v1/stacks/testing/fixtures.go
@@ -61,7 +61,7 @@
},
StatusReason: "Stack CREATE completed successfully",
Name: "postman_stack",
- CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC)),
+ CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC),
Status: "CREATE_COMPLETE",
ID: "16ef0584-4458-41eb-87c8-0dc8d5f66c87",
Tags: []string{"rackspace", "atx"},
@@ -76,8 +76,8 @@
},
StatusReason: "Stack successfully updated",
Name: "gophercloud-test-stack-2",
- CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2014, 12, 11, 17, 39, 16, 0, time.UTC)),
- UpdatedTime: gophercloud.JSONRFC3339NoZ(time.Date(2014, 12, 11, 17, 40, 37, 0, time.UTC)),
+ CreationTime: time.Date(2014, 12, 11, 17, 39, 16, 0, time.UTC),
+ UpdatedTime: time.Date(2014, 12, 11, 17, 40, 37, 0, time.UTC),
Status: "UPDATE_COMPLETE",
ID: "db6977b2-27aa-4775-9ae7-6213212d4ada",
Tags: []string{"sfo", "satx"},
@@ -158,7 +158,7 @@
StatusReason: "Stack CREATE completed successfully",
Name: "postman_stack",
Outputs: []map[string]interface{}{},
- CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC)),
+ CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC),
Links: []gophercloud.Link{
{
Href: "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87",
@@ -256,7 +256,7 @@
"OS::stack_id": "16ef0584-4458-41eb-87c8-0dc8d5f66c87",
},
Name: "postman_stack",
- CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC)),
+ CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC),
Links: []gophercloud.Link{
{
Href: "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87",
diff --git a/openstack/sharedfilesystems/v2/securityservices/results.go b/openstack/sharedfilesystems/v2/securityservices/results.go
index 746b2b3..6874208 100644
--- a/openstack/sharedfilesystems/v2/securityservices/results.go
+++ b/openstack/sharedfilesystems/v2/securityservices/results.go
@@ -1,6 +1,11 @@
package securityservices
-import "github.com/gophercloud/gophercloud"
+import (
+ "encoding/json"
+ "time"
+
+ "github.com/gophercloud/gophercloud"
+)
// SecurityService contains all the information associated with an OpenStack
// SecurityService.
@@ -28,9 +33,28 @@
// The security service host name or IP address
Server string `json:"server"`
// The date and time stamp when the security service was created
- CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
+ CreatedAt time.Time `json:"-"`
// The date and time stamp when the security service was updated
- UpdatedAt gophercloud.JSONRFC3339MilliNoZ `json:"updated_at"`
+ UpdatedAt time.Time `json:"-"`
+}
+
+func (r *SecurityService) UnmarshalJSON(b []byte) error {
+ type tmp SecurityService
+ var s struct {
+ tmp
+ CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
+ UpdatedAt gophercloud.JSONRFC3339MilliNoZ `json:"updated_at"`
+ }
+ err := json.Unmarshal(b, &s)
+ if err != nil {
+ return err
+ }
+ *r = SecurityService(s.tmp)
+
+ r.CreatedAt = time.Time(s.CreatedAt)
+ r.UpdatedAt = time.Time(s.UpdatedAt)
+
+ return nil
}
type commonResult struct {
diff --git a/openstack/sharedfilesystems/v2/sharenetworks/results.go b/openstack/sharedfilesystems/v2/sharenetworks/results.go
index 1eb64bc..6762ef2 100644
--- a/openstack/sharedfilesystems/v2/sharenetworks/results.go
+++ b/openstack/sharedfilesystems/v2/sharenetworks/results.go
@@ -1,8 +1,10 @@
package sharenetworks
import (
+ "encoding/json"
"net/url"
"strconv"
+ "time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
@@ -34,9 +36,28 @@
// The Share Network description
Description string `json:"description"`
// The date and time stamp when the Share Network was created
- CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
+ CreatedAt time.Time `json:"-"`
// The date and time stamp when the Share Network was updated
- UpdatedAt gophercloud.JSONRFC3339MilliNoZ `json:"updated_at"`
+ UpdatedAt time.Time `json:"-"`
+}
+
+func (r *ShareNetwork) UnmarshalJSON(b []byte) error {
+ type tmp ShareNetwork
+ var s struct {
+ tmp
+ CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
+ UpdatedAt gophercloud.JSONRFC3339MilliNoZ `json:"updated_at"`
+ }
+ err := json.Unmarshal(b, &s)
+ if err != nil {
+ return err
+ }
+ *r = ShareNetwork(s.tmp)
+
+ r.CreatedAt = time.Time(s.CreatedAt)
+ r.UpdatedAt = time.Time(s.UpdatedAt)
+
+ return nil
}
type commonResult struct {
diff --git a/openstack/sharedfilesystems/v2/sharenetworks/testing/requests_test.go b/openstack/sharedfilesystems/v2/sharenetworks/testing/requests_test.go
index 0b28623..46c2d92 100644
--- a/openstack/sharedfilesystems/v2/sharenetworks/testing/requests_test.go
+++ b/openstack/sharedfilesystems/v2/sharenetworks/testing/requests_test.go
@@ -4,7 +4,6 @@
"testing"
"time"
- "github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/sharenetworks"
"github.com/gophercloud/gophercloud/pagination"
th "github.com/gophercloud/gophercloud/testhelper"
@@ -63,7 +62,7 @@
{
ID: "32763294-e3d4-456a-998d-60047677c2fb",
Name: "net_my1",
- CreatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2015, 9, 4, 14, 57, 13, 0, time.UTC)),
+ CreatedAt: time.Date(2015, 9, 4, 14, 57, 13, 0, time.UTC),
Description: "descr",
NetworkType: "",
CIDR: "",
@@ -72,13 +71,13 @@
NeutronSubnetID: "53482b62-2c84-4a53-b6ab-30d9d9800d06",
IPVersion: 0,
SegmentationID: 0,
- UpdatedAt: gophercloud.JSONRFC3339MilliNoZ(nilTime),
+ UpdatedAt: nilTime,
ProjectID: "16e1ab15c35a457e9c2b2aa189f544e1",
},
{
ID: "713df749-aac0-4a54-af52-10f6c991e80c",
Name: "net_my",
- CreatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2015, 9, 4, 14, 54, 25, 0, time.UTC)),
+ CreatedAt: time.Date(2015, 9, 4, 14, 54, 25, 0, time.UTC),
Description: "desecr",
NetworkType: "",
CIDR: "",
@@ -87,13 +86,13 @@
NeutronSubnetID: "53482b62-2c84-4a53-b6ab-30d9d9800d06",
IPVersion: 0,
SegmentationID: 0,
- UpdatedAt: gophercloud.JSONRFC3339MilliNoZ(nilTime),
+ UpdatedAt: nilTime,
ProjectID: "16e1ab15c35a457e9c2b2aa189f544e1",
},
{
ID: "fa158a3d-6d9f-4187-9ca5-abbb82646eb2",
Name: "",
- CreatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2015, 9, 4, 14, 51, 41, 0, time.UTC)),
+ CreatedAt: time.Date(2015, 9, 4, 14, 51, 41, 0, time.UTC),
Description: "",
NetworkType: "",
CIDR: "",
@@ -102,7 +101,7 @@
NeutronSubnetID: "",
IPVersion: 0,
SegmentationID: 0,
- UpdatedAt: gophercloud.JSONRFC3339MilliNoZ(nilTime),
+ UpdatedAt: nilTime,
ProjectID: "16e1ab15c35a457e9c2b2aa189f544e1",
},
}
@@ -150,7 +149,7 @@
expected := sharenetworks.ShareNetwork{
ID: "7f950b52-6141-4a08-bbb5-bb7ffa3ea5fd",
Name: "net_my1",
- CreatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2015, 9, 4, 14, 56, 45, 0, time.UTC)),
+ CreatedAt: time.Date(2015, 9, 4, 14, 56, 45, 0, time.UTC),
Description: "descr",
NetworkType: "",
CIDR: "",
@@ -159,7 +158,7 @@
NeutronSubnetID: "53482b62-2c84-4a53-b6ab-30d9d9800d06",
IPVersion: 0,
SegmentationID: 0,
- UpdatedAt: gophercloud.JSONRFC3339MilliNoZ(nilTime),
+ UpdatedAt: nilTime,
ProjectID: "16e1ab15c35a457e9c2b2aa189f544e1",
}
@@ -179,7 +178,7 @@
expected := sharenetworks.ShareNetwork{
ID: "713df749-aac0-4a54-af52-10f6c991e80c",
Name: "net_my2",
- CreatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2015, 9, 4, 14, 54, 25, 0, time.UTC)),
+ CreatedAt: time.Date(2015, 9, 4, 14, 54, 25, 0, time.UTC),
Description: "new description",
NetworkType: "",
CIDR: "",
@@ -188,7 +187,7 @@
NeutronSubnetID: "new-neutron-subnet-id",
IPVersion: 4,
SegmentationID: 0,
- UpdatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2015, 9, 7, 8, 2, 53, 512184000, time.UTC)),
+ UpdatedAt: time.Date(2015, 9, 7, 8, 2, 53, 512184000, time.UTC),
ProjectID: "16e1ab15c35a457e9c2b2aa189f544e1",
}
@@ -214,7 +213,7 @@
expected := sharenetworks.ShareNetwork{
ID: "713df749-aac0-4a54-af52-10f6c991e80c",
Name: "net_my2",
- CreatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2015, 9, 4, 14, 54, 25, 0, time.UTC)),
+ CreatedAt: time.Date(2015, 9, 4, 14, 54, 25, 0, time.UTC),
Description: "new description",
NetworkType: "",
CIDR: "",
@@ -223,7 +222,7 @@
NeutronSubnetID: "",
IPVersion: 4,
SegmentationID: 0,
- UpdatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2015, 9, 7, 8, 2, 53, 512184000, time.UTC)),
+ UpdatedAt: time.Date(2015, 9, 7, 8, 2, 53, 512184000, time.UTC),
ProjectID: "16e1ab15c35a457e9c2b2aa189f544e1",
}
diff --git a/openstack/sharedfilesystems/v2/shares/results.go b/openstack/sharedfilesystems/v2/shares/results.go
index aef9f9a..224d1df 100644
--- a/openstack/sharedfilesystems/v2/shares/results.go
+++ b/openstack/sharedfilesystems/v2/shares/results.go
@@ -1,6 +1,9 @@
package shares
import (
+ "encoding/json"
+ "time"
+
"github.com/gophercloud/gophercloud"
)
@@ -60,7 +63,24 @@
SnapshotSupport bool `json:"snapshot_support"`
SourceCgsnapshotMemberID string `json:"source_cgsnapshot_member_id"`
// Timestamp when the share was created
- CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
+ CreatedAt time.Time `json:"-"`
+}
+
+func (r *Share) UnmarshalJSON(b []byte) error {
+ type tmp Share
+ var s struct {
+ tmp
+ CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
+ }
+ err := json.Unmarshal(b, &s)
+ if err != nil {
+ return err
+ }
+ *r = Share(s.tmp)
+
+ r.CreatedAt = time.Time(s.CreatedAt)
+
+ return nil
}
type commonResult struct {
diff --git a/openstack/sharedfilesystems/v2/shares/testing/request_test.go b/openstack/sharedfilesystems/v2/shares/testing/request_test.go
index 7735e02..5b700a6 100644
--- a/openstack/sharedfilesystems/v2/shares/testing/request_test.go
+++ b/openstack/sharedfilesystems/v2/shares/testing/request_test.go
@@ -1,12 +1,12 @@
package testing
import (
- "github.com/gophercloud/gophercloud"
+ "testing"
+ "time"
+
"github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/shares"
th "github.com/gophercloud/gophercloud/testhelper"
"github.com/gophercloud/gophercloud/testhelper/client"
- "testing"
- "time"
)
func TestCreate(t *testing.T) {
@@ -57,16 +57,15 @@
"project": "my_app",
"aim": "doc",
},
- Status: "available",
- Description: "My custom share London",
- Host: "manila2@generic1#GENERIC1",
- HasReplicas: false,
- ReplicationType: "",
- TaskState: "",
- SnapshotSupport: true,
- Name: "my_test_share",
- CreatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(
- 2015, time.September, 18, 10, 25, 24, 0, time.UTC)),
+ Status: "available",
+ Description: "My custom share London",
+ Host: "manila2@generic1#GENERIC1",
+ HasReplicas: false,
+ ReplicationType: "",
+ TaskState: "",
+ SnapshotSupport: true,
+ Name: "my_test_share",
+ CreatedAt: time.Date(2015, time.September, 18, 10, 25, 24, 0, time.UTC),
ShareProto: "NFS",
VolumeType: "default",
SourceCgsnapshotMemberID: "",