datasources.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. package datasources
  2. import (
  3. "errors"
  4. "io/ioutil"
  5. "path/filepath"
  6. "github.com/grafana/grafana/pkg/bus"
  7. "github.com/grafana/grafana/pkg/log"
  8. "github.com/grafana/grafana/pkg/models"
  9. yaml "gopkg.in/yaml.v2"
  10. )
  11. var (
  12. ErrInvalidConfigToManyDefault = errors.New("datasource.yaml config is invalid. Only one datasource can be marked as default")
  13. )
  14. func Apply(configPath string) error {
  15. dc := NewDatasourceConfiguration()
  16. return dc.applyChanges(configPath)
  17. }
  18. type DatasourceConfigurator struct {
  19. log log.Logger
  20. cfgProvider configProvider
  21. repository datasourceRepository
  22. }
  23. func NewDatasourceConfiguration() DatasourceConfigurator {
  24. return newDatasourceConfiguration(log.New("setting.datasource"), sqlDatasourceRepository{})
  25. }
  26. func newDatasourceConfiguration(log log.Logger, repo datasourceRepository) DatasourceConfigurator {
  27. return DatasourceConfigurator{
  28. log: log,
  29. repository: repo,
  30. cfgProvider: configProvider{},
  31. }
  32. }
  33. func (dc *DatasourceConfigurator) applyChanges(configPath string) error {
  34. cfg, err := dc.cfgProvider.readConfig(configPath)
  35. if err != nil {
  36. return err
  37. }
  38. defaultCount := 0
  39. for i := range cfg.Datasources {
  40. if cfg.Datasources[i].OrgId == 0 {
  41. cfg.Datasources[i].OrgId = 1
  42. }
  43. if cfg.Datasources[i].IsDefault {
  44. defaultCount++
  45. if defaultCount > 1 {
  46. return ErrInvalidConfigToManyDefault
  47. }
  48. }
  49. }
  50. allDatasources, err := dc.repository.loadAllDatasources()
  51. if err != nil {
  52. return err
  53. }
  54. if err := dc.deleteDatasourcesNotInConfiguration(cfg, allDatasources); err != nil {
  55. return err
  56. }
  57. for _, ds := range cfg.Datasources {
  58. var dbDatasource *models.DataSource
  59. for _, ddd := range allDatasources {
  60. if ddd.Name == ds.Name && ddd.OrgId == ds.OrgId {
  61. dbDatasource = ddd
  62. break
  63. }
  64. }
  65. if dbDatasource == nil {
  66. dc.log.Info("inserting datasource from configuration ", "name", ds.Name)
  67. insertCmd := createInsertCommand(ds)
  68. err := dc.repository.insert(insertCmd)
  69. if err != nil {
  70. return err
  71. }
  72. } else {
  73. dc.log.Debug("updating datasource from configuration", "name", ds.Name)
  74. updateCmd := createUpdateCommand(ds, dbDatasource.Id)
  75. if err := dc.repository.update(updateCmd); err != nil {
  76. return err
  77. }
  78. }
  79. }
  80. return nil
  81. }
  82. func (dc *DatasourceConfigurator) deleteDatasourcesNotInConfiguration(cfg *DatasourcesAsConfig, allDatasources []*models.DataSource) error {
  83. if cfg.PurgeOtherDatasources {
  84. for _, dbDS := range allDatasources {
  85. delete := true
  86. for _, cfgDS := range cfg.Datasources {
  87. if dbDS.Name == cfgDS.Name && dbDS.OrgId == cfgDS.OrgId {
  88. delete = false
  89. }
  90. }
  91. if delete {
  92. dc.log.Info("deleting datasource from configuration", "name", dbDS.Name)
  93. cmd := &models.DeleteDataSourceByIdCommand{Id: dbDS.Id, OrgId: dbDS.OrgId}
  94. if err := dc.repository.delete(cmd); err != nil {
  95. return err
  96. }
  97. }
  98. }
  99. }
  100. return nil
  101. }
  102. type datasourceRepository interface {
  103. insert(*models.AddDataSourceCommand) error
  104. update(*models.UpdateDataSourceCommand) error
  105. delete(*models.DeleteDataSourceByIdCommand) error
  106. get(*models.GetDataSourceByNameQuery) error
  107. loadAllDatasources() ([]*models.DataSource, error)
  108. }
  109. type sqlDatasourceRepository struct{}
  110. type configProvider struct{}
  111. func (configProvider) readConfig(path string) (*DatasourcesAsConfig, error) {
  112. filename, _ := filepath.Abs(path)
  113. yamlFile, err := ioutil.ReadFile(filename)
  114. if err != nil {
  115. return nil, err
  116. }
  117. var datasources *DatasourcesAsConfig
  118. err = yaml.Unmarshal(yamlFile, &datasources)
  119. if err != nil {
  120. return nil, err
  121. }
  122. return datasources, nil
  123. }
  124. func (sqlDatasourceRepository) delete(cmd *models.DeleteDataSourceByIdCommand) error {
  125. return bus.Dispatch(cmd)
  126. }
  127. func (sqlDatasourceRepository) update(cmd *models.UpdateDataSourceCommand) error {
  128. return bus.Dispatch(cmd)
  129. }
  130. func (sqlDatasourceRepository) insert(cmd *models.AddDataSourceCommand) error {
  131. return bus.Dispatch(cmd)
  132. }
  133. func (sqlDatasourceRepository) get(cmd *models.GetDataSourceByNameQuery) error {
  134. return bus.Dispatch(cmd)
  135. }
  136. func (sqlDatasourceRepository) loadAllDatasources() ([]*models.DataSource, error) {
  137. dss := &models.GetAllDataSourcesQuery{}
  138. if err := bus.Dispatch(dss); err != nil {
  139. return nil, err
  140. }
  141. return dss.Result, nil
  142. }