diff --git a/account_invoices.go b/account_invoices.go index 26529aaa7..6833ed257 100644 --- a/account_invoices.go +++ b/account_invoices.go @@ -25,6 +25,8 @@ type InvoiceItem struct { UnitPrice int `json:"unitprice"` Quantity int `json:"quantity"` Amount float32 `json:"amount"` + Tax float32 `json:"tax"` + Region *string `json:"region"` From *time.Time `json:"-"` To *time.Time `json:"-"` } diff --git a/account_transfer.go b/account_transfer.go new file mode 100644 index 000000000..115573021 --- /dev/null +++ b/account_transfer.go @@ -0,0 +1,33 @@ +package linodego + +import "context" + +// AccountTransfer represents an Account's network utilization for the current month. +type AccountTransfer struct { + Billable int `json:"billable"` + Quota int `json:"quota"` + Used int `json:"used"` + + RegionTransfers []AccountTransferRegion `json:"region_transfers"` +} + +// AccountTransferRegion represents an Account's network utilization for the current month +// in a given region. +type AccountTransferRegion struct { + ID string `json:"id"` + Billable int `json:"billable"` + Quota int `json:"quota"` + Used int `json:"used"` +} + +// GetAccountTransfer gets current Account's network utilization for the current month. +func (c *Client) GetAccountTransfer(ctx context.Context) (*AccountTransfer, error) { + req := c.R(ctx).SetResult(&AccountTransfer{}) + e := "account/transfer" + r, err := coupleAPIErrors(req.Get(e)) + if err != nil { + return nil, err + } + + return r.Result().(*AccountTransfer), nil +} diff --git a/test/integration/account_transfer_test.go b/test/integration/account_transfer_test.go new file mode 100644 index 000000000..1cac97b72 --- /dev/null +++ b/test/integration/account_transfer_test.go @@ -0,0 +1,41 @@ +package integration + +import ( + "context" + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/jarcoal/httpmock" + "github.com/linode/linodego" +) + +func TestAccount_getTransfer(t *testing.T) { + client := createMockClient(t) + + desiredResponse := linodego.AccountTransfer{ + Billable: 123, + Quota: 456, + Used: 789, + RegionTransfers: []linodego.AccountTransferRegion{ + { + ID: "us-southeast", + Billable: 987, + Quota: 654, + Used: 3211, + }, + }, + } + + httpmock.RegisterRegexpResponder("GET", mockRequestURL(t, "/account/transfer"), + httpmock.NewJsonResponderOrPanic(200, &desiredResponse)) + + questions, err := client.GetAccountTransfer(context.Background()) + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(*questions, desiredResponse) { + t.Fatalf("actual response does not equal desired response: %s", cmp.Diff(questions, desiredResponse)) + } +} diff --git a/test/integration/fixtures/TestTypes_RegionSpecific.yaml b/test/integration/fixtures/TestTypes_RegionSpecific.yaml new file mode 100644 index 000000000..3482e58e5 --- /dev/null +++ b/test/integration/fixtures/TestTypes_RegionSpecific.yaml @@ -0,0 +1,269 @@ +--- +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/linode/types + method: GET + response: + body: '{"data": [{"id": "g6-nanode-1", "label": "Nanode 1GB", "price": {"hourly": + 0.0075, "monthly": 5.0}, "region_prices": [{"id": "us-east", "hourly": 0.009, + "monthly": 6.0}], "addons": {"backups": {"price": {"hourly": 0.003, "monthly": + 2.0}, "region_prices": [{"id": "us-east", "hourly": 0.0036, "monthly": 2.4}]}}, + "memory": 1024, "disk": 25600, "transfer": 1000, "vcpus": 1, "gpus": 0, "network_out": + 1000, "class": "nanode", "successor": null}, {"id": "g6-standard-1", "label": + "Linode 2GB", "price": {"hourly": 0.015, "monthly": 10.0}, "region_prices": + [{"id": "us-east", "hourly": 0.018, "monthly": 12.0}], "addons": {"backups": + {"price": {"hourly": 0.004, "monthly": 2.5}, "region_prices": [{"id": "us-east", + "hourly": 0.0048, "monthly": 3.0}]}}, "memory": 2048, "disk": 51200, "transfer": + 2000, "vcpus": 1, "gpus": 0, "network_out": 2000, "class": "standard", "successor": + null}, {"id": "g6-standard-2", "label": "Linode 4GB", "price": {"hourly": 0.03, + "monthly": 20.0}, "region_prices": [{"id": "us-east", "hourly": 0.036, "monthly": + 24.0}], "addons": {"backups": {"price": {"hourly": 0.008, "monthly": 5.0}, "region_prices": + [{"id": "us-east", "hourly": 0.0096, "monthly": 6.0}]}}, "memory": 4096, "disk": + 81920, "transfer": 4000, "vcpus": 2, "gpus": 0, "network_out": 4000, "class": + "standard", "successor": null}, {"id": "g6-standard-4", "label": "Linode 8GB", + "price": {"hourly": 0.06, "monthly": 40.0}, "region_prices": [{"id": "us-east", + "hourly": 0.072, "monthly": 48.0}], "addons": {"backups": {"price": {"hourly": + 0.015, "monthly": 10.0}, "region_prices": [{"id": "us-east", "hourly": 0.018, + "monthly": 12.0}]}}, "memory": 8192, "disk": 163840, "transfer": 5000, "vcpus": + 4, "gpus": 0, "network_out": 5000, "class": "standard", "successor": null}, + {"id": "g6-standard-6", "label": "Linode 16GB", "price": {"hourly": 0.12, "monthly": + 80.0}, "region_prices": [{"id": "us-east", "hourly": 0.144, "monthly": 96.0}], + "addons": {"backups": {"price": {"hourly": 0.03, "monthly": 20.0}, "region_prices": + [{"id": "us-east", "hourly": 0.036, "monthly": 24.0}]}}, "memory": 16384, "disk": + 327680, "transfer": 8000, "vcpus": 6, "gpus": 0, "network_out": 6000, "class": + "standard", "successor": null}, {"id": "g6-standard-8", "label": "Linode 32GB", + "price": {"hourly": 0.24, "monthly": 160.0}, "region_prices": [{"id": "us-east", + "hourly": 0.288, "monthly": 192.0}], "addons": {"backups": {"price": {"hourly": + 0.06, "monthly": 40.0}, "region_prices": [{"id": "us-east", "hourly": 0.072, + "monthly": 48.0}]}}, "memory": 32768, "disk": 655360, "transfer": 16000, "vcpus": + 8, "gpus": 0, "network_out": 7000, "class": "standard", "successor": null}, + {"id": "g6-standard-16", "label": "Linode 64GB", "price": {"hourly": 0.48, "monthly": + 320.0}, "region_prices": [{"id": "us-east", "hourly": 0.576, "monthly": 384.0}], + "addons": {"backups": {"price": {"hourly": 0.12, "monthly": 80.0}, "region_prices": + [{"id": "us-east", "hourly": 0.144, "monthly": 96.0}]}}, "memory": 65536, "disk": + 1310720, "transfer": 20000, "vcpus": 16, "gpus": 0, "network_out": 9000, "class": + "standard", "successor": null}, {"id": "g6-standard-20", "label": "Linode 96GB", + "price": {"hourly": 0.72, "monthly": 480.0}, "region_prices": [{"id": "us-east", + "hourly": 0.864, "monthly": 576.0}], "addons": {"backups": {"price": {"hourly": + 0.18, "monthly": 120.0}, "region_prices": [{"id": "us-east", "hourly": 0.216, + "monthly": 144.0}]}}, "memory": 98304, "disk": 1966080, "transfer": 20000, "vcpus": + 20, "gpus": 0, "network_out": 10000, "class": "standard", "successor": null}, + {"id": "g6-standard-24", "label": "Linode 128GB", "price": {"hourly": 0.96, + "monthly": 640.0}, "region_prices": [{"id": "us-east", "hourly": 1.152, "monthly": + 768.0}], "addons": {"backups": {"price": {"hourly": 0.24, "monthly": 160.0}, + "region_prices": [{"id": "us-east", "hourly": 0.288, "monthly": 192.0}]}}, "memory": + 131072, "disk": 2621440, "transfer": 20000, "vcpus": 24, "gpus": 0, "network_out": + 11000, "class": "standard", "successor": null}, {"id": "g6-standard-32", "label": + "Linode 192GB", "price": {"hourly": 1.44, "monthly": 960.0}, "region_prices": + [{"id": "us-east", "hourly": 1.728, "monthly": 1152.0}], "addons": {"backups": + {"price": {"hourly": 0.36, "monthly": 240.0}, "region_prices": [{"id": "us-east", + "hourly": 0.432, "monthly": 288.0}]}}, "memory": 196608, "disk": 3932160, "transfer": + 20000, "vcpus": 32, "gpus": 0, "network_out": 12000, "class": "standard", "successor": + null}, {"id": "g7-highmem-1", "label": "Linode 24GB", "price": {"hourly": 0.09, + "monthly": 60.0}, "region_prices": [{"id": "us-east", "hourly": 0.108, "monthly": + 72.0}], "addons": {"backups": {"price": {"hourly": 0.0075, "monthly": 5.0}, + "region_prices": [{"id": "us-east", "hourly": 0.009, "monthly": 6.0}]}}, "memory": + 24576, "disk": 20480, "transfer": 5000, "vcpus": 2, "gpus": 0, "network_out": + 5000, "class": "highmem", "successor": null}, {"id": "g7-highmem-2", "label": + "Linode 48GB", "price": {"hourly": 0.18, "monthly": 120.0}, "region_prices": + [{"id": "us-east", "hourly": 0.216, "monthly": 144.0}], "addons": {"backups": + {"price": {"hourly": 0.015, "monthly": 10.0}, "region_prices": [{"id": "us-east", + "hourly": 0.018, "monthly": 12.0}]}}, "memory": 49152, "disk": 40960, "transfer": + 6000, "vcpus": 2, "gpus": 0, "network_out": 6000, "class": "highmem", "successor": + null}, {"id": "g7-highmem-4", "label": "Linode 90GB", "price": {"hourly": 0.36, + "monthly": 240.0}, "region_prices": [{"id": "us-east", "hourly": 0.432, "monthly": + 288.0}], "addons": {"backups": {"price": {"hourly": 0.03, "monthly": 20.0}, + "region_prices": [{"id": "us-east", "hourly": 0.036, "monthly": 24.0}]}}, "memory": + 92160, "disk": 92160, "transfer": 7000, "vcpus": 4, "gpus": 0, "network_out": + 7000, "class": "highmem", "successor": null}, {"id": "g7-highmem-8", "label": + "Linode 150GB", "price": {"hourly": 0.72, "monthly": 480.0}, "region_prices": + [{"id": "us-east", "hourly": 0.864, "monthly": 576.0}], "addons": {"backups": + {"price": {"hourly": 0.06, "monthly": 40.0}, "region_prices": [{"id": "us-east", + "hourly": 0.072, "monthly": 48.0}]}}, "memory": 153600, "disk": 204800, "transfer": + 8000, "vcpus": 8, "gpus": 0, "network_out": 8000, "class": "highmem", "successor": + null}, {"id": "g7-highmem-16", "label": "Linode 300GB", "price": {"hourly": + 1.44, "monthly": 960.0}, "region_prices": [{"id": "us-east", "hourly": 1.728, + "monthly": 1152.0}], "addons": {"backups": {"price": {"hourly": 0.12, "monthly": + 80.0}, "region_prices": [{"id": "us-east", "hourly": 0.144, "monthly": 96.0}]}}, + "memory": 307200, "disk": 348160, "transfer": 9000, "vcpus": 16, "gpus": 0, + "network_out": 9000, "class": "highmem", "successor": null}, {"id": "g6-dedicated-2", + "label": "Dedicated 4GB", "price": {"hourly": 0.045, "monthly": 30.0}, "region_prices": + [{"id": "us-east", "hourly": 0.054, "monthly": 36.0}], "addons": {"backups": + {"price": {"hourly": 0.008, "monthly": 5.0}, "region_prices": [{"id": "us-east", + "hourly": 0.0096, "monthly": 6.0}]}}, "memory": 4096, "disk": 81920, "transfer": + 4000, "vcpus": 2, "gpus": 0, "network_out": 4000, "class": "dedicated", "successor": + null}, {"id": "g6-dedicated-4", "label": "Dedicated 8GB", "price": {"hourly": + 0.09, "monthly": 60.0}, "region_prices": [{"id": "us-east", "hourly": 0.108, + "monthly": 72.0}], "addons": {"backups": {"price": {"hourly": 0.015, "monthly": + 10.0}, "region_prices": [{"id": "us-east", "hourly": 0.018, "monthly": 12.0}]}}, + "memory": 8192, "disk": 163840, "transfer": 5000, "vcpus": 4, "gpus": 0, "network_out": + 5000, "class": "dedicated", "successor": null}, {"id": "g6-dedicated-8", "label": + "Dedicated 16GB", "price": {"hourly": 0.18, "monthly": 120.0}, "region_prices": + [{"id": "us-east", "hourly": 0.216, "monthly": 144.0}], "addons": {"backups": + {"price": {"hourly": 0.03, "monthly": 20.0}, "region_prices": [{"id": "us-east", + "hourly": 0.036, "monthly": 24.0}]}}, "memory": 16384, "disk": 327680, "transfer": + 8000, "vcpus": 8, "gpus": 0, "network_out": 6000, "class": "dedicated", "successor": + null}, {"id": "g6-dedicated-16", "label": "Dedicated 32GB", "price": {"hourly": + 0.36, "monthly": 240.0}, "region_prices": [{"id": "us-east", "hourly": 0.432, + "monthly": 288.0}], "addons": {"backups": {"price": {"hourly": 0.06, "monthly": + 40.0}, "region_prices": [{"id": "us-east", "hourly": 0.072, "monthly": 48.0}]}}, + "memory": 32768, "disk": 655360, "transfer": 16000, "vcpus": 16, "gpus": 0, + "network_out": 7000, "class": "dedicated", "successor": null}, {"id": "g6-dedicated-32", + "label": "Dedicated 64GB", "price": {"hourly": 0.72, "monthly": 480.0}, "region_prices": + [{"id": "us-east", "hourly": 0.864, "monthly": 576.0}], "addons": {"backups": + {"price": {"hourly": 0.12, "monthly": 80.0}, "region_prices": [{"id": "us-east", + "hourly": 0.144, "monthly": 96.0}]}}, "memory": 65536, "disk": 1310720, "transfer": + 20000, "vcpus": 32, "gpus": 0, "network_out": 8000, "class": "dedicated", "successor": + null}, {"id": "g6-dedicated-48", "label": "Dedicated 96GB", "price": {"hourly": + 1.08, "monthly": 720.0}, "region_prices": [{"id": "us-east", "hourly": 1.296, + "monthly": 864.0}], "addons": {"backups": {"price": {"hourly": 0.18, "monthly": + 120.0}, "region_prices": [{"id": "us-east", "hourly": 0.216, "monthly": 144.0}]}}, + "memory": 98304, "disk": 1966080, "transfer": 20000, "vcpus": 48, "gpus": 0, + "network_out": 9000, "class": "dedicated", "successor": null}, {"id": "g6-sawhorse-64", + "label": "Sawhorse 192GB", "price": {"hourly": 4.5, "monthly": 3000.0}, "region_prices": + [{"id": "us-east", "hourly": 5.4, "monthly": 3600.0}], "addons": {"backups": + {"price": {"hourly": 0.0, "monthly": 0.0}, "region_prices": [{"id": "us-east", + "hourly": 0.0, "monthly": 0.0}]}}, "memory": 196608, "disk": 8388608, "transfer": + 9000, "vcpus": 64, "gpus": 0, "network_out": 10000, "class": "sawhorse", "successor": + null}, {"id": "g6-dedicated-50", "label": "Dedicated 128GB", "price": {"hourly": + 1.44, "monthly": 960.0}, "region_prices": [{"id": "us-east", "hourly": 1.728, + "monthly": 1152.0}], "addons": {"backups": {"price": {"hourly": 0.24, "monthly": + 160.0}, "region_prices": [{"id": "us-east", "hourly": 0.288, "monthly": 192.0}]}}, + "memory": 131072, "disk": 2560000, "transfer": 10000, "vcpus": 50, "gpus": 0, + "network_out": 10000, "class": "dedicated", "successor": null}, {"id": "g6-dedicated-56", + "label": "Dedicated 256GB", "price": {"hourly": 2.88, "monthly": 1920.0}, "region_prices": + [{"id": "us-east", "hourly": 3.456, "monthly": 2304.0}], "addons": {"backups": + {"price": {"hourly": 0.3, "monthly": 200.0}, "region_prices": [{"id": "us-east", + "hourly": 0.36, "monthly": 240.0}]}}, "memory": 262144, "disk": 5120000, "transfer": + 11000, "vcpus": 56, "gpus": 0, "network_out": 11000, "class": "dedicated", "successor": + null}, {"id": "g6-dedicated-64", "label": "Dedicated 512GB", "price": {"hourly": + 5.76, "monthly": 3840.0}, "region_prices": [{"id": "us-east", "hourly": 6.912, + "monthly": 4608.0}], "addons": {"backups": {"price": {"hourly": 0.36, "monthly": + 240.0}, "region_prices": [{"id": "us-east", "hourly": 0.432, "monthly": 288.0}]}}, + "memory": 524288, "disk": 7372800, "transfer": 12000, "vcpus": 64, "gpus": 0, + "network_out": 12000, "class": "dedicated", "successor": null}, {"id": "g1-gpu-rtx6000-1", + "label": "Dedicated 32GB + RTX6000 GPU x1", "price": {"hourly": 1.5, "monthly": + 1000.0}, "region_prices": [{"id": "us-east", "hourly": 1.8, "monthly": 1200.0}], + "addons": {"backups": {"price": {"hourly": 0.06, "monthly": 40.0}, "region_prices": + [{"id": "us-east", "hourly": 0.072, "monthly": 48.0}]}}, "memory": 32768, "disk": + 655360, "transfer": 16000, "vcpus": 8, "gpus": 0, "network_out": 10000, "class": + "gpu", "successor": null}, {"id": "g1-gpu-rtx6000-2", "label": "Dedicated 64GB + + RTX6000 GPU x2", "price": {"hourly": 3.0, "monthly": 2000.0}, "region_prices": + [{"id": "us-east", "hourly": 3.6, "monthly": 2400.0}], "addons": {"backups": + {"price": {"hourly": 0.12, "monthly": 80.0}, "region_prices": [{"id": "us-east", + "hourly": 0.144, "monthly": 96.0}]}}, "memory": 65536, "disk": 1310720, "transfer": + 20000, "vcpus": 16, "gpus": 0, "network_out": 10000, "class": "gpu", "successor": + null}, {"id": "g1-gpu-rtx6000-3", "label": "Dedicated 96GB + RTX6000 GPU x3", + "price": {"hourly": 4.5, "monthly": 3000.0}, "region_prices": [{"id": "us-east", + "hourly": 5.4, "monthly": 3600.0}], "addons": {"backups": {"price": {"hourly": + 0.18, "monthly": 160.0}, "region_prices": [{"id": "us-east", "hourly": 0.216, + "monthly": 192.0}]}}, "memory": 98304, "disk": 1966080, "transfer": 20000, "vcpus": + 20, "gpus": 0, "network_out": 10000, "class": "gpu", "successor": null}, {"id": + "g1-gpu-rtx6000-4", "label": "Dedicated 128GB + RTX6000 GPU x4", "price": {"hourly": + 6.0, "monthly": 4000.0}, "region_prices": [{"id": "us-east", "hourly": 7.2, + "monthly": 4800.0}], "addons": {"backups": {"price": {"hourly": 0.24, "monthly": + 320.0}, "region_prices": [{"id": "us-east", "hourly": 0.288, "monthly": 384.0}]}}, + "memory": 131072, "disk": 2621440, "transfer": 20000, "vcpus": 24, "gpus": 0, + "network_out": 10000, "class": "gpu", "successor": null}, {"id": "g6-premium-2", + "label": "Premium 4GB", "price": {"hourly": 0.05, "monthly": 36.0}, "region_prices": + [{"id": "us-east", "hourly": 0.06, "monthly": 43.2}], "addons": {"backups": + {"price": {"hourly": 0.008, "monthly": 5.0}, "region_prices": [{"id": "us-east", + "hourly": 0.0096, "monthly": 6.0}]}}, "memory": 4096, "disk": 81920, "transfer": + 4000, "vcpus": 2, "gpus": 0, "network_out": 4000, "class": "premium", "successor": + null}, {"id": "g6-premium-4", "label": "Premium 8GB", "price": {"hourly": 0.11, + "monthly": 72.0}, "region_prices": [{"id": "us-east", "hourly": 0.132, "monthly": + 86.4}], "addons": {"backups": {"price": {"hourly": 0.015, "monthly": 10.0}, + "region_prices": [{"id": "us-east", "hourly": 0.018, "monthly": 12.0}]}}, "memory": + 8192, "disk": 163840, "transfer": 5000, "vcpus": 4, "gpus": 0, "network_out": + 5000, "class": "premium", "successor": null}, {"id": "g6-premium-8", "label": + "Premium 16GB", "price": {"hourly": 0.22, "monthly": 144.0}, "region_prices": + [{"id": "us-east", "hourly": 0.264, "monthly": 172.8}], "addons": {"backups": + {"price": {"hourly": 0.03, "monthly": 20.0}, "region_prices": [{"id": "us-east", + "hourly": 0.036, "monthly": 24.0}]}}, "memory": 16384, "disk": 327680, "transfer": + 6000, "vcpus": 8, "gpus": 0, "network_out": 6000, "class": "premium", "successor": + null}, {"id": "g6-premium-16", "label": "Premium 32GB", "price": {"hourly": + 0.43, "monthly": 288.0}, "region_prices": [{"id": "us-east", "hourly": 0.516, + "monthly": 345.6}], "addons": {"backups": {"price": {"hourly": 0.06, "monthly": + 40.0}, "region_prices": [{"id": "us-east", "hourly": 0.072, "monthly": 48.0}]}}, + "memory": 32768, "disk": 655360, "transfer": 7000, "vcpus": 16, "gpus": 0, "network_out": + 7000, "class": "premium", "successor": null}, {"id": "g6-premium-32", "label": + "Premium 64GB", "price": {"hourly": 0.86, "monthly": 576.0}, "region_prices": + [{"id": "us-east", "hourly": 1.032, "monthly": 691.2}], "addons": {"backups": + {"price": {"hourly": 0.12, "monthly": 80.0}, "region_prices": [{"id": "us-east", + "hourly": 0.144, "monthly": 96.0}]}}, "memory": 65536, "disk": 1310720, "transfer": + 8000, "vcpus": 32, "gpus": 0, "network_out": 8000, "class": "premium", "successor": + null}, {"id": "g6-premium-48", "label": "Premium 96GB", "price": {"hourly": + 1.3, "monthly": 864.0}, "region_prices": [{"id": "us-east", "hourly": 1.56, + "monthly": 1036.8}], "addons": {"backups": {"price": {"hourly": 0.18, "monthly": + 120.0}, "region_prices": [{"id": "us-east", "hourly": 0.216, "monthly": 144.0}]}}, + "memory": 98304, "disk": 1966080, "transfer": 9000, "vcpus": 48, "gpus": 0, + "network_out": 9000, "class": "premium", "successor": null}, {"id": "g6-premium-50", + "label": "Premium 128GB", "price": {"hourly": 1.73, "monthly": 1152.0}, "region_prices": + [{"id": "us-east", "hourly": 2.076, "monthly": 1382.4}], "addons": {"backups": + {"price": {"hourly": 0.24, "monthly": 160.0}, "region_prices": [{"id": "us-east", + "hourly": 0.288, "monthly": 192.0}]}}, "memory": 131072, "disk": 2560000, "transfer": + 10000, "vcpus": 50, "gpus": 0, "network_out": 10000, "class": "premium", "successor": + null}, {"id": "g6-premium-56", "label": "Premium 256GB", "price": {"hourly": + 3.46, "monthly": 2304.0}, "region_prices": [{"id": "us-east", "hourly": 4.152, + "monthly": 2764.8}], "addons": {"backups": {"price": {"hourly": 0.3, "monthly": + 200.0}, "region_prices": [{"id": "us-east", "hourly": 0.36, "monthly": 240.0}]}}, + "memory": 262144, "disk": 5120000, "transfer": 11000, "vcpus": 56, "gpus": 0, + "network_out": 11000, "class": "premium", "successor": null}, {"id": "g6-premium-64", + "label": "Premium 512GB", "price": {"hourly": 6.91, "monthly": 4608.0}, "region_prices": + [{"id": "us-east", "hourly": 8.292, "monthly": 5529.6}], "addons": {"backups": + {"price": {"hourly": 0.36, "monthly": 240.0}, "region_prices": [{"id": "us-east", + "hourly": 0.432, "monthly": 288.0}]}}, "memory": 524288, "disk": 7372800, "transfer": + 12000, "vcpus": 64, "gpus": 0, "network_out": 12000, "class": "premium", "successor": + null}], "page": 1, "pages": 1, "results": 46}' + 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 + Cache-Control: + - private, max-age=900 + - private, max-age=60, s-maxage=60 + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Server: + - nginx + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Accept-Encoding + - 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: + - "1200" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/test/integration/types_test.go b/test/integration/types_test.go index 519f08c9c..3331c6739 100644 --- a/test/integration/types_test.go +++ b/test/integration/types_test.go @@ -50,3 +50,50 @@ func TestTypes_List(t *testing.T) { t.Errorf("Expected a list of images, but got none %v", i) } } + +func TestTypes_RegionSpecific(t *testing.T) { + client, teardown := createTestClient(t, "fixtures/TestTypes_RegionSpecific") + defer teardown() + + validateOverride := func(override linodego.LinodeRegionPrice) { + if override.ID == "" { + t.Fatal("Expected region; got nil") + } + + if override.Monthly <= 0 { + t.Fatalf("Expected monthly cost; got %f", override.Monthly) + } + + if override.Hourly <= 0 { + t.Fatalf("Expected hourly cost; got %f", override.Hourly) + } + } + + types, err := client.ListTypes(context.Background(), nil) + if err != nil { + t.Errorf("Error listing images, expected struct, got error %v", err) + } + + var targetType *linodego.LinodeType + for _, t := range types { + if t.RegionPrices != nil && + len(t.RegionPrices) > 0 && + t.RegionPrices[0].Hourly > 0 { + targetType = &t + break + } + } + + if targetType == nil { + t.Fatal("expected type with region override, got none") + } + + // Validate overrides + for _, override := range targetType.RegionPrices { + validateOverride(override) + } + + for _, override := range targetType.Addons.Backups.RegionPrices { + validateOverride(override) + } +} diff --git a/types.go b/types.go index 01d655340..1d8341367 100644 --- a/types.go +++ b/types.go @@ -10,18 +10,19 @@ import ( // LinodeType represents a linode type object type LinodeType struct { - ID string `json:"id"` - Disk int `json:"disk"` - Class LinodeTypeClass `json:"class"` // enum: nanode, standard, highmem, dedicated, gpu - Price *LinodePrice `json:"price"` - Label string `json:"label"` - Addons *LinodeAddons `json:"addons"` - NetworkOut int `json:"network_out"` - Memory int `json:"memory"` - Transfer int `json:"transfer"` - VCPUs int `json:"vcpus"` - GPUs int `json:"gpus"` - Successor string `json:"successor"` + ID string `json:"id"` + Disk int `json:"disk"` + Class LinodeTypeClass `json:"class"` // enum: nanode, standard, highmem, dedicated, gpu + Price *LinodePrice `json:"price"` + Label string `json:"label"` + Addons *LinodeAddons `json:"addons"` + RegionPrices []LinodeRegionPrice `json:"region_prices"` + NetworkOut int `json:"network_out"` + Memory int `json:"memory"` + Transfer int `json:"transfer"` + VCPUs int `json:"vcpus"` + GPUs int `json:"gpus"` + Successor string `json:"successor"` } // LinodePrice represents a linode type price object @@ -32,7 +33,8 @@ type LinodePrice struct { // LinodeBackupsAddon represents a linode backups addon object type LinodeBackupsAddon struct { - Price *LinodePrice `json:"price"` + Price *LinodePrice `json:"price"` + RegionPrices []LinodeRegionPrice `json:"region_prices"` } // LinodeAddons represent the linode addons object @@ -40,6 +42,14 @@ type LinodeAddons struct { Backups *LinodeBackupsAddon `json:"backups"` } +// LinodeRegionPrice represents an individual type or addon +// price exception for a region. +type LinodeRegionPrice struct { + ID string `json:"id"` + Hourly float32 `json:"hourly"` + Monthly float32 `json:"monthly"` +} + // LinodeTypeClass constants start with Class and include Linode API Instance Type Classes type LinodeTypeClass string