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  }