Skip to content

Commit

Permalink
GTM-52 Fix parsing of GCP pricing and create new node diagnostic pric…
Browse files Browse the repository at this point in the history
…ing API

Signed-off-by: Niko Kovacevic <nikovacevic@gmail.com>
  • Loading branch information
nikovacevic committed Aug 11, 2023
1 parent c324846 commit 933b097
Show file tree
Hide file tree
Showing 13 changed files with 646 additions and 259 deletions.
8 changes: 5 additions & 3 deletions pkg/cloud/alibaba/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -514,23 +514,25 @@ func (alibaba *Alibaba) AllNodePricing() (interface{}, error) {
}

// NodePricing gives pricing information of a specific node given by the key
func (alibaba *Alibaba) NodePricing(key models.Key) (*models.Node, error) {
func (alibaba *Alibaba) NodePricing(key models.Key) (*models.Node, models.PricingMetadata, error) {
alibaba.DownloadPricingDataLock.RLock()
defer alibaba.DownloadPricingDataLock.RUnlock()

// Get node features for the key
keyFeature := key.Features()

meta := models.PricingMetadata{}

pricing, ok := alibaba.Pricing[keyFeature]
if !ok {
log.Errorf("Node pricing information not found for node with feature: %s", keyFeature)
return nil, fmt.Errorf("Node pricing information not found for node with feature: %s letting it use default values", keyFeature)
return nil, meta, fmt.Errorf("Node pricing information not found for node with feature: %s letting it use default values", keyFeature)
}

log.Debugf("returning the node price for the node with feature: %s", keyFeature)
returnNode := pricing.Node

return returnNode, nil
return returnNode, meta, nil
}

// PVPricing gives a pricing information of a specific PV given by PVkey
Expand Down
26 changes: 15 additions & 11 deletions pkg/cloud/aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1240,9 +1240,11 @@ func (aws *AWS) savingsPlanPricing(instanceID string) (*SavingsPlanData, bool) {
return data, ok
}

func (aws *AWS) createNode(terms *AWSProductTerms, usageType string, k models.Key) (*models.Node, error) {
func (aws *AWS) createNode(terms *AWSProductTerms, usageType string, k models.Key) (*models.Node, models.PricingMetadata, error) {
key := k.Features()

meta := models.PricingMetadata{}

if spotInfo, ok := aws.spotPricing(k.ID()); ok {
var spotcost string
log.DedupedInfof(5, "Looking up spot data from feed for node %s", k.ID())
Expand All @@ -1262,7 +1264,7 @@ func (aws *AWS) createNode(terms *AWSProductTerms, usageType string, k models.Ke
BaseRAMPrice: aws.BaseRAMPrice,
BaseGPUPrice: aws.BaseGPUPrice,
UsageType: PreemptibleType,
}, nil
}, meta, nil
} else if aws.isPreemptible(key) { // Preemptible but we don't have any data in the pricing report.
log.DedupedWarningf(5, "Node %s marked preemptible but we have no data in spot feed", k.ID())
return &models.Node{
Expand All @@ -1275,7 +1277,7 @@ func (aws *AWS) createNode(terms *AWSProductTerms, usageType string, k models.Ke
BaseRAMPrice: aws.BaseRAMPrice,
BaseGPUPrice: aws.BaseGPUPrice,
UsageType: PreemptibleType,
}, nil
}, meta, nil
} else if sp, ok := aws.savingsPlanPricing(k.ID()); ok {
strCost := fmt.Sprintf("%f", sp.EffectiveCost)
return &models.Node{
Expand All @@ -1288,7 +1290,7 @@ func (aws *AWS) createNode(terms *AWSProductTerms, usageType string, k models.Ke
BaseRAMPrice: aws.BaseRAMPrice,
BaseGPUPrice: aws.BaseGPUPrice,
UsageType: usageType,
}, nil
}, meta, nil

} else if ri, ok := aws.reservedInstancePricing(k.ID()); ok {
strCost := fmt.Sprintf("%f", ri.EffectiveCost)
Expand All @@ -1302,7 +1304,7 @@ func (aws *AWS) createNode(terms *AWSProductTerms, usageType string, k models.Ke
BaseRAMPrice: aws.BaseRAMPrice,
BaseGPUPrice: aws.BaseGPUPrice,
UsageType: usageType,
}, nil
}, meta, nil

}
var cost string
Expand All @@ -1315,7 +1317,7 @@ func (aws *AWS) createNode(terms *AWSProductTerms, usageType string, k models.Ke
if ok {
cost = c.PricePerUnit.CNY
} else {
return nil, fmt.Errorf("Could not fetch data for \"%s\"", k.ID())
return nil, meta, fmt.Errorf("Could not fetch data for \"%s\"", k.ID())
}
}

Expand All @@ -1329,11 +1331,11 @@ func (aws *AWS) createNode(terms *AWSProductTerms, usageType string, k models.Ke
BaseRAMPrice: aws.BaseRAMPrice,
BaseGPUPrice: aws.BaseGPUPrice,
UsageType: usageType,
}, nil
}, meta, nil
}

