Skip to content

Commit b2ccdc6

Browse files
authored
[VPCEP] Add endpoints support (#261)
[VPCEP] Add `endpoints` support What this PR does / why we need it Implement methods for handling VPC EP endpoints Which issue this PR fixes Refers to #257 Special notes for your reviewer === RUN TestEndpointLifecycle --- PASS: TestEndpointLifecycle (14.06s) PASS Process finished with the exit code 0 Reviewed-by: None <None> Reviewed-by: Rodion Gyrbu <[email protected]> Reviewed-by: Anton Sidelnikov <None>
1 parent 94e7e59 commit b2ccdc6

File tree

6 files changed

+558
-0
lines changed

6 files changed

+558
-0
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package vpcep
2+
3+
import (
4+
"testing"
5+
6+
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
7+
"github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients"
8+
"github.com/opentelekomcloud/gophertelekomcloud/acceptance/tools"
9+
"github.com/opentelekomcloud/gophertelekomcloud/openstack/common/tags"
10+
"github.com/opentelekomcloud/gophertelekomcloud/openstack/vpcep/v1/endpoints"
11+
"github.com/opentelekomcloud/gophertelekomcloud/openstack/vpcep/v1/services"
12+
th "github.com/opentelekomcloud/gophertelekomcloud/testhelper"
13+
)
14+
15+
func createService(t *testing.T, client *golangsdk.ServiceClient, elbPortID string) string {
16+
iFalse := false
17+
createOpts := &services.CreateOpts{
18+
PortID: elbPortID,
19+
ServiceName: tools.RandomString("svc-", 5),
20+
RouterID: routerID,
21+
ServerType: services.ServerTypeLB,
22+
ServiceType: services.ServiceTypeInterface,
23+
Ports: []services.PortMapping{
24+
{
25+
ClientPort: 80,
26+
ServerPort: 8080,
27+
},
28+
},
29+
ApprovalEnabled: &iFalse,
30+
}
31+
svc, err := services.Create(client, createOpts).Extract()
32+
th.AssertNoErr(t, err)
33+
34+
err = services.WaitForServiceStatus(client, svc.ID, services.StatusAvailable, 30)
35+
th.AssertNoErr(t, err)
36+
return svc.ID
37+
}
38+
39+
func deleteService(t *testing.T, client *golangsdk.ServiceClient, id string) {
40+
th.AssertNoErr(t, services.Delete(client, id).ExtractErr())
41+
}
42+
43+
func TestEndpointLifecycle(t *testing.T) {
44+
if routerID == "" || networkID == "" || subnetID == "" {
45+
t.Skip("OS_ROUTER_ID/VPC_ID, OS_SUBNET_ID and OS_NETWORK_ID variables need to be set")
46+
}
47+
48+
client, err := clients.NewVPCEndpointV1Client()
49+
th.AssertNoErr(t, err)
50+
51+
elb := createELB(t)
52+
defer deleteELB(t, elb.ID)
53+
54+
srvID := createService(t, client, elb.VipPortID)
55+
defer deleteService(t, client, srvID)
56+
57+
opts := endpoints.CreateOpts{
58+
NetworkID: networkID,
59+
ServiceID: srvID,
60+
RouterID: routerID,
61+
EnableDNS: true,
62+
Tags: []tags.ResourceTag{{Key: "fizz", Value: "buzz"}},
63+
}
64+
created, err := endpoints.Create(client, opts).Extract()
65+
th.AssertNoErr(t, err)
66+
67+
defer func() {
68+
th.AssertNoErr(t, endpoints.Delete(client, created.ID).ExtractErr())
69+
}()
70+
71+
got, err := endpoints.Get(client, created.ID).Extract()
72+
th.AssertNoErr(t, err)
73+
th.AssertEquals(t, endpoints.StatusCreating, got.Status)
74+
75+
th.AssertNoErr(t, endpoints.WaitForEndpointStatus(client, created.ID, endpoints.StatusAccepted, 30))
76+
77+
pages, err := endpoints.List(client, nil).AllPages()
78+
th.AssertNoErr(t, err)
79+
80+
eps, err := endpoints.ExtractEndpoints(pages)
81+
th.AssertNoErr(t, err)
82+
83+
th.AssertEquals(t, created.ID, eps[0].ID)
84+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package endpoints
2+
3+
import (
4+
"net/http"
5+
6+
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
7+
"github.com/opentelekomcloud/gophertelekomcloud/openstack/common/tags"
8+
"github.com/opentelekomcloud/gophertelekomcloud/pagination"
9+
)
10+
11+
type CreateOpts struct {
12+
// The value must be the ID of the subnet created in the VPC specified by vpc_id and in the format of the UUID.
13+
// This parameter is mandatory only if you create a VPC endpoint for connecting to an interface VPC endpoint service.
14+
NetworkID string `json:"subnet_id,omitempty"`
15+
16+
// Specifies the ID of the VPC endpoint service.
17+
ServiceID string `json:"endpoint_service_id" required:"true"`
18+
19+
// Specifies the ID of the VPC where the VPC endpoint is to be created.
20+
RouterID string `json:"vpc_id" required:"true"`
21+
22+
// Specifies whether to create a private domain name.
23+
EnableDNS bool `json:"enable_dns"`
24+
25+
// Lists the resource tags.
26+
Tags []tags.ResourceTag `json:"tags,omitempty"`
27+
28+
// Lists the IDs of route tables.
29+
// This parameter is mandatory only if you create a VPC endpoint for connecting to a `gateway` VPC endpoint service.
30+
RouteTables []string `json:"routetables,omitempty"`
31+
32+
// Specifies the IP address for accessing the associated VPC endpoint service.
33+
// This parameter is mandatory only if you create a VPC endpoint for connecting to an `interface` VPC endpoint service.
34+
PortID string `json:"port_id,omitempty"`
35+
36+
// Specifies the whitelist for controlling access to the VPC endpoint.
37+
//
38+
// IPv4 addresses or CIDR blocks can be specified to control access when you create a VPC endpoint.
39+
//
40+
// This parameter is mandatory only when you create a VPC endpoint for connecting to an interface VPC endpoint service.
41+
Whitelist []string `json:"whitelist,omitempty"`
42+
43+
// Specifies whether to enable access control.
44+
EnableWhitelist *bool `json:"enable_whitelist,omitempty"`
45+
}
46+
47+
type CreateOptsBuilder interface {
48+
ToEndpointCreateMap() (map[string]interface{}, error)
49+
}
50+
51+
func (opts CreateOpts) ToEndpointCreateMap() (map[string]interface{}, error) {
52+
return golangsdk.BuildRequestBody(opts, "")
53+
}
54+
55+
func Create(client *golangsdk.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
56+
b, err := opts.ToEndpointCreateMap()
57+
if err != nil {
58+
r.Err = err
59+
return
60+
}
61+
_, r.Err = client.Post(baseURL(client), b, &r.Body, &golangsdk.RequestOpts{
62+
OkCodes: []int{http.StatusOK, http.StatusCreated},
63+
})
64+
return
65+
}
66+
67+
func Get(client *golangsdk.ServiceClient, id string) (r GetResult) {
68+
_, r.Err = client.Get(resourceURL(client, id), &r.Body, nil)
69+
return
70+
}
71+
72+
func Delete(client *golangsdk.ServiceClient, id string) (r DeleteResult) {
73+
_, r.Err = client.Delete(resourceURL(client, id), &golangsdk.RequestOpts{
74+
OkCodes: []int{http.StatusNoContent},
75+
})
76+
return
77+
}
78+
79+
type ListOptsBuilder interface {
80+
ToEndpointListQuery() (string, error)
81+
}
82+
83+
type ListOpts struct {
84+
ServiceName string `q:"endpoint_service_name"`
85+
RouterID string `q:"vpc_id"`
86+
ID string `q:"id"`
87+
SortKey string `q:"sort_key"`
88+
SortDir string `q:"sort_dir"`
89+
}
90+
91+
func (opts ListOpts) ToEndpointListQuery() (string, error) {
92+
q, err := golangsdk.BuildQueryString(opts)
93+
if err != nil {
94+
return "", err
95+
}
96+
return q.String(), nil
97+
}
98+
99+
func List(client *golangsdk.ServiceClient, opts ListOptsBuilder) pagination.Pager {
100+
url := baseURL(client)
101+
if opts != nil {
102+
q, err := opts.ToEndpointListQuery()
103+
if err != nil {
104+
return pagination.Pager{Err: err}
105+
}
106+
url += q
107+
}
108+
return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
109+
return EndpointPage{OffsetPageBase: pagination.OffsetPageBase{PageResult: r}}
110+
})
111+
}
112+
113+
func WaitForEndpointStatus(client *golangsdk.ServiceClient, id string, status Status, timeout int) error {
114+
return golangsdk.WaitFor(timeout, func() (bool, error) {
115+
ep, err := Get(client, id).Extract()
116+
if err != nil {
117+
if _, ok := err.(golangsdk.ErrDefault404); ok && status == "" {
118+
return true, nil
119+
}
120+
return false, err
121+
}
122+
if ep.Status == status {
123+
return true, nil
124+
}
125+
return false, nil
126+
})
127+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package endpoints
2+
3+
import (
4+
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
5+
"github.com/opentelekomcloud/gophertelekomcloud/openstack/common/tags"
6+
"github.com/opentelekomcloud/gophertelekomcloud/openstack/vpcep/v1/services"
7+
"github.com/opentelekomcloud/gophertelekomcloud/pagination"
8+
)
9+
10+
type Status string
11+
12+
const (
13+
StatusPendingAcceptance Status = "pendingAcceptance"
14+
StatusCreating Status = "creating"
15+
StatusAccepted Status = "accepted"
16+
StatusFailed Status = "failed"
17+
)
18+
19+
type Endpoint struct {
20+
// Specifies the unique ID of the VPC endpoint.
21+
ID string `json:"id"`
22+
23+
// Specifies the type of the VPC endpoint service that is associated with the VPC endpoint.
24+
ServiceType services.ServiceType `json:"service_type"`
25+
26+
// Specifies the packet ID of the VPC endpoint.
27+
MarkerID int `json:"marker_id"`
28+
29+
// Specifies the connection status of the VPC endpoint.
30+
//
31+
// pendingAcceptance: indicates that the VPC endpoint is pending acceptance.
32+
// creating: indicates the VPC endpoint is being created.
33+
// accepted: indicates the VPC endpoint has been accepted.
34+
// failed: indicates the creation of the VPC endpoint failed.
35+
Status Status `json:"status"`
36+
37+
// Specifies the ID of the VPC where the VPC endpoint is to be created.
38+
RouterID string `json:"vpc_id"`
39+
40+
// Specifies whether to create a private domain name.
41+
EnableDNS bool `json:"enable_dns"`
42+
43+
// Specifies the name of the VPC endpoint service.
44+
ServiceName string `json:"endpoint_service_name"`
45+
46+
// Specifies the ID of the VPC endpoint service.
47+
ServiceID string `json:"endpoint_service_id"`
48+
49+
// Specifies the project ID.
50+
ProjectID string `json:"project_id"`
51+
52+
// Specifies the whitelist for controlling access to the VPC endpoint.
53+
Whitelist []string `json:"whitelist"`
54+
55+
// Specifies whether to enable access control.
56+
EnableWhitelist bool `json:"enable_whitelist"`
57+
58+
// Specifies the creation time of the VPC endpoint.
59+
CreatedAt string `json:"created_at"`
60+
61+
// Specifies the update time of the VPC endpoint.
62+
UpdatedAt string `json:"updated_at"`
63+
64+
// Lists the resource tags.
65+
Tags []tags.ResourceTag `json:"tags"`
66+
}
67+
68+
type commonResult struct {
69+
golangsdk.Result
70+
}
71+
72+
func (r commonResult) Extract() (*Endpoint, error) {
73+
ep := new(Endpoint)
74+
err := r.ExtractIntoStructPtr(ep, "")
75+
if err != nil {
76+
return nil, err
77+
}
78+
return ep, nil
79+
}
80+
81+
type CreateResult struct {
82+
commonResult
83+
}
84+
85+
type GetResult struct {
86+
commonResult
87+
}
88+
89+
type UpdateResult struct {
90+
commonResult
91+
}
92+
93+
type DeleteResult struct {
94+
golangsdk.ErrResult
95+
}
96+
97+
type EndpointPage struct {
98+
pagination.OffsetPageBase
99+
}
100+
101+
func (p EndpointPage) IsEmpty() (bool, error) {
102+
eps, err := ExtractEndpoints(p)
103+
if err != nil {
104+
return false, err
105+
}
106+
return len(eps) == 0, nil
107+
}
108+
109+
func ExtractEndpoints(p pagination.Page) ([]Endpoint, error) {
110+
var eps []Endpoint
111+
err := p.(EndpointPage).ExtractIntoSlicePtr(&eps, "endpoints")
112+
return eps, err
113+
}

0 commit comments

Comments
 (0)