Skip to content

Commit 34a1e5c

Browse files
Added support for missing Service Transfer related endpoints (#632)
* Added support for service transfers * Fix lint * Reran GetMonthlyTransfer fixture
1 parent 55f9fb9 commit 34a1e5c

File tree

5 files changed

+261
-0
lines changed

5 files changed

+261
-0
lines changed

account_service_transfer.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package linodego
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"time"
7+
8+
"github.com/linode/linodego/internal/parseabletime"
9+
)
10+
11+
// AccountServiceTransferStatus constants start with AccountServiceTransfer and
12+
// include Linode API Account Service Transfer Status values.
13+
type AccountServiceTransferStatus string
14+
15+
// AccountServiceTransferStatus constants reflect the current status of an AccountServiceTransfer
16+
const (
17+
AccountServiceTransferAccepted AccountServiceTransferStatus = "accepted"
18+
AccountServiceTransferCanceled AccountServiceTransferStatus = "canceled"
19+
AccountServiceTransferCompleted AccountServiceTransferStatus = "completed"
20+
AccountServiceTransferFailed AccountServiceTransferStatus = "failed"
21+
AccountServiceTransferPending AccountServiceTransferStatus = "pending"
22+
AccountServiceTransferStale AccountServiceTransferStatus = "stale"
23+
)
24+
25+
// AccountServiceTransfer represents a request to transfer a service on an Account
26+
type AccountServiceTransfer struct {
27+
Created *time.Time `json:"-"`
28+
Entities AccountServiceTransferEntity `json:"entities"`
29+
Expiry *time.Time `json:"-"`
30+
IsSender bool `json:"is_sender"`
31+
Status AccountServiceTransferStatus `json:"status"`
32+
Token string `json:"token"`
33+
Updated *time.Time `json:"-"`
34+
}
35+
36+
// AccountServiceTransferEntity represents a collection of the services to include
37+
// in a transfer request, separated by type.
38+
// Note: At this time, only Linodes can be transferred.
39+
type AccountServiceTransferEntity struct {
40+
Linodes []int `json:"linodes"`
41+
}
42+
43+
type AccountServiceTransferRequestOptions struct {
44+
Entities AccountServiceTransferEntity `json:"entities"`
45+
}
46+
47+
// UnmarshalJSON implements the json.Unmarshaler interface
48+
func (ast *AccountServiceTransfer) UnmarshalJSON(b []byte) error {
49+
type Mask AccountServiceTransfer
50+
51+
p := struct {
52+
*Mask
53+
Created *parseabletime.ParseableTime `json:"created"`
54+
Expiry *parseabletime.ParseableTime `json:"expiry"`
55+
Updated *parseabletime.ParseableTime `json:"updated"`
56+
}{
57+
Mask: (*Mask)(ast),
58+
}
59+
60+
if err := json.Unmarshal(b, &p); err != nil {
61+
return err
62+
}
63+
64+
ast.Created = (*time.Time)(p.Created)
65+
ast.Expiry = (*time.Time)(p.Expiry)
66+
ast.Updated = (*time.Time)(p.Updated)
67+
68+
return nil
69+
}
70+
71+
// ListAccountServiceTransfer gets a paginated list of AccountServiceTransfer for the Account.
72+
func (c *Client) ListAccountServiceTransfer(ctx context.Context, opts *ListOptions) ([]AccountServiceTransfer, error) {
73+
e := "account/service-transfers"
74+
return getPaginatedResults[AccountServiceTransfer](ctx, c, e, opts)
75+
}
76+
77+
// GetAccountServiceTransfer gets the details of the AccountServiceTransfer for the provided token.
78+
func (c *Client) GetAccountServiceTransfer(ctx context.Context, token string) (*AccountServiceTransfer, error) {
79+
e := formatAPIPath("account/service-transfers/%s", token)
80+
return doGETRequest[AccountServiceTransfer](ctx, c, e)
81+
}
82+
83+
// RequestAccountServiceTransfer creates a transfer request for the specified services.
84+
func (c *Client) RequestAccountServiceTransfer(ctx context.Context, opts AccountServiceTransferRequestOptions) (*AccountServiceTransfer, error) {
85+
e := "account/service-transfers"
86+
return doPOSTRequest[AccountServiceTransfer](ctx, c, e, opts)
87+
}
88+
89+
// AcceptAccountServiceTransfer accepts an AccountServiceTransfer for the provided token to
90+
// receive the services included in the transfer to the Account.
91+
func (c *Client) AcceptAccountServiceTransfer(ctx context.Context, token string) error {
92+
e := formatAPIPath("account/service-transfers/%s/accept", token)
93+
_, err := doPOSTRequest[AccountServiceTransfer, any](ctx, c, e)
94+
return err
95+
}
96+
97+
// CancelAccountServiceTransfer cancels the AccountServiceTransfer for the provided token.
98+
func (c *Client) CancelAccountServiceTransfer(ctx context.Context, token string) error {
99+
e := formatAPIPath("account/service-transfers/%s", token)
100+
return doDELETERequest(ctx, c, e)
101+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package unit
2+
3+
import (
4+
"context"
5+
"github.com/jarcoal/httpmock"
6+
"github.com/linode/linodego"
7+
"github.com/stretchr/testify/assert"
8+
"testing"
9+
"time"
10+
)
11+
12+
func TestAccountServiceTransfer_List(t *testing.T) {
13+
fixtureData, err := fixtures.GetFixture("account_service_transfers_list")
14+
assert.NoError(t, err)
15+
16+
var base ClientBaseCase
17+
base.SetUp(t)
18+
defer base.TearDown(t)
19+
20+
base.MockGet("account/service-transfers", fixtureData)
21+
22+
transfers, err := base.Client.ListAccountServiceTransfer(context.Background(), nil)
23+
assert.NoError(t, err)
24+
25+
assert.Equal(t, 1, len(transfers))
26+
ast := transfers[0]
27+
assert.Equal(t, time.Time(time.Date(2021, time.February, 11, 16, 37, 3, 0, time.UTC)), *ast.Created)
28+
assert.Equal(t, time.Time(time.Date(2021, time.February, 12, 16, 37, 3, 0, time.UTC)), *ast.Expiry)
29+
assert.Equal(t, time.Time(time.Date(2021, time.February, 11, 16, 37, 3, 0, time.UTC)), *ast.Updated)
30+
assert.Equal(t, 111, ast.Entities.Linodes[0])
31+
assert.Equal(t, 222, ast.Entities.Linodes[1])
32+
assert.Equal(t, true, ast.IsSender)
33+
assert.Equal(t, linodego.AccountServiceTransferStatus("pending"), ast.Status)
34+
assert.Equal(t, "123E4567-E89B-12D3-A456-426614174000", ast.Token)
35+
}
36+
37+
func TestAccountServiceTransfer_Get(t *testing.T) {
38+
fixtureData, err := fixtures.GetFixture("account_service_transfers_get")
39+
assert.NoError(t, err)
40+
41+
var base ClientBaseCase
42+
base.SetUp(t)
43+
defer base.TearDown(t)
44+
45+
base.MockGet("account/service-transfers/123E4567-E89B-12D3-A456-426614174000", fixtureData)
46+
47+
ast, err := base.Client.GetAccountServiceTransfer(context.Background(), "123E4567-E89B-12D3-A456-426614174000")
48+
assert.NoError(t, err)
49+
50+
assert.Equal(t, time.Time(time.Date(2021, time.February, 11, 16, 37, 3, 0, time.UTC)), *ast.Created)
51+
assert.Equal(t, time.Time(time.Date(2021, time.February, 12, 16, 37, 3, 0, time.UTC)), *ast.Expiry)
52+
assert.Equal(t, time.Time(time.Date(2021, time.February, 11, 16, 37, 3, 0, time.UTC)), *ast.Updated)
53+
assert.Equal(t, 111, ast.Entities.Linodes[0])
54+
assert.Equal(t, 222, ast.Entities.Linodes[1])
55+
assert.Equal(t, true, ast.IsSender)
56+
assert.Equal(t, linodego.AccountServiceTransferStatus("pending"), ast.Status)
57+
assert.Equal(t, "123E4567-E89B-12D3-A456-426614174000", ast.Token)
58+
}
59+
60+
func TestAccountServiceTransfer_Request(t *testing.T) {
61+
fixtureData, err := fixtures.GetFixture("account_service_transfers_request")
62+
assert.NoError(t, err)
63+
64+
var base ClientBaseCase
65+
base.SetUp(t)
66+
defer base.TearDown(t)
67+
68+
requestData := linodego.AccountServiceTransferRequestOptions{
69+
Entities: linodego.AccountServiceTransferEntity{
70+
Linodes: []int{111, 222},
71+
},
72+
}
73+
74+
base.MockPost("account/service-transfers", fixtureData)
75+
76+
ast, err := base.Client.RequestAccountServiceTransfer(context.Background(), requestData)
77+
assert.NoError(t, err)
78+
79+
assert.Equal(t, time.Time(time.Date(2021, time.February, 11, 16, 37, 3, 0, time.UTC)), *ast.Created)
80+
assert.Equal(t, time.Time(time.Date(2021, time.February, 12, 16, 37, 3, 0, time.UTC)), *ast.Expiry)
81+
assert.Equal(t, time.Time(time.Date(2021, time.February, 11, 16, 37, 3, 0, time.UTC)), *ast.Updated)
82+
assert.Equal(t, 111, ast.Entities.Linodes[0])
83+
assert.Equal(t, 222, ast.Entities.Linodes[1])
84+
assert.Equal(t, true, ast.IsSender)
85+
assert.Equal(t, linodego.AccountServiceTransferStatus("pending"), ast.Status)
86+
assert.Equal(t, "123E4567-E89B-12D3-A456-426614174000", ast.Token)
87+
}
88+
89+
func TestAccountServiceTransfer_Accept(t *testing.T) {
90+
client := createMockClient(t)
91+
92+
httpmock.RegisterRegexpResponder("POST",
93+
mockRequestURL(t, "account/service-transfers/123E4567-E89B-12D3-A456-426614174000/accept"),
94+
httpmock.NewStringResponder(200, "{}"))
95+
96+
if err := client.AcceptAccountServiceTransfer(context.Background(), "123E4567-E89B-12D3-A456-426614174000"); err != nil {
97+
t.Fatal(err)
98+
}
99+
}
100+
101+
func TestAccountServiceTransfer_Cancel(t *testing.T) {
102+
client := createMockClient(t)
103+
104+
httpmock.RegisterRegexpResponder("DELETE",
105+
mockRequestURL(t, "account/service-transfers/123E4567-E89B-12D3-A456-426614174000"),
106+
httpmock.NewStringResponder(200, "{}"))
107+
108+
if err := client.CancelAccountServiceTransfer(context.Background(), "123E4567-E89B-12D3-A456-426614174000"); err != nil {
109+
t.Fatal(err)
110+
}
111+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"created": "2021-02-11T16:37:03",
3+
"entities": {
4+
"linodes": [
5+
111,
6+
222
7+
]
8+
},
9+
"expiry": "2021-02-12T16:37:03",
10+
"is_sender": true,
11+
"status": "pending",
12+
"token": "123E4567-E89B-12D3-A456-426614174000",
13+
"updated": "2021-02-11T16:37:03"
14+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"data": [
3+
{
4+
"created": "2021-02-11T16:37:03",
5+
"entities": {
6+
"linodes": [
7+
111,
8+
222
9+
]
10+
},
11+
"expiry": "2021-02-12T16:37:03",
12+
"is_sender": true,
13+
"status": "pending",
14+
"token": "123E4567-E89B-12D3-A456-426614174000",
15+
"updated": "2021-02-11T16:37:03"
16+
}
17+
],
18+
"page": 1,
19+
"pages": 1,
20+
"results": 1
21+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"created": "2021-02-11T16:37:03",
3+
"entities": {
4+
"linodes": [
5+
111,
6+
222
7+
]
8+
},
9+
"expiry": "2021-02-12T16:37:03",
10+
"is_sender": true,
11+
"status": "pending",
12+
"token": "123E4567-E89B-12D3-A456-426614174000",
13+
"updated": "2021-02-11T16:37:03"
14+
}

0 commit comments

Comments
 (0)