datasources.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. package datasources
  2. import (
  3. "io/ioutil"
  4. "path/filepath"
  5. "github.com/grafana/grafana/pkg/bus"
  6. "github.com/grafana/grafana/pkg/log"
  7. "github.com/grafana/grafana/pkg/models"
  8. yaml "gopkg.in/yaml.v2"
  9. )
  10. // TODO: secure jsonData
  11. // TODO: auto reload on file changes
  12. // TODO: remove get method since all datasources is in memory
  13. type DatasourcesAsConfig struct {
  14. PurgeOtherDatasources bool
  15. Datasources []models.DataSource
  16. }
  17. func Init(configPath string) error {
  18. dc := NewDatasourceConfiguration()
  19. return dc.applyChanges(configPath)
  20. }
  21. type DatasourceConfigurator struct {
  22. log log.Logger
  23. cfgProvider configProvider
  24. repository datasourceRepository
  25. }
  26. func NewDatasourceConfiguration() DatasourceConfigurator {
  27. return newDatasourceConfiguration(log.New("setting.datasource"), diskConfigReader{}, sqlDatasourceRepository{})
  28. }
  29. func newDatasourceConfiguration(log log.Logger, cfgProvider configProvider, repo datasourceRepository) DatasourceConfigurator {
  30. return DatasourceConfigurator{
  31. log: log.New("setting.datasource"),
  32. repository: repo,
  33. cfgProvider: cfgProvider,
  34. }
  35. }
  36. func (dc *DatasourceConfigurator) applyChanges(configPath string) error {
  37. cfg, err := dc.cfgProvider.readConfig(configPath)
  38. if err != nil {
  39. return err
  40. }
  41. all, err := dc.repository.loadAllDatasources()
  42. if err != nil {
  43. return err
  44. }
  45. for i, _ := range cfg.Datasources {
  46. if cfg.Datasources[i].OrgId == 0 {
  47. cfg.Datasources[i].OrgId = 1
  48. }
  49. }
  50. if cfg.PurgeOtherDatasources {
  51. for _, dbDatasource := range all {
  52. delete := true
  53. for _, cfgDatasource := range cfg.Datasources {
  54. if dbDatasource.Name == cfgDatasource.Name && dbDatasource.OrgId == cfgDatasource.OrgId {
  55. delete = false
  56. }
  57. }
  58. if delete {
  59. dc.log.Info("deleting datasource since PurgeOtherDatasource is enabled", "name", dbDatasource.Name)
  60. dc.repository.delete(&models.DeleteDataSourceByIdCommand{Id: dbDatasource.Id, OrgId: dbDatasource.OrgId})
  61. }
  62. }
  63. }
  64. for _, ds := range cfg.Datasources {
  65. query := &models.GetDataSourceByNameQuery{Name: ds.Name, OrgId: ds.OrgId}
  66. err := dc.repository.get(query)
  67. if err != nil && err != models.ErrDataSourceNotFound {
  68. return err
  69. }
  70. if query.Result == nil {
  71. dc.log.Info("inserting ", "name", ds.Name)
  72. insertCmd := createInsertCommand(ds)
  73. if err := dc.repository.insert(insertCmd); err != nil {
  74. return err
  75. }
  76. } else {
  77. dc.log.Info("updating", "name", ds.Name)
  78. updateCmd := createUpdateCommand(ds, query.Result.Id)
  79. if err := dc.repository.update(updateCmd); err != nil {
  80. return err
  81. }
  82. }
  83. }
  84. return nil
  85. }
  86. func createInsertCommand(ds models.DataSource) *models.AddDataSourceCommand {
  87. return &models.AddDataSourceCommand{
  88. OrgId: ds.OrgId,
  89. Name: ds.Name,
  90. Type: ds.Type,
  91. Access: ds.Access,
  92. Url: ds.Url,
  93. Password: ds.Password,
  94. User: ds.User,
  95. Database: ds.Database,
  96. BasicAuth: ds.BasicAuth,
  97. BasicAuthUser: ds.BasicAuthUser,
  98. BasicAuthPassword: ds.BasicAuthPassword,
  99. WithCredentials: ds.WithCredentials,
  100. IsDefault: ds.IsDefault,
  101. JsonData: ds.JsonData,
  102. }
  103. }
  104. func createUpdateCommand(ds models.DataSource, id int64) *models.UpdateDataSourceCommand {
  105. return &models.UpdateDataSourceCommand{
  106. Id: id,
  107. OrgId: ds.OrgId,
  108. Name: ds.Name,
  109. Type: ds.Type,
  110. Access: ds.Access,
  111. Url: ds.Url,
  112. Password: ds.Password,
  113. User: ds.User,
  114. Database: ds.Database,
  115. BasicAuth: ds.BasicAuth,
  116. BasicAuthUser: ds.BasicAuthUser,
  117. BasicAuthPassword: ds.BasicAuthPassword,
  118. WithCredentials: ds.WithCredentials,
  119. IsDefault: ds.IsDefault,
  120. JsonData: ds.JsonData,
  121. }
  122. }
  123. type datasourceRepository interface {
  124. insert(*models.AddDataSourceCommand) error
  125. update(*models.UpdateDataSourceCommand) error
  126. delete(*models.DeleteDataSourceByIdCommand) error
  127. get(*models.GetDataSourceByNameQuery) error
  128. loadAllDatasources() ([]*models.DataSource, error)
  129. }
  130. type configProvider interface {
  131. readConfig(string) (*DatasourcesAsConfig, error)
  132. }
  133. type sqlDatasourceRepository struct{}
  134. type diskConfigReader struct{}
  135. func (diskConfigReader) readConfig(path string) (*DatasourcesAsConfig, error) {
  136. filename, _ := filepath.Abs(path)
  137. yamlFile, err := ioutil.ReadFile(filename)
  138. if err != nil {
  139. return nil, err
  140. }
  141. var datasources *DatasourcesAsConfig
  142. err = yaml.Unmarshal(yamlFile, &datasources)
  143. if err != nil {
  144. return nil, err
  145. }
  146. return datasources, nil
  147. }
  148. func (sqlDatasourceRepository) delete(cmd *models.DeleteDataSourceByIdCommand) error {
  149. return bus.Dispatch(cmd)
  150. }
  151. func (sqlDatasourceRepository) update(cmd *models.UpdateDataSourceCommand) error {
  152. return bus.Dispatch(cmd)
  153. }
  154. func (sqlDatasourceRepository) insert(cmd *models.AddDataSourceCommand) error {
  155. return bus.Dispatch(cmd)
  156. }
  157. func (sqlDatasourceRepository) get(cmd *models.GetDataSourceByNameQuery) error {
  158. return bus.Dispatch(cmd)
  159. }
  160. func (sqlDatasourceRepository) loadAllDatasources() ([]*models.DataSource, error) {
  161. dss := &models.GetAllDataSourcesQuery{}
  162. if err := bus.Dispatch(dss); err != nil {
  163. return nil, err
  164. }
  165. return dss.Result, nil
  166. }