From d9d1196a68a7766e3a48262a389c940a540cfe30 Mon Sep 17 00:00:00 2001 From: anton-sidelnikov Date: Thu, 19 Sep 2024 13:40:45 +0200 Subject: [PATCH 1/5] Feat. DirectConnect V3 implementation --- acceptance/clients/clients.go | 16 +++- .../openstack/dcaas/v3/hosted_connect_test.go | 44 ++++++++++ .../dcaas/v3/virtual_gateway_test.go | 72 ++++++++++++++++ openstack/client.go | 10 +++ openstack/dcaas/v3/hosted-connect/Create.go | 83 +++++++++++++++++++ openstack/dcaas/v3/hosted-connect/Delete.go | 10 +++ openstack/dcaas/v3/virtual-gateway/Create.go | 50 +++++++++++ openstack/dcaas/v3/virtual-gateway/Delete.go | 10 +++ openstack/dcaas/v3/virtual-gateway/Get.go | 17 ++++ openstack/dcaas/v3/virtual-gateway/List.go | 77 +++++++++++++++++ openstack/dcaas/v3/virtual-gateway/Update.go | 38 +++++++++ .../dcaas/v3/virtual-interface/Create.go | 43 ++++++++++ .../dcaas/v3/virtual-interface/Delete.go | 13 +++ openstack/dcaas/v3/virtual-interface/Get.go | 18 ++++ openstack/dcaas/v3/virtual-interface/List.go | 64 ++++++++++++++ .../dcaas/v3/virtual-interface/Update.go | 32 +++++++ 16 files changed, 596 insertions(+), 1 deletion(-) create mode 100644 acceptance/openstack/dcaas/v3/hosted_connect_test.go create mode 100644 acceptance/openstack/dcaas/v3/virtual_gateway_test.go create mode 100644 openstack/dcaas/v3/hosted-connect/Create.go create mode 100644 openstack/dcaas/v3/hosted-connect/Delete.go create mode 100644 openstack/dcaas/v3/virtual-gateway/Create.go create mode 100644 openstack/dcaas/v3/virtual-gateway/Delete.go create mode 100644 openstack/dcaas/v3/virtual-gateway/Get.go create mode 100644 openstack/dcaas/v3/virtual-gateway/List.go create mode 100644 openstack/dcaas/v3/virtual-gateway/Update.go create mode 100644 openstack/dcaas/v3/virtual-interface/Create.go create mode 100644 openstack/dcaas/v3/virtual-interface/Delete.go create mode 100644 openstack/dcaas/v3/virtual-interface/Get.go create mode 100644 openstack/dcaas/v3/virtual-interface/List.go create mode 100644 openstack/dcaas/v3/virtual-interface/Update.go diff --git a/acceptance/clients/clients.go b/acceptance/clients/clients.go index f4b596c1d..fa8787e7f 100644 --- a/acceptance/clients/clients.go +++ b/acceptance/clients/clients.go @@ -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() @@ -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. diff --git a/acceptance/openstack/dcaas/v3/hosted_connect_test.go b/acceptance/openstack/dcaas/v3/hosted_connect_test.go new file mode 100644 index 000000000..0ef0a7e12 --- /dev/null +++ b/acceptance/openstack/dcaas/v3/hosted_connect_test.go @@ -0,0 +1,44 @@ +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("The API does not exist or has not been published in the environment") + hostingId := os.Getenv("DCAAS_HOSTING_ID") + if hostingId == "" { + 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.Cleanup(func() { + t.Logf("Attempting to delte DCaaSv3 hosted connect: %s", created.ID) + + err = hosted_connect.Delete(client, created.ID) + th.AssertNoErr(t, err) + }) +} diff --git a/acceptance/openstack/dcaas/v3/virtual_gateway_test.go b/acceptance/openstack/dcaas/v3/virtual_gateway_test.go new file mode 100644 index 000000000..aa3bb8d1a --- /dev/null +++ b/acceptance/openstack/dcaas/v3/virtual_gateway_test.go @@ -0,0 +1,72 @@ +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" + th "github.com/opentelekomcloud/gophertelekomcloud/testhelper" +) + +func TestVirtualGatewayListing(t *testing.T) { + 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) { + if os.Getenv("OS_VPC_ID") == "" { + t.Skip("OS_VPC_ID necessary for this test") + } + client, err := clients.NewDCaaSV3Client() + th.AssertNoErr(t, err) + + // Create a virtual gateway + name := strings.ToLower(tools.RandomString("test-virtual-gateway", 5)) + createOpts := virtual_gateway.CreateOpts{ + Name: name, + VpcId: os.Getenv("OS_VPC_ID"), + Description: "test-virtual-gateway-v3", + LocalEpGroup: []string{""}, + Tags: []tags.ResourceTag{ + { + Key: "TestKey", + Value: "TestValue", + }, + }, + } + + created, err := virtual_gateway.Create(client, createOpts) + th.AssertNoErr(t, err) + + _, err = virtual_gateway.Get(client, created.ID) + th.AssertNoErr(t, err) + + updateOpts := virtual_gateway.UpdateOpts{ + Name: tools.RandomString(name, 3), + Description: pointerto.String("test-virtual-gateway-v3-updated"), + } + _ = virtual_gateway.Update(client, created.ID, updateOpts) + th.AssertNoErr(t, err) + + opts := virtual_gateway.ListOpts{} + _, err = virtual_gateway.List(client, opts) + th.AssertNoErr(t, err) + + t.Cleanup(func() { + err = virtual_gateway.Delete(client, created.ID) + th.AssertNoErr(t, err) + }) +} diff --git a/openstack/client.go b/openstack/client.go index 4467e8e0b..2e5e98be5 100644 --- a/openstack/client.go +++ b/openstack/client.go @@ -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") diff --git a/openstack/dcaas/v3/hosted-connect/Create.go b/openstack/dcaas/v3/hosted-connect/Create.go new file mode 100644 index 000000000..c1ff579d9 --- /dev/null +++ b/openstack/dcaas/v3/hosted-connect/Create.go @@ -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, "direct_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 +} diff --git a/openstack/dcaas/v3/hosted-connect/Delete.go b/openstack/dcaas/v3/hosted-connect/Delete.go new file mode 100644 index 000000000..cd046e7f4 --- /dev/null +++ b/openstack/dcaas/v3/hosted-connect/Delete.go @@ -0,0 +1,10 @@ +package hosted_connect + +import golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + +func Delete(c *golangsdk.ServiceClient, id string) (err error) { + _, err = c.Delete(c.ServiceURL("dcaas", "hosted-connects", id), &golangsdk.RequestOpts{ + OkCodes: []int{200, 201, 204}, + }) + return +} diff --git a/openstack/dcaas/v3/virtual-gateway/Create.go b/openstack/dcaas/v3/virtual-gateway/Create.go new file mode 100644 index 000000000..b2efba3a1 --- /dev/null +++ b/openstack/dcaas/v3/virtual-gateway/Create.go @@ -0,0 +1,50 @@ +package virtual_gateway + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/common/tags" +) + +type CreateOpts struct { + // The ID of the VPC connected to the virtual gateway. + VpcId string `json:"vpc_id" required:"true"` + // The list of IPv4 subnets from the virtual gateway to access cloud services, which is usually the CIDR block of + // the VPC. + LocalEpGroup []string `json:"local_ep_group" required:"true"` + // The list of IPv6 subnets from the virtual gateway to access cloud services, which is usually the CIDR block of + // the VPC. + LocalEpGroupIpv6 []string `json:"local_ep_group_ipv6,omitempty"` + // Specifies the name of the virtual gateway. + // The valid length is limited from 0 to 64, only chinese and english letters, digits, hyphens (-), underscores (_) + // and dots (.) are allowed. + // The name must start with a chinese or english letter, and the Chinese characters must be in **UTF-8** or + // **Unicode** format. + Name string `json:"name,omitempty"` + // Specifies the description of the virtual gateway. + // The description contain a maximum of 64 characters and the angle brackets (< and >) are not allowed. + // Chinese characters must be in **UTF-8** or **Unicode** format. + Description string `json:"description,omitempty"` + // The local BGP ASN of the virtual gateway. + BgpAsn int `json:"bgp_asn,omitempty"` + // The key/value pairs to associate with the virtual gateway. + Tags []tags.ResourceTag `json:"tags,omitempty"` +} + +func Create(c *golangsdk.ServiceClient, opts CreateOpts) (*VirtualGateway, error) { + b, err := build.RequestBody(opts, "virtual_gateway") + if err != nil { + return nil, err + } + raw, err := c.Post(c.ServiceURL("dcaas", "virtual-gateways"), b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{201}, + }) + if err != nil { + return nil, err + } + + var res VirtualGateway + err = extract.IntoStructPtr(raw.Body, &res, "virtual_gateway") + return &res, err +} diff --git a/openstack/dcaas/v3/virtual-gateway/Delete.go b/openstack/dcaas/v3/virtual-gateway/Delete.go new file mode 100644 index 000000000..5af2a98bd --- /dev/null +++ b/openstack/dcaas/v3/virtual-gateway/Delete.go @@ -0,0 +1,10 @@ +package virtual_gateway + +import golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + +func Delete(c *golangsdk.ServiceClient, id string) (err error) { + _, err = c.Delete(c.ServiceURL("dcaas", "virtual-gateways", id), &golangsdk.RequestOpts{ + OkCodes: []int{200, 201, 204}, + }) + return +} diff --git a/openstack/dcaas/v3/virtual-gateway/Get.go b/openstack/dcaas/v3/virtual-gateway/Get.go new file mode 100644 index 000000000..47c7a703e --- /dev/null +++ b/openstack/dcaas/v3/virtual-gateway/Get.go @@ -0,0 +1,17 @@ +package virtual_gateway + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +func Get(c *golangsdk.ServiceClient, id string) (*VirtualGateway, error) { + raw, err := c.Get(c.ServiceURL("dcaas", "virtual-gateways", id), nil, nil) + if err != nil { + return nil, err + } + + var res VirtualGateway + err = extract.IntoStructPtr(raw.Body, &res, "virtual_gateway") + return &res, err +} diff --git a/openstack/dcaas/v3/virtual-gateway/List.go b/openstack/dcaas/v3/virtual-gateway/List.go new file mode 100644 index 000000000..0c27d3a08 --- /dev/null +++ b/openstack/dcaas/v3/virtual-gateway/List.go @@ -0,0 +1,77 @@ +package virtual_gateway + +import ( + "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" + "github.com/opentelekomcloud/gophertelekomcloud/openstack" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/common/tags" +) + +type ListOpts struct { + // virtual gateway by ID + ID string `q:"id,omitempty"` + // Specifies the number of records returned on each page. Value range: 1-2000 + Limit int `q:"limit,omitempty"` + // Specifies the ID of the last resource record on the previous page. If this parameter is left blank, the first page is queried. + // This parameter must be used together with limit. + Marker string `q:"marker,omitempty"` + // Specifies the list of fields to be displayed. + Fields []interface{} `q:"fields,omitempty"` + // Specifies the sorting order of returned results. The value can be asc (default) or desc. + SortDir string `q:"sort_dir,omitempty"` + // Specifies the field for sorting. + SortKey string `q:"sort_key,omitempty"` + // Specifies the VPC ID by which virtual gateways are queried. + VpcId string `q:"vpc_id,omitempty"` +} + +// List is used to obtain the virtual gateway list +func List(client *golangsdk.ServiceClient, opts ListOpts) ([]VirtualGateway, error) { + url, err := golangsdk.NewURLBuilder().WithEndpoints("dcaas", "virtual-gateways").WithQueryParams(&opts).Build() + if err != nil { + return nil, err + } + + // GET https://{Endpoint}/v3/{project_id}/virtual-gateways + raw, err := client.Get(client.ServiceURL(url.String()), nil, openstack.StdRequestOpts()) + if err != nil { + return nil, err + } + + var res []VirtualGateway + err = extract.IntoSlicePtr(raw.Body, &res, "virtual_gateways") + return res, err +} + +type VirtualGateway struct { + // The ID of the virtual gateway. + ID string `json:"id"` + // The ID of the VPC connected to the virtual gateway. + VpcId string `json:"vpc_id"` + // The project ID to which the virtual gateway belongs. + TenantId string `json:"tenant_id"` + // Specifies the name of the virtual gateway. + // The valid length is limited from 0 to 64, only chinese and english letters, digits, hyphens (-), underscores (_) + // and dots (.) are allowed. + // The name must start with a chinese or english letter, and the Chinese characters must be in **UTF-8** or + // **Unicode** format. + Name string `json:"name"` + // Specifies the description of the virtual gateway. + // The description contain a maximum of 64 characters and the angle brackets (< and >) are not allowed. + // Chinese characters must be in **UTF-8** or **Unicode** format. + Description string `json:"description"` + // The type of virtual gateway. + Type string `json:"type"` + // The list of IPv4 subnets from the virtual gateway to access cloud services, which is usually the CIDR block of + // the VPC. + LocalEpGroup []string `json:"local_ep_group"` + // The list of IPv6 subnets from the virtual gateway to access cloud services, which is usually the CIDR block of + // the VPC. + LocalEpGroupIpv6 []string `json:"local_ep_group_ipv6"` + // The current status of the virtual gateway. + Status string `json:"status"` + // The local BGP ASN of the virtual gateway. + BgpAsn int `json:"bgp_asn"` + // The key/value pairs to associate with the virtual gateway. + Tags []tags.ResourceTag `json:"tags"` +} diff --git a/openstack/dcaas/v3/virtual-gateway/Update.go b/openstack/dcaas/v3/virtual-gateway/Update.go new file mode 100644 index 000000000..8f093fb9b --- /dev/null +++ b/openstack/dcaas/v3/virtual-gateway/Update.go @@ -0,0 +1,38 @@ +package virtual_gateway + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" +) + +type UpdateOpts struct { + // The list of IPv4 subnets from the virtual gateway to access cloud services, which is usually the CIDR block of + // the VPC. + LocalEpGroup []string `json:"local_ep_group" required:"true"` + // The list of IPv6 subnets from the virtual gateway to access cloud services, which is usually the CIDR block of + // the VPC. + LocalEpGroupIpv6 []string `json:"local_ep_group_ipv6,omitempty"` + // Specifies the name of the virtual gateway. + // The valid length is limited from 0 to 64, only chinese and english letters, digits, hyphens (-), underscores (_) + // and dots (.) are allowed. + // The name must start with a chinese or english letter, and the Chinese characters must be in **UTF-8** or + // **Unicode** format. + Name string `json:"name,omitempty"` + // Specifies the description of the virtual gateway. + // The description contain a maximum of 64 characters and the angle brackets (< and >) are not allowed. + // Chinese characters must be in **UTF-8** or **Unicode** format. + Description *string `json:"description,omitempty"` +} + +func Update(c *golangsdk.ServiceClient, id string, opts UpdateOpts) (err error) { + b, err := build.RequestBody(opts, "virtual_gateway") + if err != nil { + return + } + + _, err = c.Put(c.ServiceURL("dcaas", "virtual-gateways", id), b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{200, 202}, + }) + + return +} diff --git a/openstack/dcaas/v3/virtual-interface/Create.go b/openstack/dcaas/v3/virtual-interface/Create.go new file mode 100644 index 000000000..e9caa97d6 --- /dev/null +++ b/openstack/dcaas/v3/virtual-interface/Create.go @@ -0,0 +1,43 @@ +package virtual_interface + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +type CreateOpts struct { + TenantID string `json:"tenant_id,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + DirectConnectID string `json:"direct_connect_id" required:"true"` + VgwID string `json:"vgw_id" required:"true"` + Type string `json:"type" required:"true"` + ServiceType string `json:"service_type" required:"true"` + VLAN int `json:"vlan" required:"true"` + Bandwidth int `json:"bandwidth" required:"true"` + LocalGatewayV4IP string `json:"local_gateway_v4_ip" required:"true"` + RemoteGatewayV4IP string `json:"remote_gateway_v4_ip" required:"true"` + RouteMode string `json:"route_mode" required:"true"` + BGPASN int `json:"bgp_asn,omitempty"` + BGPMD5 string `json:"bgp_md5,omitempty"` + RemoteEPGroupID string `json:"remote_ep_group_id" required:"true"` + AdminStateUp bool `json:"admin_state_up,omitempty"` +} + +func Create(c *golangsdk.ServiceClient, opts CreateOpts) (*VirtualInterface, error) { + b, err := build.RequestBody(opts, "virtual_interface") + if err != nil { + return nil, err + } + raw, err := c.Post(c.ServiceURL("dcaas", "virtual-interfaces"), b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{201}, + }) + if err != nil { + return nil, err + } + + var res VirtualInterface + err = extract.IntoStructPtr(raw.Body, &res, "virtual_interface") + return &res, err +} diff --git a/openstack/dcaas/v3/virtual-interface/Delete.go b/openstack/dcaas/v3/virtual-interface/Delete.go new file mode 100644 index 000000000..a35ce6567 --- /dev/null +++ b/openstack/dcaas/v3/virtual-interface/Delete.go @@ -0,0 +1,13 @@ +package virtual_interface + +import golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + +// Delete will permanently delete a particular VirtualInterface based on its +// unique ID. + +func Delete(c *golangsdk.ServiceClient, id string) (err error) { + _, err = c.Delete(c.ServiceURL("dcaas", "virtual-interfaces", id), &golangsdk.RequestOpts{ + OkCodes: []int{200, 201, 204}, + }) + return +} diff --git a/openstack/dcaas/v3/virtual-interface/Get.go b/openstack/dcaas/v3/virtual-interface/Get.go new file mode 100644 index 000000000..231266998 --- /dev/null +++ b/openstack/dcaas/v3/virtual-interface/Get.go @@ -0,0 +1,18 @@ +package virtual_interface + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +// Get retrieves a particular virtual gateway based on its unique ID. +func Get(client *golangsdk.ServiceClient, id string) (*VirtualInterface, error) { + raw, err := client.Get(client.ServiceURL("dcaas", "virtual-interfaces", id), nil, nil) + if err != nil { + return nil, err + } + + var res VirtualInterface + err = extract.IntoStructPtr(raw.Body, &res, "virtual_interface") + return &res, err +} diff --git a/openstack/dcaas/v3/virtual-interface/List.go b/openstack/dcaas/v3/virtual-interface/List.go new file mode 100644 index 000000000..608207811 --- /dev/null +++ b/openstack/dcaas/v3/virtual-interface/List.go @@ -0,0 +1,64 @@ +package virtual_interface + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" + "github.com/opentelekomcloud/gophertelekomcloud/openstack" +) + +type ListOpts struct { + ID string `q:"id"` +} + +type VirtualInterface struct { + ID string `json:"id"` + TenantID string `json:"tenant_id"` + Name string `json:"name"` + Description string `json:"description"` + DirectConnectID string `json:"direct_connect_id"` + VgwID string `json:"vgw_id"` + Type string `json:"type"` + ServiceType string `json:"service_type"` + VLAN int `json:"vlan"` + Bandwidth int `json:"bandwidth"` + LocalGatewayV4IP string `json:"local_gateway_v4_ip"` + RemoteGatewayV4IP string `json:"remote_gateway_v4_ip"` + RouteMode string `json:"route_mode"` + BGPASN int `json:"bgp_asn"` + BGPMD5 string `json:"bgp_md5"` + RemoteEPGroupID string `json:"remote_ep_group_id"` + ServiceEPGroupID string `json:"service_ep_group_id"` + CreateTime string `json:"create_time"` + Status string `json:"status"` + AdminStateUp bool `json:"admin_state_up"` + AddressFamily string `json:"address_family"` + EnableBFD bool `json:"enable_bfd"` + HealthCheckSourceIP string `json:"health_check_source_ip"` + RateLimit bool `json:"rate_limit"` + RouteLimit int `json:"route_limit"` + RegionID string `json:"region_id"` + EnableNQA bool `json:"enable_nqa"` + EnableGRE bool `json:"enable_gre"` + LocalGatewayV6IP string `json:"local_gateway_v6_ip"` + RemoteGatewayV6IP string `json:"remote_gateway_v6_ip"` + LocalGRETunnelIP string `json:"local_gre_tunnel_ip"` + RemoteGRETunnelIP string `json:"remote_gre_tunnel_ip"` + LagID string `json:"lag_id"` +} + +func List(client *golangsdk.ServiceClient, opts ListOpts) ([]VirtualInterface, error) { + url, err := golangsdk.NewURLBuilder().WithEndpoints("dcaas", "virtual-interfaces").WithQueryParams(&opts).Build() + if err != nil { + return nil, err + } + + // GET https://{Endpoint}/v2.0/{project_id}/virtual-interfaces?id={id} + raw, err := client.Get(client.ServiceURL(url.String()), nil, openstack.StdRequestOpts()) + if err != nil { + return nil, err + } + + var res []VirtualInterface + err = extract.IntoSlicePtr(raw.Body, &res, "virtual_interfaces") + return res, err +} diff --git a/openstack/dcaas/v3/virtual-interface/Update.go b/openstack/dcaas/v3/virtual-interface/Update.go new file mode 100644 index 000000000..9e766b197 --- /dev/null +++ b/openstack/dcaas/v3/virtual-interface/Update.go @@ -0,0 +1,32 @@ +package virtual_interface + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" +) + +// UpdateOpts represents options for updating a Virtual Interface. +type UpdateOpts struct { + // Provides supplementary information about the virtual interface. + Description string `json:"description,omitempty"` + // Specifies the virtual interface name. + Name string `json:"name,omitempty"` + // Specifies the virtual interface bandwidth. + Bandwidth int `json:"bandwidth,omitempty"` + // Specifies the ID of the remote endpoint group that records the CIDR blocks used by the on-premises network. + RemoteEndpointGroupId string `json:"remote_ep_group_id,omitempty"` +} + +// Update is an operation which modifies the attributes of the specified +func Update(c *golangsdk.ServiceClient, id string, opts UpdateOpts) (err error) { + b, err := build.RequestBody(opts, "virtual_interface") + if err != nil { + return + } + + _, err = c.Put(c.ServiceURL("dcaas", "virtual-interfaces", id), b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{200, 202}, + }) + + return +} From aa90dd7f0aa356800b47eafa07bea2b6ffa23fe2 Mon Sep 17 00:00:00 2001 From: anton-sidelnikov Date: Fri, 20 Sep 2024 14:40:09 +0200 Subject: [PATCH 2/5] virtual interfaces --- .../dcaas/v3/virtual_gateway_test.go | 30 ++- .../dcaas/v3/virtual_interface_test.go | 121 +++++++++++ openstack/dcaas/v3/virtual-gateway/Update.go | 17 +- .../dcaas/v3/virtual-interface/Create.go | 68 ++++-- .../dcaas/v3/virtual-interface/CreatePeer.go | 49 +++++ .../dcaas/v3/virtual-interface/DeletePeer.go | 10 + openstack/dcaas/v3/virtual-interface/List.go | 198 +++++++++++++++--- .../dcaas/v3/virtual-interface/Update.go | 42 ++-- .../dcaas/v3/virtual-interface/UpdatePeer.go | 34 +++ 9 files changed, 492 insertions(+), 77 deletions(-) create mode 100644 acceptance/openstack/dcaas/v3/virtual_interface_test.go create mode 100644 openstack/dcaas/v3/virtual-interface/CreatePeer.go create mode 100644 openstack/dcaas/v3/virtual-interface/DeletePeer.go create mode 100644 openstack/dcaas/v3/virtual-interface/UpdatePeer.go diff --git a/acceptance/openstack/dcaas/v3/virtual_gateway_test.go b/acceptance/openstack/dcaas/v3/virtual_gateway_test.go index aa3bb8d1a..224a23ca8 100644 --- a/acceptance/openstack/dcaas/v3/virtual_gateway_test.go +++ b/acceptance/openstack/dcaas/v3/virtual_gateway_test.go @@ -10,6 +10,7 @@ import ( "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" ) @@ -27,19 +28,24 @@ func TestVirtualGatewayListing(t *testing.T) { } func TestVirtualGatewayLifecycle(t *testing.T) { - if os.Getenv("OS_VPC_ID") == "" { + 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) // Create a virtual gateway - name := strings.ToLower(tools.RandomString("test-virtual-gateway", 5)) + name := strings.ToLower(tools.RandomString("acc-virtual-gateway-v3-", 5)) createOpts := virtual_gateway.CreateOpts{ Name: name, - VpcId: os.Getenv("OS_VPC_ID"), - Description: "test-virtual-gateway-v3", - LocalEpGroup: []string{""}, + VpcId: vpcID, + Description: "acc-virtual-gateway-v3", + LocalEpGroup: []string{vpc.CIDR}, Tags: []tags.ResourceTag{ { Key: "TestKey", @@ -51,19 +57,23 @@ func TestVirtualGatewayLifecycle(t *testing.T) { created, err := virtual_gateway.Create(client, createOpts) th.AssertNoErr(t, err) - _, err = virtual_gateway.Get(client, created.ID) + vgw, err := virtual_gateway.Get(client, created.ID) th.AssertNoErr(t, err) + th.AssertEquals(t, name, vgw.Name) + nameUpdated := strings.ToLower(tools.RandomString("acc-virtual-gateway-v3-up", 5)) updateOpts := virtual_gateway.UpdateOpts{ - Name: tools.RandomString(name, 3), - Description: pointerto.String("test-virtual-gateway-v3-updated"), + Name: nameUpdated, + Description: pointerto.String("acc-virtual-gateway-v3-updated"), } - _ = virtual_gateway.Update(client, created.ID, updateOpts) + updated, err := virtual_gateway.Update(client, created.ID, updateOpts) th.AssertNoErr(t, err) + th.AssertEquals(t, nameUpdated, updated.Name) opts := virtual_gateway.ListOpts{} - _, err = virtual_gateway.List(client, opts) + gateways, err := virtual_gateway.List(client, opts) th.AssertNoErr(t, err) + th.AssertEquals(t, 1, len(gateways)) t.Cleanup(func() { err = virtual_gateway.Delete(client, created.ID) diff --git a/acceptance/openstack/dcaas/v3/virtual_interface_test.go b/acceptance/openstack/dcaas/v3/virtual_interface_test.go new file mode 100644 index 000000000..1f5a2a331 --- /dev/null +++ b/acceptance/openstack/dcaas/v3/virtual_interface_test.go @@ -0,0 +1,121 @@ +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" + direct_connect "github.com/opentelekomcloud/gophertelekomcloud/openstack/dcaas/v2/direct-connect" + "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) { + 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) { + if os.Getenv("RUN_DCAAS_VIRTUAL_INTERFACE") == "" { + t.Skip("DIRECT_CONNECT_ID necessary for this test or run it only in test_terraform") + } + vpcID := os.Getenv("OS_VPC_ID") + if vpcID == "" { + t.Skip("OS_VPC_ID necessary for this test") + } + clientV2, err := clients.NewDCaaSV2Client() + th.AssertNoErr(t, err) + clientV3, err := clients.NewDCaaSV3Client() + th.AssertNoErr(t, err) + + name := strings.ToLower(tools.RandomString("acc-direct-connect", 5)) + createOpts := direct_connect.CreateOpts{ + Name: name, + PortType: "1G", + Bandwidth: 100, + Location: "Biere", + Provider: "OTC", + } + + dc, err := direct_connect.Create(clientV2, createOpts) + th.AssertNoErr(t, err) + + clientNet, err := clients.NewNetworkV1Client() + th.AssertNoErr(t, err) + vpc, err := vpcs.Get(clientNet, vpcID).Extract() + th.AssertNoErr(t, err) + + // Create a virtual gateway + nameVgw := strings.ToLower(tools.RandomString("acc-virtual-gateway-v3-", 5)) + vgOpts := virtual_gateway.CreateOpts{ + Name: nameVgw, + VpcId: vpcID, + Description: "acc-virtual-gateway-v3", + LocalEpGroup: []string{vpc.CIDR}, + Tags: []tags.ResourceTag{ + { + Key: "TestKey", + Value: "TestValue", + }, + }, + } + + vg, err := virtual_gateway.Create(clientV3, vgOpts) + th.AssertNoErr(t, err) + + t.Cleanup(func() { + err = virtual_gateway.Delete(clientV3, vg.ID) + th.AssertNoErr(t, err) + }) + + // Create a virtual interface + nameVi := tools.RandomString("acc-virtual-interface-", 5) + viOpts := virtual_interface.CreateOpts{ + Name: nameVi, + DirectConnectID: dc.ID, + 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{vpc.CIDR}, + } + + created, err := virtual_interface.Create(clientV3, viOpts) + th.AssertNoErr(t, err) + + vi, err := virtual_interface.Get(clientV3, created.ID) + th.AssertNoErr(t, err) + th.AssertEquals(t, vi.RemoteEpGroup[0], vpc.CIDR) + + updated, err := virtual_interface.Update(clientV3, created.ID, virtual_interface.UpdateOpts{ + Name: name + "-updated", + Description: pointerto.String("New description"), + }) + th.AssertNoErr(t, err) + th.AssertEquals(t, name+"-updated", updated.Name) + + // Cleanup + t.Cleanup(func() { + err = virtual_interface.Delete(clientV3, created.ID) + th.AssertNoErr(t, err) + }) +} diff --git a/openstack/dcaas/v3/virtual-gateway/Update.go b/openstack/dcaas/v3/virtual-gateway/Update.go index 8f093fb9b..08e0fa64f 100644 --- a/openstack/dcaas/v3/virtual-gateway/Update.go +++ b/openstack/dcaas/v3/virtual-gateway/Update.go @@ -3,12 +3,13 @@ package virtual_gateway import ( golangsdk "github.com/opentelekomcloud/gophertelekomcloud" "github.com/opentelekomcloud/gophertelekomcloud/internal/build" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" ) type UpdateOpts struct { // The list of IPv4 subnets from the virtual gateway to access cloud services, which is usually the CIDR block of // the VPC. - LocalEpGroup []string `json:"local_ep_group" required:"true"` + LocalEpGroup []string `json:"local_ep_group,omitempty"` // The list of IPv6 subnets from the virtual gateway to access cloud services, which is usually the CIDR block of // the VPC. LocalEpGroupIpv6 []string `json:"local_ep_group_ipv6,omitempty"` @@ -24,15 +25,19 @@ type UpdateOpts struct { Description *string `json:"description,omitempty"` } -func Update(c *golangsdk.ServiceClient, id string, opts UpdateOpts) (err error) { +func Update(c *golangsdk.ServiceClient, id string, opts UpdateOpts) (*VirtualGateway, error) { b, err := build.RequestBody(opts, "virtual_gateway") if err != nil { - return + return nil, err } - - _, err = c.Put(c.ServiceURL("dcaas", "virtual-gateways", id), b, nil, &golangsdk.RequestOpts{ + raw, err := c.Put(c.ServiceURL("dcaas", "virtual-gateways", id), b, nil, &golangsdk.RequestOpts{ OkCodes: []int{200, 202}, }) + if err != nil { + return nil, err + } - return + var res VirtualGateway + err = extract.IntoStructPtr(raw.Body, &res, "virtual_gateway") + return &res, err } diff --git a/openstack/dcaas/v3/virtual-interface/Create.go b/openstack/dcaas/v3/virtual-interface/Create.go index e9caa97d6..7791f36ee 100644 --- a/openstack/dcaas/v3/virtual-interface/Create.go +++ b/openstack/dcaas/v3/virtual-interface/Create.go @@ -7,22 +7,58 @@ import ( ) type CreateOpts struct { - TenantID string `json:"tenant_id,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - DirectConnectID string `json:"direct_connect_id" required:"true"` - VgwID string `json:"vgw_id" required:"true"` - Type string `json:"type" required:"true"` - ServiceType string `json:"service_type" required:"true"` - VLAN int `json:"vlan" required:"true"` - Bandwidth int `json:"bandwidth" required:"true"` - LocalGatewayV4IP string `json:"local_gateway_v4_ip" required:"true"` - RemoteGatewayV4IP string `json:"remote_gateway_v4_ip" required:"true"` - RouteMode string `json:"route_mode" required:"true"` - BGPASN int `json:"bgp_asn,omitempty"` - BGPMD5 string `json:"bgp_md5,omitempty"` - RemoteEPGroupID string `json:"remote_ep_group_id" required:"true"` - AdminStateUp bool `json:"admin_state_up,omitempty"` + // Specifies the project ID of another tenant, which is used to create virtual interfaces across tenants. + ResourceTenantID string `json:"resource_tenant_id,omitempty"` + // Specifies the virtual interface name. + Name string `json:"name,omitempty"` + // Provides supplementary information about the virtual interface. + Description string `json:"description,omitempty"` + // Specifies the ID of the connection associated with the virtual interface. + // When creating a virtual interface, you need to specify direct_connect_id or lag_id. + // This parameter is mandatory when LAG is not supported at the site. + DirectConnectID string `json:"direct_connect_id,omitempty"` + // Specifies the type of the virtual interface. The value is private. + Type string `json:"type" required:"true"` + // Specifies the type of the access gateway. You do not need to set this parameter. + ServiceType string `json:"service_type,omitempty"` + // Specifies the customer VLAN to be connected. + // If you select a hosted connection, the VLAN must be the same as that of the hosted connection. + VLAN int `json:"vlan" required:"true"` + // Specifies the virtual interface bandwidth. + Bandwidth int `json:"bandwidth" required:"true"` + // Specifies the IPv4 interface address of the gateway used on the cloud. + // This parameter is mandatory if address_family is set to an IPv4 address. + LocalGatewayV4IP string `json:"local_gateway_v4_ip,omitempty"` + // Specifies the IPv4 interface address of the gateway on the on-premises network. + // This parameter is mandatory if address_family is set to an IPv4 address. + RemoteGatewayV4IP string `json:"remote_gateway_v4_ip,omitempty"` + // Specifies the address family of the virtual interface. + // The value can be IPv4 or IPv6. + AddressFamily string `json:"address_family,omitempty"` + // Specifies the IPv6 interface address of the gateway used on the cloud. + // This parameter is mandatory if address_family is set to an IPv6 address. + LocalGatewayV6IP string `json:"local_gateway_v6_ip,omitempty"` + // Specifies the IPv6 interface address of the gateway on the on-premises network. + // This parameter is mandatory if address_family is set to an IPv6 address. + RemoteGatewayV6IP string `json:"remote_gateway_v6_ip,omitempty"` + // Specifies the ID of the virtual gateway connected by the virtual interface. + VgwId string `json:"vgw_id,omitempty" required:"true"` + // Specifies the routing mode. The value can be static or bgp. + RouteMode string `json:"route_mode" required:"true"` + // Specifies the ASN of the BGP peer on the customer side. + BGPASN int `json:"bgp_asn,omitempty"` + // Specifies the MD5 password of the BGP peer. + BGPMD5 string `json:"bgp_md5,omitempty"` + // Specifies the remote subnet list, which records the CIDR blocks used in the on-premises data center. + RemoteEpGroup []string `json:"remote_ep_group" required:"true"` + // Specifies the subnets that access Internet services through a connection. + ServiceEpGroup []string `json:"service_ep_group,omitempty"` + // Specifies whether to enable BFD. + EnableBfd bool `json:"enable_bfd,omitempty"` + // Specifies whether to enable NQA. + EnableNqa bool `json:"enable_nqa,omitempty"` + // Specifies the ID of the LAG associated with the virtual interface. + LagId string `json:"lag_id,omitempty"` } func Create(c *golangsdk.ServiceClient, opts CreateOpts) (*VirtualInterface, error) { diff --git a/openstack/dcaas/v3/virtual-interface/CreatePeer.go b/openstack/dcaas/v3/virtual-interface/CreatePeer.go new file mode 100644 index 000000000..77ff12272 --- /dev/null +++ b/openstack/dcaas/v3/virtual-interface/CreatePeer.go @@ -0,0 +1,49 @@ +package virtual_interface + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +type CreatePeerOpts struct { + // Specifies the name of the virtual interface peer. + Name string `json:"name" required:"true"` + // Provides supplementary information about the virtual interface peer. + Description string `json:"description,omitempty"` + // Specifies the gateway address of the virtual interface peer used on the cloud. + LocalGatewayIP string `json:"local_gateway_ip" required:"true"` + // Specifies the IPv4 interface address of the gateway on the on-premises network. + // This parameter is mandatory if address_family is set to an IPv4 address. + RemoteGatewayIP string `json:"remote_gateway_ip" required:"true"` + // Specifies the address family of the virtual interface. + // The value can be IPv4 or IPv6. + AddressFamily string `json:"address_family" required:"true"` + // Specifies the routing mode. The value can be static or bgp. + RouteMode string `json:"route_mode" required:"true"` + // Specifies the ASN of the BGP peer on the customer side. + BGPASN int `json:"bgp_asn,omitempty"` + // Specifies the MD5 password of the BGP peer. + BGPMD5 string `json:"bgp_md5,omitempty"` + // Specifies the remote subnet list, which records the CIDR blocks used in the on-premises data center. + RemoteEpGroup []string `json:"remote_ep_group,omitempty"` + // Specifies the ID of the virtual interface corresponding to the virtual interface peer. + VifId string `json:"vif_id" required:"true"` +} + +func CreatePeer(c *golangsdk.ServiceClient, opts CreatePeerOpts) (*VifPeer, error) { + b, err := build.RequestBody(opts, "vif_peer") + if err != nil { + return nil, err + } + raw, err := c.Post(c.ServiceURL("dcaas", "vif-peers"), b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{201}, + }) + if err != nil { + return nil, err + } + + var res VifPeer + err = extract.IntoStructPtr(raw.Body, &res, "vif_peer") + return &res, err +} diff --git a/openstack/dcaas/v3/virtual-interface/DeletePeer.go b/openstack/dcaas/v3/virtual-interface/DeletePeer.go new file mode 100644 index 000000000..89dbf19d8 --- /dev/null +++ b/openstack/dcaas/v3/virtual-interface/DeletePeer.go @@ -0,0 +1,10 @@ +package virtual_interface + +import golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + +func DeletePeer(c *golangsdk.ServiceClient, id string) (err error) { + _, err = c.Delete(c.ServiceURL("dcaas", "vif-peers", id), &golangsdk.RequestOpts{ + OkCodes: []int{200, 201, 204}, + }) + return +} diff --git a/openstack/dcaas/v3/virtual-interface/List.go b/openstack/dcaas/v3/virtual-interface/List.go index 608207811..0baab6eb5 100644 --- a/openstack/dcaas/v3/virtual-interface/List.go +++ b/openstack/dcaas/v3/virtual-interface/List.go @@ -4,46 +4,178 @@ import ( golangsdk "github.com/opentelekomcloud/gophertelekomcloud" "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" "github.com/opentelekomcloud/gophertelekomcloud/openstack" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/common/tags" ) type ListOpts struct { ID string `q:"id"` } +// VirtualInterface is the structure that represents the details of the virtual interface. type VirtualInterface struct { - ID string `json:"id"` - TenantID string `json:"tenant_id"` - Name string `json:"name"` - Description string `json:"description"` - DirectConnectID string `json:"direct_connect_id"` - VgwID string `json:"vgw_id"` - Type string `json:"type"` - ServiceType string `json:"service_type"` - VLAN int `json:"vlan"` - Bandwidth int `json:"bandwidth"` - LocalGatewayV4IP string `json:"local_gateway_v4_ip"` - RemoteGatewayV4IP string `json:"remote_gateway_v4_ip"` - RouteMode string `json:"route_mode"` - BGPASN int `json:"bgp_asn"` - BGPMD5 string `json:"bgp_md5"` - RemoteEPGroupID string `json:"remote_ep_group_id"` - ServiceEPGroupID string `json:"service_ep_group_id"` - CreateTime string `json:"create_time"` - Status string `json:"status"` - AdminStateUp bool `json:"admin_state_up"` - AddressFamily string `json:"address_family"` - EnableBFD bool `json:"enable_bfd"` - HealthCheckSourceIP string `json:"health_check_source_ip"` - RateLimit bool `json:"rate_limit"` - RouteLimit int `json:"route_limit"` - RegionID string `json:"region_id"` - EnableNQA bool `json:"enable_nqa"` - EnableGRE bool `json:"enable_gre"` - LocalGatewayV6IP string `json:"local_gateway_v6_ip"` - RemoteGatewayV6IP string `json:"remote_gateway_v6_ip"` - LocalGRETunnelIP string `json:"local_gre_tunnel_ip"` - RemoteGRETunnelIP string `json:"remote_gre_tunnel_ip"` - LagID string `json:"lag_id"` + // The ID of the virtual interface. + ID string `json:"id"` + // Specifies the name of the virtual interface. + // The valid length is limited from 0 to 64, only chinese and english letters, digits, hyphens (-), underscores (_) + // and dots (.) are allowed. + // The name must start with a chinese or english letter, and the Chinese characters must be in **UTF-8** or + // **Unicode** format. + Name string `json:"name"` + // Manage status. + // The valid values are 'true' and 'false'. + AdminStateUp bool `json:"admin_state_up"` + // The ingress bandwidth size of the virtual interface. + Bandwidth int `json:"bandwidth"` + // The creation time of the virtual interface. + CreatedAt string `json:"create_time"` + // The latest update time of the virtual interface. + UpdatedAt string `json:"update_time"` + // Specifies the description of the virtual interface. + // The description contain a maximum of 128 characters and the angle brackets (< and >) are not allowed. + // Chinese characters must be in **UTF-8** or **Unicode** format. + Description string `json:"description"` + // The ID of the direct connection associated with the virtual interface. + DirectConnectId string `json:"direct_connect_id"` + // The service type of the virtual interface. + ServiceType string `json:"service_type"` + // The current status of the virtual interface. + // The valid values are as follows: + // + ACTIVE + // + DOWN + // + BUILD + // + ERROR + // + PENDING_CREATE + // + PENDING_UPDATE + // + PENDING_DELETE + // + DELETED + // + AUTHORIZATION + // + REJECTED + Status string `json:"status"` + // The ID of the target tenant ID, which is used for cross tenant virtual interface creation. + TenantId string `json:"tenant_id"` + // The type of the virtual interface. + Type string `json:"type"` + // The ID of the virtual gateway to which the virtual interface is connected. + VgwId string `json:"vgw_id"` + // The VLAN for constom side. + Vlan int `json:"vlan"` + // The route specification of the remote VIF network. + RouteLimit int `json:"route_limit"` + // Whether to enable the Bidirectional Forwarding Detection (BFD) function. + EnableBfd bool `json:"enable_bfd"` + // Whether to enable the Network Quality Analysis (NQA) function. + EnableNqa bool `json:"enable_nqa"` + // The ID of the Intelligent EdgeSite (IES) associated with the virtual interface. + IesId string `json:"ies_id"` + // The ID of the link aggregation group (LAG) associated with the virtual interface. + LagId string `json:"lag_id"` + // The ID of the local gateway (LGW) associated with the virtual interface. + LgwId string `json:"lgw_id"` + // The local BGP ASN in client side. + BgpAsn int `json:"bgp_asn"` + // The (MD5) password for the local BGP. + BgpMd5 string `json:"bgp_md5"` + // The attributed Device ID. + DeviceId string `json:"device_id"` + // The IPv4 address of the virtual interface in cloud side. + LocalGatewayV4Ip string `json:"local_gateway_v4_ip"` + // The IPv4 address of the virtual interface in client side. + RemoteGatewayV4Ip string `json:"remote_gateway_v4_ip"` + // The address family type. + AddressFamily string `json:"address_family"` + // The IPv6 address of the virtual interface in cloud side. + LocalGatewayV6Ip string `json:"local_gateway_v6_ip"` + // The IPv6 address of the virtual interface in client side. + RemoteGatewayV6Ip string `json:"remote_gateway_v6_ip"` + // The CIDR list of remote subnets. + RemoteEpGroup []string `json:"remote_ep_group"` + // The CIDR list of subnets in service side. + ServiceEpGroup []string `json:"service_ep_group"` + // The route mode of the virtual interface. + RouteMode string `json:"route_mode"` + // Whether limit rate. + RateLimit bool `json:"rate_limit"` + // The VLAN for constom side. + VifPeers []VifPeer `json:"vif_peers"` + // The Peer details of the VIF. + ExtendAttribute VifExtendAttribute `json:"extend_attribute"` + // The enterprise project ID to which the virtual interface belongs. + EnterpriseProjectId string `json:"enterprise_project_id"` + // The key/value pairs to associate with the virtual interface. + Tags []tags.ResourceTag `json:"tags"` +} + +type VifPeer struct { + // Resource ID. + ID string `json:"id"` + // The ID of the target tenant ID, which is used for cross tenant virtual interface creation. + TenantId string `json:"tenant_id"` + // Specifies the name of the VIF peer. + // The valid length is limited from 0 to 64, only chinese and english letters, digits, hyphens (-), underscores (_) + // and dots (.) are allowed. + // The name must start with a chinese or english letter, and the Chinese characters must be in **UTF-8** or + // **Unicode** format. + Name string `json:"name"` + // Specifies the description of the virtual interface. + // The description contain a maximum of 128 characters and the angle brackets (< and >) are not allowed. + // Chinese characters must be in **UTF-8** or **Unicode** format. + Description string `json:"description"` + // The address family type. + AddressFamily string `json:"address_family"` + // Local gateway IP. + LocalGatewayIp string `json:"local_gateway_ip"` + // Remote gateway IP. + RemoteGatewayIp string `json:"remote_gateway_ip"` + // The routing mode, which can be static or bgp. + RouteMode string `json:"route_mode"` + // BGP ASN. + BgpAsn int `json:"bgp_asn"` + // BGP MD5 password. + BgpMd5 string `json:"bgp_md5"` + // The CIDR list of remote subnets. + RemoteEpGroup []string `json:"remote_ep_group"` + // The CIDR list of subnets in service side. + ServiceEpGroup []string `json:"service_ep_group"` + // Attributed Device ID. + DeviceId string `json:"device_id"` + // Whether to enable BFD. + EnableBfd bool `json:"enable_bfd"` + // Whether to enable NQA. + EnableNqa bool `json:"enable_nqa"` + // Attributed Device ID. + BgpRouteLimit int `json:"bgp_route_limit"` + // Attributed Device ID. + BgpStatus string `json:"bgp_status"` + // The status of the virtual interface peer. + Status string `json:"status"` + // The virtual interface ID corresponding to the VIF peer. + VifId string `json:"vif_id"` + // The number of received BGP routes if BGP routing is used. + ReceiveRouteNum int `json:"receive_route_num"` +} + +type VifExtendAttribute struct { + // The availability detection types for virtual interface. + // + nqa + // + bfd + HaType string `json:"ha_type"` + // The specific configuration mode detected for virtual interface. + // + auto_single + // + auto_multi + // + static_single + // + static_multi + // + enhance_nqa + HaMode string `json:"ha_mode"` + // The detection retries. + DetectMultiplier string `json:"detect_multiplier"` + // The reception time interval for detection. + MinRxInterval string `json:"min_rx_interval"` + // To transmit time interval for detection. + MinTxInterval string `json:"min_tx_interval"` + // The identifier of the detected remote side, used for static BFD. + RemoteDisclaim string `json:"remote_disclaim"` + // The identifier of the detected local side, used for static BFD. + LocalDisclaim string `json:"local_disclaim"` } func List(client *golangsdk.ServiceClient, opts ListOpts) ([]VirtualInterface, error) { diff --git a/openstack/dcaas/v3/virtual-interface/Update.go b/openstack/dcaas/v3/virtual-interface/Update.go index 9e766b197..6b41f4206 100644 --- a/openstack/dcaas/v3/virtual-interface/Update.go +++ b/openstack/dcaas/v3/virtual-interface/Update.go @@ -3,30 +3,48 @@ package virtual_interface import ( golangsdk "github.com/opentelekomcloud/gophertelekomcloud" "github.com/opentelekomcloud/gophertelekomcloud/internal/build" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" ) -// UpdateOpts represents options for updating a Virtual Interface. type UpdateOpts struct { - // Provides supplementary information about the virtual interface. - Description string `json:"description,omitempty"` - // Specifies the virtual interface name. + // Specifies the name of the virtual interface. + // The valid length is limited from 0 to 64, only chinese and english letters, digits, hyphens (-), underscores (_) + // and dots (.) are allowed. + // The name must start with a chinese or english letter, and the Chinese characters must be in **UTF-8** or + // **Unicode** format. Name string `json:"name,omitempty"` - // Specifies the virtual interface bandwidth. + // Specifies the description of the virtual interface. + // The description contain a maximum of 128 characters and the angle brackets (< and >) are not allowed. + // Chinese characters must be in **UTF-8** or **Unicode** format. + Description *string `json:"description,omitempty"` + // The ingress bandwidth size of the virtual interface. Bandwidth int `json:"bandwidth,omitempty"` - // Specifies the ID of the remote endpoint group that records the CIDR blocks used by the on-premises network. - RemoteEndpointGroupId string `json:"remote_ep_group_id,omitempty"` + // The CIDR list of remote subnets. + RemoteEpGroup []string `json:"remote_ep_group,omitempty"` + // The CIDR list of subnets in service side. + ServiceEpGroup []string `json:"service_ep_group,omitempty"` + // Whether to enable the Bidirectional Forwarding Detection (BFD) function. + EnableBfd *bool `json:"enable_bfd,omitempty"` + // Whether to enable the Network Quality Analysis (NQA) function. + EnableNqa *bool `json:"enable_nqa,omitempty"` + // The status of the virtual interface to be changed. + Status string `json:"status,omitempty"` } // Update is an operation which modifies the attributes of the specified -func Update(c *golangsdk.ServiceClient, id string, opts UpdateOpts) (err error) { +func Update(c *golangsdk.ServiceClient, id string, opts UpdateOpts) (*VirtualInterface, error) { b, err := build.RequestBody(opts, "virtual_interface") if err != nil { - return + return nil, err } - _, err = c.Put(c.ServiceURL("dcaas", "virtual-interfaces", id), b, nil, &golangsdk.RequestOpts{ + raw, err := c.Put(c.ServiceURL("dcaas", "virtual-interfaces", id), b, nil, &golangsdk.RequestOpts{ OkCodes: []int{200, 202}, }) - - return + if err != nil { + return nil, err + } + var res VirtualInterface + err = extract.IntoStructPtr(raw.Body, &res, "virtual_interface") + return &res, err } diff --git a/openstack/dcaas/v3/virtual-interface/UpdatePeer.go b/openstack/dcaas/v3/virtual-interface/UpdatePeer.go new file mode 100644 index 000000000..028194ed1 --- /dev/null +++ b/openstack/dcaas/v3/virtual-interface/UpdatePeer.go @@ -0,0 +1,34 @@ +package virtual_interface + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +type UpdatePeerOpts struct { + // Specifies the name of the virtual interface peer. + Name string `json:"name" required:"true"` + // Provides supplementary information about the virtual interface peer. + Description string `json:"description,omitempty"` + // Specifies the remote subnet list, which records the CIDR blocks used in the on-premises data center. + RemoteEpGroup []string `json:"remote_ep_group,omitempty"` + // Specifies the ID of the virtual interface corresponding to the virtual interface peer. +} + +func UpdatePeer(c *golangsdk.ServiceClient, id string, opts UpdatePeerOpts) (*VifPeer, error) { + b, err := build.RequestBody(opts, "vif_peer") + if err != nil { + return nil, err + } + + raw, err := c.Put(c.ServiceURL("dcaas", "vif-peers", id), b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{200, 202}, + }) + if err != nil { + return nil, err + } + var res VifPeer + err = extract.IntoStructPtr(raw.Body, &res, "vif_peer") + return &res, err +} From f6c2b78599d9ecd937f1fb91d5899d4eecd12971 Mon Sep 17 00:00:00 2001 From: anton-sidelnikov Date: Fri, 20 Sep 2024 14:41:56 +0200 Subject: [PATCH 3/5] skip --- acceptance/openstack/dcaas/v3/virtual_gateway_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/acceptance/openstack/dcaas/v3/virtual_gateway_test.go b/acceptance/openstack/dcaas/v3/virtual_gateway_test.go index 224a23ca8..9d51b44f8 100644 --- a/acceptance/openstack/dcaas/v3/virtual_gateway_test.go +++ b/acceptance/openstack/dcaas/v3/virtual_gateway_test.go @@ -28,6 +28,7 @@ func TestVirtualGatewayListing(t *testing.T) { } 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") From e9f868b2866c846077b7e9d78eac2cc30c8073e6 Mon Sep 17 00:00:00 2001 From: anton-sidelnikov Date: Mon, 21 Oct 2024 13:39:03 +0200 Subject: [PATCH 4/5] Missing methods and tests --- .../openstack/dcaas/v3/hosted_connect_test.go | 24 ++++++- .../dcaas/v3/virtual_gateway_test.go | 13 +++- .../dcaas/v3/virtual_interface_test.go | 67 ++++++++----------- openstack/dcaas/v3/hosted-connect/Create.go | 2 +- openstack/dcaas/v3/hosted-connect/Get.go | 19 ++++++ openstack/dcaas/v3/hosted-connect/List.go | 61 +++++++++++++++++ openstack/dcaas/v3/hosted-connect/Update.go | 37 ++++++++++ 7 files changed, 179 insertions(+), 44 deletions(-) create mode 100644 openstack/dcaas/v3/hosted-connect/Get.go create mode 100644 openstack/dcaas/v3/hosted-connect/List.go create mode 100644 openstack/dcaas/v3/hosted-connect/Update.go diff --git a/acceptance/openstack/dcaas/v3/hosted_connect_test.go b/acceptance/openstack/dcaas/v3/hosted_connect_test.go index 0ef0a7e12..2a81fc7d5 100644 --- a/acceptance/openstack/dcaas/v3/hosted_connect_test.go +++ b/acceptance/openstack/dcaas/v3/hosted_connect_test.go @@ -12,9 +12,10 @@ import ( ) func TestHostedConnectLifecycle(t *testing.T) { - t.Skip("The API does not exist or has not been published in the environment") + 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") } @@ -35,8 +36,27 @@ func TestHostedConnectLifecycle(t *testing.T) { 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 delte DCaaSv3 hosted connect: %s", created.ID) + t.Logf("Attempting to delete DCaaSv3 hosted connect: %s", created.ID) err = hosted_connect.Delete(client, created.ID) th.AssertNoErr(t, err) diff --git a/acceptance/openstack/dcaas/v3/virtual_gateway_test.go b/acceptance/openstack/dcaas/v3/virtual_gateway_test.go index 9d51b44f8..82f74bc23 100644 --- a/acceptance/openstack/dcaas/v3/virtual_gateway_test.go +++ b/acceptance/openstack/dcaas/v3/virtual_gateway_test.go @@ -15,6 +15,7 @@ import ( ) 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) @@ -40,7 +41,8 @@ func TestVirtualGatewayLifecycle(t *testing.T) { th.AssertNoErr(t, err) vpc, err := vpcs.Get(clientNet, vpcID).Extract() th.AssertNoErr(t, err) - // Create a virtual gateway + + t.Logf("Attempting to create DCaaSv3 virtual gateway") name := strings.ToLower(tools.RandomString("acc-virtual-gateway-v3-", 5)) createOpts := virtual_gateway.CreateOpts{ Name: name, @@ -58,10 +60,12 @@ func TestVirtualGatewayLifecycle(t *testing.T) { 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, @@ -71,12 +75,15 @@ func TestVirtualGatewayLifecycle(t *testing.T) { th.AssertNoErr(t, err) th.AssertEquals(t, nameUpdated, updated.Name) - opts := virtual_gateway.ListOpts{} - gateways, err := virtual_gateway.List(client, opts) + 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) }) diff --git a/acceptance/openstack/dcaas/v3/virtual_interface_test.go b/acceptance/openstack/dcaas/v3/virtual_interface_test.go index 1f5a2a331..a7344edd5 100644 --- a/acceptance/openstack/dcaas/v3/virtual_interface_test.go +++ b/acceptance/openstack/dcaas/v3/virtual_interface_test.go @@ -9,7 +9,6 @@ import ( "github.com/opentelekomcloud/gophertelekomcloud/acceptance/tools" "github.com/opentelekomcloud/gophertelekomcloud/openstack/common/pointerto" "github.com/opentelekomcloud/gophertelekomcloud/openstack/common/tags" - direct_connect "github.com/opentelekomcloud/gophertelekomcloud/openstack/dcaas/v2/direct-connect" "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" @@ -17,6 +16,7 @@ import ( ) 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) @@ -31,28 +31,13 @@ func TestVirtualInterfaceListing(t *testing.T) { } func TestVirtualInterfaceLifecycle(t *testing.T) { - if os.Getenv("RUN_DCAAS_VIRTUAL_INTERFACE") == "" { - t.Skip("DIRECT_CONNECT_ID necessary for this test or run it only in test_terraform") - } + 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 == "" { - t.Skip("OS_VPC_ID necessary for this test") - } - clientV2, err := clients.NewDCaaSV2Client() - th.AssertNoErr(t, err) - clientV3, err := clients.NewDCaaSV3Client() - th.AssertNoErr(t, err) - - name := strings.ToLower(tools.RandomString("acc-direct-connect", 5)) - createOpts := direct_connect.CreateOpts{ - Name: name, - PortType: "1G", - Bandwidth: 100, - Location: "Biere", - Provider: "OTC", + if vpcID == "" && dcID == "" { + t.Skip("DIRECT_CONNECT_ID and OS_VPC_ID necessary for this test") } - - dc, err := direct_connect.Create(clientV2, createOpts) + client, err := clients.NewDCaaSV3Client() th.AssertNoErr(t, err) clientNet, err := clients.NewNetworkV1Client() @@ -60,10 +45,10 @@ func TestVirtualInterfaceLifecycle(t *testing.T) { vpc, err := vpcs.Get(clientNet, vpcID).Extract() th.AssertNoErr(t, err) - // Create a virtual gateway - nameVgw := strings.ToLower(tools.RandomString("acc-virtual-gateway-v3-", 5)) - vgOpts := virtual_gateway.CreateOpts{ - Name: nameVgw, + 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}, @@ -74,20 +59,19 @@ func TestVirtualInterfaceLifecycle(t *testing.T) { }, }, } - - vg, err := virtual_gateway.Create(clientV3, vgOpts) + vg, err := virtual_gateway.Create(client, createOpts) th.AssertNoErr(t, err) t.Cleanup(func() { - err = virtual_gateway.Delete(clientV3, vg.ID) + err = virtual_gateway.Delete(client, vg.ID) th.AssertNoErr(t, err) }) - // Create a virtual interface + t.Logf("Attempting to create DCaaSv3 virtual interface") nameVi := tools.RandomString("acc-virtual-interface-", 5) viOpts := virtual_interface.CreateOpts{ Name: nameVi, - DirectConnectID: dc.ID, + DirectConnectID: dcID, VgwId: vg.ID, Type: "private", ServiceType: "vpc", @@ -96,26 +80,33 @@ func TestVirtualInterfaceLifecycle(t *testing.T) { LocalGatewayV4IP: "16.16.16.1/30", RemoteGatewayV4IP: "16.16.16.2/30", RouteMode: "static", - RemoteEpGroup: []string{vpc.CIDR}, + RemoteEpGroup: []string{"16.16.16.0/30"}, } - - created, err := virtual_interface.Create(clientV3, viOpts) + created, err := virtual_interface.Create(client, viOpts) th.AssertNoErr(t, err) - vi, err := virtual_interface.Get(clientV3, created.ID) + 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, vi.RemoteEpGroup[0], vpc.CIDR) + th.AssertEquals(t, "16.16.16.0/30", vi.RemoteEpGroup[0]) - updated, err := virtual_interface.Update(clientV3, created.ID, virtual_interface.UpdateOpts{ + 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)) - // Cleanup t.Cleanup(func() { - err = virtual_interface.Delete(clientV3, created.ID) + t.Logf("Attempting to delete DCaaSv3 virtual interface: %s", created.ID) + err = virtual_interface.Delete(client, created.ID) th.AssertNoErr(t, err) }) } diff --git a/openstack/dcaas/v3/hosted-connect/Create.go b/openstack/dcaas/v3/hosted-connect/Create.go index c1ff579d9..90edfbcb9 100644 --- a/openstack/dcaas/v3/hosted-connect/Create.go +++ b/openstack/dcaas/v3/hosted-connect/Create.go @@ -66,7 +66,7 @@ type HostedConnect struct { } func Create(c *golangsdk.ServiceClient, opts CreateOpts) (*HostedConnect, error) { - b, err := build.RequestBody(opts, "direct_connect") + b, err := build.RequestBody(opts, "hosted_connect") if err != nil { return nil, err } diff --git a/openstack/dcaas/v3/hosted-connect/Get.go b/openstack/dcaas/v3/hosted-connect/Get.go new file mode 100644 index 000000000..43b72e982 --- /dev/null +++ b/openstack/dcaas/v3/hosted-connect/Get.go @@ -0,0 +1,19 @@ +package hosted_connect + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +// Get retrieves a particular hosted connect based on its unique ID. +func Get(c *golangsdk.ServiceClient, id string) (*HostedConnect, error) { + // GET /v3/{project_id}/dcaas/hosted-connects/{hosted_connect_id} + raw, err := c.Get(c.ServiceURL("dcaas", "hosted-connects", id), nil, nil) + if err != nil { + return nil, err + } + + var res HostedConnect + err = extract.IntoStructPtr(raw.Body, &res, "hosted_connect") + return &res, err +} diff --git a/openstack/dcaas/v3/hosted-connect/List.go b/openstack/dcaas/v3/hosted-connect/List.go new file mode 100644 index 000000000..42c1d0db5 --- /dev/null +++ b/openstack/dcaas/v3/hosted-connect/List.go @@ -0,0 +1,61 @@ +package hosted_connect + +import ( + "bytes" + + "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" + "github.com/opentelekomcloud/gophertelekomcloud/pagination" +) + +type ListOpts struct { + // virtual gateway by ID + ID []string `q:"id,omitempty"` + // Specifies the number of records returned on each page. Value range: 1-2000 + Limit int `q:"limit,omitempty"` + // Specifies the ID of the last resource record on the previous page. If this parameter is left blank, the first page is queried. + // This parameter must be used together with limit. + Marker string `q:"marker,omitempty"` + // Specifies the list of fields to be displayed. + Fields []interface{} `q:"fields,omitempty"` + // Specifies the sorting order of returned results. The value can be asc (default) or desc. + SortDir string `q:"sort_dir,omitempty"` + // Specifies the field for sorting. + SortKey string `q:"sort_key,omitempty"` + // Specifies operations connection ID by which hosted connections are queried. + HostingId []string `q:"hosting_id,omitempty"` + // Specifies the resource name by which instances are queried. You can specify multiple names. + Name []string `q:"name,omitempty"` +} + +// List is used to obtain the virtual gateway list +func List(client *golangsdk.ServiceClient, opts ListOpts) ([]HostedConnect, error) { + url, err := golangsdk.NewURLBuilder().WithEndpoints("dcaas", "hosted-connects").WithQueryParams(&opts).Build() + if err != nil { + return nil, err + } + pages, err := pagination.Pager{ + Client: client, + InitialURL: client.ServiceURL(url.String()), + CreatePage: func(r pagination.NewPageResult) pagination.NewPage { + return HcPage{NewSinglePageBase: pagination.NewSinglePageBase{NewPageResult: r}} + }, + }.NewAllPages() + + if err != nil { + return nil, err + } + return ExtractHCs(pages) +} + +type HcPage struct { + pagination.NewSinglePageBase +} + +func ExtractHCs(r pagination.NewPage) ([]HostedConnect, error) { + var s struct { + Connects []HostedConnect `json:"hosted_connects"` + } + err := extract.Into(bytes.NewReader((r.(HcPage)).Body), &s) + return s.Connects, err +} diff --git a/openstack/dcaas/v3/hosted-connect/Update.go b/openstack/dcaas/v3/hosted-connect/Update.go new file mode 100644 index 000000000..2ac5a3f1e --- /dev/null +++ b/openstack/dcaas/v3/hosted-connect/Update.go @@ -0,0 +1,37 @@ +package hosted_connect + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +type UpdateOpts struct { + // Provides supplementary information about the connection. + Description string `json:"description,omitempty"` + // Specifies the connection name. + Name string `json:"name,omitempty"` + // Specifies the bandwidth of the hosted connection, in Mbit/s. + Bandwidth int `json:"bandwidth,omitempty"` + // 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"` +} + +// Update is an operation which modifies the attributes of the specified hosted connect +func Update(c *golangsdk.ServiceClient, id string, opts UpdateOpts) (*HostedConnect, error) { + // PUT /v3/{project_id}/dcaas/hosted-connects/{hosted_connect_id} + b, err := build.RequestBody(opts, "hosted_connect") + if err != nil { + return nil, err + } + + raw, err := c.Put(c.ServiceURL("dcaas", "hosted-connects", id), b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{200, 202}, + }) + + var res HostedConnect + + err = extract.IntoStructPtr(raw.Body, &res, "hosted_connect") + return &res, err +} From b02d43544b78c449e297d48447a262da358b1fee Mon Sep 17 00:00:00 2001 From: anton-sidelnikov Date: Mon, 21 Oct 2024 13:46:44 +0200 Subject: [PATCH 5/5] fix lint --- openstack/dcaas/v3/hosted-connect/Update.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openstack/dcaas/v3/hosted-connect/Update.go b/openstack/dcaas/v3/hosted-connect/Update.go index 2ac5a3f1e..dfd055534 100644 --- a/openstack/dcaas/v3/hosted-connect/Update.go +++ b/openstack/dcaas/v3/hosted-connect/Update.go @@ -29,9 +29,11 @@ func Update(c *golangsdk.ServiceClient, id string, opts UpdateOpts) (*HostedConn raw, err := c.Put(c.ServiceURL("dcaas", "hosted-connects", id), b, nil, &golangsdk.RequestOpts{ OkCodes: []int{200, 202}, }) + if err != nil { + return nil, err + } var res HostedConnect - err = extract.IntoStructPtr(raw.Body, &res, "hosted_connect") return &res, err }