Skip to content

Commit 288ac4a

Browse files
committed
Networking v2: Support two time formats for network resources
1 parent ef348b6 commit 288ac4a

12 files changed

Lines changed: 218 additions & 30 deletions

File tree

openstack/networking/v2/extensions/layer3/floatingips/results.go

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package floatingips
22

33
import (
4+
"encoding/json"
45
"time"
56

67
"github.com/gophercloud/gophercloud"
@@ -41,8 +42,8 @@ type FloatingIP struct {
4142

4243
// UpdatedAt and CreatedAt contain ISO-8601 timestamps of when the state of
4344
// the floating ip last changed, and when it was created.
44-
UpdatedAt time.Time `json:"updated_at"`
45-
CreatedAt time.Time `json:"created_at"`
45+
UpdatedAt time.Time `json:"-"`
46+
CreatedAt time.Time `json:"-"`
4647

4748
// ProjectID is the project owner of the floating IP.
4849
ProjectID string `json:"project_id"`
@@ -57,6 +58,44 @@ type FloatingIP struct {
5758
Tags []string `json:"tags"`
5859
}
5960

61+
func (r *FloatingIP) UnmarshalJSON(b []byte) error {
62+
type tmp FloatingIP
63+
64+
// Support for older neutron time format
65+
var s1 struct {
66+
tmp
67+
CreatedAt gophercloud.JSONRFC3339NoZ `json:"created_at"`
68+
UpdatedAt gophercloud.JSONRFC3339NoZ `json:"updated_at"`
69+
}
70+
71+
err := json.Unmarshal(b, &s1)
72+
if err == nil {
73+
*r = FloatingIP(s1.tmp)
74+
r.CreatedAt = time.Time(s1.CreatedAt)
75+
r.UpdatedAt = time.Time(s1.UpdatedAt)
76+
77+
return nil
78+
}
79+
80+
// Support for newer neutron time format
81+
var s2 struct {
82+
tmp
83+
CreatedAt time.Time `json:"created_at"`
84+
UpdatedAt time.Time `json:"updated_at"`
85+
}
86+
87+
err = json.Unmarshal(b, &s2)
88+
if err != nil {
89+
return err
90+
}
91+
92+
*r = FloatingIP(s2.tmp)
93+
r.CreatedAt = time.Time(s2.CreatedAt)
94+
r.UpdatedAt = time.Time(s2.UpdatedAt)
95+
96+
return nil
97+
}
98+
6099
type commonResult struct {
61100
gophercloud.Result
62101
}

openstack/networking/v2/extensions/layer3/floatingips/testing/fixtures.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ const FipDNS = `{
1010
"fixed_ip_address": null,
1111
"floating_ip_address": "192.0.0.4",
1212
"tenant_id": "017d8de156df4177889f31a9bd6edc00",
13-
"created_at": "2019-06-30T04:15:37Z",
14-
"updated_at": "2019-06-30T05:18:49Z",
13+
"created_at": "2019-06-30T04:15:37",
14+
"updated_at": "2019-06-30T05:18:49",
1515
"status": "DOWN",
1616
"port_id": null,
1717
"id": "2f95fd2b-9f6a-4e8e-9e9a-2cbe286cbf9e",

openstack/networking/v2/extensions/layer3/floatingips/testing/requests_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func TestList(t *testing.T) {
2828

2929
count := 0
3030

31-
floatingips.List(fake.ServiceClient(), floatingips.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
31+
err := floatingips.List(fake.ServiceClient(), floatingips.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
3232
count++
3333
actual, err := floatingips.ExtractFloatingIPs(page)
3434
if err != nil {
@@ -73,6 +73,8 @@ func TestList(t *testing.T) {
7373
return true, nil
7474
})
7575

76+
th.AssertNoErr(t, err)
77+
7678
if count != 1 {
7779
t.Errorf("Expected 1 page, got %d", count)
7880
}

openstack/networking/v2/extensions/security/groups/results.go

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package groups
22

33
import (
4+
"encoding/json"
45
"time"
56

67
"github.com/gophercloud/gophercloud"
@@ -29,8 +30,8 @@ type SecGroup struct {
2930

3031
// UpdatedAt and CreatedAt contain ISO-8601 timestamps of when the state of the
3132
// security group last changed, and when it was created.
32-
UpdatedAt time.Time `json:"updated_at"`
33-
CreatedAt time.Time `json:"created_at"`
33+
UpdatedAt time.Time `json:"-"`
34+
CreatedAt time.Time `json:"-"`
3435

3536
// ProjectID is the project owner of the security group.
3637
ProjectID string `json:"project_id"`
@@ -39,6 +40,44 @@ type SecGroup struct {
3940
Tags []string `json:"tags"`
4041
}
4142

43+
func (r *SecGroup) UnmarshalJSON(b []byte) error {
44+
type tmp SecGroup
45+
46+
// Support for older neutron time format
47+
var s1 struct {
48+
tmp
49+
CreatedAt gophercloud.JSONRFC3339NoZ `json:"created_at"`
50+
UpdatedAt gophercloud.JSONRFC3339NoZ `json:"updated_at"`
51+
}
52+
53+
err := json.Unmarshal(b, &s1)
54+
if err == nil {
55+
*r = SecGroup(s1.tmp)
56+
r.CreatedAt = time.Time(s1.CreatedAt)
57+
r.UpdatedAt = time.Time(s1.UpdatedAt)
58+
59+
return nil
60+
}
61+
62+
// Support for newer neutron time format
63+
var s2 struct {
64+
tmp
65+
CreatedAt time.Time `json:"created_at"`
66+
UpdatedAt time.Time `json:"updated_at"`
67+
}
68+
69+
err = json.Unmarshal(b, &s2)
70+
if err != nil {
71+
return err
72+
}
73+
74+
*r = SecGroup(s2.tmp)
75+
r.CreatedAt = time.Time(s2.CreatedAt)
76+
r.UpdatedAt = time.Time(s2.UpdatedAt)
77+
78+
return nil
79+
}
80+
4281
// SecGroupPage is the page returned by a pager when traversing over a
4382
// collection of security groups.
4483
type SecGroupPage struct {

openstack/networking/v2/extensions/security/groups/testing/fixtures.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ const SecurityGroupListResponse = `
1616
"name": "default",
1717
"security_group_rules": [],
1818
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550",
19-
"created_at": "2019-06-30T04:15:37Z",
20-
"updated_at": "2019-06-30T05:18:49Z"
19+
"created_at": "2019-06-30T04:15:37",
20+
"updated_at": "2019-06-30T05:18:49"
2121
}
2222
]
2323
}

