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

Added support for missing Account-related endpoints #598

Merged
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
51 changes: 42 additions & 9 deletions account.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,56 @@ type Account struct {
ActiveSince *time.Time `json:"active_since"`
}

// AccountUpdateOptions fields are those accepted by UpdateAccount
type AccountUpdateOptions struct {
Address1 string `json:"address_1,omitempty"`
Address2 string `json:"address_2,omitempty"`
City string `json:"city,omitempty"`
Company string `json:"company,omitempty"`
Country string `json:"country,omitempty"`
Email string `json:"email,omitempty"`
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
Phone string `json:"phone,omitempty"`
State string `json:"state,omitempty"`
TaxID string `json:"tax_id,omitempty"`
Zip string `json:"zip,omitempty"`
}

// GetUpdateOptions converts an Account to AccountUpdateOptions for use in UpdateAccount
func (i Account) GetUpdateOptions() (o AccountUpdateOptions) {
o.Address1 = i.Address1
o.Address2 = i.Address2
o.City = i.City
o.Company = i.Company
o.Country = i.Country
o.Email = i.Email
o.FirstName = i.FirstName
o.LastName = i.LastName
o.Phone = i.Phone
o.State = i.State
o.TaxID = i.TaxID
o.Zip = i.Zip

return
}

// UnmarshalJSON implements the json.Unmarshaler interface
func (account *Account) UnmarshalJSON(b []byte) error {
func (i *Account) UnmarshalJSON(b []byte) error {
type Mask Account

p := struct {
*Mask
ActiveSince *parseabletime.ParseableTime `json:"active_since"`
}{
Mask: (*Mask)(account),
Mask: (*Mask)(i),
}

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

account.ActiveSince = (*time.Time)(p.ActiveSince)
i.ActiveSince = (*time.Time)(p.ActiveSince)

return nil
}
Expand All @@ -59,11 +93,10 @@ type CreditCard struct {

// GetAccount gets the contact and billing information related to the Account.
func (c *Client) GetAccount(ctx context.Context) (*Account, error) {
e := "account"
response, err := doGETRequest[Account](ctx, c, e)
if err != nil {
return nil, err
}
return doGETRequest[Account](ctx, c, "account")
}

return response, nil
// UpdateAccount updates the Account
func (c *Client) UpdateAccount(ctx context.Context, opts AccountUpdateOptions) (*Account, error) {
return doPUTRequest[Account](ctx, c, "account", opts)
}
37 changes: 37 additions & 0 deletions account_agreements.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package linodego

import "context"

// AccountAgreements represents the agreements and their acceptance status for an Account
type AccountAgreements struct {
EUModel bool `json:"eu_model"`
MasterServiceAgreement bool `json:"master_service_agreement"`
PrivacyPolicy bool `json:"privacy_policy"`
}

// AccountAgreementsUpdateOptions fields are those accepted by UpdateAccountAgreements
type AccountAgreementsUpdateOptions struct {
EUModel bool `json:"eu_model,omitempty"`
MasterServiceAgreement bool `json:"master_service_agreement,omitempty"`
PrivacyPolicy bool `json:"privacy_policy,omitempty"`
}

// GetUpdateOptions converts an AccountAgreements to AccountAgreementsUpdateOptions for use in UpdateAccountAgreements
func (i AccountAgreements) GetUpdateOptions() (o AccountAgreementsUpdateOptions) {
o.EUModel = i.EUModel
o.MasterServiceAgreement = i.MasterServiceAgreement
o.PrivacyPolicy = i.PrivacyPolicy

return
}

// GetAccountAgreements gets all agreements and their acceptance status for the Account.
func (c *Client) GetAccountAgreements(ctx context.Context) (*AccountAgreements, error) {
return doGETRequest[AccountAgreements](ctx, c, "account/agreements")
}

// AcknowledgeAccountAgreements acknowledges account agreements for the Account
func (c *Client) AcknowledgeAccountAgreements(ctx context.Context, opts AccountAgreementsUpdateOptions) error {
_, err := doPOSTRequest[AccountAgreements](ctx, c, "account/agreements", opts)
return err
}
51 changes: 51 additions & 0 deletions account_maintenance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package linodego

import (
"context"
"encoding/json"
"time"

"github.com/linode/linodego/internal/parseabletime"
)

// AccountMaintenance represents a Maintenance object for any entity a user has permissions to view
type AccountMaintenance struct {
Entity *Entity `json:"entity"`
Reason string `json:"reason"`
Status string `json:"status"`
Type string `json:"type"`
When *time.Time `json:"when"`
}

// The entity being affected by maintenance
type Entity struct {
ID int `json:"id"`
Label string `json:"label"`
Type string `json:"type"`
URL string `json:"url"`
}

// UnmarshalJSON implements the json.Unmarshaler interface
func (accountMaintenance *AccountMaintenance) UnmarshalJSON(b []byte) error {
type Mask AccountMaintenance

p := struct {
*Mask
When *parseabletime.ParseableTime `json:"when"`
}{
Mask: (*Mask)(accountMaintenance),
}

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

accountMaintenance.When = (*time.Time)(p.When)

return nil
}

// ListMaintenances lists Account Maintenance objects for any entity a user has permissions to view
func (c *Client) ListMaintenances(ctx context.Context, opts *ListOptions) ([]AccountMaintenance, error) {
return getPaginatedResults[AccountMaintenance](ctx, c, "account/maintenance", opts)
}
1 change: 1 addition & 0 deletions go.work.sum
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+v
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/yuin/goldmark v1.2.1 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM=
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
Expand Down
16 changes: 16 additions & 0 deletions test/integration/account_agreements_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package integration

import (
"context"
"testing"
)

func TestAccountAgreements_Get(t *testing.T) {
client, fixtureTeardown := createTestClient(t, "fixtures/TestAccountAgreements_List")
defer fixtureTeardown()

_, err := client.GetAccountAgreements(context.Background())
if err != nil {
t.Errorf("Error getting agreements, expected struct, got error %v", err)
}
}
19 changes: 19 additions & 0 deletions test/integration/account_maintenance_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package integration

import (
"context"
"testing"

"github.com/linode/linodego"
)

func TestAccountMaintenances_List(t *testing.T) {
client, fixtureTeardown := createTestClient(t, "fixtures/TestAccountMaintenances_List")
defer fixtureTeardown()

listOpts := linodego.NewListOptions(0, "")
_, err := client.ListMaintenances(context.Background(), listOpts)
if err != nil {
t.Errorf("Error listing maintenances, expected array, got error %v", err)
}
}
66 changes: 66 additions & 0 deletions test/integration/fixtures/TestAccountAgreements_List.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
version: 1
interactions:
- request:
body: ""
form: {}
headers:
Accept:
- application/json
Content-Type:
- application/json
User-Agent:
- linodego/dev https://github.com/linode/linodego
url: https://api.linode.com/v4beta/account/agreements
method: GET
response:
body: '{"privacy_policy": true, "eu_model": false, "master_service_agreement":
false}'
headers:
Access-Control-Allow-Credentials:
- "true"
Access-Control-Allow-Headers:
- Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
Access-Control-Allow-Methods:
- HEAD, GET, OPTIONS, POST, PUT, DELETE
Access-Control-Allow-Origin:
- '*'
Access-Control-Expose-Headers:
- X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
Akamai-Internal-Account:
- '*'
Cache-Control:
- max-age=0, no-cache, no-store
Connection:
- keep-alive
Content-Length:
- "78"
Content-Security-Policy:
- default-src 'none'
Content-Type:
- application/json
Expires:
- Wed, 30 Oct 2024 14:07:33 GMT
Pragma:
- no-cache
Strict-Transport-Security:
- max-age=31536000
Vary:
- Authorization, X-Filter
- Authorization, X-Filter
X-Accepted-Oauth-Scopes:
- account:read_only
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
- DENY
X-Oauth-Scopes:
- '*'
X-Ratelimit-Limit:
- "800"
X-Xss-Protection:
- 1; mode=block
status: 200 OK
code: 200
duration: ""
65 changes: 65 additions & 0 deletions test/integration/fixtures/TestAccountMaintenances_List.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
version: 1
interactions:
- request:
body: ""
form: {}
headers:
Accept:
- application/json
Content-Type:
- application/json
User-Agent:
- linodego/dev https://github.com/linode/linodego
url: https://api.linode.com/v4beta/account/maintenance?page=1
method: GET
response:
body: '{"data": [], "page": 1, "pages": 1, "results": 0}'
headers:
Access-Control-Allow-Credentials:
- "true"
Access-Control-Allow-Headers:
- Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
Access-Control-Allow-Methods:
- HEAD, GET, OPTIONS, POST, PUT, DELETE
Access-Control-Allow-Origin:
- '*'
Access-Control-Expose-Headers:
- X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
Akamai-Internal-Account:
- '*'
Cache-Control:
- max-age=0, no-cache, no-store
Connection:
- keep-alive
Content-Length:
- "49"
Content-Security-Policy:
- default-src 'none'
Content-Type:
- application/json
Expires:
- Wed, 30 Oct 2024 14:06:55 GMT
Pragma:
- no-cache
Strict-Transport-Security:
- max-age=31536000
Vary:
- Authorization, X-Filter
- Authorization, X-Filter
X-Accepted-Oauth-Scopes:
- '*'
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
- DENY
X-Oauth-Scopes:
- unknown
X-Ratelimit-Limit:
- "800"
X-Xss-Protection:
- 1; mode=block
status: 200 OK
code: 200
duration: ""
44 changes: 44 additions & 0 deletions test/unit/account_agreements_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package unit

import (
"context"
"github.com/jarcoal/httpmock"
"github.com/linode/linodego"
"github.com/stretchr/testify/assert"
"testing"
)

func TestAccountAgreements_Get(t *testing.T) {
fixtureData, err := fixtures.GetFixture("account_agreements_get")
assert.NoError(t, err)

var base ClientBaseCase
base.SetUp(t)
defer base.TearDown(t)

base.MockGet("account/agreements", fixtureData)

agreements, err := base.Client.GetAccountAgreements(context.Background())
assert.NoError(t, err)

assert.Equal(t, true, agreements.EUModel)
assert.Equal(t, true, agreements.PrivacyPolicy)
assert.Equal(t, true, agreements.MasterServiceAgreement)
}

func TestAccountAgreements_Acknowledge(t *testing.T) {
client := createMockClient(t)

requestData := linodego.AccountAgreementsUpdateOptions{
EUModel: true,
MasterServiceAgreement: true,
PrivacyPolicy: true,
}

httpmock.RegisterRegexpResponder("POST", mockRequestURL(t, "account/agreements"),
mockRequestBodyValidate(t, requestData, nil))

if err := client.AcknowledgeAccountAgreements(context.Background(), requestData); err != nil {
t.Fatal(err)
}
}
Loading