Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d987a08

Browse filesBrowse files
authored
Merge pull request #2406 from shhgs/2022-05-20
Neutron v2: AddGatewayNetwork, RemoveGatewayNetwork and GetAdvertised…
2 parents 500e61e + b957a55 commit d987a08
Copy full SHA for d987a08

File tree

Expand file treeCollapse file tree

7 files changed

+327
-20
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+327
-20
lines changed

‎acceptance/openstack/networking/v2/extensions/bgp/speakers/bgpspeakers_test.go

Copy file name to clipboardExpand all lines: acceptance/openstack/networking/v2/extensions/bgp/speakers/bgpspeakers_test.go
+27Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"testing"
55

66
"github.com/gophercloud/gophercloud/acceptance/clients"
7+
networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
78
ap "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2/extensions/bgp/peers"
89
"github.com/gophercloud/gophercloud/acceptance/tools"
910
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/bgp/peers"
@@ -34,6 +35,11 @@ func TestBGPSpeakerCRUD(t *testing.T) {
3435
tools.PrintResource(t, allSpeakers)
3536
th.AssertIntGreaterOrEqual(t, len(allSpeakers), 1)
3637

38+
// Create a network
39+
network, err := networking.CreateNetwork(t, client)
40+
th.AssertNoErr(t, err)
41+
defer networking.DeleteNetwork(t, client, network.ID)
42+
3743
// Update BGP Speaker
3844
opts := speakers.UpdateOpts{
3945
Name: tools.RandomString("TESTACC-BGPSPEAKER-", 10),
@@ -69,6 +75,27 @@ func TestBGPSpeakerCRUD(t *testing.T) {
6975
th.AssertEquals(t, len(speakerGot.Networks), 0)
7076
t.Logf("Successfully removed BGP Peer %s to BGP Speaker %s", bgpPeer.Name, speakerUpdated.Name)
7177

78+
// GetAdvertisedRoutes
79+
pages, err := speakers.GetAdvertisedRoutes(client, bgpSpeaker.ID).AllPages()
80+
th.AssertNoErr(t, err)
81+
routes, err := speakers.ExtractAdvertisedRoutes(pages)
82+
th.AssertNoErr(t, err)
83+
th.AssertIntGreaterOrEqual(t, len(routes), 0)
84+
t.Logf("Successfully retrieved advertised routes")
85+
86+
// AddGatewayNetwork
87+
optsAddGatewayNetwork := speakers.AddGatewayNetworkOpts{NetworkID: network.ID}
88+
r, err := speakers.AddGatewayNetwork(client, bgpSpeaker.ID, optsAddGatewayNetwork).Extract()
89+
th.AssertNoErr(t, err)
90+
th.AssertEquals(t, r.NetworkID, network.ID)
91+
t.Logf("Successfully added gateway network %s to BGP Speaker", network.ID)
92+
93+
// RemoveGatewayNetwork
94+
optsRemoveGatewayNetwork := speakers.RemoveGatewayNetworkOpts{NetworkID: network.ID}
95+
err = speakers.RemoveGatewayNetwork(client, bgpSpeaker.ID, optsRemoveGatewayNetwork).ExtractErr()
96+
th.AssertNoErr(t, err)
97+
t.Logf("Successfully removed gateway network %s to BGP Speaker", network.ID)
98+
7299
// Delete a BGP Peer
73100
t.Logf("Delete the BGP Peer %s", bgpPeer.Name)
74101
err = peers.Delete(client, bgpPeer.ID).ExtractErr()

‎openstack/networking/v2/extensions/bgp/speakers/doc.go

Copy file name to clipboardExpand all lines: openstack/networking/v2/extensions/bgp/speakers/doc.go
+62-20Lines changed: 62 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ Example:
3737
3838
Example:
3939
40-
opts := speakers.CreateOpts{
41-
IPVersion: 6,
42-
AdvertiseFloatingIPHostRoutes: false,
43-
AdvertiseTenantNetworks: true,
44-
Name: "gophercloud-testing-bgp-speaker",
45-
LocalAS: "2000",
46-
Networks: []string{},
47-
}
40+
opts := speakers.CreateOpts{
41+
IPVersion: 6,
42+
AdvertiseFloatingIPHostRoutes: false,
43+
AdvertiseTenantNetworks: true,
44+
Name: "gophercloud-testing-bgp-speaker",
45+
LocalAS: "2000",
46+
Networks: []string{},
47+
}
4848
r, err := speakers.Create(c, opts).Extract()
4949
if err != nil {
5050
log.Panic(err)
@@ -67,23 +67,23 @@ Example:
6767
6868
Example:
6969
70-
opts := speakers.UpdateOpts{
71-
Name: "testing-bgp-speaker",
72-
AdvertiseTenantNetworks: false,
73-
AdvertiseFloatingIPHostRoutes: true,
74-
}
75-
spk, err := speakers.Update(c, bgpSpeakerID, opts).Extract()
76-
if err != nil {
77-
log.Panic(err)
78-
}
79-
log.Printf("%+v", spk)
70+
opts := speakers.UpdateOpts{
71+
Name: "testing-bgp-speaker",
72+
AdvertiseTenantNetworks: false,
73+
AdvertiseFloatingIPHostRoutes: true,
74+
}
75+
spk, err := speakers.Update(c, bgpSpeakerID, opts).Extract()
76+
if err != nil {
77+
log.Panic(err)
78+
}
79+
log.Printf("%+v", spk)
8080
8181
8282
7. Add BGP Peer, a.k.a. PUT /bgp-speakers/{id}/add_bgp_peer
8383
8484
Example:
8585
86-
opts := speakers.AddBGPPeerOpts{BGPPeerID: bgpPeerID}
86+
opts := speakers.AddBGPPeerOpts{BGPPeerID: bgpPeerID}
8787
r, err := speakers.AddBGPPeer(c, bgpSpeakerID, opts).Extract()
8888
if err != nil {
8989
log.Panic(err)
@@ -95,10 +95,52 @@ Example:
9595
9696
Example:
9797
98-
opts := speakers.RemoveBGPPeerOpts{BGPPeerID: bgpPeerID}
98+
opts := speakers.RemoveBGPPeerOpts{BGPPeerID: bgpPeerID}
9999
err := speakers.RemoveBGPPeer(c, bgpSpeakerID, opts).ExtractErr()
100100
if err != nil {
101101
log.Panic(err)
102102
}
103103
log.Printf("Successfully removed BGP Peer")
104+
105+
106+
9. Get advertised routes, a.k.a. GET /bgp-speakers/{id}/get_advertised_routes
107+
108+
Example:
109+
110+
pages, err := speakers.GetAdvertisedRoutes(c, speakerID).AllPages()
111+
if err != nil {
112+
log.Panic(err)
113+
}
114+
routes, err := speakers.ExtractAdvertisedRoutes(pages)
115+
if err != nil {
116+
log.Panic(err)
117+
}
118+
for _, r := range routes {
119+
log.Printf("%+v", r)
120+
}
121+
122+
123+
10. Add geteway network to BGP Speaker, a.k.a. PUT /bgp-speakers/{id}/add_gateway_network
124+
125+
Example:
126+
127+
128+
opts := speakers.AddGatewayNetworkOpts{NetworkID: networkID}
129+
r, err := speakers.AddGatewayNetwork(c, speakerID, opts).Extract()
130+
if err != nil {
131+
log.Panic(err)
132+
}
133+
log.Printf("%+v", r)
134+
135+
136+
11. Remove gateway network to BGP Speaker, a.k.a. PUT /bgp-speakers/{id}/remove_gateway_network
137+
138+
Example:
139+
140+
opts := speakers.RemoveGatewayNetworkOpts{NetworkID: networkID}
141+
err := speakers.RemoveGatewayNetwork(c, speakerID, opts).ExtractErr()
142+
if err != nil {
143+
log.Panic(err)
144+
}
145+
log.Printf("Successfully removed gateway network")
104146
*/

‎openstack/networking/v2/extensions/bgp/speakers/requests.go

Copy file name to clipboardExpand all lines: openstack/networking/v2/extensions/bgp/speakers/requests.go
+65Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,68 @@ func RemoveBGPPeer(c *gophercloud.ServiceClient, bgpSpeakerID string, opts Remov
146146
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
147147
return
148148
}
149+
150+
// GetAdvertisedRoutes a.k.a. GET /v2.0/bgp-speakers/{bgp-speaker-id}/get_advertised_routes
151+
func GetAdvertisedRoutes(c *gophercloud.ServiceClient, bgpSpeakerID string) pagination.Pager {
152+
url := getAdvertisedRoutesURL(c, bgpSpeakerID)
153+
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
154+
return AdvertisedRoutePage{pagination.SinglePageBase(r)}
155+
})
156+
}
157+
158+
// AddGatewayNetworkOptsBuilder declare a function that build AddGatewayNetworkOpts into a request body.
159+
type AddGatewayNetworkOptsBuilder interface {
160+
ToBGPSpeakerAddGatewayNetworkMap() (map[string]interface{}, error)
161+
}
162+
163+
// AddGatewayNetworkOpts represents the data that would be PUT to the endpoint
164+
type AddGatewayNetworkOpts struct {
165+
// The uuid of the network
166+
NetworkID string `json:"network_id"`
167+
}
168+
169+
// ToBGPSpeakerAddGatewayNetworkMap implements the function
170+
func (opts AddGatewayNetworkOpts) ToBGPSpeakerAddGatewayNetworkMap() (map[string]interface{}, error) {
171+
return gophercloud.BuildRequestBody(opts, "")
172+
}
173+
174+
// AddGatewayNetwork a.k.a. PUT /v2.0/bgp-speakers/{bgp-speaker-id}/add_gateway_network
175+
func AddGatewayNetwork(c *gophercloud.ServiceClient, bgpSpeakerID string, opts AddGatewayNetworkOptsBuilder) (r AddGatewayNetworkResult) {
176+
b, err := opts.ToBGPSpeakerAddGatewayNetworkMap()
177+
if err != nil {
178+
r.Err = err
179+
return
180+
}
181+
resp, err := c.Put(addGatewayNetworkURL(c, bgpSpeakerID), b, &r.Body, &gophercloud.RequestOpts{
182+
OkCodes: []int{200},
183+
})
184+
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
185+
return
186+
}
187+
188+
// RemoveGatewayNetworkOptsBuilder declare a function that build RemoveGatewayNetworkOpts into a request body.
189+
type RemoveGatewayNetworkOptsBuilder interface {
190+
ToBGPSpeakerRemoveGatewayNetworkMap() (map[string]interface{}, error)
191+
}
192+
193+
// RemoveGatewayNetworkOpts represent the data that would be PUT to the endpoint
194+
type RemoveGatewayNetworkOpts AddGatewayNetworkOpts
195+
196+
// ToBGPSpeakerRemoveGatewayNetworkMap implement the function
197+
func (opts RemoveGatewayNetworkOpts) ToBGPSpeakerRemoveGatewayNetworkMap() (map[string]interface{}, error) {
198+
return gophercloud.BuildRequestBody(opts, "")
199+
}
200+
201+
// RemoveGatewayNetwork a.k.a. PUT /v2.0/bgp-speakers/{bgp-speaker-id}/remove_gateway_network
202+
func RemoveGatewayNetwork(c *gophercloud.ServiceClient, bgpSpeakerID string, opts RemoveGatewayNetworkOptsBuilder) (r RemoveGatewayNetworkResult) {
203+
b, err := opts.ToBGPSpeakerRemoveGatewayNetworkMap()
204+
if err != nil {
205+
r.Err = err
206+
return
207+
}
208+
resp, err := c.Put(removeGatewayNetworkURL(c, bgpSpeakerID), b, &r.Body, &gophercloud.RequestOpts{
209+
OkCodes: []int{200},
210+
})
211+
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
212+
return
213+
}

‎openstack/networking/v2/extensions/bgp/speakers/results.go

Copy file name to clipboardExpand all lines: openstack/networking/v2/extensions/bgp/speakers/results.go
+51Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,54 @@ func (r AddBGPPeerResult) ExtractInto(v interface{}) error {
128128
type RemoveBGPPeerResult struct {
129129
gophercloud.ErrResult
130130
}
131+
132+
// AdvertisedRoute represents an advertised route
133+
type AdvertisedRoute struct {
134+
// NextHop IP address
135+
NextHop string `json:"next_hop"`
136+
137+
// Destination Network
138+
Destination string `json:"destination"`
139+
}
140+
141+
// AdvertisedRoutePage is the page returned by a pager when you call
142+
type AdvertisedRoutePage struct {
143+
pagination.SinglePageBase
144+
}
145+
146+
// IsEmpty checks whether a AdvertisedRoutePage struct is empty.
147+
func (r AdvertisedRoutePage) IsEmpty() (bool, error) {
148+
is, err := ExtractAdvertisedRoutes(r)
149+
return len(is) == 0, err
150+
}
151+
152+
// ExtractAdvertisedRoutes accepts a Page struct, a.k.a. AdvertisedRoutePage struct,
153+
// and extracts the elements into a slice of AdvertisedRoute structs.
154+
func ExtractAdvertisedRoutes(r pagination.Page) ([]AdvertisedRoute, error) {
155+
var s []AdvertisedRoute
156+
err := ExtractAdvertisedRoutesInto(r, &s)
157+
return s, err
158+
}
159+
160+
// ExtractAdvertisedRoutesInto extract the advertised routes from the first param into the 2nd
161+
func ExtractAdvertisedRoutesInto(r pagination.Page, v interface{}) error {
162+
return r.(AdvertisedRoutePage).Result.ExtractIntoSlicePtr(v, "advertised_routes")
163+
}
164+
165+
// AddGatewayNetworkResult represents the data that would be PUT to
166+
// /v2.0/bgp-speakers/{bgp-speaker-id}/add_gateway_network
167+
type AddGatewayNetworkResult struct {
168+
gophercloud.Result
169+
}
170+
171+
func (r AddGatewayNetworkResult) Extract() (*AddGatewayNetworkOpts, error) {
172+
var s AddGatewayNetworkOpts
173+
err := r.ExtractInto(&s)
174+
return &s, err
175+
}
176+
177+
// RemoveGatewayNetworkResult represents the data that would be PUT to
178+
// /v2.0/bgp-speakers/{bgp-speaker-id}/remove_gateway_network
179+
type RemoveGatewayNetworkResult struct {
180+
gophercloud.ErrResult
181+
}

‎openstack/networking/v2/extensions/bgp/speakers/testing/fixture.go

Copy file name to clipboardExpand all lines: openstack/networking/v2/extensions/bgp/speakers/testing/fixture.go
+25Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,28 @@ const AddRemoveBGPPeerJSON = `
122122
"bgp_peer_id": "f5884c7c-71d5-43a3-88b4-1742e97674aa"
123123
}
124124
`
125+
126+
const GetAdvertisedRoutesResult = `
127+
{
128+
"advertised_routes": [
129+
{
130+
"next_hop": "172.17.128.212",
131+
"destination": "172.17.129.192/27"
132+
},
133+
{
134+
"next_hop": "172.17.128.218",
135+
"destination": "172.17.129.0/27"
136+
},
137+
{
138+
"next_hop": "172.17.128.231",
139+
"destination": "172.17.129.160/27"
140+
}
141+
]
142+
}
143+
`
144+
145+
const AddRemoveGatewayNetworkJSON = `
146+
{
147+
"network_id": "ac13bb26-6219-49c3-a880-08847f6830b7"
148+
}
149+
`

‎openstack/networking/v2/extensions/bgp/speakers/testing/requests_test.go

Copy file name to clipboardExpand all lines: openstack/networking/v2/extensions/bgp/speakers/testing/requests_test.go
+82Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,85 @@ func TestRemoveBGPPeer(t *testing.T) {
194194
err := speakers.RemoveBGPPeer(fake.ServiceClient(), bgpSpeakerID, opts).ExtractErr()
195195
th.AssertEquals(t, err, io.EOF)
196196
}
197+
198+
func TestGetAdvertisedRoutes(t *testing.T) {
199+
th.SetupHTTP()
200+
defer th.TeardownHTTP()
201+
202+
bgpSpeakerID := "ab01ade1-ae62-43c9-8a1f-3c24225b96d8"
203+
th.Mux.HandleFunc("/v2.0/bgp-speakers/"+bgpSpeakerID+"/get_advertised_routes", func(w http.ResponseWriter, r *http.Request) {
204+
th.TestMethod(t, r, "GET")
205+
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
206+
w.Header().Add("Content-Type", "application/json")
207+
w.WriteHeader(http.StatusOK)
208+
fmt.Fprintf(w, GetAdvertisedRoutesResult)
209+
})
210+
211+
count := 0
212+
speakers.GetAdvertisedRoutes(fake.ServiceClient(), bgpSpeakerID).EachPage(
213+
func(page pagination.Page) (bool, error) {
214+
count++
215+
actual, err := speakers.ExtractAdvertisedRoutes(page)
216+
217+
if err != nil {
218+
t.Errorf("Failed to extract Advertised route: %v", err)
219+
return false, nil
220+
}
221+
222+
expected := []speakers.AdvertisedRoute{
223+
speakers.AdvertisedRoute{NextHop: "172.17.128.212", Destination: "172.17.129.192/27"},
224+
speakers.AdvertisedRoute{NextHop: "172.17.128.218", Destination: "172.17.129.0/27"},
225+
speakers.AdvertisedRoute{NextHop: "172.17.128.231", Destination: "172.17.129.160/27"},
226+
}
227+
th.CheckDeepEquals(t, count, 1)
228+
th.CheckDeepEquals(t, expected, actual)
229+
return true, nil
230+
})
231+
}
232+
233+
func TestAddGatewayNetwork(t *testing.T) {
234+
th.SetupHTTP()
235+
defer th.TeardownHTTP()
236+
237+
bgpSpeakerID := "ab01ade1-ae62-43c9-8a1f-3c24225b96d8"
238+
networkID := "ac13bb26-6219-49c3-a880-08847f6830b7"
239+
th.Mux.HandleFunc("/v2.0/bgp-speakers/"+bgpSpeakerID+"/add_gateway_network", func(w http.ResponseWriter, r *http.Request) {
240+
th.TestMethod(t, r, "PUT")
241+
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
242+
th.TestHeader(t, r, "Content-Type", "application/json")
243+
th.TestHeader(t, r, "Accept", "application/json")
244+
th.TestJSONRequest(t, r, AddRemoveGatewayNetworkJSON)
245+
246+
w.Header().Add("Content-Type", "application/json")
247+
w.WriteHeader(http.StatusOK)
248+
fmt.Fprintf(w, AddRemoveGatewayNetworkJSON)
249+
})
250+
251+
opts := speakers.AddGatewayNetworkOpts{NetworkID: networkID}
252+
r, err := speakers.AddGatewayNetwork(fake.ServiceClient(), bgpSpeakerID, opts).Extract()
253+
th.AssertNoErr(t, err)
254+
th.AssertEquals(t, r.NetworkID, networkID)
255+
}
256+
257+
func TestRemoveGatewayNetwork(t *testing.T) {
258+
th.SetupHTTP()
259+
defer th.TeardownHTTP()
260+
261+
bgpSpeakerID := "ab01ade1-ae62-43c9-8a1f-3c24225b96d8"
262+
networkID := "ac13bb26-6219-49c3-a880-08847f6830b7"
263+
th.Mux.HandleFunc("/v2.0/bgp-speakers/"+bgpSpeakerID+"/remove_gateway_network", func(w http.ResponseWriter, r *http.Request) {
264+
th.TestMethod(t, r, "PUT")
265+
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
266+
th.TestHeader(t, r, "Content-Type", "application/json")
267+
th.TestHeader(t, r, "Accept", "application/json")
268+
th.TestJSONRequest(t, r, AddRemoveGatewayNetworkJSON)
269+
270+
w.Header().Add("Content-Type", "application/json")
271+
w.WriteHeader(http.StatusOK)
272+
fmt.Fprintf(w, "")
273+
})
274+
275+
opts := speakers.RemoveGatewayNetworkOpts{NetworkID: networkID}
276+
err := speakers.RemoveGatewayNetwork(fake.ServiceClient(), bgpSpeakerID, opts).ExtractErr()
277+
th.AssertEquals(t, err, io.EOF)
278+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.