mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge pull request #10896 from bergquist/provisioning_cfg_camelCase
Change naming format to camelCase for provisioning configs
This commit is contained in:
@@ -2,6 +2,7 @@ package dashboards
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@@ -14,11 +15,48 @@ type configReader struct {
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func (cr *configReader) parseConfigs(file os.FileInfo) ([]*DashboardsAsConfig, error) {
|
||||
filename, _ := filepath.Abs(filepath.Join(cr.path, file.Name()))
|
||||
yamlFile, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
apiVersion := &ConfigVersion{ApiVersion: 0}
|
||||
yaml.Unmarshal(yamlFile, &apiVersion)
|
||||
|
||||
if apiVersion.ApiVersion > 0 {
|
||||
|
||||
v1 := &DashboardAsConfigV1{}
|
||||
err := yaml.Unmarshal(yamlFile, &v1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if v1 != nil {
|
||||
return v1.mapToDashboardAsConfig(), nil
|
||||
}
|
||||
|
||||
} else {
|
||||
var v0 []*DashboardsAsConfigV0
|
||||
err := yaml.Unmarshal(yamlFile, &v0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if v0 != nil {
|
||||
cr.log.Warn("[Deprecated] the dashboard provisioning config is outdated. please upgrade", "filename", filename)
|
||||
return mapV0ToDashboardAsConfig(v0), nil
|
||||
}
|
||||
}
|
||||
|
||||
return []*DashboardsAsConfig{}, nil
|
||||
}
|
||||
|
||||
func (cr *configReader) readConfig() ([]*DashboardsAsConfig, error) {
|
||||
var dashboards []*DashboardsAsConfig
|
||||
|
||||
files, err := ioutil.ReadDir(cr.path)
|
||||
|
||||
if err != nil {
|
||||
cr.log.Error("cant read dashboard provisioning files from directory", "path", cr.path)
|
||||
return dashboards, nil
|
||||
@@ -29,19 +67,14 @@ func (cr *configReader) readConfig() ([]*DashboardsAsConfig, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
filename, _ := filepath.Abs(filepath.Join(cr.path, file.Name()))
|
||||
yamlFile, err := ioutil.ReadFile(filename)
|
||||
parsedDashboards, err := cr.parseConfigs(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
}
|
||||
|
||||
var dashCfg []*DashboardsAsConfig
|
||||
err = yaml.Unmarshal(yamlFile, &dashCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if len(parsedDashboards) > 0 {
|
||||
dashboards = append(dashboards, parsedDashboards...)
|
||||
}
|
||||
|
||||
dashboards = append(dashboards, dashCfg...)
|
||||
}
|
||||
|
||||
for i := range dashboards {
|
||||
|
||||
@@ -9,48 +9,33 @@ import (
|
||||
|
||||
var (
|
||||
simpleDashboardConfig string = "./test-configs/dashboards-from-disk"
|
||||
oldVersion string = "./test-configs/version-0"
|
||||
brokenConfigs string = "./test-configs/broken-configs"
|
||||
)
|
||||
|
||||
func TestDashboardsAsConfig(t *testing.T) {
|
||||
Convey("Dashboards as configuration", t, func() {
|
||||
logger := log.New("test-logger")
|
||||
|
||||
Convey("Can read config file", func() {
|
||||
|
||||
cfgProvider := configReader{path: simpleDashboardConfig, log: log.New("test-logger")}
|
||||
Convey("Can read config file version 1 format", func() {
|
||||
cfgProvider := configReader{path: simpleDashboardConfig, log: logger}
|
||||
cfg, err := cfgProvider.readConfig()
|
||||
if err != nil {
|
||||
t.Fatalf("readConfig return an error %v", err)
|
||||
}
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(len(cfg), ShouldEqual, 2)
|
||||
validateDashboardAsConfig(cfg)
|
||||
})
|
||||
|
||||
ds := cfg[0]
|
||||
Convey("Can read config file in version 0 format", func() {
|
||||
cfgProvider := configReader{path: oldVersion, log: logger}
|
||||
cfg, err := cfgProvider.readConfig()
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(ds.Name, ShouldEqual, "general dashboards")
|
||||
So(ds.Type, ShouldEqual, "file")
|
||||
So(ds.OrgId, ShouldEqual, 2)
|
||||
So(ds.Folder, ShouldEqual, "developers")
|
||||
So(ds.Editable, ShouldBeTrue)
|
||||
|
||||
So(len(ds.Options), ShouldEqual, 1)
|
||||
So(ds.Options["path"], ShouldEqual, "/var/lib/grafana/dashboards")
|
||||
|
||||
ds2 := cfg[1]
|
||||
|
||||
So(ds2.Name, ShouldEqual, "default")
|
||||
So(ds2.Type, ShouldEqual, "file")
|
||||
So(ds2.OrgId, ShouldEqual, 1)
|
||||
So(ds2.Folder, ShouldEqual, "")
|
||||
So(ds2.Editable, ShouldBeFalse)
|
||||
|
||||
So(len(ds2.Options), ShouldEqual, 1)
|
||||
So(ds2.Options["path"], ShouldEqual, "/var/lib/grafana/dashboards")
|
||||
validateDashboardAsConfig(cfg)
|
||||
})
|
||||
|
||||
Convey("Should skip invalid path", func() {
|
||||
|
||||
cfgProvider := configReader{path: "/invalid-directory", log: log.New("test-logger")}
|
||||
cfgProvider := configReader{path: "/invalid-directory", log: logger}
|
||||
cfg, err := cfgProvider.readConfig()
|
||||
if err != nil {
|
||||
t.Fatalf("readConfig return an error %v", err)
|
||||
@@ -61,7 +46,7 @@ func TestDashboardsAsConfig(t *testing.T) {
|
||||
|
||||
Convey("Should skip broken config files", func() {
|
||||
|
||||
cfgProvider := configReader{path: brokenConfigs, log: log.New("test-logger")}
|
||||
cfgProvider := configReader{path: brokenConfigs, log: logger}
|
||||
cfg, err := cfgProvider.readConfig()
|
||||
if err != nil {
|
||||
t.Fatalf("readConfig return an error %v", err)
|
||||
@@ -71,3 +56,23 @@ func TestDashboardsAsConfig(t *testing.T) {
|
||||
})
|
||||
})
|
||||
}
|
||||
func validateDashboardAsConfig(cfg []*DashboardsAsConfig) {
|
||||
So(len(cfg), ShouldEqual, 2)
|
||||
|
||||
ds := cfg[0]
|
||||
So(ds.Name, ShouldEqual, "general dashboards")
|
||||
So(ds.Type, ShouldEqual, "file")
|
||||
So(ds.OrgId, ShouldEqual, 2)
|
||||
So(ds.Folder, ShouldEqual, "developers")
|
||||
So(ds.Editable, ShouldBeTrue)
|
||||
So(len(ds.Options), ShouldEqual, 1)
|
||||
So(ds.Options["path"], ShouldEqual, "/var/lib/grafana/dashboards")
|
||||
ds2 := cfg[1]
|
||||
So(ds2.Name, ShouldEqual, "default")
|
||||
So(ds2.Type, ShouldEqual, "file")
|
||||
So(ds2.OrgId, ShouldEqual, 1)
|
||||
So(ds2.Folder, ShouldEqual, "")
|
||||
So(ds2.Editable, ShouldBeFalse)
|
||||
So(len(ds2.Options), ShouldEqual, 1)
|
||||
So(ds2.Options["path"], ShouldEqual, "/var/lib/grafana/dashboards")
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
apiVersion: 1
|
||||
|
||||
providers:
|
||||
- name: 'general dashboards'
|
||||
org_id: 2
|
||||
orgId: 2
|
||||
folder: 'developers'
|
||||
editable: true
|
||||
type: file
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
- name: 'general dashboards'
|
||||
org_id: 2
|
||||
folder: 'developers'
|
||||
editable: true
|
||||
type: file
|
||||
options:
|
||||
path: /var/lib/grafana/dashboards
|
||||
|
||||
- name: 'default'
|
||||
type: file
|
||||
options:
|
||||
path: /var/lib/grafana/dashboards
|
||||
@@ -10,6 +10,15 @@ import (
|
||||
)
|
||||
|
||||
type DashboardsAsConfig struct {
|
||||
Name string
|
||||
Type string
|
||||
OrgId int64
|
||||
Folder string
|
||||
Editable bool
|
||||
Options map[string]interface{}
|
||||
}
|
||||
|
||||
type DashboardsAsConfigV0 struct {
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Type string `json:"type" yaml:"type"`
|
||||
OrgId int64 `json:"org_id" yaml:"org_id"`
|
||||
@@ -18,6 +27,23 @@ type DashboardsAsConfig struct {
|
||||
Options map[string]interface{} `json:"options" yaml:"options"`
|
||||
}
|
||||
|
||||
type ConfigVersion struct {
|
||||
ApiVersion int64 `json:"apiVersion" yaml:"apiVersion"`
|
||||
}
|
||||
|
||||
type DashboardAsConfigV1 struct {
|
||||
Providers []*DashboardProviderConfigs `json:"providers" yaml:"providers"`
|
||||
}
|
||||
|
||||
type DashboardProviderConfigs struct {
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Type string `json:"type" yaml:"type"`
|
||||
OrgId int64 `json:"orgId" yaml:"orgId"`
|
||||
Folder string `json:"folder" yaml:"folder"`
|
||||
Editable bool `json:"editable" yaml:"editable"`
|
||||
Options map[string]interface{} `json:"options" yaml:"options"`
|
||||
}
|
||||
|
||||
func createDashboardJson(data *simplejson.Json, lastModified time.Time, cfg *DashboardsAsConfig, folderId int64) (*dashboards.SaveDashboardDTO, error) {
|
||||
dash := &dashboards.SaveDashboardDTO{}
|
||||
dash.Dashboard = models.NewDashboardFromJson(data)
|
||||
@@ -36,3 +62,37 @@ func createDashboardJson(data *simplejson.Json, lastModified time.Time, cfg *Das
|
||||
|
||||
return dash, nil
|
||||
}
|
||||
|
||||
func mapV0ToDashboardAsConfig(v0 []*DashboardsAsConfigV0) []*DashboardsAsConfig {
|
||||
var r []*DashboardsAsConfig
|
||||
|
||||
for _, v := range v0 {
|
||||
r = append(r, &DashboardsAsConfig{
|
||||
Name: v.Name,
|
||||
Type: v.Type,
|
||||
OrgId: v.OrgId,
|
||||
Folder: v.Folder,
|
||||
Editable: v.Editable,
|
||||
Options: v.Options,
|
||||
})
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (dc *DashboardAsConfigV1) mapToDashboardAsConfig() []*DashboardsAsConfig {
|
||||
var r []*DashboardsAsConfig
|
||||
|
||||
for _, v := range dc.Providers {
|
||||
r = append(r, &DashboardsAsConfig{
|
||||
Name: v.Name,
|
||||
Type: v.Type,
|
||||
OrgId: v.OrgId,
|
||||
Folder: v.Folder,
|
||||
Editable: v.Editable,
|
||||
Options: v.Options,
|
||||
})
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
109
pkg/services/provisioning/datasources/config_reader.go
Normal file
109
pkg/services/provisioning/datasources/config_reader.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package datasources
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/log"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type configReader struct {
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func (cr *configReader) readConfig(path string) ([]*DatasourcesAsConfig, error) {
|
||||
var datasources []*DatasourcesAsConfig
|
||||
|
||||
files, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
cr.log.Error("cant read datasource provisioning files from directory", "path", path)
|
||||
return datasources, nil
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if strings.HasSuffix(file.Name(), ".yaml") || strings.HasSuffix(file.Name(), ".yml") {
|
||||
datasource, err := cr.parseDatasourceConfig(path, file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if datasource != nil {
|
||||
datasources = append(datasources, datasource)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = validateDefaultUniqueness(datasources)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return datasources, nil
|
||||
}
|
||||
|
||||
func (cr *configReader) parseDatasourceConfig(path string, file os.FileInfo) (*DatasourcesAsConfig, error) {
|
||||
filename, _ := filepath.Abs(filepath.Join(path, file.Name()))
|
||||
yamlFile, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiVersion *ConfigVersion
|
||||
err = yaml.Unmarshal(yamlFile, &apiVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if apiVersion.ApiVersion > 0 {
|
||||
var v1 *DatasourcesAsConfigV1
|
||||
err = yaml.Unmarshal(yamlFile, &v1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return v1.mapToDatasourceFromConfig(apiVersion.ApiVersion), nil
|
||||
}
|
||||
|
||||
var v0 *DatasourcesAsConfigV0
|
||||
err = yaml.Unmarshal(yamlFile, &v0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cr.log.Warn("[Deprecated] the datasource provisioning config is outdated. please upgrade", "filename", filename)
|
||||
|
||||
return v0.mapToDatasourceFromConfig(apiVersion.ApiVersion), nil
|
||||
}
|
||||
|
||||
func validateDefaultUniqueness(datasources []*DatasourcesAsConfig) error {
|
||||
defaultCount := 0
|
||||
for i := range datasources {
|
||||
if datasources[i].Datasources == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, ds := range datasources[i].Datasources {
|
||||
if ds.OrgId == 0 {
|
||||
ds.OrgId = 1
|
||||
}
|
||||
|
||||
if ds.IsDefault {
|
||||
defaultCount++
|
||||
if defaultCount > 1 {
|
||||
return ErrInvalidConfigToManyDefault
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, ds := range datasources[i].DeleteDatasources {
|
||||
if ds.OrgId == 0 {
|
||||
ds.OrgId = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -17,6 +17,7 @@ var (
|
||||
twoDatasourcesConfigPurgeOthers string = "./test-configs/insert-two-delete-two"
|
||||
doubleDatasourcesConfig string = "./test-configs/double-default"
|
||||
allProperties string = "./test-configs/all-properties"
|
||||
versionZero string = "./test-configs/version-0"
|
||||
brokenYaml string = "./test-configs/broken-yaml"
|
||||
|
||||
fakeRepo *fakeRepository
|
||||
@@ -130,7 +131,7 @@ func TestDatasourceAsConfig(t *testing.T) {
|
||||
So(len(cfg), ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("can read all properties", func() {
|
||||
Convey("can read all properties from version 1", func() {
|
||||
cfgProvifer := &configReader{log: log.New("test logger")}
|
||||
cfg, err := cfgProvifer.readConfig(allProperties)
|
||||
if err != nil {
|
||||
@@ -140,38 +141,65 @@ func TestDatasourceAsConfig(t *testing.T) {
|
||||
So(len(cfg), ShouldEqual, 2)
|
||||
|
||||
dsCfg := cfg[0]
|
||||
ds := dsCfg.Datasources[0]
|
||||
|
||||
So(ds.Name, ShouldEqual, "name")
|
||||
So(ds.Type, ShouldEqual, "type")
|
||||
So(ds.Access, ShouldEqual, models.DS_ACCESS_PROXY)
|
||||
So(ds.OrgId, ShouldEqual, 2)
|
||||
So(ds.Url, ShouldEqual, "url")
|
||||
So(ds.User, ShouldEqual, "user")
|
||||
So(ds.Password, ShouldEqual, "password")
|
||||
So(ds.Database, ShouldEqual, "database")
|
||||
So(ds.BasicAuth, ShouldBeTrue)
|
||||
So(ds.BasicAuthUser, ShouldEqual, "basic_auth_user")
|
||||
So(ds.BasicAuthPassword, ShouldEqual, "basic_auth_password")
|
||||
So(ds.WithCredentials, ShouldBeTrue)
|
||||
So(ds.IsDefault, ShouldBeTrue)
|
||||
So(ds.Editable, ShouldBeTrue)
|
||||
So(dsCfg.ApiVersion, ShouldEqual, 1)
|
||||
|
||||
So(len(ds.JsonData), ShouldBeGreaterThan, 2)
|
||||
So(ds.JsonData["graphiteVersion"], ShouldEqual, "1.1")
|
||||
So(ds.JsonData["tlsAuth"], ShouldEqual, true)
|
||||
So(ds.JsonData["tlsAuthWithCACert"], ShouldEqual, true)
|
||||
validateDatasource(dsCfg)
|
||||
validateDeleteDatasources(dsCfg)
|
||||
})
|
||||
|
||||
So(len(ds.SecureJsonData), ShouldBeGreaterThan, 2)
|
||||
So(ds.SecureJsonData["tlsCACert"], ShouldEqual, "MjNOcW9RdkbUDHZmpco2HCYzVq9dE+i6Yi+gmUJotq5CDA==")
|
||||
So(ds.SecureJsonData["tlsClientCert"], ShouldEqual, "ckN0dGlyMXN503YNfjTcf9CV+GGQneN+xmAclQ==")
|
||||
So(ds.SecureJsonData["tlsClientKey"], ShouldEqual, "ZkN4aG1aNkja/gKAB1wlnKFIsy2SRDq4slrM0A==")
|
||||
Convey("can read all properties from version 0", func() {
|
||||
cfgProvifer := &configReader{log: log.New("test logger")}
|
||||
cfg, err := cfgProvifer.readConfig(versionZero)
|
||||
if err != nil {
|
||||
t.Fatalf("readConfig return an error %v", err)
|
||||
}
|
||||
|
||||
dstwo := cfg[1].Datasources[0]
|
||||
So(dstwo.Name, ShouldEqual, "name2")
|
||||
So(len(cfg), ShouldEqual, 1)
|
||||
|
||||
dsCfg := cfg[0]
|
||||
|
||||
So(dsCfg.ApiVersion, ShouldEqual, 0)
|
||||
|
||||
validateDatasource(dsCfg)
|
||||
validateDeleteDatasources(dsCfg)
|
||||
})
|
||||
})
|
||||
}
|
||||
func validateDeleteDatasources(dsCfg *DatasourcesAsConfig) {
|
||||
So(len(dsCfg.DeleteDatasources), ShouldEqual, 1)
|
||||
deleteDs := dsCfg.DeleteDatasources[0]
|
||||
So(deleteDs.Name, ShouldEqual, "old-graphite3")
|
||||
So(deleteDs.OrgId, ShouldEqual, 2)
|
||||
}
|
||||
func validateDatasource(dsCfg *DatasourcesAsConfig) {
|
||||
ds := dsCfg.Datasources[0]
|
||||
So(ds.Name, ShouldEqual, "name")
|
||||
So(ds.Type, ShouldEqual, "type")
|
||||
So(ds.Access, ShouldEqual, models.DS_ACCESS_PROXY)
|
||||
So(ds.OrgId, ShouldEqual, 2)
|
||||
So(ds.Url, ShouldEqual, "url")
|
||||
So(ds.User, ShouldEqual, "user")
|
||||
So(ds.Password, ShouldEqual, "password")
|
||||
So(ds.Database, ShouldEqual, "database")
|
||||
So(ds.BasicAuth, ShouldBeTrue)
|
||||
So(ds.BasicAuthUser, ShouldEqual, "basic_auth_user")
|
||||
So(ds.BasicAuthPassword, ShouldEqual, "basic_auth_password")
|
||||
So(ds.WithCredentials, ShouldBeTrue)
|
||||
So(ds.IsDefault, ShouldBeTrue)
|
||||
So(ds.Editable, ShouldBeTrue)
|
||||
So(ds.Version, ShouldEqual, 10)
|
||||
|
||||
So(len(ds.JsonData), ShouldBeGreaterThan, 2)
|
||||
So(ds.JsonData["graphiteVersion"], ShouldEqual, "1.1")
|
||||
So(ds.JsonData["tlsAuth"], ShouldEqual, true)
|
||||
So(ds.JsonData["tlsAuthWithCACert"], ShouldEqual, true)
|
||||
|
||||
So(len(ds.SecureJsonData), ShouldBeGreaterThan, 2)
|
||||
So(ds.SecureJsonData["tlsCACert"], ShouldEqual, "MjNOcW9RdkbUDHZmpco2HCYzVq9dE+i6Yi+gmUJotq5CDA==")
|
||||
So(ds.SecureJsonData["tlsClientCert"], ShouldEqual, "ckN0dGlyMXN503YNfjTcf9CV+GGQneN+xmAclQ==")
|
||||
So(ds.SecureJsonData["tlsClientKey"], ShouldEqual, "ZkN4aG1aNkja/gKAB1wlnKFIsy2SRDq4slrM0A==")
|
||||
}
|
||||
|
||||
type fakeRepository struct {
|
||||
inserted []*models.AddDataSourceCommand
|
||||
@@ -2,16 +2,12 @@ package datasources
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
|
||||
"github.com/grafana/grafana/pkg/log"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -94,65 +90,3 @@ func (dc *DatasourceProvisioner) deleteDatasources(dsToDelete []*DeleteDatasourc
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type configReader struct {
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func (cr *configReader) readConfig(path string) ([]*DatasourcesAsConfig, error) {
|
||||
var datasources []*DatasourcesAsConfig
|
||||
|
||||
files, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
cr.log.Error("cant read datasource provisioning files from directory", "path", path)
|
||||
return datasources, nil
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var datasource *DatasourcesAsConfig
|
||||
err = yaml.Unmarshal(yamlFile, &datasource)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if datasource != nil {
|
||||
datasources = append(datasources, datasource)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultCount := 0
|
||||
for i := range datasources {
|
||||
if datasources[i].Datasources == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, ds := range datasources[i].Datasources {
|
||||
if ds.OrgId == 0 {
|
||||
ds.OrgId = 1
|
||||
}
|
||||
|
||||
if ds.IsDefault {
|
||||
defaultCount++
|
||||
if defaultCount > 1 {
|
||||
return nil, ErrInvalidConfigToManyDefault
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, ds := range datasources[i].DeleteDatasources {
|
||||
if ds.OrgId == 0 {
|
||||
ds.OrgId = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return datasources, nil
|
||||
}
|
||||
|
||||
@@ -1,23 +1,30 @@
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
- name: name
|
||||
type: type
|
||||
access: proxy
|
||||
org_id: 2
|
||||
orgId: 2
|
||||
url: url
|
||||
password: password
|
||||
user: user
|
||||
database: database
|
||||
basic_auth: true
|
||||
basic_auth_user: basic_auth_user
|
||||
basic_auth_password: basic_auth_password
|
||||
with_credentials: true
|
||||
is_default: true
|
||||
json_data:
|
||||
basicAuth: true
|
||||
basicAuthUser: basic_auth_user
|
||||
basicAuthPassword: basic_auth_password
|
||||
withCredentials: true
|
||||
isDefault: true
|
||||
jsonData:
|
||||
graphiteVersion: "1.1"
|
||||
tlsAuth: true
|
||||
tlsAuthWithCACert: true
|
||||
secure_json_data:
|
||||
secureJsonData:
|
||||
tlsCACert: "MjNOcW9RdkbUDHZmpco2HCYzVq9dE+i6Yi+gmUJotq5CDA=="
|
||||
tlsClientCert: "ckN0dGlyMXN503YNfjTcf9CV+GGQneN+xmAclQ=="
|
||||
tlsClientKey: "ZkN4aG1aNkja/gKAB1wlnKFIsy2SRDq4slrM0A=="
|
||||
editable: true
|
||||
version: 10
|
||||
|
||||
deleteDatasources:
|
||||
- name: old-graphite3
|
||||
orgId: 2
|
||||
|
||||
@@ -3,5 +3,5 @@ datasources:
|
||||
- name: name2
|
||||
type: type2
|
||||
access: proxy
|
||||
org_id: 2
|
||||
orgId: 2
|
||||
url: url2
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
datasources:
|
||||
- name: name
|
||||
type: type
|
||||
access: proxy
|
||||
org_id: 2
|
||||
url: url
|
||||
password: password
|
||||
user: user
|
||||
database: database
|
||||
basic_auth: true
|
||||
basic_auth_user: basic_auth_user
|
||||
basic_auth_password: basic_auth_password
|
||||
with_credentials: true
|
||||
is_default: true
|
||||
json_data:
|
||||
graphiteVersion: "1.1"
|
||||
tlsAuth: true
|
||||
tlsAuthWithCACert: true
|
||||
secure_json_data:
|
||||
tlsCACert: "MjNOcW9RdkbUDHZmpco2HCYzVq9dE+i6Yi+gmUJotq5CDA=="
|
||||
tlsClientCert: "ckN0dGlyMXN503YNfjTcf9CV+GGQneN+xmAclQ=="
|
||||
tlsClientKey: "ZkN4aG1aNkja/gKAB1wlnKFIsy2SRDq4slrM0A=="
|
||||
editable: true
|
||||
version: 10
|
||||
|
||||
delete_datasources:
|
||||
- name: old-graphite3
|
||||
org_id: 2
|
||||
@@ -1,22 +1,74 @@
|
||||
package datasources
|
||||
|
||||
import "github.com/grafana/grafana/pkg/models"
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
import "github.com/grafana/grafana/pkg/components/simplejson"
|
||||
|
||||
type ConfigVersion struct {
|
||||
ApiVersion int64 `json:"apiVersion" yaml:"apiVersion"`
|
||||
}
|
||||
|
||||
type DatasourcesAsConfig struct {
|
||||
Datasources []*DataSourceFromConfig `json:"datasources" yaml:"datasources"`
|
||||
DeleteDatasources []*DeleteDatasourceConfig `json:"delete_datasources" yaml:"delete_datasources"`
|
||||
ApiVersion int64
|
||||
|
||||
Datasources []*DataSourceFromConfig
|
||||
DeleteDatasources []*DeleteDatasourceConfig
|
||||
}
|
||||
|
||||
type DeleteDatasourceConfig struct {
|
||||
OrgId int64
|
||||
Name string
|
||||
}
|
||||
|
||||
type DataSourceFromConfig struct {
|
||||
OrgId int64
|
||||
Version int
|
||||
|
||||
Name string
|
||||
Type string
|
||||
Access string
|
||||
Url string
|
||||
Password string
|
||||
User string
|
||||
Database string
|
||||
BasicAuth bool
|
||||
BasicAuthUser string
|
||||
BasicAuthPassword string
|
||||
WithCredentials bool
|
||||
IsDefault bool
|
||||
JsonData map[string]interface{}
|
||||
SecureJsonData map[string]string
|
||||
Editable bool
|
||||
}
|
||||
|
||||
type DatasourcesAsConfigV0 struct {
|
||||
ConfigVersion
|
||||
|
||||
Datasources []*DataSourceFromConfigV0 `json:"datasources" yaml:"datasources"`
|
||||
DeleteDatasources []*DeleteDatasourceConfigV0 `json:"delete_datasources" yaml:"delete_datasources"`
|
||||
}
|
||||
|
||||
type DatasourcesAsConfigV1 struct {
|
||||
ConfigVersion
|
||||
|
||||
Datasources []*DataSourceFromConfigV1 `json:"datasources" yaml:"datasources"`
|
||||
DeleteDatasources []*DeleteDatasourceConfigV1 `json:"deleteDatasources" yaml:"deleteDatasources"`
|
||||
}
|
||||
|
||||
type DeleteDatasourceConfigV0 struct {
|
||||
OrgId int64 `json:"org_id" yaml:"org_id"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
}
|
||||
|
||||
type DataSourceFromConfig struct {
|
||||
OrgId int64 `json:"org_id" yaml:"org_id"`
|
||||
Version int `json:"version" yaml:"version"`
|
||||
type DeleteDatasourceConfigV1 struct {
|
||||
OrgId int64 `json:"orgId" yaml:"orgId"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
}
|
||||
|
||||
type DataSourceFromConfigV0 struct {
|
||||
OrgId int64 `json:"org_id" yaml:"org_id"`
|
||||
Version int `json:"version" yaml:"version"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Type string `json:"type" yaml:"type"`
|
||||
Access string `json:"access" yaml:"access"`
|
||||
@@ -34,6 +86,100 @@ type DataSourceFromConfig struct {
|
||||
Editable bool `json:"editable" yaml:"editable"`
|
||||
}
|
||||
|
||||
type DataSourceFromConfigV1 struct {
|
||||
OrgId int64 `json:"orgId" yaml:"orgId"`
|
||||
Version int `json:"version" yaml:"version"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Type string `json:"type" yaml:"type"`
|
||||
Access string `json:"access" yaml:"access"`
|
||||
Url string `json:"url" yaml:"url"`
|
||||
Password string `json:"password" yaml:"password"`
|
||||
User string `json:"user" yaml:"user"`
|
||||
Database string `json:"database" yaml:"database"`
|
||||
BasicAuth bool `json:"basicAuth" yaml:"basicAuth"`
|
||||
BasicAuthUser string `json:"basicAuthUser" yaml:"basicAuthUser"`
|
||||
BasicAuthPassword string `json:"basicAuthPassword" yaml:"basicAuthPassword"`
|
||||
WithCredentials bool `json:"withCredentials" yaml:"withCredentials"`
|
||||
IsDefault bool `json:"isDefault" yaml:"isDefault"`
|
||||
JsonData map[string]interface{} `json:"jsonData" yaml:"jsonData"`
|
||||
SecureJsonData map[string]string `json:"secureJsonData" yaml:"secureJsonData"`
|
||||
Editable bool `json:"editable" yaml:"editable"`
|
||||
}
|
||||
|
||||
func (cfg *DatasourcesAsConfigV1) mapToDatasourceFromConfig(apiVersion int64) *DatasourcesAsConfig {
|
||||
r := &DatasourcesAsConfig{}
|
||||
|
||||
r.ApiVersion = apiVersion
|
||||
|
||||
for _, ds := range cfg.Datasources {
|
||||
r.Datasources = append(r.Datasources, &DataSourceFromConfig{
|
||||
OrgId: ds.OrgId,
|
||||
Name: ds.Name,
|
||||
Type: ds.Type,
|
||||
Access: ds.Access,
|
||||
Url: ds.Url,
|
||||
Password: ds.Password,
|
||||
User: ds.User,
|
||||
Database: ds.Database,
|
||||
BasicAuth: ds.BasicAuth,
|
||||
BasicAuthUser: ds.BasicAuthUser,
|
||||
BasicAuthPassword: ds.BasicAuthPassword,
|
||||
WithCredentials: ds.WithCredentials,
|
||||
IsDefault: ds.IsDefault,
|
||||
JsonData: ds.JsonData,
|
||||
SecureJsonData: ds.SecureJsonData,
|
||||
Editable: ds.Editable,
|
||||
Version: ds.Version,
|
||||
})
|
||||
}
|
||||
|
||||
for _, ds := range cfg.DeleteDatasources {
|
||||
r.DeleteDatasources = append(r.DeleteDatasources, &DeleteDatasourceConfig{
|
||||
OrgId: ds.OrgId,
|
||||
Name: ds.Name,
|
||||
})
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (cfg *DatasourcesAsConfigV0) mapToDatasourceFromConfig(apiVersion int64) *DatasourcesAsConfig {
|
||||
r := &DatasourcesAsConfig{}
|
||||
|
||||
r.ApiVersion = apiVersion
|
||||
|
||||
for _, ds := range cfg.Datasources {
|
||||
r.Datasources = append(r.Datasources, &DataSourceFromConfig{
|
||||
OrgId: ds.OrgId,
|
||||
Name: ds.Name,
|
||||
Type: ds.Type,
|
||||
Access: ds.Access,
|
||||
Url: ds.Url,
|
||||
Password: ds.Password,
|
||||
User: ds.User,
|
||||
Database: ds.Database,
|
||||
BasicAuth: ds.BasicAuth,
|
||||
BasicAuthUser: ds.BasicAuthUser,
|
||||
BasicAuthPassword: ds.BasicAuthPassword,
|
||||
WithCredentials: ds.WithCredentials,
|
||||
IsDefault: ds.IsDefault,
|
||||
JsonData: ds.JsonData,
|
||||
SecureJsonData: ds.SecureJsonData,
|
||||
Editable: ds.Editable,
|
||||
Version: ds.Version,
|
||||
})
|
||||
}
|
||||
|
||||
for _, ds := range cfg.DeleteDatasources {
|
||||
r.DeleteDatasources = append(r.DeleteDatasources, &DeleteDatasourceConfig{
|
||||
OrgId: ds.OrgId,
|
||||
Name: ds.Name,
|
||||
})
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func createInsertCommand(ds *DataSourceFromConfig) *models.AddDataSourceCommand {
|
||||
jsonData := simplejson.New()
|
||||
if len(ds.JsonData) > 0 {
|
||||
|
||||
Reference in New Issue
Block a user