func()

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
}