Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat.] Enterprise VPN Connection Monitoring and EVPN Tags #734

Merged
merged 2 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 77 additions & 1 deletion acceptance/openstack/evpn/connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ import (
"github.com/opentelekomcloud/gophertelekomcloud/openstack/common/pointerto"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/common/tags"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/evpn/v5/connection"
cm "github.com/opentelekomcloud/gophertelekomcloud/openstack/evpn/v5/connection-monitoring"
cgw "github.com/opentelekomcloud/gophertelekomcloud/openstack/evpn/v5/customer-gateway"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/evpn/v5/gateway"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/evpn/v5/quota"
vpntags "github.com/opentelekomcloud/gophertelekomcloud/openstack/evpn/v5/tags"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/networking/v1/eips"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/networking/v2/subnets"
th "github.com/opentelekomcloud/gophertelekomcloud/testhelper"
Expand Down Expand Up @@ -73,7 +76,6 @@ func TestConnectionLifecycle(t *testing.T) {
t.Logf("Attempting to DELETE Enterprise VPN Connection: %s", gw.ID)
th.AssertNoErr(t, connection.Delete(client, conn.ID))
th.AssertNoErr(t, WaitForConnectionDeleted(client, conn.ID, 800))

})

t.Logf("Attempting to GET Enterprise VPN Connection: %s", conn.ID)
Expand Down Expand Up @@ -106,6 +108,52 @@ func TestConnectionLifecycle(t *testing.T) {
})
th.AssertNoErr(t, err)
th.AssertEquals(t, 1, len(connList))

t.Logf("Attempting to CREATE Enterprise VPN Connection Monitoring")
monitoring, err := cm.Create(client, cm.CreateOpts{ConnectionID: conn.ID})
th.AssertNoErr(t, err)
th.AssertNoErr(t, WaitForConnectionMonitoringActive(client, monitoring.ID, 800))
th.AssertEquals(t, conn.ID, monitoring.ConnectionId)

t.Cleanup(func() {
t.Logf("Attempting to DELETE Enterprise VPN Connection Monitoring: %s", monitoring.ID)
th.AssertNoErr(t, cm.Delete(client, monitoring.ID))
th.AssertNoErr(t, WaitForConnectionMonitoringDeleted(client, monitoring.ID, 800))
})

t.Logf("Attempting to GET Enterprise VPN Connection Monitor: %s", monitoring.ID)
monitor, err := cm.Get(client, monitoring.ID)
th.AssertNoErr(t, err)
th.AssertEquals(t, "ACTIVE", monitor.Status)

t.Logf("Attempting to LIST Enterprise VPN Connection Monitor: %s", monitoring.ID)
monitorList, err := cm.List(client, cm.ListOpts{ConnectionId: conn.ID})
th.AssertNoErr(t, err)
th.AssertEquals(t, 1, len(monitorList))

t.Logf("Attempting to GET Enterprise VPN Quotas: %s", monitoring.ID)
quotas, err := quota.Get(client)
th.AssertNoErr(t, err)
th.AssertEquals(t, 3, len(quotas.Resources))

extraTag := []tags.ResourceTag{
{
Key: "One",
Value: "gopher",
},
}
t.Logf("Attempting to CREATE Enterprise VPN Connection Tag: %s", extraTag)
err = vpntags.Create(client, "vpn-connection", conn.ID, vpntags.TagsOpts{Tags: extraTag})
th.AssertNoErr(t, err)

t.Cleanup(func() {
t.Logf("Attempting to DELETE Enterprise VPN Connection Tag: %s", extraTag)
th.AssertNoErr(t, vpntags.Delete(client, "vpn-connection", conn.ID, vpntags.TagsOpts{Tags: extraTag}))
})
t.Logf("Attempting to LIST Enterprise VPN Connection Tags: %s", conn.ID)
tagList, err := vpntags.List(client, "vpn-connection", conn.ID)
th.AssertNoErr(t, err)
th.AssertEquals(t, 2, len(tagList))
}

