| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- package pricing
- import (
- "context"
- "embed"
- "encoding/json"
- "fmt"
- "path/filepath"
- "strings"
- "github.com/opencost/opencost/core/pkg/reader"
- "gopkg.in/yaml.v3"
- )
- type MockPricingRepository struct {
- NodePricing []*NodePricing
- VolumePricing []*VolumePricing
- }
- func NewMockPricingRepository() (*MockPricingRepository, error) {
- repo := &MockPricingRepository{
- NodePricing: []*NodePricing{},
- VolumePricing: []*VolumePricing{},
- }
- // Default
- defaultPricingSet, err := loadTestFile("default.yaml")
- if err != nil {
- return nil, fmt.Errorf("error loading test default pricing: %w", err)
- }
- repo.NodePricing = append(repo.NodePricing, defaultPricingSet.Nodes...)
- repo.VolumePricing = append(repo.VolumePricing, defaultPricingSet.Volumes...)
- // AWS
- awsPricingSet, err := loadTestFile("aws.yaml")
- if err != nil {
- return nil, fmt.Errorf("error loading test AWS pricing: %w", err)
- }
- repo.NodePricing = append(repo.NodePricing, awsPricingSet.Nodes...)
- repo.VolumePricing = append(repo.VolumePricing, awsPricingSet.Volumes...)
- // Azure
- azurePricingSet, err := loadTestFile("azure.yaml")
- if err != nil {
- return nil, fmt.Errorf("error loading test Azure pricing: %w", err)
- }
- repo.NodePricing = append(repo.NodePricing, azurePricingSet.Nodes...)
- repo.VolumePricing = append(repo.VolumePricing, azurePricingSet.Volumes...)
- // GCP
- gcpPricingSet, err := loadTestFile("gcp.yaml")
- if err != nil {
- return nil, fmt.Errorf("error loading test GCP pricing: %w", err)
- }
- repo.NodePricing = append(repo.NodePricing, gcpPricingSet.Nodes...)
- repo.VolumePricing = append(repo.VolumePricing, gcpPricingSet.Volumes...)
- return repo, nil
- }
- func (repo *MockPricingRepository) NewNodePricingReader(ctx context.Context) (reader.Reader[*NodePricing], error) {
- return reader.NewSliceReader(repo.NodePricing), nil
- }
- func (repo *MockPricingRepository) GetNodePricing(provider Provider, instanceType string, region string) (*NodePricing, error) {
- // Search through the mock data for a matching node pricing entry
- for _, np := range repo.NodePricing {
- if np.Properties.Provider == provider &&
- np.Properties.InstanceType == instanceType &&
- np.Properties.Region == region {
- return np, nil
- }
- }
- return nil, fmt.Errorf("node pricing not found for provider=%s, instanceType=%s, region=%s", provider, instanceType, region)
- }
- func (repo *MockPricingRepository) NewVolumePricingReader(ctx context.Context) (reader.Reader[*VolumePricing], error) {
- return reader.NewSliceReader(repo.VolumePricing), nil
- }
- func (repo *MockPricingRepository) GetVolumePricing(props VolumePricingProperties) (*VolumePricing, error) {
- // Search through the mock data for a matching volume pricing entry
- for _, vp := range repo.VolumePricing {
- if vp.Properties.Provider == props.Provider &&
- vp.Properties.Region == props.Region &&
- vp.Properties.VolumeType == props.VolumeType {
- return vp, nil
- }
- }
- return nil, fmt.Errorf("volume pricing not found for provider=%s, region=%s, volumeType=%s", props.Provider, props.Region, props.VolumeType)
- }
- //go:embed test/*
- var pricingTestFS embed.FS
- func loadTestFile(filename string) (*PricingSet, error) {
- path := filepath.Join("test", filename)
- bs, err := pricingTestFS.ReadFile(path)
- if err != nil {
- panic(fmt.Errorf("failed to read embedded pricing file: %w", err))
- }
- var set *PricingSet
- // Detect file format based on extension
- ext := strings.ToLower(filepath.Ext(filename))
- switch ext {
- case ".json":
- err = json.Unmarshal(bs, &set)
- if err != nil {
- return nil, fmt.Errorf("failed to parse json: %w", err)
- }
- case ".yaml", ".yml":
- err = yaml.Unmarshal(bs, &set)
- if err != nil {
- return nil, fmt.Errorf("failed to parse yaml: %w", err)
- }
- default:
- return nil, fmt.Errorf("unsupported file format: %s (expected .json, .yaml, or .yml)", ext)
- }
- return set, nil
- }
|