generator.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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. ServicePricing: []*pricing.ServicePricing{},
  67. }
  68. // Fetch AWS pricing
  69. awsSet, err := GenerateAWSPricing(currency)
  70. if err != nil {
  71. return nil, fmt.Errorf("failed to get AWS pricing: %w", err)
  72. }
  73. combinedSet.NodePricing = append(combinedSet.NodePricing, awsSet.NodePricing...)
  74. combinedSet.PersistentVolumePricing = append(combinedSet.PersistentVolumePricing, awsSet.PersistentVolumePricing...)
  75. combinedSet.ServicePricing = append(combinedSet.ServicePricing, awsSet.ServicePricing...)
  76. log.Infof("Added %d AWS node pricing entries, %d service pricing entries", len(awsSet.NodePricing), len(awsSet.ServicePricing))
  77. // Fetch Azure pricing
  78. azureSet, err := GenerateAzurePricing(currency)
  79. if err != nil {
  80. return nil, fmt.Errorf("failed to get Azure pricing: %w", err)
  81. }
  82. combinedSet.NodePricing = append(combinedSet.NodePricing, azureSet.NodePricing...)
  83. combinedSet.PersistentVolumePricing = append(combinedSet.PersistentVolumePricing, azureSet.PersistentVolumePricing...)
  84. combinedSet.ServicePricing = append(combinedSet.ServicePricing, azureSet.ServicePricing...)
  85. log.Infof("Added %d Azure node pricing entries, %d service pricing entries", len(azureSet.NodePricing), len(azureSet.ServicePricing))
  86. // GCP does NOT support CNY
  87. if currency != "CNY" {
  88. gcpSet, err := GenerateGCPPricing(currency)
  89. if err != nil {
  90. return nil, fmt.Errorf("failed to get GCP pricing: %w", err)
  91. }
  92. combinedSet.NodePricing = append(combinedSet.NodePricing, gcpSet.NodePricing...)
  93. combinedSet.PersistentVolumePricing = append(combinedSet.PersistentVolumePricing, gcpSet.PersistentVolumePricing...)
  94. combinedSet.ServicePricing = append(combinedSet.ServicePricing, gcpSet.ServicePricing...)
  95. log.Infof("Added %d GCP node pricing entries, %d service pricing entries", len(gcpSet.NodePricing), len(gcpSet.ServicePricing))
  96. }
  97. // Sort the combined set to ensure deterministic output
  98. combinedSet.Sort()
  99. log.Infof("Generated combined pricing set with %d total node entries, %d volume entries, %d service entries",
  100. len(combinedSet.NodePricing), len(combinedSet.PersistentVolumePricing), len(combinedSet.ServicePricing))
  101. return combinedSet, nil
  102. }