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.] DirectConnect V3 implementation #719

Merged
merged 6 commits into from
Oct 21, 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
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