in pkg/selector/selector.go [262:381]
func (s Selector) prepareFilter(ctx context.Context, filters Filters, instanceTypeInfo instancetypes.Details, availabilityZones []string, locationInstanceOfferings map[ec2types.InstanceType]string) (*instancetypes.Details, error) {
instanceTypeName := instanceTypeInfo.InstanceType
isFpga := instanceTypeInfo.FpgaInfo != nil
var instanceTypeHourlyPriceForFilter float64 // Price used to filter based on usage class
var instanceTypeHourlyPriceOnDemand, instanceTypeHourlyPriceSpot *float64
// If prices are fetched, populate the fields irrespective of the price filters
if s.EC2Pricing.OnDemandCacheCount() > 0 {
price, err := s.EC2Pricing.GetOnDemandInstanceTypeCost(ctx, instanceTypeName)
if err != nil {
s.Logger.Printf("Could not retrieve instantaneous hourly on-demand price for instance type %s - %s\n", instanceTypeName, err)
} else {
instanceTypeHourlyPriceOnDemand = &price
instanceTypeInfo.OndemandPricePerHour = instanceTypeHourlyPriceOnDemand
}
}
isSpotUsageClass := false
for _, it := range instanceTypeInfo.SupportedUsageClasses {
if it == ec2types.UsageClassTypeSpot {
isSpotUsageClass = true
}
}
if s.EC2Pricing.SpotCacheCount() > 0 && isSpotUsageClass {
price, err := s.EC2Pricing.GetSpotInstanceTypeNDayAvgCost(ctx, instanceTypeName, availabilityZones, 30)
if err != nil {
s.Logger.Printf("Could not retrieve 30 day avg hourly spot price for instance type %s\n", instanceTypeName)
} else {
instanceTypeHourlyPriceSpot = &price
instanceTypeInfo.SpotPrice = instanceTypeHourlyPriceSpot
}
}
if filters.PricePerHour != nil {
// If price filter is present, prices should be already fetched
// If prices are not fetched, filter should fail and the corresponding error is already printed
if filters.UsageClass != nil && *filters.UsageClass == ec2types.UsageClassTypeSpot && instanceTypeHourlyPriceSpot != nil {
instanceTypeHourlyPriceForFilter = *instanceTypeHourlyPriceSpot
} else if instanceTypeHourlyPriceOnDemand != nil {
instanceTypeHourlyPriceForFilter = *instanceTypeHourlyPriceOnDemand
}
}
eneaSupport := string(instanceTypeInfo.NetworkInfo.EnaSupport)
ebsOptimizedSupport := string(instanceTypeInfo.EbsInfo.EbsOptimizedSupport)
// If an empty slice is passed, treat the filter as nil
filterInstanceTypes := filters.InstanceTypes
if filterInstanceTypes != nil && len(*filterInstanceTypes) == 0 {
filterInstanceTypes = nil
}
var cpuManufacturerFilter *string
if filters.CPUManufacturer != nil {
cpuManufacturerFilter = aws.String(string(*filters.CPUManufacturer))
}
// filterToInstanceSpecMappingPairs is a map of filter name [key] to filter pair [value].
// A filter pair includes user input filter value and instance spec value retrieved from DescribeInstanceTypes
filterToInstanceSpecMappingPairs := map[string]filterPair{
cpuArchitecture: {filters.CPUArchitecture, instanceTypeInfo.ProcessorInfo.SupportedArchitectures},
cpuManufacturer: {cpuManufacturerFilter, instanceTypeInfo.ProcessorInfo.Manufacturer},
usageClass: {filters.UsageClass, instanceTypeInfo.SupportedUsageClasses},
rootDeviceType: {filters.RootDeviceType, instanceTypeInfo.SupportedRootDeviceTypes},
hibernationSupported: {filters.HibernationSupported, instanceTypeInfo.HibernationSupported},
vcpusRange: {filters.VCpusRange, instanceTypeInfo.VCpuInfo.DefaultVCpus},
memoryRange: {filters.MemoryRange, instanceTypeInfo.MemoryInfo.SizeInMiB},
gpuMemoryRange: {filters.GpuMemoryRange, getTotalGpuMemory(instanceTypeInfo.GpuInfo)},
gpusRange: {filters.GpusRange, getTotalGpusCount(instanceTypeInfo.GpuInfo)},
inferenceAcceleratorsRange: {filters.InferenceAcceleratorsRange, getTotalAcceleratorsCount(instanceTypeInfo.InferenceAcceleratorInfo)},
placementGroupStrategy: {filters.PlacementGroupStrategy, instanceTypeInfo.PlacementGroupInfo.SupportedStrategies},
hypervisor: {filters.Hypervisor, instanceTypeInfo.Hypervisor},
baremetal: {filters.BareMetal, instanceTypeInfo.BareMetal},
burstable: {filters.Burstable, instanceTypeInfo.BurstablePerformanceSupported},
fpga: {filters.Fpga, &isFpga},
enaSupport: {filters.EnaSupport, supportSyntaxToBool(&eneaSupport)},
efaSupport: {filters.EfaSupport, instanceTypeInfo.NetworkInfo.EfaSupported},
vcpusToMemoryRatio: {filters.VCpusToMemoryRatio, calculateVCpusToMemoryRatio(instanceTypeInfo.VCpuInfo.DefaultVCpus, instanceTypeInfo.MemoryInfo.SizeInMiB)},
currentGeneration: {filters.CurrentGeneration, instanceTypeInfo.CurrentGeneration},
networkInterfaces: {filters.NetworkInterfaces, instanceTypeInfo.NetworkInfo.MaximumNetworkInterfaces},
networkPerformance: {filters.NetworkPerformance, getNetworkPerformance(instanceTypeInfo.NetworkInfo.NetworkPerformance)},
networkEncryption: {filters.NetworkEncryption, instanceTypeInfo.NetworkInfo.EncryptionInTransitSupported},
ipv6: {filters.IPv6, instanceTypeInfo.NetworkInfo.Ipv6Supported},
instanceTypes: {filterInstanceTypes, aws.String(string(instanceTypeInfo.InstanceType))},
virtualizationType: {filters.VirtualizationType, instanceTypeInfo.SupportedVirtualizationTypes},
pricePerHour: {filters.PricePerHour, &instanceTypeHourlyPriceForFilter},
instanceStorageRange: {filters.InstanceStorageRange, getInstanceStorage(instanceTypeInfo.InstanceStorageInfo)},
diskType: {filters.DiskType, getDiskType(instanceTypeInfo.InstanceStorageInfo)},
nvme: {filters.NVME, getNVMESupport(instanceTypeInfo.InstanceStorageInfo, instanceTypeInfo.EbsInfo)},
ebsOptimized: {filters.EBSOptimized, supportSyntaxToBool(&ebsOptimizedSupport)},
diskEncryption: {filters.DiskEncryption, getDiskEncryptionSupport(instanceTypeInfo.InstanceStorageInfo, instanceTypeInfo.EbsInfo)},
ebsOptimizedBaselineBandwidth: {filters.EBSOptimizedBaselineBandwidth, getEBSOptimizedBaselineBandwidth(instanceTypeInfo.EbsInfo)},
ebsOptimizedBaselineThroughput: {filters.EBSOptimizedBaselineThroughput, getEBSOptimizedBaselineThroughput(instanceTypeInfo.EbsInfo)},
ebsOptimizedBaselineIOPS: {filters.EBSOptimizedBaselineIOPS, getEBSOptimizedBaselineIOPS(instanceTypeInfo.EbsInfo)},
freeTier: {filters.FreeTier, instanceTypeInfo.FreeTierEligible},
autoRecovery: {filters.AutoRecovery, instanceTypeInfo.AutoRecoverySupported},
gpuManufacturer: {filters.GPUManufacturer, getGPUManufacturers(instanceTypeInfo.GpuInfo)},
gpuModel: {filters.GPUModel, getGPUModels(instanceTypeInfo.GpuInfo)},
inferenceAcceleratorManufacturer: {filters.InferenceAcceleratorManufacturer, getInferenceAcceleratorManufacturers(instanceTypeInfo.InferenceAcceleratorInfo)},
inferenceAcceleratorModel: {filters.InferenceAcceleratorModel, getInferenceAcceleratorModels(instanceTypeInfo.InferenceAcceleratorInfo)},
dedicatedHosts: {filters.DedicatedHosts, instanceTypeInfo.DedicatedHostsSupported},
generation: {filters.Generation, getInstanceTypeGeneration(string(instanceTypeInfo.InstanceType))},
}
if isInDenyList(filters.DenyList, instanceTypeName) || !isInAllowList(filters.AllowList, instanceTypeName) {
return nil, nil
}
if !isSupportedInLocation(locationInstanceOfferings, instanceTypeName) {
return nil, nil
}
var isInstanceSupported bool
isInstanceSupported, err := s.executeFilters(ctx, filterToInstanceSpecMappingPairs, instanceTypeName)
if err != nil {
return nil, err
}
if !isInstanceSupported {
return nil, nil
}
return &instanceTypeInfo, nil
}