Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Private Links Management Support #97

Merged
merged 4 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,20 @@ 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.8.1...HEAD)

## [0.8.0](https://github.com/fivetran/go-fivetran/compare/v0.7.11...v0.8.10)
## [0.8.1](https://github.com/fivetran/go-fivetran/compare/v0.8.0...v0.8.1)

## 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.15...v0.8.0)

## Added

Expand Down
26 changes: 26 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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()}
}
Expand Down Expand Up @@ -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()}
}
16 changes: 16 additions & 0 deletions connectors/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
}
43 changes: 43 additions & 0 deletions connectors/connectors_source_metadata.go
Original file line number Diff line number Diff line change
@@ -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
}
5 changes: 5 additions & 0 deletions fivetran.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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)
}
Expand Down
9 changes: 9 additions & 0 deletions groups/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
47 changes: 47 additions & 0 deletions groups/group_private_links_list.go
Original file line number Diff line number Diff line change
@@ -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
}
109 changes: 109 additions & 0 deletions groups/group_private_links_list_test.go
Original file line number Diff line number Diff line change
@@ -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)
}

34 changes: 34 additions & 0 deletions private_links/common_types.go
Original file line number Diff line number Diff line change
@@ -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"`
}
Loading