github.com/openshift/installer@v1.4.17/pkg/asset/quota/aws/aws.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "regexp" 6 "sort" 7 "strings" 8 9 "github.com/sirupsen/logrus" 10 "k8s.io/apimachinery/pkg/util/sets" 11 12 machineapi "github.com/openshift/api/machine/v1beta1" 13 "github.com/openshift/installer/pkg/quota" 14 "github.com/openshift/installer/pkg/types" 15 ) 16 17 // Constraints returns a list of quota constraints based on the InstallConfig. 18 // These constraints can be used to check if there is enough quota for creating a cluster 19 // for the isntall config. 20 func Constraints(config *types.InstallConfig, controlPlanes []machineapi.Machine, computes []machineapi.MachineSet, instanceTypes map[string]InstanceTypeInfo) []quota.Constraint { 21 ctrplConfigs := make([]*machineapi.AWSMachineProviderConfig, len(controlPlanes)) 22 for i, m := range controlPlanes { 23 ctrplConfigs[i] = m.Spec.ProviderSpec.Value.Object.(*machineapi.AWSMachineProviderConfig) 24 } 25 computeReplicas := make([]int64, len(computes)) 26 computeConfigs := make([]*machineapi.AWSMachineProviderConfig, len(computes)) 27 for i, w := range computes { 28 computeReplicas[i] = int64(*w.Spec.Replicas) 29 computeConfigs[i] = w.Spec.Template.Spec.ProviderSpec.Value.Object.(*machineapi.AWSMachineProviderConfig) 30 } 31 32 var ret []quota.Constraint 33 for _, gen := range []constraintGenerator{ 34 network(config, append(ctrplConfigs, computeConfigs...)), 35 controlPlane(config, ctrplConfigs, instanceTypes), 36 compute(config, computeReplicas, computeConfigs, instanceTypes), 37 others, 38 } { 39 ret = append(ret, gen()...) 40 } 41 return aggregate(ret) 42 } 43 44 func aggregate(quotas []quota.Constraint) []quota.Constraint { 45 sort.SliceStable(quotas, func(i, j int) bool { 46 return quotas[i].Name < quotas[j].Name 47 }) 48 49 i := 0 50 for j := 1; j < len(quotas); j++ { 51 if quotas[i].Name == quotas[j].Name && quotas[i].Region == quotas[j].Region { 52 quotas[i].Count += quotas[j].Count 53 } else { 54 i++ 55 if i != j { 56 quotas[i] = quotas[j] 57 } 58 } 59 } 60 return quotas[:i+1] 61 } 62 63 // constraintGenerator generates a list of constraints. 64 type constraintGenerator func() []quota.Constraint 65 66 func network(config *types.InstallConfig, machines []*machineapi.AWSMachineProviderConfig) func() []quota.Constraint { 67 return func() []quota.Constraint { 68 zones := sets.NewString() 69 for _, m := range machines { 70 zones.Insert(m.Placement.AvailabilityZone) 71 } 72 73 var ret []quota.Constraint 74 ret = append(ret, quota.Constraint{ 75 Name: "vpc/L-E79EC296", // 2 sg 76 Region: config.Platform.AWS.Region, 77 Count: 2, 78 }) 79 if len(config.Platform.AWS.Subnets) == 0 { 80 ret = append(ret, []quota.Constraint{{ 81 Name: "vpc/L-F678F1CE", // 1 vpc 82 Region: config.Platform.AWS.Region, 83 Count: 1, 84 }, { 85 Name: "vpc/L-A4707A72", // 1 ig 86 Region: config.Platform.AWS.Region, 87 Count: 1, 88 }, { 89 Name: "vpc/L-FE5A380F", // 1 nat gw per AZ 90 Region: config.Platform.AWS.Region, 91 Count: 1, 92 }}...) 93 94 ret = append(ret, quota.Constraint{ 95 Name: "ec2/L-0263D0A3", // 1 eip per AZ 96 Region: config.Platform.AWS.Region, 97 Count: int64(zones.Len()), 98 }) 99 } 100 101 return ret 102 } 103 } 104 105 func controlPlane(config *types.InstallConfig, machines []*machineapi.AWSMachineProviderConfig, instanceTypes map[string]InstanceTypeInfo) func() []quota.Constraint { 106 return func() []quota.Constraint { 107 var ret []quota.Constraint 108 for _, m := range machines { 109 q := machineTypeToQuota(m.InstanceType, instanceTypes) 110 q.Region = config.Platform.AWS.Region 111 ret = append(ret, q) 112 } 113 return ret 114 } 115 } 116 117 func compute(config *types.InstallConfig, replicas []int64, machines []*machineapi.AWSMachineProviderConfig, instanceTypes map[string]InstanceTypeInfo) func() []quota.Constraint { 118 return func() []quota.Constraint { 119 var ret []quota.Constraint 120 for idx, m := range machines { 121 q := machineTypeToQuota(m.InstanceType, instanceTypes) 122 q.Count = q.Count * replicas[idx] 123 q.Region = config.Platform.AWS.Region 124 ret = append(ret, q) 125 } 126 return ret 127 } 128 } 129 130 func others() []quota.Constraint { 131 return []quota.Constraint{} 132 } 133 134 func machineTypeToQuota(t string, instanceTypes map[string]InstanceTypeInfo) quota.Constraint { 135 info, ok := instanceTypes[t] 136 warnMessage := fmt.Sprintf("The instance class is unknown for the instance type %q. The vCPU quota check will be skipped.", t) 137 if !ok { 138 logrus.Warnf(warnMessage) 139 return quota.Constraint{Name: "ec2/L-7295265B", Count: 0} 140 } 141 r := regexp.MustCompile(`^([A-Za-z]+)[0-9]`) 142 match := r.FindStringSubmatch(strings.ToLower(t)) 143 if match == nil { 144 logrus.Warnf(warnMessage) 145 return quota.Constraint{Name: "ec2/L-7295265B", Count: 0} 146 } 147 switch match[1] { 148 case "a", "c", "d", "h", "i", "is", "im", "m", "r", "t", "z": 149 return quota.Constraint{Name: "ec2/L-1216C47A", Count: info.vCPU} 150 case "g", "vt": 151 return quota.Constraint{Name: "ec2/L-DB2E81BA", Count: info.vCPU} 152 case "x": 153 return quota.Constraint{Name: "ec2/L-7295265B", Count: info.vCPU} 154 default: 155 logrus.Warnf(warnMessage) 156 return quota.Constraint{Name: "ec2/L-7295265B", Count: 0} 157 } 158 }