github.com/darmach/terratest@v0.34.8-0.20210517103231-80931f95e3ff/modules/aws/region.go (about) 1 package aws 2 3 import ( 4 "os" 5 6 "github.com/aws/aws-sdk-go/aws" 7 "github.com/aws/aws-sdk-go/service/ec2" 8 "github.com/gruntwork-io/terratest/modules/collections" 9 "github.com/gruntwork-io/terratest/modules/logger" 10 "github.com/gruntwork-io/terratest/modules/random" 11 "github.com/gruntwork-io/terratest/modules/testing" 12 ) 13 14 // You can set this environment variable to force Terratest to use a specific region rather than a random one. This is 15 // convenient when iterating locally. 16 const regionOverrideEnvVarName = "TERRATEST_REGION" 17 18 // AWS API calls typically require an AWS region. We typically require the user to set one explicitly, but in some 19 // cases, this doesn't make sense (e.g., for fetching the lsit of regions in an account), so for those cases, we use 20 // this region as a default. 21 const defaultRegion = "us-east-1" 22 23 // Reference for launch dates: https://aws.amazon.com/about-aws/global-infrastructure/ 24 var stableRegions = []string{ 25 "us-east-1", // Launched 2006 26 "us-east-2", // Launched 2016 27 "us-west-1", // Launched 2009 28 "us-west-2", // Launched 2011 29 "ca-central-1", // Launched 2016 30 "sa-east-1", // Launched 2011 31 "eu-west-1", // Launched 2007 32 "eu-west-2", // Launched 2016 33 "eu-west-3", // Launched 2017 34 "eu-central-1", // Launched 2014 35 "ap-southeast-1", // Launched 2010 36 "ap-southeast-2", // Launched 2012 37 "ap-northeast-1", // Launched 2011 38 "ap-northeast-2", // Launched 2016 39 "ap-south-1", // Launched 2016 40 "eu-north-1", // Launched 2018 41 } 42 43 // GetRandomStableRegion gets a randomly chosen AWS region that is considered stable. Like GetRandomRegion, you can 44 // further restrict the stable region list using approvedRegions and forbiddenRegions. We consider stable regions to be 45 // those that have been around for at least 1 year. 46 // Note that regions in the approvedRegions list that are not considered stable are ignored. 47 func GetRandomStableRegion(t testing.TestingT, approvedRegions []string, forbiddenRegions []string) string { 48 regionsToPickFrom := stableRegions 49 if len(approvedRegions) > 0 { 50 regionsToPickFrom = collections.ListIntersection(regionsToPickFrom, approvedRegions) 51 } 52 if len(forbiddenRegions) > 0 { 53 regionsToPickFrom = collections.ListSubtract(regionsToPickFrom, forbiddenRegions) 54 } 55 return GetRandomRegion(t, regionsToPickFrom, nil) 56 } 57 58 // GetRandomRegion gets a randomly chosen AWS region. If approvedRegions is not empty, this will be a region from the approvedRegions 59 // list; otherwise, this method will fetch the latest list of regions from the AWS APIs and pick one of those. If 60 // forbiddenRegions is not empty, this method will make sure the returned region is not in the forbiddenRegions list. 61 func GetRandomRegion(t testing.TestingT, approvedRegions []string, forbiddenRegions []string) string { 62 region, err := GetRandomRegionE(t, approvedRegions, forbiddenRegions) 63 if err != nil { 64 t.Fatal(err) 65 } 66 return region 67 } 68 69 // GetRandomRegionE gets a randomly chosen AWS region. If approvedRegions is not empty, this will be a region from the approvedRegions 70 // list; otherwise, this method will fetch the latest list of regions from the AWS APIs and pick one of those. If 71 // forbiddenRegions is not empty, this method will make sure the returned region is not in the forbiddenRegions list. 72 func GetRandomRegionE(t testing.TestingT, approvedRegions []string, forbiddenRegions []string) (string, error) { 73 regionFromEnvVar := os.Getenv(regionOverrideEnvVarName) 74 if regionFromEnvVar != "" { 75 logger.Logf(t, "Using AWS region %s from environment variable %s", regionFromEnvVar, regionOverrideEnvVarName) 76 return regionFromEnvVar, nil 77 } 78 79 regionsToPickFrom := approvedRegions 80 81 if len(regionsToPickFrom) == 0 { 82 allRegions, err := GetAllAwsRegionsE(t) 83 if err != nil { 84 return "", err 85 } 86 regionsToPickFrom = allRegions 87 } 88 89 regionsToPickFrom = collections.ListSubtract(regionsToPickFrom, forbiddenRegions) 90 region := random.RandomString(regionsToPickFrom) 91 92 logger.Logf(t, "Using region %s", region) 93 return region, nil 94 } 95 96 // GetAllAwsRegions gets the list of AWS regions available in this account. 97 func GetAllAwsRegions(t testing.TestingT) []string { 98 out, err := GetAllAwsRegionsE(t) 99 if err != nil { 100 t.Fatal(err) 101 } 102 return out 103 } 104 105 // GetAllAwsRegionsE gets the list of AWS regions available in this account. 106 func GetAllAwsRegionsE(t testing.TestingT) ([]string, error) { 107 logger.Log(t, "Looking up all AWS regions available in this account") 108 109 ec2Client, err := NewEc2ClientE(t, defaultRegion) 110 if err != nil { 111 return nil, err 112 } 113 114 out, err := ec2Client.DescribeRegions(&ec2.DescribeRegionsInput{}) 115 if err != nil { 116 return nil, err 117 } 118 119 regions := []string{} 120 for _, region := range out.Regions { 121 regions = append(regions, aws.StringValue(region.RegionName)) 122 } 123 124 return regions, nil 125 } 126 127 // GetAvailabilityZones gets the Availability Zones for a given AWS region. Note that for certain regions (e.g. us-east-1), different AWS 128 // accounts have access to different availability zones. 129 func GetAvailabilityZones(t testing.TestingT, region string) []string { 130 out, err := GetAvailabilityZonesE(t, region) 131 if err != nil { 132 t.Fatal(err) 133 } 134 return out 135 } 136 137 // GetAvailabilityZonesE gets the Availability Zones for a given AWS region. Note that for certain regions (e.g. us-east-1), different AWS 138 // accounts have access to different availability zones. 139 func GetAvailabilityZonesE(t testing.TestingT, region string) ([]string, error) { 140 logger.Logf(t, "Looking up all availability zones available in this account for region %s", region) 141 142 ec2Client, err := NewEc2ClientE(t, region) 143 if err != nil { 144 return nil, err 145 } 146 147 resp, err := ec2Client.DescribeAvailabilityZones(&ec2.DescribeAvailabilityZonesInput{}) 148 if err != nil { 149 return nil, err 150 } 151 152 var out []string 153 for _, availabilityZone := range resp.AvailabilityZones { 154 out = append(out, aws.StringValue(availabilityZone.ZoneName)) 155 } 156 157 return out, nil 158 }