// NodePricing takes in a key from GetKey and returns a Node object for use in building the cost model.
func (aws *AWS) NodePricing(k models.Key) (*models.Node, error) {
func (aws *AWS) NodePricing(k models.Key) (*models.Node, models.PricingMetadata, error) {
aws.DownloadPricingDataLock.RLock()
defer aws.DownloadPricingDataLock.RUnlock()

Expand All @@ -1343,6 +1345,8 @@ func (aws *AWS) NodePricing(k models.Key) (*models.Node, error) {
usageType = PreemptibleType
}

meta := models.PricingMetadata{}

terms, ok := aws.Pricing[key]
if ok {
return aws.createNode(terms, usageType, k)
Expand All @@ -1358,7 +1362,7 @@ func (aws *AWS) NodePricing(k models.Key) (*models.Node, error) {
BaseGPUPrice: aws.BaseGPUPrice,
UsageType: usageType,
UsesBaseCPUPrice: true,
}, err
}, meta, err
}
terms, termsOk := aws.Pricing[key]
if !termsOk {
Expand All @@ -1369,11 +1373,11 @@ func (aws *AWS) NodePricing(k models.Key) (*models.Node, error) {
BaseGPUPrice: aws.BaseGPUPrice,
UsageType: usageType,
UsesBaseCPUPrice: true,
}, fmt.Errorf("Unable to find any Pricing data for \"%s\"", key)
}, meta, fmt.Errorf("Unable to find any Pricing data for \"%s\"", key)
}
return aws.createNode(terms, usageType, k)
} else { // Fall back to base pricing if we can't find the key. Base pricing is handled at the costmodel level.
return nil, fmt.Errorf("Invalid Pricing Key \"%s\"", key)
return nil, meta, fmt.Errorf("Invalid Pricing Key \"%s\"", key)

}
}
Expand Down
20 changes: 11 additions & 9 deletions pkg/cloud/azure/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1079,7 +1079,7 @@ func (az *Azure) AllNodePricing() (interface{}, error) {
}

// NodePricing returns Azure pricing data for a single node
func (az *Azure) NodePricing(key models.Key) (*models.Node, error) {
func (az *Azure) NodePricing(key models.Key) (*models.Node, models.PricingMetadata, error) {
az.DownloadPricingDataLock.RLock()
defer az.DownloadPricingDataLock.RUnlock()
pricingDataExists := true
Expand All @@ -1088,9 +1088,11 @@ func (az *Azure) NodePricing(key models.Key) (*models.Node, error) {
log.DedupedWarningf(1, "Unable to download Azure pricing data")
}

meta := models.PricingMetadata{}

azKey, ok := key.(*azureKey)
if !ok {
return nil, fmt.Errorf("azure: NodePricing: key is of type %T", key)
return nil, meta, fmt.Errorf("azure: NodePricing: key is of type %T", key)
}
config, _ := az.GetConfig()

Expand All @@ -1105,7 +1107,7 @@ func (az *Azure) NodePricing(key models.Key) (*models.Node, error) {
if azKey.isValidGPUNode() {
n.Node.GPU = "1" // TODO: support multiple GPUs
}
return n.Node, nil
return n.Node, meta, nil
}
log.Infof("[Info] found spot instance, trying to get retail price for %s: %s, ", spotFeatures, azKey)
spotCost, err := getRetailPrice(region, instance, config.CurrencyCode, true)
Expand All @@ -1124,7 +1126,7 @@ func (az *Azure) NodePricing(key models.Key) (*models.Node, error) {
az.addPricing(spotFeatures, &AzurePricing{
Node: spotNode,
})
return spotNode, nil
return spotNode, meta, nil
}
}

Expand All @@ -1136,13 +1138,13 @@ func (az *Azure) NodePricing(key models.Key) (*models.Node, error) {
if azKey.isValidGPUNode() {
n.Node.GPU = azKey.GetGPUCount()
}
return n.Node, nil
return n.Node, meta, nil
}
log.DedupedWarningf(5, "No pricing data found for node %s from key %s", azKey, azKey.Features())
}
c, err := az.GetConfig()
if err != nil {
return nil, fmt.Errorf("No default pricing data available")
return nil, meta, fmt.Errorf("No default pricing data available")
}

// GPU Node
Expand All @@ -1153,7 +1155,7 @@ func (az *Azure) NodePricing(key models.Key) (*models.Node, error) {
UsesBaseCPUPrice: true,
GPUCost: c.GPU,
GPU: azKey.GetGPUCount(),
}, nil
}, meta, nil
}

// Serverless Node. This is an Azure Container Instance, and no pods can be
Expand All @@ -1163,15 +1165,15 @@ func (az *Azure) NodePricing(key models.Key) (*models.Node, error) {
return &models.Node{
VCPUCost: "0",
RAMCost: "0",
}, nil
}, meta, nil
}

// Regular Node
return &models.Node{
VCPUCost: c.CPU,
RAMCost: c.RAM,
UsesBaseCPUPrice: true,
}, nil
}, meta, nil
}

// Stubbed NetworkPricing for Azure. Pull directly from azure.json for now
Expand Down
Loading

0 comments on commit 933b097

Please sign in to comment.