github.com/openshift/installer@v1.4.17/pkg/asset/installconfig/aws/availabilityzones.go (about) 1 package aws 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/aws/aws-sdk-go/aws" 8 "github.com/aws/aws-sdk-go/aws/session" 9 "github.com/aws/aws-sdk-go/service/ec2" 10 11 typesaws "github.com/openshift/installer/pkg/types/aws" 12 ) 13 14 // Zones stores the map of Zone attributes indexed by Zone Name. 15 type Zones map[string]*Zone 16 17 // Zone stores the Availability or Local Zone attributes used to set machine attributes, and to 18 // feed VPC resources as a source for for terraform variables. 19 type Zone struct { 20 21 // Name is the availability, local or wavelength zone name. 22 Name string 23 24 // ZoneType is the type of subnet's availability zone. 25 // The valid values are availability-zone and local-zone. 26 Type string 27 28 // ZoneGroupName is the AWS zone group name. 29 // For Availability Zones, this parameter has the same value as the Region name. 30 // 31 // For Local Zones, the name of the associated group, for example us-west-2-lax-1. 32 GroupName string 33 34 // ParentZoneName is the name of the zone that handles some of the Local Zone 35 // control plane operations, such as API calls. 36 ParentZoneName string 37 38 // PreferredInstanceType is the offered instance type on the subnet's zone. 39 // It's used for the edge pools which does not offer the same type across different zone groups. 40 PreferredInstanceType string 41 } 42 43 // describeAvailabilityZones retrieves a list of all zones for the given region. 44 func describeAvailabilityZones(ctx context.Context, session *session.Session, region string, zones []string) ([]*ec2.AvailabilityZone, error) { 45 client := ec2.New(session, aws.NewConfig().WithRegion(region)) 46 input := &ec2.DescribeAvailabilityZonesInput{ 47 AllAvailabilityZones: aws.Bool(true), 48 Filters: []*ec2.Filter{ 49 { 50 Name: aws.String("region-name"), 51 Values: []*string{aws.String(region)}, 52 }, 53 { 54 Name: aws.String("state"), 55 Values: []*string{aws.String("available")}, 56 }, 57 }, 58 } 59 if len(zones) > 0 { 60 for _, zone := range zones { 61 input.ZoneNames = append(input.ZoneNames, aws.String(zone)) 62 } 63 } 64 resp, err := client.DescribeAvailabilityZonesWithContext(ctx, input) 65 if err != nil { 66 return nil, fmt.Errorf("fetching zones: %w", err) 67 } 68 69 return resp.AvailabilityZones, nil 70 } 71 72 // filterZonesByType retrieves a list of zones by a given ZoneType attribute within the region. 73 // ZoneType can be availability-zone, local-zone or wavelength-zone. 74 func filterZonesByType(ctx context.Context, session *session.Session, region, zoneType string) ([]string, error) { 75 azs, err := describeAvailabilityZones(ctx, session, region, []string{}) 76 if err != nil { 77 return nil, fmt.Errorf("fetching %s: %w", zoneType, err) 78 } 79 zones := []string{} 80 for _, zone := range azs { 81 if aws.StringValue(zone.ZoneType) == zoneType { 82 zones = append(zones, aws.StringValue(zone.ZoneName)) 83 } 84 } 85 86 return zones, nil 87 } 88 89 // availabilityZones retrieves a list of zones type 'availability-zone' in the region. 90 func availabilityZones(ctx context.Context, session *session.Session, region string) ([]string, error) { 91 zones, err := filterZonesByType(ctx, session, region, typesaws.AvailabilityZoneType) 92 if err != nil { 93 return nil, err 94 } 95 if len(zones) == 0 { 96 return nil, fmt.Errorf("no zones with type availability-zone in %s", region) 97 } 98 return zones, nil 99 } 100 101 // edgeZones retrieves a list of zones type 'local-zone' and 'wavelength-zone' in the region. 102 func edgeZones(ctx context.Context, session *session.Session, region string) ([]string, error) { 103 localZones, err := filterZonesByType(ctx, session, region, typesaws.LocalZoneType) 104 if err != nil { 105 return nil, fmt.Errorf("unable to retrieve Local Zone names: %w", err) 106 } 107 108 wavelengthZones, err := filterZonesByType(ctx, session, region, typesaws.WavelengthZoneType) 109 if err != nil { 110 return nil, fmt.Errorf("unable to retrieve Wavelength Zone names: %w", err) 111 } 112 edgeZones := make([]string, 0, len(localZones)+len(wavelengthZones)) 113 edgeZones = append(edgeZones, localZones...) 114 edgeZones = append(edgeZones, wavelengthZones...) 115 116 if len(edgeZones) == 0 { 117 return nil, fmt.Errorf("unable to find zone types with local-zone or wavelength-zone in the region %s", region) 118 } 119 120 return edgeZones, nil 121 } 122 123 // describeFilteredZones retrieves a list of all zones for the given region. 124 func describeFilteredZones(ctx context.Context, session *session.Session, region string, zones []string) ([]*ec2.AvailabilityZone, error) { 125 azs, err := describeAvailabilityZones(ctx, session, region, zones) 126 if err != nil { 127 return nil, fmt.Errorf("fetching %s: %w", zones, err) 128 } 129 130 return azs, nil 131 }