@@ -45,6 +45,7 @@ type pricingProvider struct {
4545 mu sync.RWMutex
4646 onUpdateFuncs []func ()
4747 onDemandPrices map [ec2types.InstanceType ]float64
48+ autoManagementPrices map [ec2types.InstanceType ]float64
4849 spotPrices map [ec2types.InstanceType ]zonalPricing
4950 fargateVCPUPricePerHour float64
5051 fargateGBPricePerHour float64
@@ -55,13 +56,23 @@ func (p *pricingProvider) OnUpdate(onUpdate func()) {
5556}
5657
5758func (p * pricingProvider ) NodePrice (n * model.Node ) (float64 , bool ) {
59+ autoManagementPrice := 0.0
60+ if n .IsAuto () {
61+ if price , ok := p .AutoManagementPrice (n .InstanceType ()); ok {
62+ autoManagementPrice = price
63+ } else {
64+ // don't return a price until we've looked up the management price
65+ return 0.0 , false
66+ }
67+ }
68+
5869 if n .IsOnDemand () {
5970 if price , ok := p .OnDemandPrice (n .InstanceType ()); ok {
60- return price , true
71+ return autoManagementPrice + price , true
6172 }
6273 } else if n .IsSpot () {
6374 if price , ok := p .SpotPrice (n .InstanceType (), n .Zone ()); ok {
64- return price , true
75+ return autoManagementPrice + price , true
6576 }
6677 } else if n .IsFargate () && len (n .Pods ()) == 1 {
6778 cpu , mem , ok := n .Pods ()[0 ].FargateCapacityProvisioned ()
@@ -189,6 +200,18 @@ func (p *pricingProvider) OnDemandPrice(instanceType ec2types.InstanceType) (flo
189200 return price , true
190201}
191202
203+ // AutoManagementPrice returns the EKS Auto Mode management price for the given instance type.
204+ func (p * pricingProvider ) AutoManagementPrice (instanceType ec2types.InstanceType ) (float64 , bool ) {
205+ p .mu .RLock ()
206+ defer p .mu .RUnlock ()
207+ price , ok := p .autoManagementPrices [instanceType ]
208+ if ! ok {
209+ return 0.0 , false
210+ }
211+ return price , true
212+ }
213+
214+ // FargatePrice returns the last known Fargate price for the given CPU/memory.
192215func (p * pricingProvider ) FargatePrice (cpu , memory float64 ) (float64 , bool ) {
193216 p .mu .RLock ()
194217 defer p .mu .RUnlock ()
@@ -237,6 +260,14 @@ func (p *pricingProvider) updatePricing(ctx context.Context) {
237260 log .Printf ("updating fargate pricing, %s" , err )
238261 }
239262 }()
263+
264+ wg .Add (1 )
265+ go func () {
266+ defer wg .Done ()
267+ if err := p .updateAutoManagementPricing (ctx ); err != nil {
268+ log .Printf ("updating auto management pricing, %s" , err )
269+ }
270+ }()
240271 wg .Wait ()
241272
242273 // notify anyone that cares
@@ -245,6 +276,47 @@ func (p *pricingProvider) updatePricing(ctx context.Context) {
245276 }
246277}
247278
279+ func (p * pricingProvider ) updateAutoManagementPricing (ctx context.Context ) error {
280+ if p .pricingClient == nil {
281+ return errors .New ("pricing client not initialized" )
282+ }
283+ prices := map [ec2types.InstanceType ]float64 {}
284+ filters := []pricingtypes.Filter {
285+ {
286+ Type : pricingtypes .FilterTypeTermMatch ,
287+ Field : aws .String ("operation" ),
288+ Value : aws .String ("EKSAutoUsage" ),
289+ },
290+ {
291+ Type : pricingtypes .FilterTypeTermMatch ,
292+ Field : aws .String ("regionCode" ),
293+ Value : aws .String ("us-west-2" ),
294+ },
295+ }
296+
297+ paginator := pricing .NewGetProductsPaginator (p .pricingClient , & pricing.GetProductsInput {
298+ Filters : filters ,
299+ ServiceCode : aws .String ("AmazonEKS" ),
300+ MaxResults : aws .Int32 (100 ),
301+ })
302+
303+ for paginator .HasMorePages () {
304+ output , err := paginator .NextPage (ctx )
305+ if err != nil {
306+ return err
307+ }
308+ p .processInstancePricingPage (output , prices )
309+ }
310+ if len (prices ) == 0 {
311+ log .Printf ("No Auto Mode managment prices found" )
312+ }
313+
314+ p .mu .Lock ()
315+ defer p .mu .Unlock ()
316+ p .autoManagementPrices = prices
317+ return nil
318+ }
319+
248320func (p * pricingProvider ) updateOnDemandPricing (ctx context.Context ) error {
249321 if p .pricingClient == nil {
250322 return errors .New ("pricing client not initialized" )
@@ -347,14 +419,15 @@ func (p *pricingProvider) fetchOnDemandPricing(ctx context.Context, additionalFi
347419 paginator := pricing .NewGetProductsPaginator (p .pricingClient , & pricing.GetProductsInput {
348420 Filters : filters ,
349421 ServiceCode : aws .String ("AmazonEC2" ),
422+ MaxResults : aws .Int32 (100 ),
350423 })
351424
352425 for paginator .HasMorePages () {
353426 output , err := paginator .NextPage (ctx )
354427 if err != nil {
355428 return nil , err
356429 }
357- p .processOnDemandPage (output , prices )
430+ p .processInstancePricingPage (output , prices )
358431 }
359432
360433 return prices , nil
@@ -363,7 +436,7 @@ func (p *pricingProvider) fetchOnDemandPricing(ctx context.Context, additionalFi
363436// turning off cyclo here, it measures as a 12 due to all of the type checks of the pricing data which returns a deeply
364437// nested map[string]interface{}
365438// nolint: gocyclo
366- func (p * pricingProvider ) processOnDemandPage (output * pricing.GetProductsOutput , prices map [ec2types.InstanceType ]float64 ) {
439+ func (p * pricingProvider ) processInstancePricingPage (output * pricing.GetProductsOutput , prices map [ec2types.InstanceType ]float64 ) {
367440 // this isn't the full pricing struct, just the portions we care about
368441 type priceItem struct {
369442 Product struct {
@@ -482,6 +555,7 @@ func (p *pricingProvider) updateFargatePricing(ctx context.Context) error {
482555 paginator := pricing .NewGetProductsPaginator (p .pricingClient , & pricing.GetProductsInput {
483556 Filters : filters ,
484557 ServiceCode : aws .String ("AmazonEKS" ),
558+ MaxResults : aws .Int32 (100 ),
485559 })
486560
487561 for paginator .HasMorePages () {
0 commit comments