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/ngalert/notifier/config.go

84 lines
2.3 KiB

package notifier
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/grafana/grafana/pkg/infra/log"
api "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
)
func PersistTemplates(cfg *api.PostableUserConfig, path string) ([]string, bool, error) {
if len(cfg.TemplateFiles) < 1 {
return nil, false, nil
}
var templatesChanged bool
pathSet := map[string]struct{}{}
for name, content := range cfg.TemplateFiles {
if name != filepath.Base(filepath.Clean(name)) {
return nil, false, fmt.Errorf("template file name '%s' is not valid", name)
}
err := os.MkdirAll(path, 0750)
if err != nil {
return nil, false, fmt.Errorf("unable to create template directory %q: %s", path, err)
}
file := filepath.Join(path, name)
pathSet[file] = struct{}{}
// Check if the template file already exists and if it has changed
// We can safeily ignore gosec here and we've previously checked the filename is clean
// nolint:gosec
if tmpl, err := ioutil.ReadFile(file); err == nil && string(tmpl) == content {
// Templates file is the same we have, no-op and continue.
continue
} else if err != nil && !os.IsNotExist(err) {
return nil, false, err
}
if err := ioutil.WriteFile(file, []byte(content), 0644); err != nil {
return nil, false, fmt.Errorf("unable to create Alertmanager template file %q: %s", file, err)
}
// nolint:gosec
templatesChanged = true
}
// Now that we have the list of _actual_ templates, let's remove the ones that we don't need.
existingFiles, err := ioutil.ReadDir(path)
if err != nil {
log.Error("unable to read directory for deleting Alertmanager templates", "err", err, "path", path)
}
for _, existingFile := range existingFiles {
p := filepath.Join(path, existingFile.Name())
_, ok := pathSet[p]
if !ok {
templatesChanged = true
err := os.Remove(p)
if err != nil {
log.Error("unable to delete template", "err", err, "file", p)
}
}
}
paths := make([]string, 0, len(pathSet))
for path := range pathSet {
paths = append(paths, path)
}
return paths, templatesChanged, nil
}
func Load(rawConfig []byte) (*api.PostableUserConfig, error) {
cfg := &api.PostableUserConfig{}
if err := json.Unmarshal(rawConfig, cfg); err != nil {
return nil, fmt.Errorf("unable to parse Alertmanager configuration: %w", err)
}
return cfg, nil
}