configmanager.go 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package config
  2. import (
  3. "io/ioutil"
  4. "sync"
  5. "github.com/opencost/opencost/pkg/log"
  6. "github.com/opencost/opencost/pkg/storage"
  7. )
  8. //--------------------------------------------------------------------------
  9. // ConfigFileManagerOpts
  10. //--------------------------------------------------------------------------
  11. // ConfigFileManagerOpts describes how to configure the ConfigFileManager for
  12. // serving configuration files
  13. type ConfigFileManagerOpts struct {
  14. // BucketStoreConfig is the local file location for the configuration used to
  15. // write and read configuration data to/from the bucket. The format of this
  16. // configuration file should be compatible with storage.NewBucketStorage
  17. BucketStoreConfig string
  18. // LocalConfigPath provides a backup location for storing the configuration
  19. // files
  20. LocalConfigPath string
  21. }
  22. // IsBucketStorageEnabled returns true if bucket storage is enabled.
  23. func (cfmo *ConfigFileManagerOpts) IsBucketStorageEnabled() bool {
  24. return cfmo.BucketStoreConfig != ""
  25. }
  26. // DefaultConfigFileManagerOpts returns the default configuration options for the
  27. // config file manager
  28. func DefaultConfigFileManagerOpts() *ConfigFileManagerOpts {
  29. return &ConfigFileManagerOpts{
  30. BucketStoreConfig: "",
  31. LocalConfigPath: "/",
  32. }
  33. }
  34. //--------------------------------------------------------------------------
  35. // ConfigFileManager
  36. //--------------------------------------------------------------------------
  37. // ConfigFileManager is a fascade for a central API used to create and watch
  38. // config files.
  39. type ConfigFileManager struct {
  40. lock *sync.Mutex
  41. store storage.Storage
  42. files map[string]*ConfigFile
  43. }
  44. // NewConfigFileManager creates a new backing storage and configuration file manager
  45. func NewConfigFileManager(opts *ConfigFileManagerOpts) *ConfigFileManager {
  46. if opts == nil {
  47. opts = DefaultConfigFileManagerOpts()
  48. }
  49. var configStore storage.Storage
  50. if opts.IsBucketStorageEnabled() {
  51. bucketConfig, err := ioutil.ReadFile(opts.BucketStoreConfig)
  52. if err != nil {
  53. log.Warnf("Failed to initialize config bucket storage: %s", err)
  54. } else {
  55. bucketStore, err := storage.NewBucketStorage(bucketConfig)
  56. if err != nil {
  57. log.Warnf("Failed to create config bucket storage: %s", err)
  58. } else {
  59. configStore = bucketStore
  60. }
  61. }
  62. } else {
  63. configStore = storage.NewFileStorage(opts.LocalConfigPath)
  64. }
  65. return &ConfigFileManager{
  66. lock: new(sync.Mutex),
  67. store: configStore,
  68. files: make(map[string]*ConfigFile),
  69. }
  70. }
  71. // ConfigFileAt returns an existing configuration file for the provided path if it exists. Otherwise,
  72. // a new instance is created and returned. Note that the path does not have to exist in order for the
  73. // instance to be created. It can exist as a potential file path on the storage, and be written to
  74. // later
  75. func (cfm *ConfigFileManager) ConfigFileAt(path string) *ConfigFile {
  76. cfm.lock.Lock()
  77. defer cfm.lock.Unlock()
  78. if cf, ok := cfm.files[path]; ok {
  79. return cf
  80. }
  81. cf := NewConfigFile(cfm.store, path)
  82. cfm.files[path] = cf
  83. return cf
  84. }