generator.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package public
  2. import (
  3. "fmt"
  4. "os"
  5. "github.com/opencost/opencost/core/pkg/log"
  6. "github.com/opencost/opencost/core/pkg/pricing"
  7. "github.com/opencost/opencost/core/pkg/unit"
  8. "github.com/opencost/opencost/modules/pricing/public/aws"
  9. "github.com/opencost/opencost/modules/pricing/public/azure"
  10. "github.com/opencost/opencost/modules/pricing/public/gcp"
  11. )
  12. // GenerateAWSPricing fetches AWS pricing data in the specified currency
  13. func GenerateAWSPricing(currency unit.Currency) (*pricing.PricingSet, error) {
  14. log.Infof("Generating AWS pricing for currency: %s", currency)
  15. source := aws.NewAWSPricingSource(aws.AWSPricingSourceConfig{
  16. CurrencyCode: string(currency),
  17. })
  18. pricingSet, err := source.GetPricing()
  19. if err != nil {
  20. return nil, fmt.Errorf("failed to get AWS pricing: %w", err)
  21. }
  22. // Sort to ensure deterministic output for checksums
  23. pricingSet.Sort()
  24. log.Infof("Generated %d AWS node pricing entries", len(pricingSet.NodePricing))
  25. return pricingSet, nil
  26. }
  27. // GenerateAzurePricing fetches Azure pricing data in the specified currency
  28. func GenerateAzurePricing(currency unit.Currency) (*pricing.PricingSet, error) {
  29. log.Infof("Generating Azure pricing for currency: %s", currency)
  30. source := azure.NewAzurePricingSource(azure.AzurePricingSourceConfig{
  31. CurrencyCode: string(currency),
  32. })
  33. pricingSet, err := source.GetPricing()
  34. if err != nil {
  35. return nil, fmt.Errorf("failed to get Azure pricing: %w", err)
  36. }
  37. // Sort to ensure deterministic output for checksums
  38. pricingSet.Sort()
  39. log.Infof("Generated %d Azure node pricing entries", len(pricingSet.NodePricing))
  40. return pricingSet, nil
  41. }
  42. // GenerateGCPPricing fetches GCP pricing data in the specified currency
  43. func GenerateGCPPricing(currency unit.Currency) (*pricing.PricingSet, error) {
  44. log.Infof("Generating GCP pricing for currency: %s", currency)
  45. source := gcp.NewGCPPricingSource(gcp.GCPPricingSourceConfig{
  46. CurrencyCode: string(currency),
  47. APIKey: os.Getenv("GCP_API_KEY"),
  48. })
  49. pricingSet, err := source.GetPricing()
  50. if err != nil {
  51. return nil, fmt.Errorf("failed to get GCP pricing: %w", err)
  52. }
  53. // Sort to ensure deterministic output for checksums
  54. pricingSet.Sort()
  55. log.Infof("Generated %d GCP node pricing entries", len(pricingSet.NodePricing))
  56. return pricingSet, nil
  57. }
  58. // GeneratePricing fetches pricing data for all supported providers
  59. // and combines them into a single PricingSet
  60. func GeneratePricing(currency unit.Currency) (*pricing.PricingSet, error) {
  61. log.Infof("Generating pricing for providers in currency: %s", currency)
  62. // Create a combined pricing set
  63. combinedSet := &pricing.PricingSet{
  64. NodePricing: []*pricing.NodePricing{},
  65. PersistentVolumePricing: []*pricing.PersistentVolumePricing{},
  66. }
  67. // Fetch AWS pricing
  68. awsSet, err := GenerateAWSPricing(currency)
  69. if err != nil {
  70. return nil, fmt.Errorf("failed to get AWS pricing: %w", err)
  71. }
  72. combinedSet.NodePricing = append(combinedSet.NodePricing, awsSet.NodePricing...)
  73. combinedSet.PersistentVolumePricing = append(combinedSet.PersistentVolumePricing, awsSet.PersistentVolumePricing...)
  74. log.Infof("Added %d AWS node pricing entries", len(awsSet.NodePricing))
  75. // Fetch Azure pricing
  76. azureSet, err := GenerateAzurePricing(currency)
  77. if err != nil {
  78. return nil, fmt.Errorf("failed to get Azure pricing: %w", err)
  79. }
  80. combinedSet.NodePricing = append(combinedSet.NodePricing, azureSet.NodePricing...)
  81. combinedSet.PersistentVolumePricing = append(combinedSet.PersistentVolumePricing, azureSet.PersistentVolumePricing...)
  82. log.Infof("Added %d Azure node pricing entries", len(azureSet.NodePricing))
  83. // GCP does NOT support CNY
  84. if currency != "CNY" {
  85. gcpSet, err := GenerateGCPPricing(currency)
  86. if err != nil {
  87. return nil, fmt.Errorf("failed to get GCP pricing: %w", err)
  88. }
  89. combinedSet.NodePricing = append(combinedSet.NodePricing, gcpSet.NodePricing...)
  90. combinedSet.PersistentVolumePricing = append(combinedSet.PersistentVolumePricing, gcpSet.PersistentVolumePricing...)
  91. log.Infof("Added %d GCP node pricing entries", len(gcpSet.NodePricing))
  92. }
  93. // Sort the combined set to ensure deterministic output
  94. combinedSet.Sort()
  95. log.Infof("Generated combined pricing set with %d total node entries and %d volume entries",
  96. len(combinedSet.NodePricing), len(combinedSet.PersistentVolumePricing))
  97. return combinedSet, nil
  98. }