Skip to content

Commit

Permalink
[Feat.] DirectConnect V3 implementation (#719)
Browse files Browse the repository at this point in the history
  • Loading branch information
anton-sidelnikov authored Oct 21, 2024
1 parent 121e91b commit e793177
Show file tree
Hide file tree
Showing 23 changed files with 1,149 additions and 1 deletion.
16 changes: 15 additions & 1 deletion acceptance/clients/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func NewCTSV3Client() (*golangsdk.ServiceClient, error) {
}

// NewDCaaSV2Client returns a *ServiceClient for making calls
// to the OpenStack v2 API. An error will be returned
// to the OpenStack DCaaS v2 API. An error will be returned
// if authentication or client creation was not possible.
func NewDCaaSV2Client() (*golangsdk.ServiceClient, error) {
cc, err := CloudAndClient()
Expand All @@ -164,6 +164,20 @@ func NewDCaaSV2Client() (*golangsdk.ServiceClient, error) {
})
}

// NewDCaaSV3Client returns a *ServiceClient for making calls
// to the OpenStack DCaaS v3 API. An error will be returned
// if authentication or client creation was not possible.
func NewDCaaSV3Client() (*golangsdk.ServiceClient, error) {
cc, err := CloudAndClient()
if err != nil {
return nil, err
}

return openstack.NewDCaaSV3(cc.ProviderClient, golangsdk.EndpointOpts{
Region: cc.RegionName,
})
}

// NewDNSV2Client returns a *ServiceClient for making calls
// to the OpenStack Compute v2 API. An error will be returned
// if authentication or client creation was not possible.
Expand Down
64 changes: 64 additions & 0 deletions acceptance/openstack/dcaas/v3/hosted_connect_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package v3

import (
"os"
"strings"
"testing"

"github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients"
"github.com/opentelekomcloud/gophertelekomcloud/acceptance/tools"
hosted_connect "github.com/opentelekomcloud/gophertelekomcloud/openstack/dcaas/v3/hosted-connect"
th "github.com/opentelekomcloud/gophertelekomcloud/testhelper"
)

func TestHostedConnectLifecycle(t *testing.T) {
t.Skip("This API only available in eu-ch2 region for now")
hostingId := os.Getenv("DCAAS_HOSTING_ID")
if hostingId == "" {
// hostingId = "45d7cbf9-b78e-4273-9a16-68f772b6c71d"
t.Skip("DCAAS_HOSTING_ID must be set for test")
}

client, err := clients.NewDCaaSV3Client()
th.AssertNoErr(t, err)

// Create a hosted connect
name := strings.ToLower(tools.RandomString("test-hosted-connect", 5))
createOpts := hosted_connect.CreateOpts{
Name: name,
Description: "hosted",
Bandwidth: 10,
Vlan: 441,
ResourceTenantId: client.ProjectID,
HostingID: hostingId,
}
t.Logf("Attempting to create DCaaSv3 hosted connect")
created, err := hosted_connect.Create(client, createOpts)
th.AssertNoErr(t, err)

t.Logf("Attempting to retrieve list of DCaaSv3 hosted connects")
l, err := hosted_connect.List(client, hosted_connect.ListOpts{ID: []string{created.ID}})
th.AssertNoErr(t, err)
th.AssertEquals(t, name, l[0].Name)

t.Logf("Attempting to retrieve DCaaSv3 hosted connect: %s", created.ID)
c, err := hosted_connect.Get(client, created.ID)
th.AssertNoErr(t, err)
th.AssertEquals(t, name, c.Name)

t.Logf("Attempting to update DCaaSv3 hosted connect: %s", created.ID)
u, err := hosted_connect.Update(client, created.ID, hosted_connect.UpdateOpts{
Description: "update",
Bandwidth: 20,
})
th.AssertNoErr(t, err)
th.AssertEquals(t, "update", u.Description)
th.AssertEquals(t, 20, u.Bandwidth)

t.Cleanup(func() {
t.Logf("Attempting to delete DCaaSv3 hosted connect: %s", created.ID)

err = hosted_connect.Delete(client, created.ID)
th.AssertNoErr(t, err)
})
}
90 changes: 90 additions & 0 deletions acceptance/openstack/dcaas/v3/virtual_gateway_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package v3

