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

new: Add support LKE, Volume, NodeBalancer, and network transfer pricing endpoints #573

Merged
merged 8 commits into from
Sep 6, 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
29 changes: 29 additions & 0 deletions base_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// This package contains various type-related base classes intended
// to be used in composition across type structures in this project.

package linodego

// baseType is a base struct containing the core fields of a resource type
// returned from the Linode API.
type baseType[PriceType any, RegionPriceType any] struct {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to use a generic base struct so we can still share common type fields while allowing resource types of diverge without a breaking change if necessary.

ID string `json:"id"`
Label string `json:"label"`
Price PriceType `json:"price"`
RegionPrices []RegionPriceType `json:"region_prices"`
Transfer int `json:"transfer"`
}

// baseTypePrice is a base struct containing the core fields of a resource type's
// base price.
type baseTypePrice struct {
Hourly float64 `json:"hourly"`
Monthly float64 `json:"monthly"`
}

// baseTypeRegionPrice is a base struct containing the core fields of a resource type's
// region-specific price.
type baseTypeRegionPrice struct {
baseTypePrice

ID string `json:"id"`
}
47 changes: 47 additions & 0 deletions lke_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package linodego

import (
"context"
)

// LKEType represents a single valid LKE type.
// NOTE: This typically corresponds to the availability of a cluster's
// control plane.
type LKEType struct {
baseType[LKETypePrice, LKETypeRegionPrice]
}

// LKETypePrice represents the base hourly and monthly prices
// for an LKE type entry.
type LKETypePrice struct {
baseTypePrice
}

// LKETypeRegionPrice represents the regional hourly and monthly prices
// for an LKE type entry.
type LKETypeRegionPrice struct {
baseTypeRegionPrice
}

// ListLKETypes lists LKE types. This endpoint is cached by default.
func (c *Client) ListLKETypes(ctx context.Context, opts *ListOptions) ([]LKEType, error) {
e := "lke/types"

endpoint, err := generateListCacheURL(e, opts)
if err != nil {
return nil, err
}

if result := c.getCachedResponse(endpoint); result != nil {
return result.([]LKEType), nil
}

response, err := getPaginatedResults[LKEType](ctx, c, e, opts)
if err != nil {
return nil, err
}

c.addCachedResponse(endpoint, response, &cacheExpiryTime)

return response, nil
}
45 changes: 45 additions & 0 deletions network_transfer_prices.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package linodego

import (
"context"
)

// NetworkTransferPrice represents a single valid network transfer price.
type NetworkTransferPrice struct {
baseType[NetworkTransferTypePrice, NetworkTransferTypeRegionPrice]
}

// NetworkTransferTypePrice represents the base hourly and monthly prices
// for a network transfer price entry.
type NetworkTransferTypePrice struct {
baseTypePrice
}

// NetworkTransferTypeRegionPrice represents the regional hourly and monthly prices
// for a network transfer price entry.
type NetworkTransferTypeRegionPrice struct {
baseTypeRegionPrice
}

// ListNetworkTransferPrices lists network transfer prices. This endpoint is cached by default.
func (c *Client) ListNetworkTransferPrices(ctx context.Context, opts *ListOptions) ([]NetworkTransferPrice, error) {
e := "network-transfer/prices"

endpoint, err := generateListCacheURL(e, opts)
if err != nil {
return nil, err
}

if result := c.getCachedResponse(endpoint); result != nil {
return result.([]NetworkTransferPrice), nil
}

response, err := getPaginatedResults[NetworkTransferPrice](ctx, c, e, opts)
if err != nil {
return nil, err
}

c.addCachedResponse(endpoint, response, &cacheExpiryTime)

return response, nil
}
45 changes: 45 additions & 0 deletions nodebalancer_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package linodego

import (
"context"
)

// NodeBalancerType represents a single valid NodeBalancer type.
type NodeBalancerType struct {
baseType[NodeBalancerTypePrice, NodeBalancerTypeRegionPrice]
}

