Skip to content

Commit b6c358f

Browse files
Added support for missing Account-related endpoints (#598)
* Added support for missing account endpoints * Addressed PR comments * Fix lint
1 parent 551a48a commit b6c358f

14 files changed

+492
-9
lines changed

account.go

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,56 @@ type Account struct {
3131
ActiveSince *time.Time `json:"active_since"`
3232
}
3333

34+
// AccountUpdateOptions fields are those accepted by UpdateAccount
35+
type AccountUpdateOptions struct {
36+
Address1 string `json:"address_1,omitempty"`
37+
Address2 string `json:"address_2,omitempty"`
38+
City string `json:"city,omitempty"`
39+
Company string `json:"company,omitempty"`
40+
Country string `json:"country,omitempty"`
41+
Email string `json:"email,omitempty"`
42+
FirstName string `json:"first_name,omitempty"`
43+
LastName string `json:"last_name,omitempty"`
44+
Phone string `json:"phone,omitempty"`
45+
State string `json:"state,omitempty"`
46+
TaxID string `json:"tax_id,omitempty"`
47+
Zip string `json:"zip,omitempty"`
48+
}
49+
50+
// GetUpdateOptions converts an Account to AccountUpdateOptions for use in UpdateAccount
51+
func (i Account) GetUpdateOptions() (o AccountUpdateOptions) {
52+
o.Address1 = i.Address1
53+
o.Address2 = i.Address2
54+
o.City = i.City
55+
o.Company = i.Company
56+
o.Country = i.Country
57+
o.Email = i.Email
58+
o.FirstName = i.FirstName
59+
o.LastName = i.LastName
60+
o.Phone = i.Phone
61+
o.State = i.State
62+
o.TaxID = i.TaxID
63+
o.Zip = i.Zip
64+
65+
return
66+
}
67+
3468
// UnmarshalJSON implements the json.Unmarshaler interface
35-
func (account *Account) UnmarshalJSON(b []byte) error {
69+
func (i *Account) UnmarshalJSON(b []byte) error {
3670
type Mask Account
3771

3872
p := struct {
3973
*Mask
4074
ActiveSince *parseabletime.ParseableTime `json:"active_since"`
4175
}{
42-
Mask: (*Mask)(account),
76+
Mask: (*Mask)(i),
4377
}
4478

4579
if err := json.Unmarshal(b, &p); err != nil {
4680
return err
4781
}
4882

49-
account.ActiveSince = (*time.Time)(p.ActiveSince)
83+
i.ActiveSince = (*time.Time)(p.ActiveSince)
5084

5185
return nil
5286
}
@@ -59,11 +93,10 @@ type CreditCard struct {
5993

6094
// GetAccount gets the contact and billing information related to the Account.
6195
func (c *Client) GetAccount(ctx context.Context) (*Account, error) {
62-
e := "account"
63-
response, err := doGETRequest[Account](ctx, c, e)
64-
if err != nil {
65-
return nil, err
66-
}
96+
return doGETRequest[Account](ctx, c, "account")
97+
}
6798

68-
return response, nil
99+
// UpdateAccount updates the Account
100+
func (c *Client) UpdateAccount(ctx context.Context, opts AccountUpdateOptions) (*Account, error) {
101+
return doPUTRequest[Account](ctx, c, "account", opts)
69102
}

account_agreements.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package linodego
2+
3+
import "context"
4+
5+
// AccountAgreements represents the agreements and their acceptance status for an Account
6+
type AccountAgreements struct {
7+
EUModel bool `json:"eu_model"`
8+
MasterServiceAgreement bool `json:"master_service_agreement"`
9+
PrivacyPolicy bool `json:"privacy_policy"`
10+
}
11+
12+
// AccountAgreementsUpdateOptions fields are those accepted by UpdateAccountAgreements
13+
type AccountAgreementsUpdateOptions struct {
14+
EUModel bool `json:"eu_model,omitempty"`
15+
MasterServiceAgreement bool `json:"master_service_agreement,omitempty"`
16+
PrivacyPolicy bool `json:"privacy_policy,omitempty"`
17+
}
18+
19+
// GetUpdateOptions converts an AccountAgreements to AccountAgreementsUpdateOptions for use in UpdateAccountAgreements
20+
func (i AccountAgreements) GetUpdateOptions() (o AccountAgreementsUpdateOptions) {
21+
o.EUModel = i.EUModel
22+
o.MasterServiceAgreement = i.MasterServiceAgreement
23+
o.PrivacyPolicy = i.PrivacyPolicy
24+
25+
return
26+
}
27+
28+
// GetAccountAgreements gets all agreements and their acceptance status for the Account.
29+
func (c *Client) GetAccountAgreements(ctx context.Context) (*AccountAgreements, error) {
30+
return doGETRequest[AccountAgreements](ctx, c, "account/agreements")
31+
}
32+
33+
// AcknowledgeAccountAgreements acknowledges account agreements for the Account
34+
func (c *Client) AcknowledgeAccountAgreements(ctx context.Context, opts AccountAgreementsUpdateOptions) error {
35+
_, err := doPOSTRequest[AccountAgreements](ctx, c, "account/agreements", opts)
36+
return err
37+
}

account_maintenance.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package linodego
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"time"
7+
8+
"github.com/linode/linodego/internal/parseabletime"
9+
)
10+
11+
// AccountMaintenance represents a Maintenance object for any entity a user has permissions to view
12+
type AccountMaintenance struct {
13+
Entity *Entity `json:"entity"`
14+
Reason string `json:"reason"`
15+
Status string `json:"status"`
16+
Type string `json:"type"`
17+
When *time.Time `json:"when"`
18+
}
19+
20+
// The entity being affected by maintenance
21+
type Entity struct {
22+
ID int `json:"id"`
23+
Label string `json:"label"`
24+
Type string `json:"type"`
25+
URL string `json:"url"`
26+
}
27+
28+
// UnmarshalJSON implements the json.Unmarshaler interface
29+
func (accountMaintenance *AccountMaintenance) UnmarshalJSON(b []byte) error {
30+
type Mask AccountMaintenance
31+
32+
p := struct {
33+
*Mask
34+
When *parseabletime.ParseableTime `json:"when"`
35+
}{
36+
Mask: (*Mask)(accountMaintenance),
37+
}
38+
39+
if err := json.Unmarshal(b, &p); err != nil {
40+
return err
41+
}
42+
43+
accountMaintenance.When = (*time.Time)(p.When)
44+
45+
return nil
46+
}
47+
48+
// ListMaintenances lists Account Maintenance objects for any entity a user has permissions to view
49+
func (c *Client) ListMaintenances(ctx context.Context, opts *ListOptions) ([]AccountMaintenance, error) {
50+
return getPaginatedResults[AccountMaintenance](ctx, c, "account/maintenance", opts)
51+
}

go.work.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+v
2929
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
3030
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
3131
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
32+
github.com/yuin/goldmark v1.2.1 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM=
3233
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
3334
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
3435
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package integration
2+
3+
import (
4+
"context"
5+
"testing"
6+
)
7+
8+
func TestAccountAgreements_Get(t *testing.T) {
9+
client, fixtureTeardown := createTestClient(t, "fixtures/TestAccountAgreements_List")
10+
defer fixtureTeardown()
11+
12+
_, err := client.GetAccountAgreements(context.Background())
13+
if err != nil {
14+
t.Errorf("Error getting agreements, expected struct, got error %v", err)
15+
}
16+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package integration
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/linode/linodego"
8+
)
9+
10+
func TestAccountMaintenances_List(t *testing.T) {
11+
client, fixtureTeardown := createTestClient(t, "fixtures/TestAccountMaintenances_List")
12+
defer fixtureTeardown()
13+
14+
listOpts := linodego.NewListOptions(0, "")
15+
_, err := client.ListMaintenances(context.Background(), listOpts)
16+
if err != nil {
17+
t.Errorf("Error listing maintenances, expected array, got error %v", err)
18+
}
19+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
version: 1
3+
interactions:
4+
- request:
5+
body: ""
6+
form: {}
7+
headers:
8+
Accept:
9+
- application/json
10+
Content-Type:
11+
- application/json
12+
User-Agent:
13+
- linodego/dev https://github.com/linode/linodego
14+
url: https://api.linode.com/v4beta/account/agreements
15+
method: GET
16+
response:
17+
body: '{"privacy_policy": true, "eu_model": false, "master_service_agreement":
18+
false}'
19+
headers:
20+
Access-Control-Allow-Credentials:
21+
- "true"
22+
Access-Control-Allow-Headers:
23+
- Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
24+
Access-Control-Allow-Methods:
25+
- HEAD, GET, OPTIONS, POST, PUT, DELETE
26+
Access-Control-Allow-Origin:
27+
- '*'
28+
Access-Control-Expose-Headers:
29+
- X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
30+
Akamai-Internal-Account:
31+
- '*'
32+
Cache-Control:
33+
- max-age=0, no-cache, no-store
34+
Connection:
35+
- keep-alive
36+
Content-Length:
37+
- "78"
38+
Content-Security-Policy:
39+
- default-src 'none'
40+
Content-Type:
41+
- application/json
42+
Expires:
43+
- Wed, 30 Oct 2024 14:07:33 GMT
44+
Pragma:
45+
- no-cache
46+
Strict-Transport-Security:
47+
- max-age=31536000
48+
Vary:
49+
- Authorization, X-Filter
50+
- Authorization, X-Filter
51+
X-Accepted-Oauth-Scopes:
52+
- account:read_only
53+
X-Content-Type-Options:
54+
- nosniff
55+
X-Frame-Options:
56+
- DENY
57+
- DENY
58+
X-Oauth-Scopes:
59+
- '*'
60+
X-Ratelimit-Limit:
61+
- "800"
62+
X-Xss-Protection:
63+
- 1; mode=block
64+
status: 200 OK
65+
code: 200
66+
duration: ""
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
version: 1
3+
interactions:
4+
- request:
5+
body: ""
6+
form: {}
7+
headers:
8+
Accept:
9+
- application/json
10+
Content-Type:
11+
- application/json
12+
User-Agent:
13+
- linodego/dev https://github.com/linode/linodego
14+
url: https://api.linode.com/v4beta/account/maintenance?page=1
15+
method: GET
16+
response:
17+
body: '{"data": [], "page": 1, "pages": 1, "results": 0}'
18+
headers:
19+
Access-Control-Allow-Credentials:
20+
- "true"
21+
Access-Control-Allow-Headers:
22+
- Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
23+
Access-Control-Allow-Methods:
24+
- HEAD, GET, OPTIONS, POST, PUT, DELETE
25+
Access-Control-Allow-Origin:
26+
- '*'
27+
Access-Control-Expose-Headers:
28+
- X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
29+
Akamai-Internal-Account:
30+
- '*'
31+
Cache-Control:
32+
- max-age=0, no-cache, no-store
33+
Connection:
34+
- keep-alive
35+
Content-Length:
36+
- "49"
37+
Content-Security-Policy:
38+
- default-src 'none'
39+
Content-Type:
40+
- application/json
41+
Expires:
42+
- Wed, 30 Oct 2024 14:06:55 GMT
43+
Pragma:
44+
- no-cache
45+
Strict-Transport-Security:
46+
- max-age=31536000
47+
Vary:
48+
- Authorization, X-Filter
49+
- Authorization, X-Filter
50+
X-Accepted-Oauth-Scopes:
51+
- '*'
52+
X-Content-Type-Options:
53+
- nosniff
54+
X-Frame-Options:
55+
- DENY
56+
- DENY
57+
X-Oauth-Scopes:
58+
- unknown
59+
X-Ratelimit-Limit:
60+
- "800"
61+
X-Xss-Protection:
62+
- 1; mode=block
63+
status: 200 OK
64+
code: 200
65+
duration: ""
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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+
)
10+
11+
func TestAccountAgreements_Get(t *testing.T) {
12+
fixtureData, err := fixtures.GetFixture("account_agreements_get")
13+
assert.NoError(t, err)
14+
15+
var base ClientBaseCase
16+
base.SetUp(t)
17+
defer base.TearDown(t)
18+
19+
base.MockGet("account/agreements", fixtureData)
20+
21+
agreements, err := base.Client.GetAccountAgreements(context.Background())
22+
assert.NoError(t, err)
23+
24+
assert.Equal(t, true, agreements.EUModel)
25+
assert.Equal(t, true, agreements.PrivacyPolicy)
26+
assert.Equal(t, true, agreements.MasterServiceAgreement)
27+
}
28+
29+
func TestAccountAgreements_Acknowledge(t *testing.T) {
30+
client := createMockClient(t)
31+
32+
requestData := linodego.AccountAgreementsUpdateOptions{
33+
EUModel: true,
34+
MasterServiceAgreement: true,
35+
PrivacyPolicy: true,
36+
}
37+
38+
httpmock.RegisterRegexpResponder("POST", mockRequestURL(t, "account/agreements"),
39+
mockRequestBodyValidate(t, requestData, nil))
40+
41+
if err := client.AcknowledgeAccountAgreements(context.Background(), requestData); err != nil {
42+
t.Fatal(err)
43+
}
44+
}

0 commit comments

Comments
 (0)