datasources.go 4.6 KB

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