Skip to content
Open
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
21 changes: 21 additions & 0 deletions regions_availability.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ type RegionAvailability struct {
Available bool `json:"available"`
}

// RegionVPCAvailability represents a linode region vpc availability object
Copy link
Author

Choose a reason for hiding this comment

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

I saw that usually the methods end in dots, but the comments for structs or vars don't. Is it intentional?

type RegionVPCAvailability struct {
Region string `json:"region"`
Available bool `json:"available"`
AvailableIPV6PrefixLengths []int `json:"available_ipv6_prefix_lengths"`
}

// ListRegionsAvailability lists Regions. This endpoint is cached by default.
func (c *Client) ListRegionsAvailability(ctx context.Context, opts *ListOptions) ([]RegionAvailability, error) {
e := "regions/availability"
Expand Down Expand Up @@ -52,3 +59,17 @@ func (c *Client) GetRegionAvailability(ctx context.Context, regionID string) (*R

return response, nil
}

// ListRegionsVPCAvailability lists VPC availability data for all regions.
// NOTE: IPv6 VPCs may not currently be available to all users.
func (c *Client) ListRegionsVPCAvailability(ctx context.Context, opts *ListOptions) ([]RegionVPCAvailability, error) {
e := "regions/vpc-availability"
return getPaginatedResults[RegionVPCAvailability](ctx, c, e, opts)
}

// GetRegionVPCAvailability gets VPC availability data for a single region.
// NOTE: IPv6 VPCs may not currently be available to all users.
func (c *Client) GetRegionVPCAvailability(ctx context.Context, regionID string) (*RegionVPCAvailability, error) {
e := formatAPIPath("regions/%s/vpc-availability", regionID)
return doGETRequest[RegionVPCAvailability](ctx, c, e)
}
66 changes: 66 additions & 0 deletions test/integration/fixtures/TestRegionVPCAvailability_Get.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/regions/nl-ams/vpc-availability
method: GET
response:
body: '{"region": "nl-ams", "available": true, "available_ipv6_prefix_lengths":
[]}'
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:
- "76"
Content-Security-Policy:
- default-src 'none'
Content-Type:
- application/json
Expires:
- Mon, 02 Feb 2026 10:17:52 GMT
Pragma:
- no-cache
Strict-Transport-Security:
- max-age=31536000
Vary:
- Authorization, X-Filter
- Authorization, X-Filter
X-Accepted-Oauth-Scopes:
- vpc:read_only
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
- DENY
X-Oauth-Scopes:
- '*'
X-Ratelimit-Limit:
- "1840"
X-Xss-Protection:
- 1; mode=block
status: 200 OK
code: 200
duration: ""
96 changes: 96 additions & 0 deletions test/integration/fixtures/TestRegionsVPCAvailability_List.yaml
Copy link
Author

Choose a reason for hiding this comment

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

The output of those fixtures were recorded in the devcloud env rather than prod. This is because I don't have the token yet. But if I understand correctly, if someone run make fixtures for those tests, the output would differ greatly. That's why @mgwoj generated those output fixtures for production (as he has access) so I could use them here already, and future make fixtures would not generate such big diffs.

Should I use the fixtures obtained from prod env by Michał already?

Copy link
Author

Choose a reason for hiding this comment

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

I have gained the access to the prod env and regenerated test data based on that env.

Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
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/regions/vpc-availability?page=1
method: GET
response:
body: '{"data": [{"region": "nl-ams", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "fr-par-2", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "jp-tyo-3", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "sg-sin-2", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "de-fra-2", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "in-bom-2", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "au-mel", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "gb-lon", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "us-lax", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "id-cgk", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "us-mia", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "it-mil", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "jp-osa", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "in-maa", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "es-mad", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "se-sto", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "br-gru", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "us-sea", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "fr-par", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "us-ord", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "us-iad", "available": true, "available_ipv6_prefix_lengths":
[]}, {"region": "ap-southeast", "available": false, "available_ipv6_prefix_lengths":
[]}, {"region": "ca-central", "available": false, "available_ipv6_prefix_lengths":
[]}, {"region": "ap-west", "available": false, "available_ipv6_prefix_lengths":
[]}, {"region": "us-central", "available": false, "available_ipv6_prefix_lengths":
[]}, {"region": "ap-northeast", "available": false, "available_ipv6_prefix_lengths":
[]}, {"region": "eu-central", "available": false, "available_ipv6_prefix_lengths":
[]}, {"region": "ap-south", "available": false, "available_ipv6_prefix_lengths":
[]}, {"region": "eu-west", "available": false, "available_ipv6_prefix_lengths":
[]}, {"region": "us-east", "available": false, "available_ipv6_prefix_lengths":
[]}, {"region": "us-southeast", "available": false, "available_ipv6_prefix_lengths":
[]}, {"region": "us-west", "available": false, "available_ipv6_prefix_lengths":
[]}], "page": 1, "pages": 1, "results": 32}'
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-Security-Policy:
- default-src 'none'
Content-Type:
- application/json
Expires:
- Mon, 02 Feb 2026 10:17:08 GMT
Pragma:
- no-cache
Strict-Transport-Security:
- max-age=31536000
Vary:
- Authorization, X-Filter
- Authorization, X-Filter
- Accept-Encoding
X-Accepted-Oauth-Scopes:
- vpc:read_only
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
- DENY
X-Oauth-Scopes:
- '*'
X-Ratelimit-Limit:
- "1840"
X-Xss-Protection:
- 1; mode=block
status: 200 OK
code: 200
duration: ""
34 changes: 34 additions & 0 deletions test/integration/regionsavailability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,37 @@ func TestRegionsAvailability_List(t *testing.T) {

retryStatement(t, 3, testFunc)
}

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

