Skip to content

Commit 5afeaf8

Browse files
authored
Merge pull request #3318 from shiftstack/network-standard-attr
Improve support for network `standard-attr-*` extensions
2 parents 7889e7f + 39fc33c commit 5afeaf8

23 files changed

Lines changed: 650 additions & 162 deletions

File tree

internal/acceptance/openstack/networking/v2/extensions/layer3/floatingips_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package layer3
44

55
import (
66
"context"
7+
"strings"
78
"testing"
89

910
"github.com/gophercloud/gophercloud/v2/internal/acceptance/clients"
@@ -203,3 +204,62 @@ func TestLayer3FloatingIPsCreateDeleteBySubnetID(t *testing.T) {
203204

204205
DeleteFloatingIP(t, client, fip.ID)
205206
}
207+
208+
func TestLayer3FloatingIPsRevision(t *testing.T) {
209+
client, err := clients.NewNetworkV2Client()
210+
th.AssertNoErr(t, err)
211+
212+
choices, err := clients.AcceptanceTestChoicesFromEnv()
213+
th.AssertNoErr(t, err)
214+
215+
fip, err := CreateFloatingIP(t, client, choices.ExternalNetworkID, "")
216+
th.AssertNoErr(t, err)
217+
defer DeleteFloatingIP(t, client, fip.ID)
218+
219+
tools.PrintResource(t, fip)
220+
221+
// Store the current revision number.
222+
oldRevisionNumber := fip.RevisionNumber
223+
224+
// Update the fip without revision number.
225+
// This should work.
226+
newDescription := ""
227+
updateOpts := &floatingips.UpdateOpts{
228+
Description: &newDescription,
229+
}
230+
fip, err = floatingips.Update(context.TODO(), client, fip.ID, updateOpts).Extract()
231+
th.AssertNoErr(t, err)
232+
233+
tools.PrintResource(t, fip)
234+
235+
// This should fail due to an old revision number.
236+
newDescription = "new description"
237+
updateOpts = &floatingips.UpdateOpts{
238+
Description: &newDescription,
239+
RevisionNumber: &oldRevisionNumber,
240+
}
241+
_, err = floatingips.Update(context.TODO(), client, fip.ID, updateOpts).Extract()
242+
th.AssertErr(t, err)
243+
if !strings.Contains(err.Error(), "RevisionNumberConstraintFailed") {
244+
t.Fatalf("expected to see an error of type RevisionNumberConstraintFailed, but got the following error instead: %v", err)
245+
}
246+
247+
// Reread the fip to show that it did not change.
248+
fip, err = floatingips.Get(context.TODO(), client, fip.ID).Extract()
249+
th.AssertNoErr(t, err)
250+
251+
tools.PrintResource(t, fip)
252+
253+
// This should work because now we do provide a valid revision number.
254+
newDescription = "new description"
255+
updateOpts = &floatingips.UpdateOpts{
256+
Description: &newDescription,
257+
RevisionNumber: &fip.RevisionNumber,
258+
}
259+
fip, err = floatingips.Update(context.TODO(), client, fip.ID, updateOpts).Extract()
260+
th.AssertNoErr(t, err)
261+
262+
tools.PrintResource(t, fip)
263+
264+
th.AssertEquals(t, fip.Description, newDescription)
265+
}

internal/acceptance/openstack/networking/v2/extensions/layer3/routers_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package layer3
44

55
import (
66
"context"
7+
"strings"
78
"testing"
89

910
"github.com/gophercloud/gophercloud/v2/internal/acceptance/clients"
@@ -213,3 +214,68 @@ func TestLayer3RouterAgents(t *testing.T) {
213214

214215
th.AssertEquals(t, found, true)
215216
}
217+
218+
func TestLayer3RouterRevision(t *testing.T) {
219+
client, err := clients.NewNetworkV2Client()
220+
th.AssertNoErr(t, err)
221+
222+
network, err := networking.CreateNetwork(t, client)
223+
th.AssertNoErr(t, err)
224+
defer networking.DeleteNetwork(t, client, network.ID)
225+
226+
router, err := CreateRouter(t, client, network.ID)
227+
th.AssertNoErr(t, err)
228+
defer DeleteRouter(t, client, router.ID)
229+
230+
tools.PrintResource(t, router)
231+
232+
// Store the current revision number.
233+
oldRevisionNumber := router.RevisionNumber
234+
235+
// Update the router without revision number.
236+
// This should work.
237+
newName := tools.RandomString("TESTACC-", 8)
238+
newDescription := ""
239+
updateOpts := &routers.UpdateOpts{
240+
Name: newName,
241+
Description: &newDescription,
242+
}
243+
router, err = routers.Update(context.TODO(), client, router.ID, updateOpts).Extract()
244+
th.AssertNoErr(t, err)
245+
246+
tools.PrintResource(t, router)
247+
248+
// This should fail due to an old revision number.
249+
newDescription = "new description"
250+
updateOpts = &routers.UpdateOpts{
251+
Name: newName,
252+
Description: &newDescription,
253+
RevisionNumber: &oldRevisionNumber,
254+
}
255+
_, err = routers.Update(context.TODO(), client, router.ID, updateOpts).Extract()
256+
th.AssertErr(t, err)
257+
if !strings.Contains(err.Error(), "RevisionNumberConstraintFailed") {
258+
t.Fatalf("expected to see an error of type RevisionNumberConstraintFailed, but got the following error instead: %v", err)
259+
}
260+
261+
// Reread the router to show that it did not change.
262+
router, err = routers.Get(context.TODO(), client, router.ID).Extract()
263+
th.AssertNoErr(t, err)
264+
265+
tools.PrintResource(t, router)
266+
267+
// This should work because now we do provide a valid revision number.
268+
newDescription = "new description"
269+
updateOpts = &routers.UpdateOpts{
270+
Name: newName,
271+
Description: &newDescription,
272+
RevisionNumber: &router.RevisionNumber,
273+
}
274+
router, err = routers.Update(context.TODO(), client, router.ID, updateOpts).Extract()
275+
th.AssertNoErr(t, err)
276+
277+
tools.PrintResource(t, router)
278+
279+
th.AssertEquals(t, router.Name, newName)
280+
th.AssertEquals(t, router.Description, newDescription)
281+
}

internal/acceptance/openstack/networking/v2/extensions/qos/policies/policies_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package policies
44

55
import (
66
"context"
7+
"strings"
78
"testing"
89

910
"github.com/gophercloud/gophercloud/v2/internal/acceptance/clients"
@@ -59,3 +60,68 @@ func TestPoliciesCRUD(t *testing.T) {
5960

6061
th.AssertEquals(t, found, true)
6162
}
63+
64+
func TestPoliciesRevision(t *testing.T) {
65+
client, err := clients.NewNetworkV2Client()
66+
th.AssertNoErr(t, err)
67+
68+
// Skip these tests if we don't have the required extension
69+
v2.RequireNeutronExtension(t, client, "qos")
70+
71+
// Create a policy
72+
policy, err := CreateQoSPolicy(t, client)
73+
th.AssertNoErr(t, err)
74+
defer DeleteQoSPolicy(t, client, policy.ID)
75+
76+
tools.PrintResource(t, policy)
77+
78+
// Store the current revision number.
79+
oldRevisionNumber := policy.RevisionNumber
80+
81+
// Update the policy without revision number.
82+
// This should work.
83+
newName := tools.RandomString("TESTACC-", 8)
84+
newDescription := ""
85+
updateOpts := &policies.UpdateOpts{
86+
Name: newName,
87+
Description: &newDescription,
88+
}
89+
policy, err = policies.Update(context.TODO(), client, policy.ID, updateOpts).Extract()
90+
th.AssertNoErr(t, err)
91+
92+
tools.PrintResource(t, policy)
93+
94+
// This should fail due to an old revision number.
95+
newDescription = "new description"
96+
updateOpts = &policies.UpdateOpts{
97+
Name: newName,
98+
Description: &newDescription,
99+
RevisionNumber: &oldRevisionNumber,
100+
}
101+
_, err = policies.Update(context.TODO(), client, policy.ID, updateOpts).Extract()
102+
th.AssertErr(t, err)
103+
if !strings.Contains(err.Error(), "RevisionNumberConstraintFailed") {
104+
t.Fatalf("expected to see an error of type RevisionNumberConstraintFailed, but got the following error instead: %v", err)
105+
}
106+
107+
// Reread the policy to show that it did not change.
108+
policy, err = policies.Get(context.TODO(), client, policy.ID).Extract()
109+
th.AssertNoErr(t, err)
110+
111+
tools.PrintResource(t, policy)
112+
113+
// This should work because now we do provide a valid revision number.
114+
newDescription = "new description"
115+
updateOpts = &policies.UpdateOpts{
116+
Name: newName,
117+
Description: &newDescription,
118+
RevisionNumber: &policy.RevisionNumber,
119+
}
120+
policy, err = policies.Update(context.TODO(), client, policy.ID, updateOpts).Extract()
121+
th.AssertNoErr(t, err)
122+
123+
tools.PrintResource(t, policy)
124+
125+
th.AssertEquals(t, policy.Name, newName)
126+
th.AssertEquals(t, policy.Description, newDescription)
127+
}

internal/acceptance/openstack/networking/v2/extensions/security_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package extensions
44

55
import (
66
"context"
7+
"strings"
78
"testing"
89

910
"github.com/gophercloud/gophercloud/v2/internal/acceptance/clients"
@@ -93,3 +94,65 @@ func TestSecurityGroupsPort(t *testing.T) {
9394

9495
tools.PrintResource(t, port)
9596
}
97+
98+
func TestSecurityGroupsRevision(t *testing.T) {
99+
client, err := clients.NewNetworkV2Client()
100+
th.AssertNoErr(t, err)
101+
102+
// Create a group
103+
group, err := CreateSecurityGroup(t, client)
104+
th.AssertNoErr(t, err)
105+
defer DeleteSecurityGroup(t, client, group.ID)
106+
107+
tools.PrintResource(t, group)
108+
109+
// Store the current revision number.
110+
oldRevisionNumber := group.RevisionNumber
111+
112+
// Update the group without revision number.
113+
// This should work.
114+
newName := tools.RandomString("TESTACC-", 8)
115+
newDescription := ""
116+
updateOpts := &groups.UpdateOpts{
117+
Name: newName,
118+
Description: &newDescription,
119+
}
120+
group, err = groups.Update(context.TODO(), client, group.ID, updateOpts).Extract()
121+
th.AssertNoErr(t, err)
122+
123+
tools.PrintResource(t, group)
124+
125+
// This should fail due to an old revision number.
126+
newDescription = "new description"
127+
updateOpts = &groups.UpdateOpts{
128+
Name: newName,
129+
Description: &newDescription,
130+
RevisionNumber: &oldRevisionNumber,
131+
}
132+
_, err = groups.Update(context.TODO(), client, group.ID, updateOpts).Extract()
133+
th.AssertErr(t, err)
134+
if !strings.Contains(err.Error(), "RevisionNumberConstraintFailed") {
135+
t.Fatalf("expected to see an error of type RevisionNumberConstraintFailed, but got the following error instead: %v", err)
136+
}
137+
138+
// Reread the group to show that it did not change.
139+
group, err = groups.Get(context.TODO(), client, group.ID).Extract()
140+
th.AssertNoErr(t, err)
141+
142+
tools.PrintResource(t, group)
143+
144+
// This should work because now we do provide a valid revision number.
145+
newDescription = "new description"
146+
updateOpts = &groups.UpdateOpts{
147+
Name: newName,
148+
Description: &newDescription,
149+
RevisionNumber: &group.RevisionNumber,
150+
}
151+
group, err = groups.Update(context.TODO(), client, group.ID, updateOpts).Extract()
152+
th.AssertNoErr(t, err)
153+
154+
tools.PrintResource(t, group)
155+
156+
th.AssertEquals(t, group.Name, newName)
157+
th.AssertEquals(t, group.Description, newDescription)
158+
}

internal/acceptance/openstack/networking/v2/extensions/subnetpools/subnetpools_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package v2
44

55
import (
66
"context"
7+
"strings"
78
"testing"
89

910
"github.com/gophercloud/gophercloud/v2/internal/acceptance/clients"
@@ -55,3 +56,63 @@ func TestSubnetPoolsCRUD(t *testing.T) {
5556

5657
th.AssertEquals(t, found, true)
5758
}
59+
60+
func TestSubnetPoolsRevision(t *testing.T) {
61+
client, err := clients.NewNetworkV2Client()
62+
th.AssertNoErr(t, err)
63+
64+
// Create a subnetpool
65+
subnetPool, err := CreateSubnetPool(t, client)
66+
th.AssertNoErr(t, err)
67+
defer DeleteSubnetPool(t, client, subnetPool.ID)
68+
69+
// Store the current revision number.
70+
oldRevisionNumber := subnetPool.RevisionNumber
71+
72+
// Update the subnet pool without revision number.
73+
// This should work.
74+
newName := tools.RandomString("TESTACC-", 8)
75+
newDescription := ""
76+
updateOpts := &subnetpools.UpdateOpts{
77+
Name: newName,
78+
Description: &newDescription,
79+
}
80+
subnetPool, err = subnetpools.Update(context.TODO(), client, subnetPool.ID, updateOpts).Extract()
81+
th.AssertNoErr(t, err)
82+
83+
tools.PrintResource(t, subnetPool)
84+
85+
// This should fail due to an old revision number.
86+
newDescription = "new description"
87+
updateOpts = &subnetpools.UpdateOpts{
88+
Name: newName,
89+
Description: &newDescription,
90+
RevisionNumber: &oldRevisionNumber,
91+
}
92+
_, err = subnetpools.Update(context.TODO(), client, subnetPool.ID, updateOpts).Extract()
93+
th.AssertErr(t, err)
94+
if !strings.Contains(err.Error(), "RevisionNumberConstraintFailed") {
95+
t.Fatalf("expected to see an error of type RevisionNumberConstraintFailed, but got the following error instead: %v", err)
96+
}
97+
98+
// Reread the subnet pool to show that it did not change.
99+
subnetPool, err = subnetpools.Get(context.TODO(), client, subnetPool.ID).Extract()
100+
th.AssertNoErr(t, err)
101+
102+
tools.PrintResource(t, subnetPool)
103+
104+
// This should work because now we do provide a valid revision number.
105+
newDescription = "new description"
106+
updateOpts = &subnetpools.UpdateOpts{
107+
Name: newName,
108+
Description: &newDescription,
109+
RevisionNumber: &subnetPool.RevisionNumber,
110+
}
111+
subnetPool, err = subnetpools.Update(context.TODO(), client, subnetPool.ID, updateOpts).Extract()
112+
th.AssertNoErr(t, err)
113+
114+
tools.PrintResource(t, subnetPool)
115+
116+
th.AssertEquals(t, subnetPool.Name, newName)
117+
th.AssertEquals(t, subnetPool.Description, newDescription)
118+
}

0 commit comments

Comments
 (0)