config_reader_test.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. package datasources
  2. import (
  3. "testing"
  4. "github.com/grafana/grafana/pkg/bus"
  5. "github.com/grafana/grafana/pkg/log"
  6. "github.com/grafana/grafana/pkg/models"
  7. . "github.com/smartystreets/goconvey/convey"
  8. )
  9. var (
  10. logger log.Logger = log.New("fake.log")
  11. oneDatasourcesConfig string = ""
  12. twoDatasourcesConfig string = "./test-configs/two-datasources"
  13. twoDatasourcesConfigPurgeOthers string = "./test-configs/insert-two-delete-two"
  14. doubleDatasourcesConfig string = "./test-configs/double-default"
  15. allProperties string = "./test-configs/all-properties"
  16. versionZero string = "./test-configs/version-0"
  17. brokenYaml string = "./test-configs/broken-yaml"
  18. fakeRepo *fakeRepository
  19. )
  20. func TestDatasourceAsConfig(t *testing.T) {
  21. Convey("Testing datasource as configuration", t, func() {
  22. fakeRepo = &fakeRepository{}
  23. bus.ClearBusHandlers()
  24. bus.AddHandler("test", mockDelete)
  25. bus.AddHandler("test", mockInsert)
  26. bus.AddHandler("test", mockUpdate)
  27. bus.AddHandler("test", mockGet)
  28. bus.AddHandler("test", mockGetAll)
  29. Convey("One configured datasource", func() {
  30. Convey("no datasource in database", func() {
  31. dc := newDatasourceProvisioner(logger)
  32. err := dc.applyChanges(twoDatasourcesConfig)
  33. if err != nil {
  34. t.Fatalf("applyChanges return an error %v", err)
  35. }
  36. So(len(fakeRepo.deleted), ShouldEqual, 0)
  37. So(len(fakeRepo.inserted), ShouldEqual, 2)
  38. So(len(fakeRepo.updated), ShouldEqual, 0)
  39. })
  40. Convey("One datasource in database with same name", func() {
  41. fakeRepo.loadAll = []*models.DataSource{
  42. {Name: "Graphite", OrgId: 1, Id: 1},
  43. }
  44. Convey("should update one datasource", func() {
  45. dc := newDatasourceProvisioner(logger)
  46. err := dc.applyChanges(twoDatasourcesConfig)
  47. if err != nil {
  48. t.Fatalf("applyChanges return an error %v", err)
  49. }
  50. So(len(fakeRepo.deleted), ShouldEqual, 0)
  51. So(len(fakeRepo.inserted), ShouldEqual, 1)
  52. So(len(fakeRepo.updated), ShouldEqual, 1)
  53. })
  54. })
  55. Convey("Two datasources with is_default", func() {
  56. dc := newDatasourceProvisioner(logger)
  57. err := dc.applyChanges(doubleDatasourcesConfig)
  58. Convey("should raise error", func() {
  59. So(err, ShouldEqual, ErrInvalidConfigToManyDefault)
  60. })
  61. })
  62. })
  63. Convey("Two configured datasource and purge others ", func() {
  64. Convey("two other datasources in database", func() {
  65. fakeRepo.loadAll = []*models.DataSource{
  66. {Name: "old-graphite", OrgId: 1, Id: 1},
  67. {Name: "old-graphite2", OrgId: 1, Id: 2},
  68. }
  69. Convey("should have two new datasources", func() {
  70. dc := newDatasourceProvisioner(logger)
  71. err := dc.applyChanges(twoDatasourcesConfigPurgeOthers)
  72. if err != nil {
  73. t.Fatalf("applyChanges return an error %v", err)
  74. }
  75. So(len(fakeRepo.deleted), ShouldEqual, 2)
  76. So(len(fakeRepo.inserted), ShouldEqual, 2)
  77. So(len(fakeRepo.updated), ShouldEqual, 0)
  78. })
  79. })
  80. })
  81. Convey("Two configured datasource and purge others = false", func() {
  82. Convey("two other datasources in database", func() {
  83. fakeRepo.loadAll = []*models.DataSource{
  84. {Name: "Graphite", OrgId: 1, Id: 1},
  85. {Name: "old-graphite2", OrgId: 1, Id: 2},
  86. }
  87. Convey("should have two new datasources", func() {
  88. dc := newDatasourceProvisioner(logger)
  89. err := dc.applyChanges(twoDatasourcesConfig)
  90. if err != nil {
  91. t.Fatalf("applyChanges return an error %v", err)
  92. }
  93. So(len(fakeRepo.deleted), ShouldEqual, 0)
  94. So(len(fakeRepo.inserted), ShouldEqual, 1)
  95. So(len(fakeRepo.updated), ShouldEqual, 1)
  96. })
  97. })
  98. })
  99. Convey("broken yaml should return error", func() {
  100. reader := &configReader{}
  101. _, err := reader.readConfig(brokenYaml)
  102. So(err, ShouldNotBeNil)
  103. })
  104. Convey("skip invalid directory", func() {
  105. cfgProvifer := &configReader{log: log.New("test logger")}
  106. cfg, err := cfgProvifer.readConfig("./invalid-directory")
  107. if err != nil {
  108. t.Fatalf("readConfig return an error %v", err)
  109. }
  110. So(len(cfg), ShouldEqual, 0)
  111. })
  112. Convey("can read all properties from version 1", func() {
  113. cfgProvifer := &configReader{log: log.New("test logger")}
  114. cfg, err := cfgProvifer.readConfig(allProperties)
  115. if err != nil {
  116. t.Fatalf("readConfig return an error %v", err)
  117. }
  118. So(len(cfg), ShouldEqual, 3)
  119. dsCfg := cfg[0]
  120. So(dsCfg.ApiVersion, ShouldEqual, 1)
  121. validateDatasource(dsCfg)
  122. validateDeleteDatasources(dsCfg)
  123. dsCount := 0
  124. delDsCount := 0
  125. for _, c := range cfg {
  126. dsCount += len(c.Datasources)
  127. delDsCount += len(c.DeleteDatasources)
  128. }
  129. So(dsCount, ShouldEqual, 2)
  130. So(delDsCount, ShouldEqual, 1)
  131. })
  132. Convey("can read all properties from version 0", func() {
  133. cfgProvifer := &configReader{log: log.New("test logger")}
  134. cfg, err := cfgProvifer.readConfig(versionZero)
  135. if err != nil {
  136. t.Fatalf("readConfig return an error %v", err)
  137. }
  138. So(len(cfg), ShouldEqual, 1)
  139. dsCfg := cfg[0]
  140. So(dsCfg.ApiVersion, ShouldEqual, 0)
  141. validateDatasource(dsCfg)
  142. validateDeleteDatasources(dsCfg)
  143. })
  144. })
  145. }
  146. func validateDeleteDatasources(dsCfg *DatasourcesAsConfig) {
  147. So(len(dsCfg.DeleteDatasources), ShouldEqual, 1)
  148. deleteDs := dsCfg.DeleteDatasources[0]
  149. So(deleteDs.Name, ShouldEqual, "old-graphite3")
  150. So(deleteDs.OrgId, ShouldEqual, 2)
  151. }
  152. func validateDatasource(dsCfg *DatasourcesAsConfig) {
  153. ds := dsCfg.Datasources[0]
  154. So(ds.Name, ShouldEqual, "name")
  155. So(ds.Type, ShouldEqual, "type")
  156. So(ds.Access, ShouldEqual, models.DS_ACCESS_PROXY)
  157. So(ds.OrgId, ShouldEqual, 2)
  158. So(ds.Url, ShouldEqual, "url")
  159. So(ds.User, ShouldEqual, "user")
  160. So(ds.Password, ShouldEqual, "password")
  161. So(ds.Database, ShouldEqual, "database")
  162. So(ds.BasicAuth, ShouldBeTrue)
  163. So(ds.BasicAuthUser, ShouldEqual, "basic_auth_user")
  164. So(ds.BasicAuthPassword, ShouldEqual, "basic_auth_password")
  165. So(ds.WithCredentials, ShouldBeTrue)
  166. So(ds.IsDefault, ShouldBeTrue)
  167. So(ds.Editable, ShouldBeTrue)
  168. So(ds.Version, ShouldEqual, 10)
  169. So(len(ds.JsonData), ShouldBeGreaterThan, 2)
  170. So(ds.JsonData["graphiteVersion"], ShouldEqual, "1.1")
  171. So(ds.JsonData["tlsAuth"], ShouldEqual, true)
  172. So(ds.JsonData["tlsAuthWithCACert"], ShouldEqual, true)
  173. So(len(ds.SecureJsonData), ShouldBeGreaterThan, 2)
  174. So(ds.SecureJsonData["tlsCACert"], ShouldEqual, "MjNOcW9RdkbUDHZmpco2HCYzVq9dE+i6Yi+gmUJotq5CDA==")
  175. So(ds.SecureJsonData["tlsClientCert"], ShouldEqual, "ckN0dGlyMXN503YNfjTcf9CV+GGQneN+xmAclQ==")
  176. So(ds.SecureJsonData["tlsClientKey"], ShouldEqual, "ZkN4aG1aNkja/gKAB1wlnKFIsy2SRDq4slrM0A==")
  177. }
  178. type fakeRepository struct {
  179. inserted []*models.AddDataSourceCommand
  180. deleted []*models.DeleteDataSourceByNameCommand
  181. updated []*models.UpdateDataSourceCommand
  182. loadAll []*models.DataSource
  183. }
  184. func mockDelete(cmd *models.DeleteDataSourceByNameCommand) error {
  185. fakeRepo.deleted = append(fakeRepo.deleted, cmd)
  186. return nil
  187. }
  188. func mockUpdate(cmd *models.UpdateDataSourceCommand) error {
  189. fakeRepo.updated = append(fakeRepo.updated, cmd)
  190. return nil
  191. }
  192. func mockInsert(cmd *models.AddDataSourceCommand) error {
  193. fakeRepo.inserted = append(fakeRepo.inserted, cmd)
  194. return nil
  195. }
  196. func mockGetAll(cmd *models.GetAllDataSourcesQuery) error {
  197. cmd.Result = fakeRepo.loadAll
  198. return nil
  199. }
  200. func mockGet(cmd *models.GetDataSourceByNameQuery) error {
  201. for _, v := range fakeRepo.loadAll {
  202. if cmd.Name == v.Name && cmd.OrgId == v.OrgId {
  203. cmd.Result = v
  204. return nil
  205. }
  206. }
  207. return models.ErrDataSourceNotFound
  208. }