| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- package pricingmodel
- import (
- "fmt"
- "strings"
- "time"
- "github.com/opencost/opencost/core/pkg/exporter"
- "github.com/opencost/opencost/core/pkg/exporter/pathing"
- "github.com/opencost/opencost/core/pkg/log"
- "github.com/opencost/opencost/core/pkg/model/pricingmodel"
- "github.com/opencost/opencost/core/pkg/pipelines"
- "github.com/opencost/opencost/core/pkg/storage"
- )
- // storageWriter wraps a Storage backend with a StaticFileStoragePathFormatter,
- // translating source keys into full storage paths on write.
- type storageWriter struct {
- store storage.Storage
- encoder exporter.Encoder[pricingmodel.PricingModelSet]
- pathing *pathing.StaticFileStoragePathFormatter
- }
- func newStorageWriter(store storage.Storage, appName string) (*storageWriter, error) {
- p, err := pathing.NewStaticFileStoragePathFormatter(appName, pipelines.PricingModelPipelineName)
- if err != nil {
- return nil, fmt.Errorf("newStorageWriter: failed to create path formatter: %w", err)
- }
- return &storageWriter{
- store: store,
- encoder: exporter.NewBingenFileEncoder[pricingmodel.PricingModelSet](),
- pathing: p,
- }, nil
- }
- func (sw *storageWriter) Write(pms *pricingmodel.PricingModelSet) error {
- fullPath := sw.pathing.ToFullPath("", pms.SourceKey, sw.encoder.FileExt())
- data, err := sw.encoder.Encode(pms)
- if err != nil {
- return fmt.Errorf("failed to encode data: %w", err)
- }
- err = sw.store.Write(fullPath, data)
- if err != nil {
- return fmt.Errorf("failed to write to storage: %w", err)
- }
- log.Infof("PricingModel[%s]: exported pricing model set (%d bytes)", pms.SourceKey, len(data))
- return nil
- }
- // LastUpdates returns a map of source key to last modified time for each file
- // found under the formatter's directory. Source keys are reconstructed as the
- // file path relative to Dir().
- func (sw *storageWriter) LastUpdates() (map[string]time.Time, error) {
- result := make(map[string]time.Time)
- dir := sw.pathing.Dir()
- files, err := sw.store.List(dir)
- if err != nil && !storage.IsNotExist(err) {
- return nil, fmt.Errorf("collectModTimes: listing %s: %w", dir, err)
- }
- for _, f := range files {
- nameParts := strings.Split(f.Name, ".")
- key := nameParts[0]
- if modTime, ok := result[key]; ok && modTime.After(f.ModTime) {
- continue
- }
- result[key] = f.ModTime
- }
- return result, nil
- }
|