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/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",