github.com/openshift/installer@v1.4.17/pkg/asset/machines/gcp/zones.go (about) 1 package gcp 2 3 import ( 4 "context" 5 "fmt" 6 "sort" 7 "time" 8 9 "github.com/pkg/errors" 10 compute "google.golang.org/api/compute/v1" 11 "google.golang.org/api/option" 12 "k8s.io/apimachinery/pkg/util/sets" 13 14 gcpconfig "github.com/openshift/installer/pkg/asset/installconfig/gcp" 15 ) 16 17 // AvailabilityZones retrieves a list of availability zones for the given project and region. 18 func AvailabilityZones(project, region string) ([]string, error) { 19 ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) 20 defer cancel() 21 22 ssn, err := gcpconfig.GetSession(ctx) 23 if err != nil { 24 return nil, errors.Wrap(err, "failed to get session") 25 } 26 27 svc, err := compute.NewService(ctx, option.WithCredentials(ssn.Credentials)) 28 if err != nil { 29 return nil, errors.Wrap(err, "failed to create compute service") 30 } 31 32 regionURL := fmt.Sprintf("https://www.googleapis.com/compute/v1/projects/%s/regions/%s", 33 project, region) 34 filter := fmt.Sprintf("(region eq %s) (status eq UP)", regionURL) 35 zones, err := gcpconfig.GetZones(ctx, svc, project, filter) 36 if err != nil { 37 return nil, errors.New("no zone was found") 38 } 39 40 zoneNames := make([]string, 0, len(zones)) 41 for _, z := range zones { 42 zoneNames = append(zoneNames, z.Name) 43 } 44 45 sort.Strings(zoneNames) 46 return zoneNames, nil 47 } 48 49 // ZonesForInstanceType retrieves a filtered list of availability zones where 50 // the particular instance type is available. This is mainly necessary for 51 // arm64, since the instance t2a-standard-* is not available in all 52 // availability zones. 53 func ZonesForInstanceType(project, region, instanceType string) ([]string, error) { 54 ssn, err := gcpconfig.GetSession(context.Background()) 55 if err != nil { 56 return nil, fmt.Errorf("failed to get session: %w", err) 57 } 58 59 svc, err := compute.NewService(context.Background(), option.WithCredentials(ssn.Credentials)) 60 if err != nil { 61 return nil, fmt.Errorf("failed to create compute service: %w", err) 62 } 63 64 ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) 65 defer cancel() 66 67 pZones, err := gcpconfig.GetZones(ctx, svc, project, fmt.Sprintf("(region eq .*%s) (status eq UP)", region)) 68 if err != nil { 69 return nil, fmt.Errorf("failed to get zones for project: %w", err) 70 } 71 pZoneNames := sets.New[string]() 72 for _, z := range pZones { 73 pZoneNames.Insert(z.Name) 74 } 75 76 machines, err := gcpconfig.GetMachineTypeList(ctx, svc, project, region, instanceType, "items/*/machineTypes(zone),nextPageToken") 77 if err != nil { 78 return nil, fmt.Errorf("failed to get zones for instance type: %w", err) 79 } 80 // Custom machine types do not show up in the list. Let's fallback to the project zones 81 if len(machines) == 0 { 82 return sets.List(pZoneNames), nil 83 } 84 85 zones := sets.New[string]() 86 for _, machine := range machines { 87 zones.Insert(machine.Zone) 88 } 89 90 // Not all instance zones might be available in the project 91 return sets.List(zones.Intersection(pZoneNames)), nil 92 }