The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
grafana/pkg/services/provisioning/dashboards/config_reader.go

119 lines
3.0 KiB

package dashboards
import (
"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
}
func (cr *configReader) parseConfigs(file os.FileInfo) ([]*config, error) {
filename, _ := filepath.Abs(filepath.Join(cr.path, file.Name()))
Security: Add gosec G304 auditing annotations (#29578) * Security: Add gosec G304 auditing annotations Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * add G304 auditing comment Signed-off-by: bergquist <carl.bergquist@gmail.com> * add G304 auditing comment Signed-off-by: bergquist <carl.bergquist@gmail.com> * add G304 auditing comment Signed-off-by: bergquist <carl.bergquist@gmail.com> * add G304 auditing comment Signed-off-by: bergquist <carl.bergquist@gmail.com> * add G304 auditing comment Signed-off-by: bergquist <carl.bergquist@gmail.com> * add G304 auditing comment Signed-off-by: bergquist <carl.bergquist@gmail.com> * add G304 auditing comment Signed-off-by: bergquist <carl.bergquist@gmail.com> * add G304 auditing comment Signed-off-by: bergquist <carl.bergquist@gmail.com> * Add gosec annotations Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * add G304 auditing comment Signed-off-by: bergquist <carl.bergquist@gmail.com> * add G304 auditing comment Signed-off-by: bergquist <carl.bergquist@gmail.com> * Add gosec annotations Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * add G304 auditing comment Signed-off-by: bergquist <carl.bergquist@gmail.com> * add G304 auditing comment Signed-off-by: bergquist <carl.bergquist@gmail.com> * add G304 auditing comment Signed-off-by: bergquist <carl.bergquist@gmail.com> * Add gosec annotations Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * space Signed-off-by: bergquist <carl.bergquist@gmail.com> * Add gosec annotations Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> Co-authored-by: bergquist <carl.bergquist@gmail.com>
5 years ago
// 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() ([]*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(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 'folderUid' is used more than once", "folderUid", uid)
}
}
return dashboards, nil
}