From 868a423a0e28c437c641f464da2cd08c7ee6c30a Mon Sep 17 00:00:00 2001 From: Aleksandr Boldyrev Date: Wed, 29 Nov 2023 11:39:09 +0100 Subject: [PATCH 1/4] init --- CHANGELOG.md | 13 ++- client.go | 26 +++++ connectors/common_types.go | 16 +++ connectors/connectors_source_metadata.go | 43 ++++++++ fivetran.go | 5 + groups/common_types.go | 9 ++ groups/group_private_links_list.go | 47 +++++++++ groups/group_private_links_list_test.go | 109 ++++++++++++++++++++ private_links/common_types.go | 34 ++++++ private_links/private_links_config.go | 107 +++++++++++++++++++ private_links/private_links_create.go | 60 +++++++++++ private_links/private_links_create_test.go | 86 +++++++++++++++ private_links/private_links_delete.go | 32 ++++++ private_links/private_links_delete_test.go | 49 +++++++++ private_links/private_links_details.go | 31 ++++++ private_links/private_links_details_test.go | 100 ++++++++++++++++++ private_links/private_links_modify.go | 49 +++++++++ private_links/private_links_modify_test.go | 87 ++++++++++++++++ test_utils/test_utils.go | 99 ++++++++++++++++++ tests/e2e/group_private_links_list_test.go | 26 +++++ tests/e2e/private_links_create_test.go | 43 ++++++++ tests/e2e/private_links_delete_test.go | 29 ++++++ tests/e2e/private_links_modify_test.go | 30 ++++++ 23 files changed, 1129 insertions(+), 1 deletion(-) create mode 100644 connectors/connectors_source_metadata.go create mode 100644 groups/group_private_links_list.go create mode 100644 groups/group_private_links_list_test.go create mode 100644 private_links/common_types.go create mode 100644 private_links/private_links_config.go create mode 100644 private_links/private_links_create.go create mode 100644 private_links/private_links_create_test.go create mode 100644 private_links/private_links_delete.go create mode 100644 private_links/private_links_delete_test.go create mode 100644 private_links/private_links_details.go create mode 100644 private_links/private_links_details_test.go create mode 100644 private_links/private_links_modify.go create mode 100644 private_links/private_links_modify_test.go create mode 100644 tests/e2e/group_private_links_list_test.go create mode 100644 tests/e2e/private_links_create_test.go create mode 100644 tests/e2e/private_links_delete_test.go create mode 100644 tests/e2e/private_links_modify_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index daf19fe9..edc8af53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased](https://github.com/fivetran/go-fivetran/compare/v0.7.13...HEAD) +## [Unreleased](https://github.com/fivetran/go-fivetran/compare/v0.7.17...HEAD) + +## [0.7.16](https://github.com/fivetran/go-fivetran/compare/v0.7.15...v0.7.16) + +## Added + +Supported the following Fivetran API endpoints for Private Links Management: +- [Create a Private Link](https://fivetran.com/docs/rest-api/private-links-management#createaprivatelink) +- [List all Private Links within Group](https://fivetran.com/docs/rest-api/private-links-management#listallprivatelinkswithingroup) +- [Retrieve Private Link Details](https://fivetran.com/docs/rest-api/private-links-management#retrieveprivatelinkdetails) +- [Update a Private Link](https://fivetran.com/docs/rest-api/private-links-management#updateaprivatelink) +- [Delete a Private Link](https://fivetran.com/docs/rest-api/private-links-management#deleteaprivatelink) ## [0.8.0](https://github.com/fivetran/go-fivetran/compare/v0.7.11...v0.8.10) diff --git a/client.go b/client.go index 1b1fd88e..57528d1e 100644 --- a/client.go +++ b/client.go @@ -17,6 +17,7 @@ import ( "github.com/fivetran/go-fivetran/teams" "github.com/fivetran/go-fivetran/roles" "github.com/fivetran/go-fivetran/connect_card" + "github.com/fivetran/go-fivetran/private_links" httputils "github.com/fivetran/go-fivetran/http_utils" ) @@ -231,6 +232,10 @@ func (c *Client) NewGroupListUsers() *groups.GroupListUsersService { return &groups.GroupListUsersService{HttpService: c.NewHttpService()} } +func (c *Client) NewGroupListPrivateLinks() *groups.GroupListPrivateLinksService { + return &groups.GroupListPrivateLinksService{HttpService: c.NewHttpService()} +} + func (c *Client) NewGroupsList() *groups.GroupsListService { return &groups.GroupsListService{HttpService: c.NewHttpService()} } @@ -564,4 +569,25 @@ func (c *Client) NewConnectorSchemaUpdateService() *connectors.ConnectorSchemaCo func (c *Client) NewConnectorTableConfigModifyService() *connectors.ConnectorTableConfigModifyService { return &connectors.ConnectorTableConfigModifyService{HttpService: c.NewHttpService()} +} + +func (c *Client) NewConnectorsSourceMetadata() *connectors.ConnectorsSourceMetadataService { + return &connectors.ConnectorsSourceMetadataService{HttpService: c.NewHttpService()} +} + +/* Private Links */ +func (c *Client) NewPrivateLinksCreate() *privatelinks.PrivateLinksCreateService { + return &privatelinks.PrivateLinksCreateService{HttpService: c.NewHttpService()} +} + +func (c *Client) NewPrivateLinksDelete() *privatelinks.PrivateLinksDeleteService { + return &privatelinks.PrivateLinksDeleteService{HttpService: c.NewHttpService()} +} + +func (c *Client) NewPrivateLinksDetails() *privatelinks.PrivateLinksDetailsService { + return &privatelinks.PrivateLinksDetailsService{HttpService: c.NewHttpService()} +} + +func (c *Client) NewPrivateLinksModify() *privatelinks.PrivateLinksModifyService { + return &privatelinks.PrivateLinksModifyService{HttpService: c.NewHttpService()} } \ No newline at end of file diff --git a/connectors/common_types.go b/connectors/common_types.go index 3c771168..e174cb13 100644 --- a/connectors/common_types.go +++ b/connectors/common_types.go @@ -182,3 +182,19 @@ type connectorTableConfigModifyRequest struct { SyncMode *string `json:"sync_mode,omitempty"` Columns map[string]*ConnectorSchemaConfigColumnRequest `json:"columns,omitempty"` } + +type ConnectorsSourceMetadataResponse struct { + common.CommonResponse + Data struct { + Items []struct { + ID string `json:"id"` + Name string `json:"name"` + Type string `json:"type"` + Description string `json:"description"` + IconURL string `json:"icon_url"` + LinkToDocs string `json:"link_to_docs"` + LinkToErd string `json:"link_to_erd"` + } `json:"items"` + NextCursor string `json:"next_cursor"` + } `json:"data"` +} diff --git a/connectors/connectors_source_metadata.go b/connectors/connectors_source_metadata.go new file mode 100644 index 00000000..ee84ddf0 --- /dev/null +++ b/connectors/connectors_source_metadata.go @@ -0,0 +1,43 @@ +package connectors + +import ( + "context" + "fmt" + + httputils "github.com/fivetran/go-fivetran/http_utils" +) + +// ConnectorsSourceMetadataService implements the Connector Management, Retrieve source metadata API. +// Ref. https://fivetran.com/docs/rest-api/connectors#retrievesourcemetadata +type ConnectorsSourceMetadataService struct { + httputils.HttpService + limit *int + cursor *string +} + +func (s *ConnectorsSourceMetadataService) Limit(value int) *ConnectorsSourceMetadataService { + s.limit = &value + return s +} + +func (s *ConnectorsSourceMetadataService) Cursor(value string) *ConnectorsSourceMetadataService { + s.cursor = &value + return s +} + +func (s *ConnectorsSourceMetadataService) Do(ctx context.Context) (ConnectorsSourceMetadataResponse, error) { + var response ConnectorsSourceMetadataResponse + var queries map[string]string = nil + if s.cursor != nil || s.limit != nil { + queries = make(map[string]string) + if s.cursor != nil { + queries["cursor"] = *s.cursor + } + if s.limit != nil { + queries["limit"] = fmt.Sprintf("%v", *s.limit) + } + } + + err := s.HttpService.Do(ctx, "GET", "/metadata/connectors", nil, queries, 200, &response) + return response, err +} \ No newline at end of file diff --git a/fivetran.go b/fivetran.go index 6372d247..8f8ebdfd 100644 --- a/fivetran.go +++ b/fivetran.go @@ -6,6 +6,7 @@ import ( "github.com/fivetran/go-fivetran/destinations" "github.com/fivetran/go-fivetran/connect_card" externallogging "github.com/fivetran/go-fivetran/external_logging" + "github.com/fivetran/go-fivetran/private_links" httputils "github.com/fivetran/go-fivetran/http_utils" ) @@ -73,6 +74,10 @@ func NewConnectCardConfig() *connectcard.ConnectCardConfig { return &connectcard.ConnectCardConfig{} } +func NewPrivateLinksConfig() *privatelinks.PrivateLinksConfig { + return &privatelinks.PrivateLinksConfig{} +} + func Debug(value bool) { httputils.Debug(value) } diff --git a/groups/common_types.go b/groups/common_types.go index 83549736..4168d5f0 100644 --- a/groups/common_types.go +++ b/groups/common_types.go @@ -6,6 +6,7 @@ import ( "github.com/fivetran/go-fivetran/common" "github.com/fivetran/go-fivetran/connectors" "github.com/fivetran/go-fivetran/users" + "github.com/fivetran/go-fivetran/private_links" ) type GroupItem struct { @@ -49,6 +50,14 @@ type GroupListUsersResponse struct { } `json:"data"` } +type GroupListPrivateLinksResponse struct { + common.CommonResponse + Data struct { + Items []privatelinks.PrivateLinksResponseBase `json:"items"` + NextCursor string `json:"next_cursor"` + } `json:"data"` +} + type GroupsListResponse struct { common.CommonResponse Data struct { diff --git a/groups/group_private_links_list.go b/groups/group_private_links_list.go new file mode 100644 index 00000000..1ad5780e --- /dev/null +++ b/groups/group_private_links_list.go @@ -0,0 +1,47 @@ +package groups + +import ( + "context" + "fmt" + + httputils "github.com/fivetran/go-fivetran/http_utils" +) + +type GroupListPrivateLinksService struct { + httputils.HttpService + groupID *string + limit *int + cursor *string +} + +func (s *GroupListPrivateLinksService) GroupID(value string) *GroupListPrivateLinksService { + s.groupID = &value + return s +} + +func (s *GroupListPrivateLinksService) Limit(value int) *GroupListPrivateLinksService { + s.limit = &value + return s +} + +func (s *GroupListPrivateLinksService) Cursor(value string) *GroupListPrivateLinksService { + s.cursor = &value + return s +} + +func (s *GroupListPrivateLinksService) Do(ctx context.Context) (GroupListPrivateLinksResponse, error) { + var response GroupListPrivateLinksResponse + url := fmt.Sprintf("/groups/%v/private-links", *s.groupID) + var queries map[string]string = nil + if s.cursor != nil || s.limit != nil { + queries = make(map[string]string) + if s.cursor != nil { + queries["cursor"] = *s.cursor + } + if s.limit != nil { + queries["limit"] = fmt.Sprintf("%v", *s.limit) + } + } + err := s.HttpService.Do(ctx, "GET", url, nil, queries, 200, &response) + return response, err +} diff --git a/groups/group_private_links_list_test.go b/groups/group_private_links_list_test.go new file mode 100644 index 00000000..c427b71f --- /dev/null +++ b/groups/group_private_links_list_test.go @@ -0,0 +1,109 @@ +package groups_test + +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/fivetran/go-fivetran/groups" + "github.com/fivetran/go-fivetran/tests/mock" + + testutils "github.com/fivetran/go-fivetran/test_utils" +) + +const ( + GROUP_LIST_PRIVATE_LINK_ID = "123456789123456789" + GROUP_LIST_PRIVATE_LINK_NAME = "name" + GROUP_LIST_PRIVATE_LINK_GROUP_ID = "group" + GROUP_LIST_PRIVATE_LINK_CLOUD = "cloud" + GROUP_LIST_PRIVATE_LINK_SERVICE = "service" + GROUP_LIST_PRIVATE_LINK_REGION = "region" + GROUP_LIST_PRIVATE_LINK_STATE = "state" + GROUP_LIST_PRIVATE_LINK_STATE_SUMMARY = "state_summary" + GROUP_LIST_PRIVATE_LINK_CREATED_AT = "2018-01-15T11:00:27.329220Z" + GROUP_LIST_PRIVATE_LINK_CREATED_BY = "created_by" +) + +func TestGroupListPrivateLinksServiceDo(t *testing.T) { + // arrange + groupID := "projected_sickle" + limit := 10 + cursor := "eyJza2lwIjoxfQ" + + ftClient, mockClient := testutils.CreateTestClient() + handler := mockClient.When(http.MethodGet, fmt.Sprintf("/v1/groups/%s/private-links", groupID)). + ThenCall(func(req *http.Request) (*http.Response, error) { + response := mock.NewResponse(req, http.StatusOK, prepareGroupListPrivateLinksResponse()) + return response, nil + }) + + // act + response, err := ftClient.NewGroupListPrivateLinks(). + GroupID(groupID). + Limit(limit). + Cursor(cursor). + Do(context.Background()) + + // assert + if err != nil { + t.Error(err) + } + + interactions := mockClient.Interactions() + testutils.AssertEqual(t, len(interactions), 1) + testutils.AssertEqual(t, interactions[0].Handler, handler) + testutils.AssertEqual(t, handler.Interactions, 1) + assertGroupListPrivateLinksResponse(t, response) +} + +func prepareGroupListPrivateLinksResponse() string { + value := fmt.Sprintf(`{ + "code": "Success", + "data": { + "items": [ + { + "id": "%v", + "name": "%v", + "group_id": "%v", + "cloud_provider": "%v", + "service": "%v", + "region": "%v", + "state": "%v", + "state_summary": "%v", + "created_at": "%v", + "created_by": "%v" + } + ], + "next_cursor": "eyJza2lwIjoyfQ" + } + }`, + GROUP_LIST_PRIVATE_LINK_ID, + GROUP_LIST_PRIVATE_LINK_NAME, + GROUP_LIST_PRIVATE_LINK_GROUP_ID, + GROUP_LIST_PRIVATE_LINK_CLOUD, + GROUP_LIST_PRIVATE_LINK_SERVICE, + GROUP_LIST_PRIVATE_LINK_REGION, + GROUP_LIST_PRIVATE_LINK_STATE, + GROUP_LIST_PRIVATE_LINK_STATE_SUMMARY, + GROUP_LIST_PRIVATE_LINK_CREATED_AT, + GROUP_LIST_PRIVATE_LINK_CREATED_BY) + return value +} + +func assertGroupListPrivateLinksResponse(t *testing.T, response groups.GroupListPrivateLinksResponse) { + testutils.AssertEqual(t, response.Code, "Success") + testutils.AssertEqual(t, len(response.Data.Items), 1) + item := response.Data.Items[0] + testutils.AssertEqual(t, item.Id, GROUP_LIST_PRIVATE_LINK_ID) + testutils.AssertEqual(t, item.Name, GROUP_LIST_PRIVATE_LINK_NAME) + testutils.AssertEqual(t, item.GroupId, GROUP_LIST_PRIVATE_LINK_GROUP_ID) + testutils.AssertEqual(t, item.CloudProvider, GROUP_LIST_PRIVATE_LINK_CLOUD) + testutils.AssertEqual(t, item.Service, GROUP_LIST_PRIVATE_LINK_SERVICE) + testutils.AssertEqual(t, item.Region, GROUP_LIST_PRIVATE_LINK_REGION) + testutils.AssertEqual(t, item.State, GROUP_LIST_PRIVATE_LINK_STATE) + testutils.AssertEqual(t, item.StateSummary, GROUP_LIST_PRIVATE_LINK_STATE_SUMMARY) + testutils.AssertEqual(t, item.CreatedAt, GROUP_LIST_PRIVATE_LINK_CREATED_AT) + testutils.AssertEqual(t, item.CreatedBy, GROUP_LIST_PRIVATE_LINK_CREATED_BY) +} + diff --git a/private_links/common_types.go b/private_links/common_types.go new file mode 100644 index 00000000..ae0d6616 --- /dev/null +++ b/private_links/common_types.go @@ -0,0 +1,34 @@ +package privatelinks + +type PrivateLinksResponseBase struct { + Id string `json:"id"` + Name string `json:"name"` + GroupId string `json:"group_id"` + CloudProvider string `json:"cloud_provider"` + Service string `json:"service"` + Region string `json:"region"` + State string `json:"state"` + StateSummary string `json:"state_summary"` + CreatedAt string `json:"created_at"` + CreatedBy string `json:"created_by"` +} + +type PrivateLinksResponse struct { + Code string `json:"code"` + Message string `json:"message"` + Data struct { + PrivateLinksResponseBase + Config PrivateLinksConfigResponse `json:"config"` + } `json:"data"` +} + +type privateLinksCreateRequest struct { + Name *string `json:"name,omitempty"` + Service *string `json:"service,omitempty"` + GroupId *string `json:"group_id,omitempty"` + Config any `json:"config,omitempty"` +} + +type privateLinksModifyRequest struct { + Config any `json:"config,omitempty"` +} \ No newline at end of file diff --git a/private_links/private_links_config.go b/private_links/private_links_config.go new file mode 100644 index 00000000..0d5a5c2b --- /dev/null +++ b/private_links/private_links_config.go @@ -0,0 +1,107 @@ +package privatelinks + +// PrivateLinksConfig builds Private Links Management, Private Link Config. +// Ref. https://fivetran.com/docs/rest-api/private-links-management#privatelinksetupconfigurations +type PrivateLinksConfig struct { + connectionServiceName *string + connectionServiceId *string + workspaceUrl *string + accountName *string + accountUrl *string + vpceId *string + plsId *string + awsAccountId *string + clusterIdentifier *string + subResourceName *string +} + +type privateLinksConfigRequest struct { + ConnectionServiceName *string `json:"connection_service_name,omitempty"` + ConnectionServiceId *string `json:"connection_service_id,omitempty"` + WorkspaceUrl *string `json:"workspace_url,omitempty"` + AccountName *string `json:"account_name,omitempty"` + AccountUrl *string `json:"account_url,omitempty"` + VpceId *string `json:"vpceId,omitempty"` + PlsId *string `json:"pls_id,omitempty"` + AwsAccountId *string `json:"aws_account_id,omitempty"` + ClusterIdentifier *string `json:"cluster_identifier,omitempty"` + SubResourceName *string `json:"sub_resource_name,omitempty"` +} + +type PrivateLinksConfigResponse struct { + ConnectionServiceName string `json:"connection_service_name"` + ConnectionServiceId string `json:"connection_service_id"` + WorkspaceUrl string `json:"workspace_url"` + AccountName string `json:"account_name"` + AccountUrl string `json:"account_url"` + VpceId string `json:"vpceId"` + PlsId string `json:"pls_id"` + AwsAccountId string `json:"aws_account_id"` + ClusterIdentifier string `json:"cluster_identifier"` + SubResourceName string `json:"sub_resource_name"` +} + +func (plc *PrivateLinksConfig) Request() *privateLinksConfigRequest { + return &privateLinksConfigRequest{ + ConnectionServiceName: plc.connectionServiceName, + ConnectionServiceId: plc.connectionServiceId, + WorkspaceUrl: plc.workspaceUrl, + AccountName: plc.accountName, + AccountUrl: plc.accountUrl, + VpceId: plc.vpceId, + PlsId: plc.plsId, + AwsAccountId: plc.awsAccountId, + ClusterIdentifier: plc.clusterIdentifier, + SubResourceName: plc.subResourceName, + } +} + +func (plc *PrivateLinksConfig) ConnectionServiceName(value string) *PrivateLinksConfig { + plc.connectionServiceName = &value + return plc +} + +func (plc *PrivateLinksConfig) ConnectionServiceId(value string) *PrivateLinksConfig { + plc.connectionServiceId = &value + return plc +} + +func (plc *PrivateLinksConfig) WorkspaceUrl(value string) *PrivateLinksConfig { + plc.workspaceUrl = &value + return plc +} + +func (plc *PrivateLinksConfig) AccountName(value string) *PrivateLinksConfig { + plc.accountName = &value + return plc +} + +func (plc *PrivateLinksConfig) AccountUrl(value string) *PrivateLinksConfig { + plc.accountUrl = &value + return plc +} + +func (plc *PrivateLinksConfig) VpceId(value string) *PrivateLinksConfig { + plc.vpceId = &value + return plc +} + +func (plc *PrivateLinksConfig) PlsId(value string) *PrivateLinksConfig { + plc.plsId = &value + return plc +} + +func (plc *PrivateLinksConfig) AwsAccountId(value string) *PrivateLinksConfig { + plc.awsAccountId = &value + return plc +} + +func (plc *PrivateLinksConfig) ClusterIdentifier(value string) *PrivateLinksConfig { + plc.clusterIdentifier = &value + return plc +} + +func (plc *PrivateLinksConfig) SubResourceName(value string) *PrivateLinksConfig { + plc.subResourceName = &value + return plc +} diff --git a/private_links/private_links_create.go b/private_links/private_links_create.go new file mode 100644 index 00000000..4af6ba92 --- /dev/null +++ b/private_links/private_links_create.go @@ -0,0 +1,60 @@ +package privatelinks + +import ( + "context" + "fmt" + + httputils "github.com/fivetran/go-fivetran/http_utils" +) + +// PrivateLinksCreateService implements the Log Management, Create a Log Service API. +// Ref. https://fivetran.com/docs/rest-api/log-service-management#createalogservice +type PrivateLinksCreateService struct { + httputils.HttpService + name *string + service *string + groupId *string + config *PrivateLinksConfig +} + + +func (s *PrivateLinksCreateService) request() privateLinksCreateRequest { + var config interface{} + if s.config != nil { + config = s.config.Request() + } + + return privateLinksCreateRequest{ + Name: s.name, + GroupId: s.groupId, + Service: s.service, + Config: config, + } +} + +func (s *PrivateLinksCreateService) GroupId(value string) *PrivateLinksCreateService { + s.groupId = &value + return s +} + +func (s *PrivateLinksCreateService) Service(value string) *PrivateLinksCreateService { + s.service = &value + return s +} + +func (s *PrivateLinksCreateService) Name(value string) *PrivateLinksCreateService { + s.name = &value + return s +} + +func (s *PrivateLinksCreateService) Config(value *PrivateLinksConfig) *PrivateLinksCreateService { + s.config = value + return s +} + +func (s *PrivateLinksCreateService) Do(ctx context.Context) (PrivateLinksResponse, error) { + var response PrivateLinksResponse + fmt.Printf("request %v", s.request()) + err := s.HttpService.Do(ctx, "POST", "/private-links", s.request(), nil, 201, &response) + return response, err +} \ No newline at end of file diff --git a/private_links/private_links_create_test.go b/private_links/private_links_create_test.go new file mode 100644 index 00000000..9b419b6c --- /dev/null +++ b/private_links/private_links_create_test.go @@ -0,0 +1,86 @@ +package privatelinks_test + +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/fivetran/go-fivetran/private_links" + "github.com/fivetran/go-fivetran/tests/mock" + testutils "github.com/fivetran/go-fivetran/test_utils" +) + +func TestPrivateLinksCreateServiceDo(t *testing.T) { + // arrange + + ftClient, mockClient := testutils.CreateTestClient() + handler := mockClient.When(http.MethodPost, "/v1/private-links"). + ThenCall(func(req *http.Request) (*http.Response, error) { + response := mock.NewResponse(req, http.StatusCreated, preparePrivateLinksCreateResponse()) + return response, nil + }) + + // act + response, err := ftClient.NewPrivateLinksCreate(). + Name(GROUP_LIST_PRIVATE_LINK_NAME). + Do(context.Background()) + + // assert + if err != nil { + t.Error(err) + } + + interactions := mockClient.Interactions() + testutils.AssertEqual(t, len(interactions), 1) + testutils.AssertEqual(t, interactions[0].Handler, handler) + testutils.AssertEqual(t, handler.Interactions, 1) + assertPrivateLinksCreateResponse(t, response) +} + +func preparePrivateLinksCreateResponse() string { + return fmt.Sprintf(`{ + "code": "Success", + "data": { + "id": "%v", + "name": "%v", + "group_id": "%v", + "cloud_provider": "%v", + "service": "%v", + "region": "%v", + "state": "%v", + "state_summary": "%v", + "created_at": "%v", + "created_by": "%v", + "config" : { + "workspace_url": "%v" + } + } + }`, + GROUP_LIST_PRIVATE_LINK_ID, + GROUP_LIST_PRIVATE_LINK_NAME, + GROUP_LIST_PRIVATE_LINK_GROUP_ID, + GROUP_LIST_PRIVATE_LINK_CLOUD, + GROUP_LIST_PRIVATE_LINK_SERVICE, + GROUP_LIST_PRIVATE_LINK_REGION, + GROUP_LIST_PRIVATE_LINK_STATE, + GROUP_LIST_PRIVATE_LINK_STATE_SUMMARY, + GROUP_LIST_PRIVATE_LINK_CREATED_AT, + GROUP_LIST_PRIVATE_LINK_CREATED_BY, + GROUP_LIST_PRIVATE_LINK_WORKSPACE_ID) +} + +func assertPrivateLinksCreateResponse(t *testing.T, response privatelinks.PrivateLinksResponse) { + testutils.AssertEqual(t, response.Code, "Success") + testutils.AssertEqual(t, response.Data.Id, GROUP_LIST_PRIVATE_LINK_ID) + testutils.AssertEqual(t, response.Data.Name, GROUP_LIST_PRIVATE_LINK_NAME) + testutils.AssertEqual(t, response.Data.GroupId, GROUP_LIST_PRIVATE_LINK_GROUP_ID) + testutils.AssertEqual(t, response.Data.CloudProvider, GROUP_LIST_PRIVATE_LINK_CLOUD) + testutils.AssertEqual(t, response.Data.Service, GROUP_LIST_PRIVATE_LINK_SERVICE) + testutils.AssertEqual(t, response.Data.Region, GROUP_LIST_PRIVATE_LINK_REGION) + testutils.AssertEqual(t, response.Data.State, GROUP_LIST_PRIVATE_LINK_STATE) + testutils.AssertEqual(t, response.Data.StateSummary, GROUP_LIST_PRIVATE_LINK_STATE_SUMMARY) + testutils.AssertEqual(t, response.Data.CreatedAt, GROUP_LIST_PRIVATE_LINK_CREATED_AT) + testutils.AssertEqual(t, response.Data.CreatedBy, GROUP_LIST_PRIVATE_LINK_CREATED_BY) + testutils.AssertEqual(t, response.Data.Config.WorkspaceUrl, GROUP_LIST_PRIVATE_LINK_WORKSPACE_ID) +} diff --git a/private_links/private_links_delete.go b/private_links/private_links_delete.go new file mode 100644 index 00000000..2d1fe2eb --- /dev/null +++ b/private_links/private_links_delete.go @@ -0,0 +1,32 @@ +package privatelinks + +import ( + "context" + "fmt" + + "github.com/fivetran/go-fivetran/common" + httputils "github.com/fivetran/go-fivetran/http_utils" +) + +// PrivateLinksDeleteService implements the Private Links Management, Delete a Private Link +// Ref. https://fivetran.com/docs/rest-api/private-links-management#deleteaprivatelink +type PrivateLinksDeleteService struct { + httputils.HttpService + privateLinkId *string +} + +func (s *PrivateLinksDeleteService) PrivateLinkId(value string) *PrivateLinksDeleteService { + s.privateLinkId = &value + return s +} + +func (s *PrivateLinksDeleteService) Do(ctx context.Context) (common.CommonResponse, error) { + var response common.CommonResponse + if s.privateLinkId == nil { + return response, fmt.Errorf("missing required privateLinkId") + } + + url := fmt.Sprintf("/private-links/%v", *s.privateLinkId) + err := s.HttpService.Do(ctx, "DELETE", url, nil, nil, 200, &response) + return response, err +} \ No newline at end of file diff --git a/private_links/private_links_delete_test.go b/private_links/private_links_delete_test.go new file mode 100644 index 00000000..57a93f16 --- /dev/null +++ b/private_links/private_links_delete_test.go @@ -0,0 +1,49 @@ +package privatelinks_test + +import ( + "context" + "net/http" + "testing" + + "github.com/fivetran/go-fivetran/common" + "github.com/fivetran/go-fivetran/tests/mock" + testutils "github.com/fivetran/go-fivetran/test_utils" +) + +func TestPrivateLinksDeleteServiceDo(t *testing.T) { + // arrange + ftClient, mockClient := testutils.CreateTestClient() + handler := mockClient.When(http.MethodDelete, "/v1/private-links/123456"). + ThenCall(func(req *http.Request) (*http.Response, error) { + response := mock.NewResponse(req, http.StatusOK, preparePrivateLinksDeleteResponse()) + return response, nil + }) + + // act + response, err := ftClient.NewPrivateLinksDelete(). + PrivateLinkId("123456"). + Do(context.Background()) + + // assert + if err != nil { + t.Error(err) + } + + interactions := mockClient.Interactions() + testutils.AssertEqual(t, len(interactions), 1) + testutils.AssertEqual(t, interactions[0].Handler, handler) + testutils.AssertEqual(t, handler.Interactions, 1) + assertPrivateLinksDeleteResponse(t, response) +} + +func preparePrivateLinksDeleteResponse() string { + return `{ + "code": "Success", + "message": "Group has been deleted" + }` +} + +func assertPrivateLinksDeleteResponse(t *testing.T, response common.CommonResponse) { + testutils.AssertEqual(t, response.Code, "Success") + testutils.AssertEqual(t, response.Message, "Group has been deleted") +} diff --git a/private_links/private_links_details.go b/private_links/private_links_details.go new file mode 100644 index 00000000..401116f2 --- /dev/null +++ b/private_links/private_links_details.go @@ -0,0 +1,31 @@ +package privatelinks + +import ( + "context" + "fmt" + + httputils "github.com/fivetran/go-fivetran/http_utils" +) + +// PrivateLinksDetailsService implements the Private Links Management, Retrieve Private Link details API. +// Ref. https://fivetran.com/docs/rest-api/private-links-management#retrieveprivatelinkdetails +type PrivateLinksDetailsService struct { + httputils.HttpService + privateLinkId *string +} + +func (s *PrivateLinksDetailsService) PrivateLinkId(value string) *PrivateLinksDetailsService { + s.privateLinkId = &value + return s +} + +func (s *PrivateLinksDetailsService) Do(ctx context.Context) (PrivateLinksResponse, error) { + var response PrivateLinksResponse + if s.privateLinkId == nil { + return response, fmt.Errorf("missing required privateLinkId") + } + + url := fmt.Sprintf("/private-links/%v", *s.privateLinkId) + err := s.HttpService.Do(ctx, "GET", url, nil, nil, 200, &response) + return response, err +} \ No newline at end of file diff --git a/private_links/private_links_details_test.go b/private_links/private_links_details_test.go new file mode 100644 index 00000000..bdfe466c --- /dev/null +++ b/private_links/private_links_details_test.go @@ -0,0 +1,100 @@ +package privatelinks_test + +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/fivetran/go-fivetran/private_links" + "github.com/fivetran/go-fivetran/tests/mock" + testutils "github.com/fivetran/go-fivetran/test_utils" +) + +const ( + GROUP_LIST_PRIVATE_LINK_ID = "123456" + GROUP_LIST_PRIVATE_LINK_NAME = "name" + GROUP_LIST_PRIVATE_LINK_GROUP_ID = "group" + GROUP_LIST_PRIVATE_LINK_CLOUD = "cloud" + GROUP_LIST_PRIVATE_LINK_SERVICE = "service" + GROUP_LIST_PRIVATE_LINK_REGION = "region" + GROUP_LIST_PRIVATE_LINK_STATE = "state" + GROUP_LIST_PRIVATE_LINK_STATE_SUMMARY = "state_summary" + GROUP_LIST_PRIVATE_LINK_CREATED_AT = "2018-01-15T11:00:27.329220Z" + GROUP_LIST_PRIVATE_LINK_CREATED_BY = "created_by" + GROUP_LIST_PRIVATE_LINK_WORKSPACE_ID = "workspaceUrl" +) + +func TestPrivateLinksDetailsServiceDo(t *testing.T) { + // arrange + + ftClient, mockClient := testutils.CreateTestClient() + handler := mockClient.When(http.MethodGet, "/v1/private-links/" + GROUP_LIST_PRIVATE_LINK_ID). + ThenCall(func(req *http.Request) (*http.Response, error) { + response := mock.NewResponse(req, http.StatusOK, preparePrivateLinksDetailsResponse()) + return response, nil + }) + + // act + response, err := ftClient.NewPrivateLinksDetails(). + PrivateLinkId(GROUP_LIST_PRIVATE_LINK_ID). + Do(context.Background()) + + // assert + if err != nil { + t.Error(err) + } + + interactions := mockClient.Interactions() + testutils.AssertEqual(t, len(interactions), 1) + testutils.AssertEqual(t, interactions[0].Handler, handler) + testutils.AssertEqual(t, handler.Interactions, 1) + assertPrivateLinksDetailsResponse(t, response) +} + +func preparePrivateLinksDetailsResponse() string { + return fmt.Sprintf(`{ + "code": "Success", + "data": { + "id": "%v", + "name": "%v", + "group_id": "%v", + "cloud_provider": "%v", + "service": "%v", + "region": "%v", + "state": "%v", + "state_summary": "%v", + "created_at": "%v", + "created_by": "%v", + "config" : { + "workspace_url": "%v" + } + } + }`, + GROUP_LIST_PRIVATE_LINK_ID, + GROUP_LIST_PRIVATE_LINK_NAME, + GROUP_LIST_PRIVATE_LINK_GROUP_ID, + GROUP_LIST_PRIVATE_LINK_CLOUD, + GROUP_LIST_PRIVATE_LINK_SERVICE, + GROUP_LIST_PRIVATE_LINK_REGION, + GROUP_LIST_PRIVATE_LINK_STATE, + GROUP_LIST_PRIVATE_LINK_STATE_SUMMARY, + GROUP_LIST_PRIVATE_LINK_CREATED_AT, + GROUP_LIST_PRIVATE_LINK_CREATED_BY, + GROUP_LIST_PRIVATE_LINK_WORKSPACE_ID) +} + +func assertPrivateLinksDetailsResponse(t *testing.T, response privatelinks.PrivateLinksResponse) { + testutils.AssertEqual(t, response.Code, "Success") + testutils.AssertEqual(t, response.Data.Id, GROUP_LIST_PRIVATE_LINK_ID) + testutils.AssertEqual(t, response.Data.Name, GROUP_LIST_PRIVATE_LINK_NAME) + testutils.AssertEqual(t, response.Data.GroupId, GROUP_LIST_PRIVATE_LINK_GROUP_ID) + testutils.AssertEqual(t, response.Data.CloudProvider, GROUP_LIST_PRIVATE_LINK_CLOUD) + testutils.AssertEqual(t, response.Data.Service, GROUP_LIST_PRIVATE_LINK_SERVICE) + testutils.AssertEqual(t, response.Data.Region, GROUP_LIST_PRIVATE_LINK_REGION) + testutils.AssertEqual(t, response.Data.State, GROUP_LIST_PRIVATE_LINK_STATE) + testutils.AssertEqual(t, response.Data.StateSummary, GROUP_LIST_PRIVATE_LINK_STATE_SUMMARY) + testutils.AssertEqual(t, response.Data.CreatedAt, GROUP_LIST_PRIVATE_LINK_CREATED_AT) + testutils.AssertEqual(t, response.Data.CreatedBy, GROUP_LIST_PRIVATE_LINK_CREATED_BY) + testutils.AssertEqual(t, response.Data.Config.WorkspaceUrl, GROUP_LIST_PRIVATE_LINK_WORKSPACE_ID) +} diff --git a/private_links/private_links_modify.go b/private_links/private_links_modify.go new file mode 100644 index 00000000..e357acd4 --- /dev/null +++ b/private_links/private_links_modify.go @@ -0,0 +1,49 @@ +package privatelinks + +import ( + "context" + "fmt" + + httputils "github.com/fivetran/go-fivetran/http_utils" +) + +// PrivateLinksModifyService implements the Private Links Management, Modify a Private Link Service API. +// Ref. https://fivetran.com/docs/rest-api/private-links-management#updateaprivatelink +type PrivateLinksModifyService struct { + httputils.HttpService + privateLinkId *string + config *PrivateLinksConfig +} + +func (s *PrivateLinksModifyService) request() *privateLinksModifyRequest { + var config interface{} + + if s.config != nil { + config = s.config.Request() + } + + return &privateLinksModifyRequest{ + Config: config, + } +} + +func (s *PrivateLinksModifyService) PrivateLinkId(value string) *PrivateLinksModifyService { + s.privateLinkId = &value + return s +} + +func (s *PrivateLinksModifyService) Config(value *PrivateLinksConfig) *PrivateLinksModifyService { + s.config = value + return s +} + +func (s *PrivateLinksModifyService) Do(ctx context.Context) (PrivateLinksResponse, error) { + var response PrivateLinksResponse + if s.privateLinkId == nil { + return response, fmt.Errorf("missing required privateLinkId") + } + + url := fmt.Sprintf("/private-links/%v", *s.privateLinkId) + err := s.HttpService.Do(ctx, "PATCH", url, s.request(), nil, 200, &response) + return response, err +} \ No newline at end of file diff --git a/private_links/private_links_modify_test.go b/private_links/private_links_modify_test.go new file mode 100644 index 00000000..a5f8ab5c --- /dev/null +++ b/private_links/private_links_modify_test.go @@ -0,0 +1,87 @@ +package privatelinks_test + +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/fivetran/go-fivetran" + "github.com/fivetran/go-fivetran/private_links" + "github.com/fivetran/go-fivetran/tests/mock" + testutils "github.com/fivetran/go-fivetran/test_utils" +) + +func TestPrivateLinksModifyServiceDo(t *testing.T) { + // arrange + + ftClient, mockClient := testutils.CreateTestClient() + handler := mockClient.When(http.MethodPatch, "/v1/private-links/" + GROUP_LIST_PRIVATE_LINK_ID). + ThenCall(func(req *http.Request) (*http.Response, error) { + response := mock.NewResponse(req, http.StatusOK, fmt.Sprintf(`{ + "code": "Success", + "data": { + "id": "%v", + "name": "%v", + "group_id": "%v", + "cloud_provider": "%v", + "service": "%v", + "region": "%v", + "state": "%v", + "state_summary": "%v", + "created_at": "%v", + "created_by": "%v", + "config" : { + "workspace_url": "%v" + } + } + }`, + GROUP_LIST_PRIVATE_LINK_ID, + GROUP_LIST_PRIVATE_LINK_NAME, + GROUP_LIST_PRIVATE_LINK_GROUP_ID, + GROUP_LIST_PRIVATE_LINK_CLOUD, + GROUP_LIST_PRIVATE_LINK_SERVICE, + GROUP_LIST_PRIVATE_LINK_REGION, + GROUP_LIST_PRIVATE_LINK_STATE, + GROUP_LIST_PRIVATE_LINK_STATE_SUMMARY, + GROUP_LIST_PRIVATE_LINK_CREATED_AT, + GROUP_LIST_PRIVATE_LINK_CREATED_BY, + GROUP_LIST_PRIVATE_LINK_WORKSPACE_ID)) + return response, nil + }) + + // act + response, err := ftClient.NewPrivateLinksModify(). + PrivateLinkId(GROUP_LIST_PRIVATE_LINK_ID). + Config(preparePrivateLinksModifyConfig()). + Do(context.Background()) + + // assert + if err != nil { + t.Error(err) + } + + interactions := mockClient.Interactions() + testutils.AssertEqual(t, len(interactions), 1) + testutils.AssertEqual(t, interactions[0].Handler, handler) + testutils.AssertEqual(t, handler.Interactions, 1) + testutils.AssertEqual(t, response.Code, "Success") + testutils.AssertEqual(t, response.Data.Id, GROUP_LIST_PRIVATE_LINK_ID) + testutils.AssertEqual(t, response.Data.Name, GROUP_LIST_PRIVATE_LINK_NAME) + testutils.AssertEqual(t, response.Data.GroupId, GROUP_LIST_PRIVATE_LINK_GROUP_ID) + testutils.AssertEqual(t, response.Data.CloudProvider, GROUP_LIST_PRIVATE_LINK_CLOUD) + testutils.AssertEqual(t, response.Data.Service, GROUP_LIST_PRIVATE_LINK_SERVICE) + testutils.AssertEqual(t, response.Data.Region, GROUP_LIST_PRIVATE_LINK_REGION) + testutils.AssertEqual(t, response.Data.State, GROUP_LIST_PRIVATE_LINK_STATE) + testutils.AssertEqual(t, response.Data.StateSummary, GROUP_LIST_PRIVATE_LINK_STATE_SUMMARY) + testutils.AssertEqual(t, response.Data.CreatedAt, GROUP_LIST_PRIVATE_LINK_CREATED_AT) + testutils.AssertEqual(t, response.Data.CreatedBy, GROUP_LIST_PRIVATE_LINK_CREATED_BY) + testutils.AssertEqual(t, response.Data.Config.WorkspaceUrl, GROUP_LIST_PRIVATE_LINK_WORKSPACE_ID) +} + +func preparePrivateLinksModifyConfig() *privatelinks.PrivateLinksConfig { + config := fivetran.NewPrivateLinksConfig() + config.WorkspaceUrl(GROUP_LIST_PRIVATE_LINK_WORKSPACE_ID) + + return config +} \ No newline at end of file diff --git a/test_utils/test_utils.go b/test_utils/test_utils.go index 869f655a..19821213 100644 --- a/test_utils/test_utils.go +++ b/test_utils/test_utils.go @@ -508,6 +508,7 @@ func CleanupAccount() { CleanupDbtProjects() CleanupGroups() CleanupExternalLogging() + CleanupPrivateLinks() CleanupWebhooks() CleanupTeams() } @@ -598,6 +599,25 @@ func CleanupExternalLogging() { } } +func CleanupPrivateLinks() { + groups, err := Client.NewGroupsList().Do(context.Background()) + if err != nil { + log.Fatal(err) + } + for _, group := range groups.Data.Items { + privateLinks, err := Client.NewGroupListPrivateLinks().GroupID(group.ID).Do(context.Background()) + if err != nil { + log.Fatal(err) + } + for _, privateLinks := range privateLinks.Data.Items { + _, err := Client.NewPrivateLinksDelete().PrivateLinkId(privateLinks.Id).Do(context.Background()) + if err != nil && err.Error() != "status code: 404; expected: 200" { + log.Fatal(err) + } + } + } +} + func CleanupWebhooks() { list, err := Client.NewWebhookList().Do(context.Background()) if err != nil { @@ -664,6 +684,84 @@ func CreateExternalLogging(t *testing.T) string { return created.Data.Id } +/* Private Links */ +func CreatePrivateLinkGroup(t *testing.T) string { + t.Helper() + created, err := Client.NewGroupCreate().Name("private_link_test").Do(context.Background()) + if err != nil { + t.Logf("%+v\n", created) + t.Error(err) + } + return created.Data.ID +} + +func CreatePrivateLinkDestination(t *testing.T, id string) string { + t.Helper() + destination, err := Client.NewDestinationCreate(). + GroupID(id). + Service("big_query"). + Region("AWS_US_EAST_1"). + RunSetupTests(false). + TimeZoneOffset("-5"). + Config( + fivetran.NewDestinationConfig(). + ProjectID(BqProjectId). + DataSetLocation("US")). + Do(context.Background()) + if err != nil { + t.Logf("%+v\n", destination) + t.Error(err) + } + return destination.Data.ID +} + +func CreatePrivateLink(t *testing.T) (string, string, string) { + t.Helper() + plGroupId := CreatePrivateLinkGroup(t) + t.Logf("groupId %+v\n", plGroupId) + plDestinationId := CreatePrivateLinkDestination(t,plGroupId) + t.Logf("plDestinationId %+v\n", plDestinationId) + + created, err := Client.NewPrivateLinksCreate(). + Name("test"). + GroupId(plGroupId). + Service("redshift"). + Config(fivetran.NewPrivateLinksConfig(). + AwsAccountId("account_id.cloud_region_name.privatelink.snowflakecomputing.com"). + ClusterIdentifier("account_id.cloud_region_name.privatelink.snowflakecomputing.com")). + Do(context.Background()) + + if err != nil { + t.Logf("%+v\n", created) + t.Error(err) + } + return created.Data.Id, plDestinationId, plGroupId +} + +func DeletePrivateLink(t *testing.T, id string) { + t.Helper() + deleted, err := Client.NewPrivateLinksDelete().PrivateLinkId(id).Do(context.Background()) + + if err != nil { + t.Logf("%+v\n", deleted) + //t.Error(err) + } +} + +func CreateTempPrivateLink(t *testing.T) (string, string) { + t.Helper() + privateLinkId, plDestinationId, plGroupId := CreatePrivateLink(t) + + t.Cleanup(func() { + //DeletePrivateLink(t, privateLinkId) + DeleteDestination(t, plDestinationId) + DeleteGroup(t, plGroupId) + }) + return privateLinkId, plGroupId +} + +/* Private Links */ + func CreateTempWebhook(t *testing.T) string { t.Helper() webhookId := CreateWebhookAccount(t) @@ -697,6 +795,7 @@ func CreateWebhookAccount(t *testing.T) string { return created.Data.Id } + /* Begin Team Management */ func CreateTeam(t *testing.T) string { t.Helper() diff --git a/tests/e2e/group_private_links_list_test.go b/tests/e2e/group_private_links_list_test.go new file mode 100644 index 00000000..5036bf91 --- /dev/null +++ b/tests/e2e/group_private_links_list_test.go @@ -0,0 +1,26 @@ +package fivetran_test + +import ( + "context" + "testing" + + testutils "github.com/fivetran/go-fivetran/test_utils" +) + +func TestNewGroupListPrivateLinksE2E(t *testing.T) { + privateLinkId, groupId := testutils.CreateTempPrivateLink(t) + privateLinks, err := testutils.Client.NewGroupListPrivateLinks().GroupID(groupId).Do(context.Background()) + + if err != nil { + t.Logf("%+v\n", privateLinks) + t.Error(err) + } + + testutils.AssertEqual(t, privateLinks.Code, "Success") + testutils.AssertHasLength(t, privateLinks.Data.Items, 1) + + testutils.AssertEqual(t, privateLinks.Data.Items[0].Name, "test") + testutils.AssertEqual(t, privateLinks.Data.Items[0].Id, privateLinkId) + testutils.AssertEqual(t, privateLinks.Data.Items[0].GroupId, groupId) + testutils.AssertEqual(t, privateLinks.Data.Items[0].Service, "big_query") // It's a bug in PL service - in field service returned service from destination +} \ No newline at end of file diff --git a/tests/e2e/private_links_create_test.go b/tests/e2e/private_links_create_test.go new file mode 100644 index 00000000..fe173ffd --- /dev/null +++ b/tests/e2e/private_links_create_test.go @@ -0,0 +1,43 @@ +package fivetran_test + +import ( + "context" + "testing" + + "github.com/fivetran/go-fivetran" + testutils "github.com/fivetran/go-fivetran/test_utils" +) + +func TestNewPrivateLinkCreateE2E(t *testing.T) { + t.Skip("Private links have a strict limit on the number of requests per hour; to test changes in these modules, this Skip must be removed") + + plGroupId := testutils.CreatePrivateLinkGroup(t) + plDestinationId := testutils.CreatePrivateLinkDestination(t, plGroupId) + + created, err := testutils.Client.NewPrivateLinksCreate(). + Name("test"). + GroupId(plGroupId). + Service("redshift"). + Config(fivetran.NewPrivateLinksConfig(). + AwsAccountId("account_id.cloud_region_name.privatelink.snowflakecomputing.com"). + ClusterIdentifier("account_id.cloud_region_name.privatelink.snowflakecomputing.com")). + Do(context.Background()) + + if err != nil { + t.Logf("%+v\n", created) + t.Error(err) + } + + testutils.AssertEqual(t, created.Code, "Success") + testutils.AssertNotEmpty(t, created.Message) + testutils.AssertEqual(t, created.Data.Name, "test") + testutils.AssertEqual(t, created.Data.Service, "big_query") + testutils.AssertEqual(t, created.Data.GroupId, plGroupId) + testutils.AssertEqual(t, created.Data.Config.AwsAccountId, "account_id.cloud_region_name.privatelink.snowflakecomputing.com") + + t.Cleanup(func() { + testutils.DeletePrivateLink(t, created.Data.Id) + testutils.DeleteDestination(t, plDestinationId) + testutils.DeleteGroup(t, plGroupId) + }) +} diff --git a/tests/e2e/private_links_delete_test.go b/tests/e2e/private_links_delete_test.go new file mode 100644 index 00000000..b0418013 --- /dev/null +++ b/tests/e2e/private_links_delete_test.go @@ -0,0 +1,29 @@ +package fivetran_test + +import ( + "context" + "testing" + + testutils "github.com/fivetran/go-fivetran/test_utils" +) + +func TestNewPrivateLinkDeleteE2E(t *testing.T) { + t.Skip("Private links have a strict limit on the number of requests per hour; to test changes in these modules, this Skip must be removed") + + privateLinkId, plDestinationId, plGroupId := testutils.CreatePrivateLink(t) + + deleted, err := testutils.Client.NewPrivateLinksDelete().PrivateLinkId(privateLinkId).Do(context.Background()) + + if err != nil { + t.Logf("%+v\n", deleted) + t.Error(err) + } + + testutils.AssertEqual(t, deleted.Code, "Success") + testutils.AssertNotEmpty(t, deleted.Message) + + t.Cleanup(func() { + testutils.DeleteDestination(t, plDestinationId) + testutils.DeleteGroup(t, plGroupId) + }) +} diff --git a/tests/e2e/private_links_modify_test.go b/tests/e2e/private_links_modify_test.go new file mode 100644 index 00000000..067fa424 --- /dev/null +++ b/tests/e2e/private_links_modify_test.go @@ -0,0 +1,30 @@ +package fivetran_test + +import ( + "context" + "testing" + + "github.com/fivetran/go-fivetran" + testutils "github.com/fivetran/go-fivetran/test_utils" +) + +func TestNewPrivateLinkModifyE2E(t *testing.T) { + t.Skip("Private links have a strict limit on the number of requests per hour; to test changes in these modules, this Skip must be removed") + + privateLinkId, plGroupId := testutils.CreateTempPrivateLink(t) + details, err := testutils.Client.NewPrivateLinksModify().PrivateLinkId(privateLinkId). + Config(fivetran.NewPrivateLinksConfig(). + AwsAccountId("account_id1.cloud_region_name.privatelink.snowflakecomputing.com")). + Do(context.Background()) + + if err != nil { + t.Logf("%+v\n", details) + t.Error(err) + } + + testutils.AssertEqual(t, details.Code, "Success") + testutils.AssertNotEmpty(t, details.Message) + + testutils.AssertEqual(t, details.Data.GroupId, plGroupId) + testutils.AssertEqual(t, details.Data.Config.AwsAccountId, "account_id1.cloud_region_name.privatelink.snowflakecomputing.com") +} \ No newline at end of file From af7b9cb4e8b8265014f23956342d25c64280f81c Mon Sep 17 00:00:00 2001 From: Aleksandr Boldyrev Date: Thu, 21 Dec 2023 12:01:02 +0100 Subject: [PATCH 2/4] Update CHANGELOG.md --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index edc8af53..5617f5cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased](https://github.com/fivetran/go-fivetran/compare/v0.7.17...HEAD) +## [Unreleased](https://github.com/fivetran/go-fivetran/compare/v0.8.1...HEAD) -## [0.7.16](https://github.com/fivetran/go-fivetran/compare/v0.7.15...v0.7.16) +## [0.8.1](https://github.com/fivetran/go-fivetran/compare/v0.8.0...v0.8.1) ## Added @@ -18,7 +18,7 @@ Supported the following Fivetran API endpoints for Private Links Management: - [Update a Private Link](https://fivetran.com/docs/rest-api/private-links-management#updateaprivatelink) - [Delete a Private Link](https://fivetran.com/docs/rest-api/private-links-management#deleteaprivatelink) -## [0.8.0](https://github.com/fivetran/go-fivetran/compare/v0.7.11...v0.8.10) +## [0.8.0](https://github.com/fivetran/go-fivetran/compare/v0.7.15...v0.8.0) ## Added From 327ac96783817cdd5364e4667795ce4d2e95d61d Mon Sep 17 00:00:00 2001 From: Aleksandr Boldyrev <125960514+fivetran-aleksandrboldyrev@users.noreply.github.com> Date: Tue, 9 Jan 2024 14:13:01 +0100 Subject: [PATCH 3/4] Update private_links/private_links_config.go Co-authored-by: Vitaly Mosin <73104048+beevital@users.noreply.github.com> --- private_links/private_links_config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/private_links/private_links_config.go b/private_links/private_links_config.go index 0d5a5c2b..3071be0a 100644 --- a/private_links/private_links_config.go +++ b/private_links/private_links_config.go @@ -21,7 +21,7 @@ type privateLinksConfigRequest struct { WorkspaceUrl *string `json:"workspace_url,omitempty"` AccountName *string `json:"account_name,omitempty"` AccountUrl *string `json:"account_url,omitempty"` - VpceId *string `json:"vpceId,omitempty"` + VpceId *string `json:"vpce_id,omitempty"` PlsId *string `json:"pls_id,omitempty"` AwsAccountId *string `json:"aws_account_id,omitempty"` ClusterIdentifier *string `json:"cluster_identifier,omitempty"` From c0d0635b4c524bb1c8dffb488b9bc59067fe7948 Mon Sep 17 00:00:00 2001 From: Aleksandr Boldyrev <125960514+fivetran-aleksandrboldyrev@users.noreply.github.com> Date: Tue, 9 Jan 2024 14:13:08 +0100 Subject: [PATCH 4/4] Update private_links/private_links_config.go Co-authored-by: Vitaly Mosin <73104048+beevital@users.noreply.github.com> --- private_links/private_links_config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/private_links/private_links_config.go b/private_links/private_links_config.go index 3071be0a..ea81b030 100644 --- a/private_links/private_links_config.go +++ b/private_links/private_links_config.go @@ -34,7 +34,7 @@ type PrivateLinksConfigResponse struct { WorkspaceUrl string `json:"workspace_url"` AccountName string `json:"account_name"` AccountUrl string `json:"account_url"` - VpceId string `json:"vpceId"` + VpceId string `json:"vpce_id"` PlsId string `json:"pls_id"` AwsAccountId string `json:"aws_account_id"` ClusterIdentifier string `json:"cluster_identifier"`