// NodeBalancerTypePrice represents the base hourly and monthly prices
// for a NodeBalancer type entry.
type NodeBalancerTypePrice struct {
Copy link
Contributor Author

@lgarber-akamai lgarber-akamai Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave each resource type its own price and region prices structs so external users can still store & access them separate from their parent struct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I learned this pattern and put them similarly in python-sdk as well.

baseTypePrice
}

// NodeBalancerTypeRegionPrice represents the regional hourly and monthly prices
// for a NodeBalancer type entry.
type NodeBalancerTypeRegionPrice struct {
baseTypeRegionPrice
}

// ListNodeBalancerTypes lists NodeBalancer types. This endpoint is cached by default.
func (c *Client) ListNodeBalancerTypes(ctx context.Context, opts *ListOptions) ([]NodeBalancerType, error) {
e := "nodebalancers/types"

endpoint, err := generateListCacheURL(e, opts)
if err != nil {
return nil, err
}

if result := c.getCachedResponse(endpoint); result != nil {
return result.([]NodeBalancerType), nil
}

response, err := getPaginatedResults[NodeBalancerType](ctx, c, e, opts)
if err != nil {
return nil, err
}

c.addCachedResponse(endpoint, response, &cacheExpiryTime)

return response, nil
}
70 changes: 70 additions & 0 deletions test/integration/fixtures/TestLKEType_List.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
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/lke/types?page=1
method: GET
response:
body: '{"data": [{"id": "lke-sa", "label": "LKE Standard Availability", "price":
{"hourly": 0.0, "monthly": 0.0}, "region_prices": [], "transfer": 0}, {"id":
"lke-ha", "label": "LKE High Availability", "price": {"hourly": 0.09, "monthly":
60.0}, "region_prices": [{"id": "id-cgk", "hourly": 0.108, "monthly": 72.0},
{"id": "br-gru", "hourly": 0.126, "monthly": 84.0}], "transfer": 0}], "page":
1, "pages": 1, "results": 2}'
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:
- "415"
Content-Security-Policy:
- default-src 'none'
Content-Type:
- application/json
Expires:
- Thu, 05 Sep 2024 17:47:57 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:
- '*'
X-Ratelimit-Limit:
- "400"
X-Xss-Protection:
- 1; mode=block
status: 200 OK
code: 200
duration: ""
70 changes: 70 additions & 0 deletions test/integration/fixtures/TestNetworkTransferPrice_List.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
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/network-transfer/prices?page=1
method: GET
response:
body: '{"data": [{"id": "distributed_network_transfer", "label": "Distributed
Network Transfer", "price": {"hourly": 0.01, "monthly": null}, "region_prices":
[], "transfer": 0}, {"id": "network_transfer", "label": "Network Transfer",
"price": {"hourly": 0.005, "monthly": null}, "region_prices": [{"id": "id-cgk",
"hourly": 0.015, "monthly": null}, {"id": "br-gru", "hourly": 0.007, "monthly":
null}], "transfer": 0}], "page": 1, "pages": 1, "results": 2}'
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:
- "448"
Content-Security-Policy:
- default-src 'none'
Content-Type:
- application/json
Expires:
- Wed, 04 Sep 2024 18:06:01 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:
- '*'
X-Ratelimit-Limit:
- "400"
X-Xss-Protection:
- 1; mode=block
status: 200 OK
code: 200
duration: ""
68 changes: 68 additions & 0 deletions test/integration/fixtures/TestNodeBalancerType_List.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
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/nodebalancers/types?page=1
method: GET
response:
body: '{"data": [{"id": "nodebalancer", "label": "NodeBalancer", "price": {"hourly":
0.015, "monthly": 10.0}, "region_prices": [{"id": "id-cgk", "hourly": 0.018,
"monthly": 12.0}, {"id": "br-gru", "hourly": 0.021, "monthly": 14.0}], "transfer":
0}], "page": 1, "pages": 1, "results": 1}'
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:
- "279"
Content-Security-Policy:
- default-src 'none'
Content-Type:
- application/json
Expires:
- Wed, 04 Sep 2024 17:52:02 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:
- '*'
X-Ratelimit-Limit:
- "400"
X-Xss-Protection:
- 1; mode=block
status: 200 OK
code: 200
duration: ""
Loading