grafana/pkg/services/provisioning/dashboards/config_reader.go
Serge Zaitsev a231c6861c
Chore: Remove bus.Dispatch from provisioning services (#44989)
* make getordbyname a method

* remove one dispatch from plugins provisioner

* remove bus from the plugins provisioner, skip test for now

* remove bus from datasource provisioning

* resolve tests in notifier provisioning

* remove bus from the dashboards provisioning service

* fix missing struct field

* fix getorgbyid method calls

* pass org store into dashboard provisioner

* fix test function prototype

* fix tests

* attempt to fix tests after the rebase

* fix integration test

* avoid using transaction

* remove comments
2022-02-23 11:12:37 +01:00

121 lines
3.0 KiB
Go

package dashboards
import (
"context"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/provisioning/utils"
"gopkg.in/yaml.v2"
)
type configReader struct {
path string
log log.Logger
orgStore utils.OrgStore
}
func (cr *configReader) parseConfigs(file os.FileInfo) ([]*config, error) {
filename, _ := filepath.Abs(filepath.Join(cr.path, file.Name()))
// nolint:gosec
// We can ignore the gosec G304 warning on this one because `filename` comes from ps.Cfg.ProvisioningPath
yamlFile, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
apiVersion := &configVersion{APIVersion: 0}
// We ignore the error here because it errors out for version 0 which does not have apiVersion
// specified (so 0 is default). This can also error in case the apiVersion is not an integer but at the moment
// this does not handle that case and would still go on as if version = 0.
// TODO: return appropriate error in case the apiVersion is specified but isn't integer (or even if it is
// integer > max version?).
_ = yaml.Unmarshal(yamlFile, &apiVersion)
if apiVersion.APIVersion > 0 {
v1 := &configV1{}
err := yaml.Unmarshal(yamlFile, &v1)
if err != nil {
return nil, err
}
if v1 != nil {
return v1.mapToDashboardsAsConfig()
}
} else {
var v0 []*configV0
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 mapV0ToDashboardsAsConfig(v0)
}
}
return []*config{}, nil
}
func (cr *configReader) readConfig(ctx context.Context) ([]*config, error) {
var dashboards []*config
files, err := ioutil.ReadDir(cr.path)
if err != nil {
cr.log.Error("can't read dashboard provisioning files from directory", "path", cr.path, "error", err)
return dashboards, nil
}
for _, file := range files {
if !strings.HasSuffix(file.Name(), ".yaml") && !strings.HasSuffix(file.Name(), ".yml") {
continue
}
parsedDashboards, err := cr.parseConfigs(file)
if err != nil {
return nil, fmt.Errorf("could not parse provisioning config file: %s error: %v", file.Name(), err)
}
if len(parsedDashboards) > 0 {
dashboards = append(dashboards, parsedDashboards...)
}
}
uidUsage := map[string]uint8{}
for _, dashboard := range dashboards {
if dashboard.OrgID == 0 {
dashboard.OrgID = 1
}
if err := utils.CheckOrgExists(ctx, cr.orgStore, dashboard.OrgID); err != nil {
return nil, fmt.Errorf("failed to provision dashboards with %q reader: %w", dashboard.Name, err)
}
if dashboard.Type == "" {
dashboard.Type = "file"
}
if dashboard.UpdateIntervalSeconds == 0 {
dashboard.UpdateIntervalSeconds = 10
}
if len(dashboard.FolderUID) > 0 {
uidUsage[dashboard.FolderUID]++
}
}
for uid, times := range uidUsage {
if times > 1 {
cr.log.Error("the same folder UID is used more than once", "folderUid", uid)
}
}
return dashboards, nil
}