in pkg/ec2pricing/ec2pricing.go [82:142]
func (p *EC2Pricing) GetSpotInstanceTypeNDayAvgCost(instanceType string, availabilityZones []string, days int) (float64, error) {
endTime := time.Now().UTC()
startTime := endTime.Add(time.Hour * time.Duration(24*-1*days))
spotPriceHistInput := ec2.DescribeSpotPriceHistoryInput{
ProductDescriptions: []*string{aws.String(productDescription)},
StartTime: &startTime,
EndTime: &endTime,
InstanceTypes: []*string{&instanceType},
}
zoneToPriceEntries := make(map[string][]spotPricingEntry)
if _, ok := p.spotCache[instanceType]; !ok {
var processingErr error
errAPI := p.EC2Client.DescribeSpotPriceHistoryPages(&spotPriceHistInput, func(dspho *ec2.DescribeSpotPriceHistoryOutput, b bool) bool {
for _, history := range dspho.SpotPriceHistory {
var spotPrice float64
spotPrice, errParse := strconv.ParseFloat(*history.SpotPrice, 64)
if errParse != nil {
processingErr = multierr.Append(processingErr, errParse)
continue
}
zone := *history.AvailabilityZone
zoneToPriceEntries[zone] = append(zoneToPriceEntries[zone], spotPricingEntry{
Timestamp: *history.Timestamp,
SpotPrice: spotPrice,
})
}
return true
})
if errAPI != nil {
return float64(-1), errAPI
}
if processingErr != nil {
return float64(-1), processingErr
}
} else {
for zone, priceEntries := range p.spotCache[instanceType] {
for _, entry := range priceEntries {
zoneToPriceEntries[zone] = append(zoneToPriceEntries[zone], spotPricingEntry{
Timestamp: entry.Timestamp,
SpotPrice: entry.SpotPrice,
})
}
}
}
aggregateZonePriceSum := float64(0)
numOfZones := 0
for zone, priceEntries := range zoneToPriceEntries {
if len(availabilityZones) != 0 {
if !strings.Contains(strings.Join(availabilityZones, " "), zone) {
continue
}
}
numOfZones++
aggregateZonePriceSum += p.calculateSpotAggregate(priceEntries)
}
return aggregateZonePriceSum / float64(numOfZones), nil
}