diff --git a/test/integration/images_test.go b/test/integration/images_test.go index 785531d13..55159e667 100644 --- a/test/integration/images_test.go +++ b/test/integration/images_test.go @@ -107,7 +107,7 @@ func TestImage_CreateUpload(t *testing.T) { defer teardown() image, uploadURL, err := client.CreateImageUpload(context.Background(), ImageCreateUploadOptions{ - Region: getRegionsWithCaps(t, client, []string{"Metadata"})[0], + Region: getRegionsWithCaps(t, client, []string{"Metadata"}, []string{})[0], Label: "linodego-image-create-upload", Description: "An image that does stuff.", CloudInit: true, @@ -132,7 +132,7 @@ func TestImage_CloudInit(t *testing.T) { client, instance, teardown, err := setupInstance( t, "fixtures/TestImage_CloudInit", true, func(client *Client, options *InstanceCreateOptions) { - options.Region = getRegionsWithCaps(t, client, []string{"Metadata"})[0] + options.Region = getRegionsWithCaps(t, client, []string{"Metadata"}, []string{})[0] }) if err != nil { t.Fatal(err) diff --git a/test/integration/instance_config_test.go b/test/integration/instance_config_test.go index 5af8d6c68..cff9b8edf 100644 --- a/test/integration/instance_config_test.go +++ b/test/integration/instance_config_test.go @@ -67,7 +67,7 @@ func setupInstanceWithVPCAndNATOneToOne(t *testing.T, fixturesYaml string) ( t, fixturesYaml, func(client *Client, opts *InstanceCreateOptions) { - opts.Region = getRegionsWithCaps(t, client, []string{"Linodes", "VPCs"})[0] + opts.Region = getRegionsWithCaps(t, client, []string{"Linodes", "VPCs"}, []string{})[0] }, ) if err != nil { @@ -110,7 +110,7 @@ func setupInstanceWith3Interfaces(t *testing.T, fixturesYaml string) ( t, fixturesYaml, func(client *Client, opts *InstanceCreateOptions) { - opts.Region = getRegionsWithCaps(t, client, []string{"Linodes", "VPCs"})[0] + opts.Region = getRegionsWithCaps(t, client, []string{"Linodes", "VPCs"}, []string{})[0] }, ) if err != nil { @@ -153,7 +153,7 @@ func TestInstance_ConfigInterfaces_AppendDelete(t *testing.T) { "fixtures/TestInstance_ConfigInterfaces_AppendDelete", func(client *Client, opts *InstanceCreateOptions) { // Ensure we're in a region that supports VLANs - opts.Region = getRegionsWithCaps(t, client, []string{"vlans", "VPCs"})[0] + opts.Region = getRegionsWithCaps(t, client, []string{"vlans", "VPCs"}, []string{})[0] }, ) defer teardown() @@ -303,7 +303,7 @@ func TestInstance_ConfigInterfaces_Update(t *testing.T) { "fixtures/TestInstance_ConfigInterfaces_Update", func(client *Client, opts *InstanceCreateOptions) { // Ensure we're in a region that supports VLANs - opts.Region = getRegionsWithCaps(t, client, []string{"vlans", "VPCs"})[0] + opts.Region = getRegionsWithCaps(t, client, []string{"vlans", "VPCs"}, []string{})[0] }, ) defer teardown() @@ -377,7 +377,7 @@ func TestInstance_ConfigInterface_Update(t *testing.T) { "fixtures/TestInstance_ConfigInterface_Update", func(client *Client, opts *InstanceCreateOptions) { // Ensure we're in a region that supports VLANs - opts.Region = getRegionsWithCaps(t, client, []string{"vlans", "VPCs"})[0] + opts.Region = getRegionsWithCaps(t, client, []string{"vlans", "VPCs"}, []string{})[0] }, ) defer teardown() diff --git a/test/integration/instances_test.go b/test/integration/instances_test.go index bb88015b5..a5fc4668c 100644 --- a/test/integration/instances_test.go +++ b/test/integration/instances_test.go @@ -354,7 +354,7 @@ func TestInstance_Rebuild(t *testing.T) { t, "fixtures/TestInstance_Rebuild", true, func(client *linodego.Client, options *linodego.InstanceCreateOptions) { - options.Region = getRegionsWithCaps(t, client, []string{"Metadata"})[0] + options.Region = getRegionsWithCaps(t, client, []string{"Metadata"}, []string{})[0] }, ) defer teardown() @@ -392,7 +392,7 @@ func TestInstance_Clone(t *testing.T) { client, instance, teardownOriginalLinode, err := setupInstance( t, "fixtures/TestInstance_Clone", true, func(client *linodego.Client, options *linodego.InstanceCreateOptions) { - targetRegion = getRegionsWithCaps(t, client, []string{"Metadata"})[0] + targetRegion = getRegionsWithCaps(t, client, []string{"Metadata"}, []string{})[0] options.Region = targetRegion }) @@ -470,7 +470,7 @@ func TestInstance_withMetadata(t *testing.T) { options.Metadata = &linodego.InstanceMetadataOptions{ UserData: base64.StdEncoding.EncodeToString([]byte("reallycoolmetadata")), } - options.Region = getRegionsWithCaps(t, client, []string{"Metadata"})[0] + options.Region = getRegionsWithCaps(t, client, []string{"Metadata"}, []string{})[0] }) if err != nil { t.Fatal(err) @@ -519,7 +519,7 @@ func createInstance(t *testing.T, client *linodego.Client, enableCloudFirewall b createOpts := linodego.InstanceCreateOptions{ Label: "go-test-ins-" + randLabel(), RootPass: randPassword(), - Region: getRegionsWithCaps(t, client, []string{"linodes"})[0], + Region: getRegionsWithCaps(t, client, []string{"linodes"}, []string{})[0], Type: "g6-nanode-1", Image: "linode/debian9", Booted: linodego.Pointer(false), @@ -567,7 +567,7 @@ func createInstanceWithoutDisks( createOpts := linodego.InstanceCreateOptions{ Label: "go-test-ins-wo-disk-" + randLabel(), - Region: getRegionsWithCaps(t, client, []string{"linodes"})[0], + Region: getRegionsWithCaps(t, client, []string{"linodes"}, []string{})[0], Type: "g6-nanode-1", Booted: linodego.Pointer(false), } diff --git a/test/integration/integration_suite_test.go b/test/integration/integration_suite_test.go index a4534cc6e..4866b9859 100644 --- a/test/integration/integration_suite_test.go +++ b/test/integration/integration_suite_test.go @@ -166,8 +166,19 @@ func transportRecorderWrapper(t *testing.T, fixtureYaml string) (transport.Wrapp }, teardown } -// getRegionsWithCaps returns a list of regions that support the given capabilities. -func getRegionsWithCaps(t *testing.T, client *linodego.Client, capabilities []string) []string { +/* +Helper function getRegionsWithCaps returns a list of regions that support the given capabilities and plans. +It filters regions based on their capabilities and the availability of specified plans. +If the plans list is empty, it only checks for the capabilities. + +Parameters: + - capabilities: A list of required capabilities that regions must support. + - plans (optional): A list of required plans that must be available in the regions. + +Returns: + - string values representing the IDs of regions that meet the given criteria. +*/ +func getRegionsWithCaps(t *testing.T, client *linodego.Client, capabilities, plans []string) []string { result := make([]string, 0) regions, err := client.ListRegions(context.Background(), nil) @@ -175,6 +186,18 @@ func getRegionsWithCaps(t *testing.T, client *linodego.Client, capabilities []st t.Fatal(err) } + regionsAvailabilities, err := client.ListRegionsAvailability(context.Background(), nil) + + type availKey struct { + Region string + Plan string + } + + availMap := make(map[availKey]linodego.RegionAvailability, len(regionsAvailabilities)) + for _, avail := range regionsAvailabilities { + availMap[availKey{Region: avail.Region, Plan: avail.Plan}] = avail + } + regionHasCaps := func(r linodego.Region) bool { capsMap := make(map[string]bool) @@ -191,8 +214,22 @@ func getRegionsWithCaps(t *testing.T, client *linodego.Client, capabilities []st return true } + // Function to check if a region has the required plans available + regionHasPlans := func(regionID string) bool { + if len(plans) == 0 { + return true + } + + for _, plan := range plans { + if avail, ok := availMap[availKey{Region: regionID, Plan: plan}]; !ok || !avail.Available { + return false + } + } + return true + } + for _, region := range regions { - if region.Status != "ok" || !regionHasCaps(region) { + if region.Status != "ok" || !regionHasCaps(region) || !regionHasPlans(region.ID) { continue } diff --git a/test/integration/lke_clusters_test.go b/test/integration/lke_clusters_test.go index 49f0c15f1..2cd110f86 100644 --- a/test/integration/lke_clusters_test.go +++ b/test/integration/lke_clusters_test.go @@ -256,7 +256,7 @@ func setupLKECluster(t *testing.T, clusterModifiers []clusterModifier, fixturesY createOpts := linodego.LKEClusterCreateOptions{ Label: label, - Region: getRegionsWithCaps(t, client, []string{"Kubernetes"})[0], + Region: getRegionsWithCaps(t, client, []string{"Kubernetes"}, []string{})[0], K8sVersion: "1.29", Tags: []string{"testing"}, NodePools: []linodego.LKENodePoolCreateOptions{{Count: 1, Type: "g6-standard-2", Tags: []string{"test"}}}, diff --git a/test/integration/mysql_test.go b/test/integration/mysql_test.go index d1fbbaa06..f590d8ea7 100644 --- a/test/integration/mysql_test.go +++ b/test/integration/mysql_test.go @@ -180,7 +180,7 @@ func createMySQLDatabase(t *testing.T, client *linodego.Client, createOpts := linodego.MySQLCreateOptions{ Label: "go-mysql-test-def" + randLabel(), - Region: getRegionsWithCaps(t, client, []string{"Managed Databases"})[0], + Region: getRegionsWithCaps(t, client, []string{"Managed Databases"}, []string{})[0], Type: "g6-nanode-1", Engine: "mysql/8.0.30", Encrypted: false, diff --git a/test/integration/nodebalancers_test.go b/test/integration/nodebalancers_test.go index 1a786406e..a7d1ab558 100644 --- a/test/integration/nodebalancers_test.go +++ b/test/integration/nodebalancers_test.go @@ -86,7 +86,7 @@ func setupNodeBalancer(t *testing.T, fixturesYaml string) (*linodego.Client, *li client, fixtureTeardown := createTestClient(t, fixturesYaml) createOpts := linodego.NodeBalancerCreateOptions{ Label: &label, - Region: getRegionsWithCaps(t, client, []string{"NodeBalancers"})[0], + Region: getRegionsWithCaps(t, client, []string{"NodeBalancers"}, []string{})[0], ClientConnThrottle: &clientConnThrottle, FirewallID: GetFirewallID(), } diff --git a/test/integration/object_storage_buckets_test.go b/test/integration/object_storage_buckets_test.go index 0eadeac96..2548362a8 100644 --- a/test/integration/object_storage_buckets_test.go +++ b/test/integration/object_storage_buckets_test.go @@ -41,7 +41,7 @@ func TestObjectStorageBucket_Create_smoke(t *testing.T) { func TestObjectStorageBucket_Regional(t *testing.T) { // t.Skip("skipping region test before GA") client, teardown := createTestClient(t, "fixtures/TestObjectStorageBucket_Regional") - regions := getRegionsWithCaps(t, client, []string{"Object Storage"}) + regions := getRegionsWithCaps(t, client, []string{"Object Storage"}, []string{}) if len(regions) < 1 { t.Fatal("Can't get region with Object Storage capability") } diff --git a/test/integration/object_storage_keys_test.go b/test/integration/object_storage_keys_test.go index 11b6b532f..c27a24842 100644 --- a/test/integration/object_storage_keys_test.go +++ b/test/integration/object_storage_keys_test.go @@ -155,7 +155,7 @@ func TestObjectStorageKeys_Limited_NoAccess(t *testing.T) { func TestObjectStorageKeys_Regional_Limited(t *testing.T) { // t.Skip("skipping region test before GA") client, teardown := createTestClient(t, "fixtures/TestObjectStorageKeys_Regional_Limited") - regions := getRegionsWithCaps(t, client, []string{"Object Storage"}) + regions := getRegionsWithCaps(t, client, []string{"Object Storage"}, []string{}) if len(regions) < 1 { t.Fatal("Can't get region with Object Storage capability") } diff --git a/test/integration/placement_group_test.go b/test/integration/placement_group_test.go index 7507f77ff..12690de78 100644 --- a/test/integration/placement_group_test.go +++ b/test/integration/placement_group_test.go @@ -122,7 +122,7 @@ func createPlacementGroup( t.Helper() createOpts := linodego.PlacementGroupCreateOptions{ Label: "linodego-test-" + getUniqueText(), - Region: getRegionsWithCaps(t, client, []string{"Placement Group"})[0], + Region: getRegionsWithCaps(t, client, []string{"Placement Group"}, []string{})[0], AffinityType: linodego.AffinityTypeAntiAffinityLocal, IsStrict: false, } diff --git a/test/integration/postgres_test.go b/test/integration/postgres_test.go index b7be2ae8d..81eb23dbe 100644 --- a/test/integration/postgres_test.go +++ b/test/integration/postgres_test.go @@ -180,7 +180,7 @@ func createPostgresDatabase(t *testing.T, client *linodego.Client, createOpts := linodego.PostgresCreateOptions{ Label: "go-postgres-testing-def" + randLabel(), - Region: getRegionsWithCaps(t, client, []string{"Managed Databases"})[0], + Region: getRegionsWithCaps(t, client, []string{"Managed Databases"}, []string{})[0], Type: "g6-nanode-1", Engine: "postgresql/14.6", Encrypted: false, diff --git a/test/integration/tags_test.go b/test/integration/tags_test.go index a7a08d501..06dbce742 100644 --- a/test/integration/tags_test.go +++ b/test/integration/tags_test.go @@ -95,7 +95,7 @@ func setupTaggedInstance(t *testing.T, fixturesYaml string) (*Client, *Instance, client, fixtureTeardown := createTestClient(t, fixturesYaml) createOpts := InstanceCreateOptions{ Label: "go-ins-test-tag", - Region: getRegionsWithCaps(t, client, []string{"Linodes"})[0], + Region: getRegionsWithCaps(t, client, []string{"Linodes"}, []string{})[0], Type: "g6-nanode-1", Tags: []string{"go-tag-test"}, } diff --git a/test/integration/vlans_test.go b/test/integration/vlans_test.go index c8f146a13..ede8b11db 100644 --- a/test/integration/vlans_test.go +++ b/test/integration/vlans_test.go @@ -96,7 +96,7 @@ func createVLANInstance(t *testing.T, client *linodego.Client, instanceName, vla opts.Booted = &trueBool opts.Label = instanceName - opts.Region = getRegionsWithCaps(t, client, []string{"Vlans"})[0] + opts.Region = getRegionsWithCaps(t, client, []string{"Vlans"}, []string{})[0] }) if err != nil { return nil, nil, err diff --git a/test/integration/volumes_test.go b/test/integration/volumes_test.go index 605214da7..a9945f5bd 100644 --- a/test/integration/volumes_test.go +++ b/test/integration/volumes_test.go @@ -16,7 +16,7 @@ func TestVolume_Create_smoke(t *testing.T) { createOpts := linodego.VolumeCreateOptions{ Label: "go-vol-test-create", - Region: getRegionsWithCaps(t, client, []string{"Linodes"})[0], + Region: getRegionsWithCaps(t, client, []string{"Linodes"}, []string{})[0], } volume, err := client.CreateVolume(context.Background(), createOpts) if err != nil { @@ -175,7 +175,7 @@ func setupVolume(t *testing.T, fixturesYaml string) (*linodego.Client, *linodego client, fixtureTeardown := createTestClient(t, fixturesYaml) createOpts := linodego.VolumeCreateOptions{ Label: "go-vol-test-def", - Region: getRegionsWithCaps(t, client, []string{"Linodes"})[0], + Region: getRegionsWithCaps(t, client, []string{"Linodes"}, []string{})[0], } volume, err := client.CreateVolume(context.Background(), createOpts) if err != nil { @@ -201,7 +201,7 @@ func createVolume( t.Helper() createOpts := linodego.VolumeCreateOptions{ Label: "go-vol-test" + randLabel(), - Region: getRegionsWithCaps(t, client, []string{"Linodes"})[0], + Region: getRegionsWithCaps(t, client, []string{"Linodes"}, []string{})[0], } for _, mod := range vModifier { diff --git a/test/integration/vpc_subnet_test.go b/test/integration/vpc_subnet_test.go index 03be9be3a..7963e2afe 100644 --- a/test/integration/vpc_subnet_test.go +++ b/test/integration/vpc_subnet_test.go @@ -82,7 +82,7 @@ func createVPCWithSubnet(t *testing.T, client *linodego.Client, vpcModifier ...v t.Helper() createOpts := linodego.VPCCreateOptions{ Label: "go-test-vpc-" + getUniqueText(), - Region: getRegionsWithCaps(t, client, []string{"Linodes", "VPCs"})[0], + Region: getRegionsWithCaps(t, client, []string{"Linodes", "VPCs"}, []string{})[0], Subnets: []VPCSubnetCreateOptions{ { Label: "linodego-vpc-test-" + getUniqueText(), diff --git a/test/integration/vpc_test.go b/test/integration/vpc_test.go index 7ae47872d..14851cac9 100644 --- a/test/integration/vpc_test.go +++ b/test/integration/vpc_test.go @@ -35,7 +35,7 @@ func createVPC(t *testing.T, client *linodego.Client, vpcModifier ...vpcModifier t.Helper() createOpts := linodego.VPCCreateOptions{ Label: "go-test-vpc-" + getUniqueText(), - Region: getRegionsWithCaps(t, client, []string{"VPCs"})[0], + Region: getRegionsWithCaps(t, client, []string{"VPCs"}, []string{})[0], } for _, mod := range vpcModifier { @@ -59,7 +59,7 @@ func createVPC_invalid_label(t *testing.T, client *linodego.Client) error { t.Helper() createOpts := linodego.VPCCreateOptions{ Label: "gotest_vpc_invalid_label" + getUniqueText(), - Region: getRegionsWithCaps(t, client, []string{"VPCs"})[0], + Region: getRegionsWithCaps(t, client, []string{"VPCs"}, []string{})[0], } _, err := client.CreateVPC(context.Background(), createOpts) diff --git a/test/integration/waitfor_test.go b/test/integration/waitfor_test.go index 244b220f6..7981d5d6d 100644 --- a/test/integration/waitfor_test.go +++ b/test/integration/waitfor_test.go @@ -18,7 +18,7 @@ func TestEventPoller_InstancePower(t *testing.T) { } instance, err := client.CreateInstance(context.Background(), linodego.InstanceCreateOptions{ - Region: getRegionsWithCaps(t, client, []string{"Linodes"})[0], + Region: getRegionsWithCaps(t, client, []string{"Linodes"}, []string{})[0], Type: "g6-nanode-1", Image: "linode/ubuntu22.04", RootPass: randPassword(), @@ -102,7 +102,7 @@ func TestWaitForResourceFree(t *testing.T) { // Create a booted instance instance, err := client.CreateInstance(context.Background(), linodego.InstanceCreateOptions{ - Region: getRegionsWithCaps(t, client, []string{"Linodes"})[0], + Region: getRegionsWithCaps(t, client, []string{"Linodes"}, []string{})[0], Type: "g6-nanode-1", Image: "linode/ubuntu22.04", RootPass: randPassword(), @@ -145,7 +145,7 @@ func TestEventPoller_Secondary(t *testing.T) { } instance, err := client.CreateInstance(context.Background(), linodego.InstanceCreateOptions{ - Region: getRegionsWithCaps(t, client, []string{"Linodes"})[0], + Region: getRegionsWithCaps(t, client, []string{"Linodes"}, []string{})[0], Type: "g6-nanode-1", Label: "go-ins-poll-test", Booted: linodego.Pointer(false),