import (
"os"
"strings"
"testing"

"github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients"
"github.com/opentelekomcloud/gophertelekomcloud/acceptance/tools"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/common/pointerto"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/common/tags"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/dcaas/v3/virtual-gateway"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/networking/v1/vpcs"
th "github.com/opentelekomcloud/gophertelekomcloud/testhelper"
)

func TestVirtualGatewayListing(t *testing.T) {
t.Skip("This API only available in eu-ch2 region for now")
client, err := clients.NewDCaaSV3Client()
th.AssertNoErr(t, err)

opts := virtual_gateway.ListOpts{}
vgwList, err := virtual_gateway.List(client, opts)
th.AssertNoErr(t, err)

for _, vgw := range vgwList {
tools.PrintResource(t, vgw)
}
}

func TestVirtualGatewayLifecycle(t *testing.T) {
t.Skip("This API only available in eu-ch2 region for now")
vpcID := os.Getenv("OS_VPC_ID")
if vpcID == "" {
t.Skip("OS_VPC_ID necessary for this test")
}
client, err := clients.NewDCaaSV3Client()
th.AssertNoErr(t, err)

clientNet, err := clients.NewNetworkV1Client()
th.AssertNoErr(t, err)
vpc, err := vpcs.Get(clientNet, vpcID).Extract()
th.AssertNoErr(t, err)

t.Logf("Attempting to create DCaaSv3 virtual gateway")
name := strings.ToLower(tools.RandomString("acc-virtual-gateway-v3-", 5))
createOpts := virtual_gateway.CreateOpts{
Name: name,
VpcId: vpcID,
Description: "acc-virtual-gateway-v3",
LocalEpGroup: []string{vpc.CIDR},
Tags: []tags.ResourceTag{
{
Key: "TestKey",
Value: "TestValue",
},
},
}

created, err := virtual_gateway.Create(client, createOpts)
th.AssertNoErr(t, err)

t.Logf("Attempting to obtain DCaaSv3 virtual gateway: %s", created.ID)
vgw, err := virtual_gateway.Get(client, created.ID)
th.AssertNoErr(t, err)
th.AssertEquals(t, name, vgw.Name)

t.Logf("Attempting to update DCaaSv3 virtual gateway: %s", created.ID)
nameUpdated := strings.ToLower(tools.RandomString("acc-virtual-gateway-v3-up", 5))
updateOpts := virtual_gateway.UpdateOpts{
Name: nameUpdated,
Description: pointerto.String("acc-virtual-gateway-v3-updated"),
}
updated, err := virtual_gateway.Update(client, created.ID, updateOpts)
th.AssertNoErr(t, err)
th.AssertEquals(t, nameUpdated, updated.Name)

t.Logf("Attempting to obtain list of DCaaSv3 virtual gateways: %s", created.ID)
gateways, err := virtual_gateway.List(client, virtual_gateway.ListOpts{
VpcId: vpcID,
})
th.AssertNoErr(t, err)
th.AssertEquals(t, 1, len(gateways))

t.Cleanup(func() {
t.Logf("Attempting to delete DCaaSv3 virtual gateway: %s", created.ID)
err = virtual_gateway.Delete(client, created.ID)
th.AssertNoErr(t, err)
})
}
112 changes: 112 additions & 0 deletions acceptance/openstack/dcaas/v3/virtual_interface_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package v3

import (
"os"
"strings"
"testing"

"github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients"
"github.com/opentelekomcloud/gophertelekomcloud/acceptance/tools"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/common/pointerto"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/common/tags"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/dcaas/v3/virtual-gateway"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/dcaas/v3/virtual-interface"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/networking/v1/vpcs"
th "github.com/opentelekomcloud/gophertelekomcloud/testhelper"
)