func createEvpnCustomerGateway(t *testing.T, client *golangsdk.ServiceClient) *cgw.CustomerGateway {
Expand All @@ -132,6 +180,7 @@ func createEvpnCustomerGateway(t *testing.T, client *golangsdk.ServiceClient) *c
})
return gw
}

func createEvpnGateway(t *testing.T, subnet *subnets.Subnet, vpcId string, client *golangsdk.ServiceClient) *gateway.Gateway {
clientNetV1, err := clients.NewNetworkV1Client()
th.AssertNoErr(t, err)
Expand Down Expand Up @@ -210,3 +259,30 @@ func WaitForConnectionActive(c *golangsdk.ServiceClient, id string, secs int) er
return false, nil
})
}

func WaitForConnectionMonitoringDeleted(c *golangsdk.ServiceClient, id string, secs int) error {
return golangsdk.WaitFor(secs, func() (bool, error) {
_, err := cm.Get(c, id)
if err != nil {
if _, ok := err.(golangsdk.ErrDefault404); ok {
return true, nil
}
return false, fmt.Errorf("error retriving connection status: %w", err)
}
return false, nil
})
}

func WaitForConnectionMonitoringActive(c *golangsdk.ServiceClient, id string, secs int) error {
return golangsdk.WaitFor(secs, func() (bool, error) {
current, err := cm.Get(c, id)
if err != nil {
return false, err
}

if current.Status == "ACTIVE" {
return true, nil
}
return false, nil
})
}
50 changes: 50 additions & 0 deletions openstack/evpn/v5/connection-monitoring/Create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package connection_monitoring

import (
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/build"
"github.com/opentelekomcloud/gophertelekomcloud/internal/extract"
)

type CreateOpts struct {
// Specifies the ID of the VPN connection to be monitored.
ConnectionID string `json:"vpn_connection_id" required:"true"`
}

func Create(client *golangsdk.ServiceClient, opts CreateOpts) (*Monitor, error) {
b, err := build.RequestBody(opts, "connection_monitor")
if err != nil {
return nil, err
}

raw, err := client.Post(client.ServiceURL("connection-monitors"), b, nil, &golangsdk.RequestOpts{
OkCodes: []int{202, 201},
})
if err != nil {
return nil, err
}

var res Monitor
return &res, extract.IntoStructPtr(raw.Body, &res, "connection_monitor")
}

type Monitor struct {
// Specifies the ID of a VPN connection monitor.
ID string `json:"id"`
// Specifies the ID of the VPN connection to be monitored.
ConnectionId string `json:"vpn_connection_id"`
// Specifies the type of objects to be monitored.
Type string `json:"type"`
// Specifies the source address to be monitored.
SourceIp string `json:"source_ip"`
// Specifies the destination address to be monitored.
DestinationIp string `json:"destination_ip"`
// Specifies the protocol used by NQA.
ProtoType string `json:"proto_type"`
// Specifies the status of the VPN connection monitor.
// Value range:
// ACTIVE: normal
// PENDING_CREATE: creating
// PENDING_DELETE: deleting
Status string `json:"status"`
}
10 changes: 10 additions & 0 deletions openstack/evpn/v5/connection-monitoring/Delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package connection_monitoring

import (
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
)

func Delete(client *golangsdk.ServiceClient, id string) (err error) {
_, err = client.Delete(client.ServiceURL("connection-monitors", id), nil)
return
}
17 changes: 17 additions & 0 deletions openstack/evpn/v5/connection-monitoring/Get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package connection_monitoring

import (
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/extract"
)

func Get(client *golangsdk.ServiceClient, monitorId string) (*Monitor, error) {
raw, err := client.Get(client.ServiceURL("connection-monitors", monitorId), nil, nil)
if err != nil {
return nil, err
}

var res Monitor
err = extract.IntoStructPtr(raw.Body, &res, "connection_monitor")
return &res, err
}
28 changes: 28 additions & 0 deletions openstack/evpn/v5/connection-monitoring/List.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package connection_monitoring

import (
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/extract"
)

type ListOpts struct {
// Specifies a VPN connection ID.
ConnectionId string `q:"vpn_connection_id"`
}

