mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
* Alerting: Use a default configuration and periodically poll for new ones Use a default configuration to make sure we always start the grafana instance. Then, regularly poll for new ones. I've also made sure that failures to apply configuration do not stop the Grafana server but instead keep polling until it is a success.
87 lines
2.3 KiB
Go
87 lines
2.3 KiB
Go
package notifier
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/grafana/alerting-api/pkg/api"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
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, errors.Wrap(err, "unable to parse Alertmanager configuration")
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|