Skip to content

Commit

Permalink
Merge branch 'main' into zhiwei/project-label
Browse files Browse the repository at this point in the history
  • Loading branch information
jriddle-linode authored Jul 22, 2024
2 parents 2bb86b9 + 81546f3 commit 1660422
Show file tree
Hide file tree
Showing 170 changed files with 6,651 additions and 3,669 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ values are set in the supplied ListOptions.
// opts.Results == 218
```

> **_NOTES:_**
> - The ListOptions will be mutated by list endpoint functions.
> - Instances of ListOptions should NOT be shared across multiple list endpoint functions.
> - The resulting number of results and pages can be accessed through the user-supplied ListOptions instance.
#### Filtering

```go
Expand Down
8 changes: 8 additions & 0 deletions kernels.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,18 @@ func (c *Client) ListKernels(ctx context.Context, opts *ListOptions) ([]LinodeKe
// GetKernel gets the kernel with the provided ID. This endpoint is cached by default.
func (c *Client) GetKernel(ctx context.Context, kernelID string) (*LinodeKernel, error) {
e := formatAPIPath("linode/kernels/%s", kernelID)

if result := c.getCachedResponse(e); result != nil {
result := result.(LinodeKernel)
return &result, nil
}

response, err := doGETRequest[LinodeKernel](ctx, c, e)
if err != nil {
return nil, err
}

c.addCachedResponse(e, response, nil)

return response, nil
}
41 changes: 35 additions & 6 deletions lke_node_pools.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,25 @@ type LKENodePoolLinode struct {
Status LKELinodeStatus `json:"status"`
}

// LKENodePoolTaintEffect represents the effect value of a taint
type LKENodePoolTaintEffect string

const (
LKENodePoolTaintEffectNoSchedule LKENodePoolTaintEffect = "NoSchedule"
LKENodePoolTaintEffectPreferNoSchedule LKENodePoolTaintEffect = "PreferNoSchedule"
LKENodePoolTaintEffectNoExecute LKENodePoolTaintEffect = "NoExecute"
)

// LKENodePoolTaint represents a corev1.Taint to add to an LKENodePool
type LKENodePoolTaint struct {
Key string `json:"key"`
Value string `json:"value,omitempty"`
Effect LKENodePoolTaintEffect `json:"effect"`
}

// LKENodePoolLabels represents Kubernetes labels to add to an LKENodePool
type LKENodePoolLabels map[string]string

// LKENodePool represents a LKENodePool object
type LKENodePool struct {
ID int `json:"id"`
Expand All @@ -41,24 +60,30 @@ type LKENodePool struct {
Disks []LKENodePoolDisk `json:"disks"`
Linodes []LKENodePoolLinode `json:"nodes"`
Tags []string `json:"tags"`
Labels LKENodePoolLabels `json:"labels"`
Taints []LKENodePoolTaint `json:"taints"`

Autoscaler LKENodePoolAutoscaler `json:"autoscaler"`
}

// LKENodePoolCreateOptions fields are those accepted by CreateLKENodePool
type LKENodePoolCreateOptions struct {
Count int `json:"count"`
Type string `json:"type"`
Disks []LKENodePoolDisk `json:"disks"`
Tags []string `json:"tags"`
Count int `json:"count"`
Type string `json:"type"`
Disks []LKENodePoolDisk `json:"disks"`
Tags []string `json:"tags"`
Labels LKENodePoolLabels `json:"labels"`
Taints []LKENodePoolTaint `json:"taints"`

Autoscaler *LKENodePoolAutoscaler `json:"autoscaler,omitempty"`
}

// LKENodePoolUpdateOptions fields are those accepted by UpdateLKENodePoolUpdate
type LKENodePoolUpdateOptions struct {
Count int `json:"count,omitempty"`
Tags *[]string `json:"tags,omitempty"`
Count int `json:"count,omitempty"`
Tags *[]string `json:"tags,omitempty"`
Labels *LKENodePoolLabels `json:"labels,omitempty"`
Taints *[]LKENodePoolTaint `json:"taints,omitempty"`

Autoscaler *LKENodePoolAutoscaler `json:"autoscaler,omitempty"`
}
Expand All @@ -69,6 +94,8 @@ func (l LKENodePool) GetCreateOptions() (o LKENodePoolCreateOptions) {
o.Count = l.Count
o.Disks = l.Disks
o.Tags = l.Tags
o.Labels = l.Labels
o.Taints = l.Taints
o.Autoscaler = &l.Autoscaler
return
}
Expand All @@ -77,6 +104,8 @@ func (l LKENodePool) GetCreateOptions() (o LKENodePoolCreateOptions) {
func (l LKENodePool) GetUpdateOptions() (o LKENodePoolUpdateOptions) {
o.Count = l.Count
o.Tags = &l.Tags
o.Labels = &l.Labels
o.Taints = &l.Taints
o.Autoscaler = &l.Autoscaler
return
}
Expand Down
28 changes: 28 additions & 0 deletions paged_response_structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ type IPv6RangesPagedResponse legacyPagedResponse[IPv6Range]
// Deprecated: LinodeKernelsPagedResponse exists for historical compatibility and should not be used.
type LinodeKernelsPagedResponse legacyPagedResponse[LinodeKernel]

// Deprecated: LinodeTypesPagedResponse exists for historical compatibility and should not be used.
type LinodeTypesPagedResponse legacyPagedResponse[LinodeType]

// Deprecated: LoginsPagedResponse exists for historical compatibility and should not be used.
type LoginsPagedResponse legacyPagedResponse[Login]

Expand Down Expand Up @@ -130,6 +133,31 @@ type ObjectStorageClustersPagedResponse legacyPagedResponse[ObjectStorageCluster
// Deprecated: PaymentsPagedResponse exists for historical compatibility and should not be used.
type PaymentsPagedResponse legacyPagedResponse[Payment]

// Deprecated: RegionsPagedResponse exists for historical compatibility and should not be used.
type RegionsPagedResponse legacyPagedResponse[Region]

// Deprecated: SSHKeysPagedResponse exists for historical compatibility and should not be used.
type SSHKeysPagedResponse legacyPagedResponse[SSHKey]

// Deprecated: TokensPagedResponse exists for historical compatibility and should not be used.
type (
TokensPagedResponse legacyPagedResponse[Token]
// Deprecated: RegionsAvailabilityPagedResponse exists for historical compatibility and should not be used.
RegionsAvailabilityPagedResponse legacyPagedResponse[RegionAvailability]
)

// Deprecated: StackscriptsPagedResponse exists for historical compatibility and should not be used.
type StackscriptsPagedResponse legacyPagedResponse[Stackscript]

// Deprecated: TagsPagedResponse exists for historical compatibility and should not be used.
type TagsPagedResponse legacyPagedResponse[Tag]

// Deprecated: TaggedObjectsPagedResponse exists for historical compatibility and should not be used.
type TaggedObjectsPagedResponse legacyPagedResponse[TaggedObject]

// Deprecated: TicketsPagedResponse exists for historical compatibility and should not be used.
type TicketsPagedResponse legacyPagedResponse[Ticket]

// Deprecated: PostgresDatabasesPagedResponse exists for historical compatibility and should not be used.
type PostgresDatabasesPagedResponse legacyPagedResponse[PostgresDatabase]

Expand Down
36 changes: 0 additions & 36 deletions pagination.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package linodego
*/

import (
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
Expand Down Expand Up @@ -91,41 +90,6 @@ type PagedResponse interface {
castResult(*resty.Request, string) (int, int, error)
}

// listHelper abstracts fetching and pagination for GET endpoints that
// do not require any Ids (top level endpoints).
// When opts (or opts.Page) is nil, all pages will be fetched and
// returned in a single (endpoint-specific)PagedResponse
// opts.results and opts.pages will be updated from the API response
func (c *Client) listHelper(ctx context.Context, pager PagedResponse, opts *ListOptions, ids ...any) error {
req := c.R(ctx)
if err := applyListOptionsToRequest(opts, req); err != nil {
return err
}

pages, results, err := pager.castResult(req, pager.endpoint(ids...))
if err != nil {
return err
}
if opts == nil {
opts = &ListOptions{PageOptions: &PageOptions{Page: 0}}
}
if opts.PageOptions == nil {
opts.PageOptions = &PageOptions{Page: 0}
}
if opts.Page == 0 {
for page := 2; page <= pages; page++ {
opts.Page = page
if err := c.listHelper(ctx, pager, opts, ids...); err != nil {
return err
}
}
}

opts.Results = results
opts.Pages = pages
return nil
}

// flattenQueryStruct flattens a structure into a Resty-compatible query param map.
// Fields are mapped using the `query` struct tag.
func flattenQueryStruct(val any) (map[string]string, error) {
Expand Down
19 changes: 5 additions & 14 deletions profile_phone_number.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package linodego

import (
"context"
"encoding/json"
)

// SendPhoneNumberVerificationCodeOptions fields are those accepted by SendPhoneNumberVerificationCode
Expand All @@ -18,31 +17,23 @@ type VerifyPhoneNumberOptions struct {

// SendPhoneNumberVerificationCode sends a one-time verification code via SMS message to the submitted phone number.
func (c *Client) SendPhoneNumberVerificationCode(ctx context.Context, opts SendPhoneNumberVerificationCodeOptions) error {
body, err := json.Marshal(opts)
if err != nil {
return err
}

e := "profile/phone-number"
_, err = coupleAPIErrors(c.R(ctx).SetBody(string(body)).Post(e))
_, err := doPOSTRequest[any](ctx, c, e, opts)

return err
}

// DeletePhoneNumber deletes the verified phone number for the User making this request.
func (c *Client) DeletePhoneNumber(ctx context.Context) error {
e := "profile/phone-number"
_, err := coupleAPIErrors(c.R(ctx).Delete(e))
err := doDELETERequest(ctx, c, e)
return err
}

// VerifyPhoneNumber verifies a phone number by confirming the one-time code received via SMS message after accessing the Phone Verification Code Send command.
func (c *Client) VerifyPhoneNumber(ctx context.Context, opts VerifyPhoneNumberOptions) error {
body, err := json.Marshal(opts)
if err != nil {
return err
}

e := "profile/phone-number/verify"
_, err = coupleAPIErrors(c.R(ctx).SetBody(string(body)).Post(e))
_, err := doPOSTRequest[any](ctx, c, e, opts)

return err
}
16 changes: 5 additions & 11 deletions profile_security_questions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package linodego

import (
"context"
"encoding/json"
)

type SecurityQuestion struct {
Expand All @@ -27,23 +26,18 @@ type SecurityQuestionsAnswerOptions struct {
// SecurityQuestionsList returns a collection of security questions and their responses, if any, for your User Profile.
func (c *Client) SecurityQuestionsList(ctx context.Context) (*SecurityQuestionsListResponse, error) {
e := "profile/security-questions"
req := c.R(ctx).SetResult(&SecurityQuestionsListResponse{})
r, err := coupleAPIErrors(req.Get(e))
response, err := doGETRequest[SecurityQuestionsListResponse](ctx, c, e)
if err != nil {
return nil, err
}
return r.Result().(*SecurityQuestionsListResponse), nil

return response, nil
}

// SecurityQuestionsAnswer adds security question responses for your User.
func (c *Client) SecurityQuestionsAnswer(ctx context.Context, opts SecurityQuestionsAnswerOptions) error {
body, err := json.Marshal(opts)
if err != nil {
return err
}

e := "profile/security-questions"
req := c.R(ctx).SetBody(string(body))
_, err = coupleAPIErrors(req.Post(e))

_, err := doPOSTRequest[any](ctx, c, e, opts)
return err
}
63 changes: 15 additions & 48 deletions profile_sshkeys.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ package linodego
import (
"context"
"encoding/json"
"fmt"
"time"

"github.com/go-resty/resty/v2"
"github.com/linode/linodego/internal/parseabletime"
)

Expand Down Expand Up @@ -62,83 +60,52 @@ func (i SSHKey) GetUpdateOptions() (o SSHKeyUpdateOptions) {
return
}

// SSHKeysPagedResponse represents a paginated SSHKey API response
type SSHKeysPagedResponse struct {
*PageOptions
Data []SSHKey `json:"data"`
}

// endpoint gets the endpoint URL for SSHKey
func (SSHKeysPagedResponse) endpoint(_ ...any) string {
return "profile/sshkeys"
}

func (resp *SSHKeysPagedResponse) castResult(r *resty.Request, e string) (int, int, error) {
res, err := coupleAPIErrors(r.SetResult(SSHKeysPagedResponse{}).Get(e))
if err != nil {
return 0, 0, err
}
castedRes := res.Result().(*SSHKeysPagedResponse)
resp.Data = append(resp.Data, castedRes.Data...)
return castedRes.Pages, castedRes.Results, nil
}

// ListSSHKeys lists SSHKeys
func (c *Client) ListSSHKeys(ctx context.Context, opts *ListOptions) ([]SSHKey, error) {
response := SSHKeysPagedResponse{}
err := c.listHelper(ctx, &response, opts)
response, err := getPaginatedResults[SSHKey](ctx, c, "profile/sshkeys", opts)
if err != nil {
return nil, err
}
return response.Data, nil

return response, nil
}

// GetSSHKey gets the sshkey with the provided ID
func (c *Client) GetSSHKey(ctx context.Context, keyID int) (*SSHKey, error) {
e := fmt.Sprintf("profile/sshkeys/%d", keyID)
req := c.R(ctx).SetResult(&SSHKey{})
r, err := coupleAPIErrors(req.Get(e))
e := formatAPIPath("profile/sshkeys/%d", keyID)
response, err := doGETRequest[SSHKey](ctx, c, e)
if err != nil {
return nil, err
}
return r.Result().(*SSHKey), nil

return response, nil
}

// CreateSSHKey creates a SSHKey
func (c *Client) CreateSSHKey(ctx context.Context, opts SSHKeyCreateOptions) (*SSHKey, error) {
body, err := json.Marshal(opts)
if err != nil {
return nil, err
}

e := "profile/sshkeys"
req := c.R(ctx).SetResult(&SSHKey{}).SetBody(string(body))
r, err := coupleAPIErrors(req.Post(e))
response, err := doPOSTRequest[SSHKey](ctx, c, e, opts)
if err != nil {
return nil, err
}
return r.Result().(*SSHKey), nil

return response, nil
}

// UpdateSSHKey updates the SSHKey with the specified id
func (c *Client) UpdateSSHKey(ctx context.Context, keyID int, opts SSHKeyUpdateOptions) (*SSHKey, error) {
body, err := json.Marshal(opts)
e := formatAPIPath("profile/sshkeys/%d", keyID)
response, err := doPUTRequest[SSHKey](ctx, c, e, opts)
if err != nil {
return nil, err
}

e := fmt.Sprintf("profile/sshkeys/%d", keyID)
req := c.R(ctx).SetResult(&SSHKey{}).SetBody(string(body))
r, err := coupleAPIErrors(req.Put(e))
if err != nil {
return nil, err
}
return r.Result().(*SSHKey), nil
return response, nil
}

// DeleteSSHKey deletes the SSHKey with the specified id
func (c *Client) DeleteSSHKey(ctx context.Context, keyID int) error {
e := fmt.Sprintf("profile/sshkeys/%d", keyID)
_, err := coupleAPIErrors(c.R(ctx).Delete(e))
e := formatAPIPath("profile/sshkeys/%d", keyID)
err := doDELETERequest(ctx, c, e)
return err
}
Loading

0 comments on commit 1660422

Please sign in to comment.