func List(client *golangsdk.ServiceClient, opts ListOpts) ([]Monitor, error) {
url, err := golangsdk.NewURLBuilder().
WithEndpoints("connection-monitors").WithQueryParams(&opts).Build()
if err != nil {
return nil, err
}

raw, err := client.Get(client.ServiceURL(url.String()), nil, nil)
if err != nil {
return nil, err
}

var res []Monitor
err = extract.IntoSlicePtr(raw.Body, &res, "connection_monitors")
return res, err
}
2 changes: 2 additions & 0 deletions openstack/evpn/v5/gateway/Create.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ type Gateway struct {
NetworkType string `json:"network_type"`
// Specifies the association mode.
AttachmentType string `json:"attachment_type"`
// Specifies the AZ where the VPN gateway is deployed.
AvailabilityZoneIds string `json:"availability_zone_ids"`
// Specifies the ID of the enterprise router instance to which the VPN gateway connects.
// This parameter is available only when attachment_type is set to er.
ErId string `json:"er_id"`
Expand Down
40 changes: 40 additions & 0 deletions openstack/evpn/v5/quota/Get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package quota

import (
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/extract"
)

func Get(client *golangsdk.ServiceClient) (*Quota, error) {
url, err := golangsdk.NewURLBuilder().
WithEndpoints("vpn", "quotas").Build()
if err != nil {
return nil, err
}

raw, err := client.Get(client.ServiceURL(url.String()), nil, nil)
if err != nil {
return nil, err
}

var res Quota
err = extract.IntoStructPtr(raw.Body, &res, "quotas")
return &res, err
}

type Quota struct {
Resources []Info `json:"resources"`
}

type Info struct {
// Specifies a resource type.
// Value range:
// customer_gateway: customer gateway
// vpn_connection: Enterprise Edition VPN connection
// vpn_gateway: Enterprise Edition VPN gateway
Type string `json:"type"`
// Specifies the quota upper limit.
Quota int `json:"quota"`
// Specifies the number of resources in use.
Used int `json:"used"`
}
28 changes: 28 additions & 0 deletions openstack/evpn/v5/tags/Create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package tags

import (
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/build"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/common/tags"
)

type TagsOpts struct {
// Specifies a tag list.
// A maximum of 20 tags can be specified.
Tags []tags.ResourceTag `json:"tags" required:"true"`
}

// Create creates tags
// resourceType Specifies the resource type.
// The value can be vpn-gateway, customer-gateway, or vpn-connection.
func Create(client *golangsdk.ServiceClient, resourceType, resourceId string, opts TagsOpts) error {
b, err := build.RequestBody(opts, "")
if err != nil {
return err
}
_, err = client.Post(client.ServiceURL(resourceType, resourceId, "tags", "create"), b, nil, &golangsdk.RequestOpts{
OkCodes: []int{204},
MoreHeaders: map[string]string{"Content-Type": "application/json", "X-Language": "en-us"},
})
return err
}
18 changes: 18 additions & 0 deletions openstack/evpn/v5/tags/Delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package tags

import (
"github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/build"
)

func Delete(client *golangsdk.ServiceClient, resourceType, resourceId string, opts TagsOpts) error {
b, err := build.RequestBody(opts, "")
if err != nil {
return err
}
_, err = client.Post(client.ServiceURL(resourceType, resourceId, "tags", "delete"), b, nil, &golangsdk.RequestOpts{
OkCodes: []int{204},
MoreHeaders: map[string]string{"Content-Type": "application/json", "X-Language": "en-us"},
})
return err
}
24 changes: 24 additions & 0 deletions openstack/evpn/v5/tags/List.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package tags

import (
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/extract"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/common/tags"
)

func List(client *golangsdk.ServiceClient, resourceType, resourceId string) ([]tags.ResourceTag, error) {
url, err := golangsdk.NewURLBuilder().
WithEndpoints(resourceType, resourceId, "tags").Build()
if err != nil {
return nil, err
}

raw, err := client.Get(client.ServiceURL(url.String()), nil, nil)
if err != nil {
return nil, err
}

var res []tags.ResourceTag
err = extract.IntoSlicePtr(raw.Body, &res, "tags")
return res, err
}