|
|
@@ -4,6 +4,7 @@ import (
|
|
|
"errors"
|
|
|
"io/ioutil"
|
|
|
"path/filepath"
|
|
|
+ "strings"
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/bus"
|
|
|
|
|
|
@@ -17,67 +18,36 @@ var (
|
|
|
ErrInvalidConfigToManyDefault = errors.New("datasource.yaml config is invalid. Only one datasource can be marked as default")
|
|
|
)
|
|
|
|
|
|
-func Apply(configPath string) error {
|
|
|
- dc := NewDatasourceConfiguration()
|
|
|
- return dc.applyChanges(configPath)
|
|
|
+func Provision(configDirectory string) error {
|
|
|
+ dc := newDatasourceProvisioner(log.New("provisioning.datasources"))
|
|
|
+ return dc.applyChanges(configDirectory)
|
|
|
}
|
|
|
|
|
|
-type DatasourceConfigurator struct {
|
|
|
+type DatasourceProvisioner struct {
|
|
|
log log.Logger
|
|
|
- cfgProvider configProvider
|
|
|
+ cfgProvider configReader
|
|
|
}
|
|
|
|
|
|
-func NewDatasourceConfiguration() DatasourceConfigurator {
|
|
|
- return newDatasourceConfiguration(log.New("setting.datasource"))
|
|
|
-}
|
|
|
-
|
|
|
-func newDatasourceConfiguration(log log.Logger) DatasourceConfigurator {
|
|
|
- return DatasourceConfigurator{
|
|
|
+func newDatasourceProvisioner(log log.Logger) DatasourceProvisioner {
|
|
|
+ return DatasourceProvisioner{
|
|
|
log: log,
|
|
|
- cfgProvider: configProvider{},
|
|
|
+ cfgProvider: configReader{},
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func (dc *DatasourceConfigurator) applyChanges(configPath string) error {
|
|
|
- cfg, err := dc.cfgProvider.readConfig(configPath)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- defaultCount := 0
|
|
|
- for i := range cfg.Datasources {
|
|
|
- if cfg.Datasources[i].OrgId == 0 {
|
|
|
- cfg.Datasources[i].OrgId = 1
|
|
|
- }
|
|
|
-
|
|
|
- if cfg.Datasources[i].IsDefault {
|
|
|
- defaultCount++
|
|
|
- if defaultCount > 1 {
|
|
|
- return ErrInvalidConfigToManyDefault
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- cmd := &models.GetAllDataSourcesQuery{}
|
|
|
- if err = bus.Dispatch(cmd); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- allDatasources := cmd.Result
|
|
|
-
|
|
|
- if err := dc.deleteDatasourcesNotInConfiguration(cfg, allDatasources); err != nil {
|
|
|
+func (dc *DatasourceProvisioner) apply(cfg *DatasourcesAsConfig) error {
|
|
|
+ if err := dc.deleteDatasources(cfg.DeleteDatasources); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
for _, ds := range cfg.Datasources {
|
|
|
- var dbDatasource *models.DataSource
|
|
|
- for _, ddd := range allDatasources {
|
|
|
- if ddd.Name == ds.Name && ddd.OrgId == ds.OrgId {
|
|
|
- dbDatasource = ddd
|
|
|
- break
|
|
|
- }
|
|
|
+ cmd := &models.GetDataSourceByNameQuery{OrgId: ds.OrgId, Name: ds.Name}
|
|
|
+ err := bus.Dispatch(cmd)
|
|
|
+ if err != nil && err != models.ErrDataSourceNotFound {
|
|
|
+ return err
|
|
|
}
|
|
|
|
|
|
- if dbDatasource == nil {
|
|
|
+ if err == models.ErrDataSourceNotFound {
|
|
|
dc.log.Info("inserting datasource from configuration ", "name", ds.Name)
|
|
|
insertCmd := createInsertCommand(ds)
|
|
|
if err := bus.Dispatch(insertCmd); err != nil {
|
|
|
@@ -85,7 +55,7 @@ func (dc *DatasourceConfigurator) applyChanges(configPath string) error {
|
|
|
}
|
|
|
} else {
|
|
|
dc.log.Debug("updating datasource from configuration", "name", ds.Name)
|
|
|
- updateCmd := createUpdateCommand(ds, dbDatasource.Id)
|
|
|
+ updateCmd := createUpdateCommand(ds, cmd.Result.Id)
|
|
|
if err := bus.Dispatch(updateCmd); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
@@ -95,44 +65,83 @@ func (dc *DatasourceConfigurator) applyChanges(configPath string) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-func (dc *DatasourceConfigurator) deleteDatasourcesNotInConfiguration(cfg *DatasourcesAsConfig, allDatasources []*models.DataSource) error {
|
|
|
- if cfg.PurgeOtherDatasources {
|
|
|
- for _, dbDS := range allDatasources {
|
|
|
- delete := true
|
|
|
- for _, cfgDS := range cfg.Datasources {
|
|
|
- if dbDS.Name == cfgDS.Name && dbDS.OrgId == cfgDS.OrgId {
|
|
|
- delete = false
|
|
|
- }
|
|
|
- }
|
|
|
+func (dc *DatasourceProvisioner) applyChanges(configPath string) error {
|
|
|
+ configs, err := dc.cfgProvider.readConfig(configPath)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
|
|
|
- if delete {
|
|
|
- dc.log.Info("deleting datasource from configuration", "name", dbDS.Name)
|
|
|
- cmd := &models.DeleteDataSourceByIdCommand{Id: dbDS.Id, OrgId: dbDS.OrgId}
|
|
|
- if err := bus.Dispatch(cmd); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- }
|
|
|
+ for _, cfg := range configs {
|
|
|
+ if err := dc.apply(cfg); err != nil {
|
|
|
+ return err
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-type configProvider struct{}
|
|
|
+func (dc *DatasourceProvisioner) deleteDatasources(dsToDelete []*DeleteDatasourceConfig) error {
|
|
|
+ for _, ds := range dsToDelete {
|
|
|
+ cmd := &models.DeleteDataSourceByNameCommand{OrgId: ds.OrgId, Name: ds.Name}
|
|
|
+ if err := bus.Dispatch(cmd); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ if cmd.DeletedDatasourcesCount > 0 {
|
|
|
+ dc.log.Info("deleted datasource based on configuration", "name", ds.Name)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
|
|
|
-func (configProvider) readConfig(path string) (*DatasourcesAsConfig, error) {
|
|
|
- filename, _ := filepath.Abs(path)
|
|
|
- yamlFile, err := ioutil.ReadFile(filename)
|
|
|
+type configReader struct{}
|
|
|
|
|
|
+func (configReader) readConfig(path string) ([]*DatasourcesAsConfig, error) {
|
|
|
+ files, err := ioutil.ReadDir(path)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
- var datasources *DatasourcesAsConfig
|
|
|
+ var datasources []*DatasourcesAsConfig
|
|
|
+ for _, file := range files {
|
|
|
+ if strings.HasSuffix(file.Name(), ".yaml") || strings.HasSuffix(file.Name(), ".yml") {
|
|
|
+ filename, _ := filepath.Abs(filepath.Join(path, file.Name()))
|
|
|
+ yamlFile, err := ioutil.ReadFile(filename)
|
|
|
|
|
|
- err = yaml.Unmarshal(yamlFile, &datasources)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ var datasource *DatasourcesAsConfig
|
|
|
+ err = yaml.Unmarshal(yamlFile, &datasource)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ datasources = append(datasources, datasource)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ defaultCount := 0
|
|
|
+ for _, cfg := range datasources {
|
|
|
+ for _, ds := range cfg.Datasources {
|
|
|
+ if ds.OrgId == 0 {
|
|
|
+ ds.OrgId = 1
|
|
|
+ }
|
|
|
+
|
|
|
+ if ds.IsDefault {
|
|
|
+ defaultCount++
|
|
|
+ if defaultCount > 1 {
|
|
|
+ return nil, ErrInvalidConfigToManyDefault
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, ds := range cfg.DeleteDatasources {
|
|
|
+ if ds.OrgId == 0 {
|
|
|
+ ds.OrgId = 1
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return datasources, nil
|