openstack/networking/v2/extensions/security/groups/testing/requests_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func TestList(t *testing.T) {
2828

2929
count := 0
3030

31-
groups.List(fake.ServiceClient(), groups.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
31+
err := groups.List(fake.ServiceClient(), groups.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
3232
count++
3333
actual, err := groups.ExtractGroups(page)
3434
if err != nil {
@@ -42,6 +42,8 @@ func TestList(t *testing.T) {
4242
return true, nil
4343
})
4444

45+
th.AssertNoErr(t, err)
46+
4547
if count != 1 {
4648
t.Errorf("Expected 1 page, got %d", count)
4749
}

openstack/networking/v2/extensions/subnetpools/results.go

Lines changed: 71 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ type SubnetPool struct {
6767
ProjectID string `json:"project_id"`
6868

6969
// CreatedAt is the time at which subnetpool has been created.
70-
CreatedAt time.Time `json:"created_at"`
70+
CreatedAt time.Time `json:"-"`
7171

7272
// UpdatedAt is the time at which subnetpool has been created.
73-
UpdatedAt time.Time `json:"updated_at"`
73+
UpdatedAt time.Time `json:"-"`
7474

7575
// Prefixes is the list of subnet prefixes to assign to the subnetpool.
7676
// Neutron API merges adjacent prefixes and treats them as a single prefix.
@@ -118,20 +118,83 @@ type SubnetPool struct {
118118

119119
func (r *SubnetPool) UnmarshalJSON(b []byte) error {
120120
type tmp SubnetPool
121-
var s struct {
121+
122+
// Support for older neutron time format
123+
var s1 struct {
124+
tmp
125+
DefaultPrefixLen interface{} `json:"default_prefixlen"`
126+
MinPrefixLen interface{} `json:"min_prefixlen"`
127+
MaxPrefixLen interface{} `json:"max_prefixlen"`
128+
129+
CreatedAt gophercloud.JSONRFC3339NoZ `json:"created_at"`
130+
UpdatedAt gophercloud.JSONRFC3339NoZ `json:"updated_at"`
131+
}
132+
133+
err := json.Unmarshal(b, &s1)
134+
if err == nil {
135+
*r = SubnetPool(s1.tmp)
136+
137+
r.CreatedAt = time.Time(s1.CreatedAt)
138+
r.UpdatedAt = time.Time(s1.UpdatedAt)
139+
140+
switch t := s1.DefaultPrefixLen.(type) {
141+
case string:
142+
if r.DefaultPrefixLen, err = strconv.Atoi(t); err != nil {
143+
return err
144+
}
145+
case float64:
146+
r.DefaultPrefixLen = int(t)
147+
default:
148+
return fmt.Errorf("DefaultPrefixLen has unexpected type: %T", t)
149+
}
150+
151+
switch t := s1.MinPrefixLen.(type) {
152+
case string:
153+
if r.MinPrefixLen, err = strconv.Atoi(t); err != nil {
154+
return err
155+
}
156+
case float64:
157+
r.MinPrefixLen = int(t)
158+
default:
159+
return fmt.Errorf("MinPrefixLen has unexpected type: %T", t)
160+
}
161+
162+
switch t := s1.MaxPrefixLen.(type) {
163+
case string:
164+
if r.MaxPrefixLen, err = strconv.Atoi(t); err != nil {
165+
return err
166+
}
167+
case float64:
168+
r.MaxPrefixLen = int(t)
169+
default:
170+
return fmt.Errorf("MaxPrefixLen has unexpected type: %T", t)
171+
}
172+
173+
return nil
174+
}
175+
176+
// Support for newer neutron time format
177+
var s2 struct {
122178
tmp
123179
DefaultPrefixLen interface{} `json:"default_prefixlen"`
124180
MinPrefixLen interface{} `json:"min_prefixlen"`
125181
MaxPrefixLen interface{} `json:"max_prefixlen"`
182+
183+
CreatedAt time.Time `json:"created_at"`
184+
UpdatedAt time.Time `json:"updated_at"`
126185
}
127-
err := json.Unmarshal(b, &s)
186+
187+
err = json.Unmarshal(b, &s2)
128188
if err != nil {
129189
return err
130190
}
131191

132-
*r = SubnetPool(s.tmp)
192+
*r = SubnetPool(s2.tmp)
193+
194+
r.CreatedAt = time.Time(s2.CreatedAt)
195+
r.UpdatedAt = time.Time(s2.UpdatedAt)
133196

134-
switch t := s.DefaultPrefixLen.(type) {
197+
switch t := s2.DefaultPrefixLen.(type) {
135198
case string:
136199
if r.DefaultPrefixLen, err = strconv.Atoi(t); err != nil {
137200
return err
@@ -142,7 +205,7 @@ func (r *SubnetPool) UnmarshalJSON(b []byte) error {
142205
return fmt.Errorf("DefaultPrefixLen has unexpected type: %T", t)
143206
}
144207

145-
switch t := s.MinPrefixLen.(type) {
208+
switch t := s2.MinPrefixLen.(type) {
146209
case string:
147210
if r.MinPrefixLen, err = strconv.Atoi(t); err != nil {
148211
return err
@@ -153,7 +216,7 @@ func (r *SubnetPool) UnmarshalJSON(b []byte) error {
153216
return fmt.Errorf("MinPrefixLen has unexpected type: %T", t)
154217
}
155218

156-
switch t := s.MaxPrefixLen.(type) {
219+
switch t := s2.MaxPrefixLen.(type) {
157220
case string:
158221
if r.MaxPrefixLen, err = strconv.Atoi(t); err != nil {
159222
return err

openstack/networking/v2/extensions/subnetpools/testing/fixtures.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const SubnetPoolsListResult = `
5555
},
5656
{
5757
"address_scope_id": null,
58-
"created_at": "2017-12-28T07:21:27Z",
58+
"created_at": "2017-12-28T07:21:27",
5959
"default_prefixlen": "64",
6060
"default_quota": 4,
6161
"description": "PublicPool",
@@ -72,7 +72,7 @@ const SubnetPoolsListResult = `
7272
"revision_number": 1,
7373
"shared": true,
7474
"tenant_id": "ceb366d50ad54fe39717df3af60f9945",
75-
"updated_at": "2017-12-28T07:21:27Z"
75+
"updated_at": "2017-12-28T07:21:27"
7676
}
7777
]
7878
}
@@ -159,11 +159,11 @@ const SubnetPoolGetResult = `
159159
"is_default": true,
160160
"project_id": "1e2b9857295a4a3e841809ef492812c5",
161161
"tenant_id": "1e2b9857295a4a3e841809ef492812c5",
162-
"created_at": "2018-01-01T00:00:01Z",
162+
"created_at": "2018-01-01T00:00:01",
163163
"prefixes": [
164164
"2001:db8::a3/64"
165165
],
166-
"updated_at": "2018-01-01T00:10:10Z",
166+
"updated_at": "2018-01-01T00:10:10",
167167
"ip_version": 6,
168168
"shared": false,
169169
"description": "ipv6 prefixes",

openstack/networking/v2/extensions/subnetpools/testing/requests_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func TestList(t *testing.T) {
2828

2929
count := 0
3030

31-
subnetpools.List(fake.ServiceClient(), subnetpools.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
31+
err := subnetpools.List(fake.ServiceClient(), subnetpools.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
3232
count++
3333
actual, err := subnetpools.ExtractSubnetPools(page)
3434
if err != nil {
@@ -47,6 +47,8 @@ func TestList(t *testing.T) {
4747
return true, nil
4848
})
4949

50+
th.AssertNoErr(t, err)
51+
5052
if count != 1 {
5153
t.Errorf("Expected 1 page, got %d", count)
5254
}

0 commit comments

Comments
 (0)