func TestVirtualInterfaceListing(t *testing.T) {
t.Skip("This API only available in eu-ch2 region for now")
client, err := clients.NewDCaaSV3Client()
th.AssertNoErr(t, err)

// List virtual interfaces
opts := virtual_interface.ListOpts{}
viList, err := virtual_interface.List(client, opts)
th.AssertNoErr(t, err)

for _, vi := range viList {
tools.PrintResource(t, vi)
}
}

func TestVirtualInterfaceLifecycle(t *testing.T) {
t.Skip("This API only available in eu-ch2 region for now")
dcID := os.Getenv("DIRECT_CONNECT_ID")
vpcID := os.Getenv("OS_VPC_ID")
if vpcID == "" && dcID == "" {
t.Skip("DIRECT_CONNECT_ID and OS_VPC_ID necessary for this test")
}
client, err := clients.NewDCaaSV3Client()
th.AssertNoErr(t, err)

clientNet, err := clients.NewNetworkV1Client()
th.AssertNoErr(t, err)
vpc, err := vpcs.Get(clientNet, vpcID).Extract()
th.AssertNoErr(t, err)

t.Logf("Attempting to create DCaaSv3 virtual gateway")
name := strings.ToLower(tools.RandomString("acc-virtual-gateway-v3-", 5))
createOpts := virtual_gateway.CreateOpts{
Name: name,
VpcId: vpcID,
Description: "acc-virtual-gateway-v3",
LocalEpGroup: []string{vpc.CIDR},
Tags: []tags.ResourceTag{
{
Key: "TestKey",
Value: "TestValue",
},
},
}
vg, err := virtual_gateway.Create(client, createOpts)
th.AssertNoErr(t, err)

t.Cleanup(func() {
err = virtual_gateway.Delete(client, vg.ID)
th.AssertNoErr(t, err)
})

t.Logf("Attempting to create DCaaSv3 virtual interface")
nameVi := tools.RandomString("acc-virtual-interface-", 5)
viOpts := virtual_interface.CreateOpts{
Name: nameVi,
DirectConnectID: dcID,
VgwId: vg.ID,
Type: "private",
ServiceType: "vpc",
VLAN: 100,
Bandwidth: 5,
LocalGatewayV4IP: "16.16.16.1/30",
RemoteGatewayV4IP: "16.16.16.2/30",
RouteMode: "static",
RemoteEpGroup: []string{"16.16.16.0/30"},
}
created, err := virtual_interface.Create(client, viOpts)
th.AssertNoErr(t, err)

t.Logf("Attempting to obtain DCaaSv3 virtual interface: %s", created.ID)
vi, err := virtual_interface.Get(client, created.ID)
th.AssertNoErr(t, err)
th.AssertEquals(t, "16.16.16.0/30", vi.RemoteEpGroup[0])

t.Logf("Attempting to update DCaaSv3 virtual interface: %s", created.ID)
updated, err := virtual_interface.Update(client, created.ID, virtual_interface.UpdateOpts{
Name: name + "-updated",
Description: pointerto.String("New description"),
})
th.AssertNoErr(t, err)
th.AssertEquals(t, name+"-updated", updated.Name)
th.AssertEquals(t, "New description", updated.Description)

t.Logf("Attempting to obtain list of DCaaSv3 virtual interfaces")
viList, err := virtual_interface.List(client, virtual_interface.ListOpts{})
th.AssertNoErr(t, err)
th.AssertEquals(t, 1, len(viList))

t.Cleanup(func() {
t.Logf("Attempting to delete DCaaSv3 virtual interface: %s", created.ID)
err = virtual_interface.Delete(client, created.ID)
th.AssertNoErr(t, err)
})
}
10 changes: 10 additions & 0 deletions openstack/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,16 @@ func NewDCaaSV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*g
return initClientOpts(client, eo, "dcaas")
}