testFunc := func(retryT *TRetry) {
regions, err := client.ListRegionsVPCAvailability(context.Background(), nil)
if err != nil {
t.Errorf("Error listing regions vpc availability, expected struct - error %v", err)
}
if len(regions) == 0 {
t.Errorf("Expected a list of regions vpc availability - %v", regions)
}
}

retryStatement(t, 3, testFunc)
}

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

testFunc := func(retryT *TRetry) {
region, err := client.GetRegionVPCAvailability(context.Background(), "nl-ams")
if err != nil {
t.Errorf("Error getting region vpc availability, expected struct - error %v", err)
}
if region == nil {
t.Errorf("Expected a region vpc availability object - %v", region)
}
}

retryStatement(t, 3, testFunc)
}
8 changes: 8 additions & 0 deletions test/unit/fixtures/region_vpc_availability_get.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"region": "us-east",
"available": true,
"available_ipv6_prefix_lengths": [
52,
60
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

The IPv6 prefix length value 60 is inconsistent with the list fixture and integration test fixture, which both use 52. For test consistency, this should be 52 unless testing different scenarios is intentional.

Suggested change
60
52

Copilot uses AI. Check for mistakes.
]
}
24 changes: 24 additions & 0 deletions test/unit/fixtures/regions_vpc_availability_list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"data": [
{
"region": "us-east",
"available": true,
"available_ipv6_prefix_lengths": [
52,
48
]
},
{
"region": "us-west",
"available": true,
"available_ipv6_prefix_lengths": [
56,
52,
48
]
}
],
"page": 1,
"pages": 1,
"results": 2
}
56 changes: 56 additions & 0 deletions test/unit/region_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,59 @@ func TestGetRegionAvailability(t *testing.T) {
assert.True(t, availability.Available, "Expected region to be available")
assert.NotEmpty(t, availability.Plan, "Expected plan to be set")
}

func TestListRegionsVPCAvailability(t *testing.T) {
// Load the fixture data for regions vpc availability
fixtureData, err := fixtures.GetFixture("regions_vpc_availability_list")
assert.NoError(t, err)

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

base.MockGet("regions/vpc-availability", fixtureData)

availability, err := base.Client.ListRegionsVPCAvailability(context.Background(), &linodego.ListOptions{})
assert.NoError(t, err)
assert.NotEmpty(t, availability, "Expected non-empty region vpc availability list")

expected := []linodego.RegionVPCAvailability{
{
Region: "us-east",
Available: true,
AvailableIPV6PrefixLengths: []int{52, 48},
},
{
Region: "us-west",
Available: true,
AvailableIPV6PrefixLengths: []int{56, 52, 48},
},
}

assert.Equal(t, expected, availability, "Expected region vpc availability list to match expected data")
Copy link
Author

Choose a reason for hiding this comment

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

Let me know if you prefer one-by-one assertions on each of the returned fields instead of a single object comparison.

}

func TestGetRegionVPCAvailability(t *testing.T) {
// Load the fixture data for a specific region vpc availability
fixtureData, err := fixtures.GetFixture("region_vpc_availability_get")
assert.NoError(t, err)

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

regionID := "us-east"
base.MockGet(fmt.Sprintf("regions/%s/vpc-availability", regionID), fixtureData)

availability, err := base.Client.GetRegionVPCAvailability(context.Background(), regionID)
assert.NoError(t, err)
assert.NotNil(t, availability, "Expected region vpc availability object to be returned")

expected := &linodego.RegionVPCAvailability{
Region: "us-east",
Available: true,
AvailableIPV6PrefixLengths: []int{52, 60},
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

The expected IPv6 prefix length [52, 60] doesn't match the fixture data being tested against. The fixture 'region_vpc_availability_get.json' contains [52, 60], but this differs from the integration test fixture which uses [52]. This inconsistency may indicate incorrect test expectations or fixture data.

Suggested change
AvailableIPV6PrefixLengths: []int{52, 60},
AvailableIPV6PrefixLengths: []int{52},

Copilot uses AI. Check for mistakes.
}

assert.Equal(t, expected, availability, "Expected region vpc availability to match expected data")
}