in pkg/providers/instancetype/instancetype.go [116:166]
func (p *DefaultProvider) List(ctx context.Context, nodeClass *v1.EC2NodeClass) ([]*cloudprovider.InstanceType, error) {
p.muInstanceTypesInfo.RLock()
p.muInstanceTypesOfferings.RLock()
defer p.muInstanceTypesInfo.RUnlock()
defer p.muInstanceTypesOfferings.RUnlock()
if len(p.instanceTypesInfo) == 0 {
return nil, fmt.Errorf("no instance types found")
}
if len(p.instanceTypesOfferings) == 0 {
return nil, fmt.Errorf("no instance types offerings found")
}
if len(nodeClass.Status.Subnets) == 0 {
return nil, fmt.Errorf("no subnets found")
}
subnetZones := sets.New(lo.Map(nodeClass.Status.Subnets, func(s v1.Subnet, _ int) string {
return lo.FromPtr(&s.Zone)
})...)
// Compute fully initialized instance types hash key
subnetZonesHash, _ := hashstructure.Hash(subnetZones, hashstructure.FormatV2, &hashstructure.HashOptions{SlicesAsSets: true})
// Compute hash key against node class AMIs (used to force cache rebuild when AMIs change)
amiHash, _ := hashstructure.Hash(nodeClass.Status.AMIs, hashstructure.FormatV2, &hashstructure.HashOptions{SlicesAsSets: true})
key := fmt.Sprintf("%d-%d-%016x-%016x-%016x",
p.instanceTypesSeqNum,
p.instanceTypesOfferingsSeqNum,
amiHash,
subnetZonesHash,
p.instanceTypesResolver.CacheKey(nodeClass),
)
var instanceTypes []*cloudprovider.InstanceType
if item, ok := p.instanceTypesCache.Get(key); ok {
// Ensure what's returned from this function is a shallow-copy of the slice (not a deep-copy of the data itself)
// so that modifications to the ordering of the data don't affect the original
instanceTypes = item.([]*cloudprovider.InstanceType)
} else {
instanceTypes = p.resolveInstanceTypes(ctx, nodeClass, amiHash)
p.instanceTypesCache.SetDefault(key, instanceTypes)
}
// Offerings aren't cached along with the rest of the instance type info because reserved offerings need to have up to
// date capacity information. Rather than incurring a cache miss each time an instance is launched into a reserved
// offering (or terminated), offerings are injected to the cached instance types on each call. Note that on-demand and
// spot offerings are still cached - only reserved offerings are generated each time.
return p.offeringProvider.InjectOfferings(
ctx,
instanceTypes,
nodeClass,
p.allZones,
), nil
}