// NewDCaaSV3 creates a ServiceClient that may be used to access the v1 Distributed Message Service.
func NewDCaaSV3(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) {
sc, err := initClientOpts(client, eo, "dcaas")
if err != nil {
return nil, err
}
sc.Endpoint = strings.Replace(sc.Endpoint, "v2.0", "v3/"+client.ProjectID, 1)
return sc, err
}

// NewDMSServiceV1 creates a ServiceClient that may be used to access the v1 Distributed Message Service.
func NewDMSServiceV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) {
return initClientOpts(client, eo, "dmsv1")
Expand Down
83 changes: 83 additions & 0 deletions openstack/dcaas/v3/hosted-connect/Create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package hosted_connect

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

type CreateOpts struct {
// Specifies the hosted connection name.
Name string `json:"name,omitempty"`
// Provides supplementary information about the hosted connection.
Description string `json:"description,omitempty"`
// Specifies the bandwidth of the hosted connection, in Mbit/s.
Bandwidth int `json:"bandwidth" required:"true"`
// Specifies the ID of the operations connection on which the hosted connection is created.
HostingID string `json:"hosting_id" required:"true"`
// Specifies the VLAN allocated to the hosted connection.
Vlan int `json:"vlan" required:"true"`
// Specifies the project ID of the specified tenant for whom a hosted connection is to be created.
ResourceTenantId string `json:"resource_tenant_id" required:"true"`
// Specifies the location of the on-premises facility at the other end of the connection,
// specific to the street or data center name.
PeerLocation string `json:"peer_location,omitempty"`
}

type HostedConnect struct {
// Specifies the hosted connection ID.
ID string `json:"id"`
// Specifies the project ID.
TenantID string `json:"tenant_id"`
// Specifies the connection name.
Name string `json:"name"`
// Provides supplementary information about the connection.
Description string `json:"description"`
// Specifies the connection bandwidth, in Mbit/s.
Bandwidth int `json:"bandwidth"`
// Specifies information about the Direct Connect location.
Location string `json:"location"`
// Specifies the location of the on-premises facility at the other end of the connection,
// specific to the street or data center name.
PeerLocation string `json:"peer_location"`
// Specifies the ID of the operations connection on which the hosted connection is created.
HostingId string `json:"hosting_id"`
// Specifies the provider of the leased line.
Provider string `json:"provider"`
// Specifies the provider of the leased line.
AdminStateUp bool `json:"admin_state_up"`
// Specifies the VLAN allocated to the hosted connection.
Vlan int `json:"vlan"`
// Specifies the operating status.
Status string `json:"status"`
// Specifies when the connection was requested.
// The UTC time format is yyyy-MM-ddTHH:mm:ss.SSSZ.
ApplyTime string `json:"apply_time"`
// Specifies when the connection was created.
// The UTC time format is yyyy-MM-ddTHH:mm:ss.SSSZ.
CreatedAt string `json:"create_time"`
// Specifies the carrier status. The status can be ACTIVE or DOWN.
ProviderStatus string `json:"provider_status"`
// Specifies the type of the port used by the connection.
// The value can be 1G, 10G, 40G, or 100G.
PortType string `json:"port_type"`
// Specifies the type of the connection. The value is hosted.
Type string `json:"type"`
}

func Create(c *golangsdk.ServiceClient, opts CreateOpts) (*HostedConnect, error) {
b, err := build.RequestBody(opts, "hosted_connect")
if err != nil {
return nil, err
}
raw, err := c.Post(c.ServiceURL("dcaas", "hosted-connects"), b, nil, &golangsdk.RequestOpts{
OkCodes: []int{201},
})
if err != nil {
return nil, err
}

var res HostedConnect
err = extract.IntoStructPtr(raw.Body, &res, "hosted_connect")
return &res, err
}
Loading

0 comments on commit e793177

Please sign in to comment.