diff --git a/CHANGELOG.md b/CHANGELOG.md index 095fe5b00..e6d680c88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Order should be `CHANGE`, `FEATURE`, `ENHANCEMENT`, and `BUGFIX` * [CHANGE] Updates version of Go to 1.22 and Alpine to 3.19.1 in Dockerfiles * [FEATURE] Make rulerAPI Path configurable * [FEATURE] Add tool to deserialize alertmanager state file +* [ENHANCEMENT] Support loading alertmanager templates from different directories * [BUGFIX] Set tenant id in prom analyse command ## v0.11.1 diff --git a/pkg/commands/alerts.go b/pkg/commands/alerts.go index 61d3b2845..ba5950fb5 100644 --- a/pkg/commands/alerts.go +++ b/pkg/commands/alerts.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "os/signal" + "path/filepath" "strings" "time" @@ -120,16 +121,29 @@ func (a *AlertmanagerCommand) loadConfig(_ *kingpin.ParseContext) error { return err } - templates := map[string]string{} - for _, f := range a.TemplateFiles { + templates, err := createTemplates(a.TemplateFiles) + if err != nil { + return err + } + + return a.cli.CreateAlertmanagerConfig(context.Background(), cfg, templates) +} + +func createTemplates(templateFiles []string) (map[string]string, error) { + templates := make(map[string]string) + for _, f := range templateFiles { tmpl, err := os.ReadFile(f) if err != nil { - return errors.Wrap(err, "unable to load template file: "+f) + return nil, errors.Wrap(err, "unable to load template file: "+f) } - templates[f] = string(tmpl) - } - return a.cli.CreateAlertmanagerConfig(context.Background(), cfg, templates) + baseName := filepath.Base(f) + if _, ok := templates[baseName]; ok { + return nil, fmt.Errorf("duplicate template file name: %s", baseName) + } + templates[baseName] = string(tmpl) + } + return templates, nil } func (a *AlertmanagerCommand) deleteConfig(_ *kingpin.ParseContext) error { diff --git a/pkg/commands/alerts_test.go b/pkg/commands/alerts_test.go new file mode 100644 index 000000000..cf6d511ca --- /dev/null +++ b/pkg/commands/alerts_test.go @@ -0,0 +1,76 @@ +package commands + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +func TestCreateTemplates(t *testing.T) { + // Create a temporary file + tmpfile, err := os.CreateTemp("", "template") + if err != nil { + t.Fatal(err) + } + defer os.Remove(tmpfile.Name()) // clean up + + // Write some data to the file + text := "This is a test template" + if _, err := tmpfile.Write([]byte(text)); err != nil { + t.Fatal(err) + } + if err := tmpfile.Close(); err != nil { + t.Fatal(err) + } + + // Call createTemplates + templates, err := createTemplates([]string{tmpfile.Name()}) + if err != nil { + t.Fatal(err) + } + + // Check the returned map + if len(templates) != 1 { + t.Fatalf("Expected 1 template, got %d", len(templates)) + } + if templates[filepath.Base(tmpfile.Name())] != text { + t.Fatalf("Expected template content to be '%s', got '%s'", text, templates[filepath.Base(tmpfile.Name())]) + } +} + +func TestCreateTemplates_DuplicateFilenames(t *testing.T) { + // Create two temporary files with the same base name in different directories + dir1 := filepath.Join(os.TempDir(), "dir1") + if err := os.Mkdir(dir1, 0755); err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir1) // clean up + tmpfile1, err := os.Create(filepath.Join(os.TempDir(), "dir1", "fool.tmpl")) + if err != nil { + t.Fatal(err) + } + defer os.Remove(tmpfile1.Name()) // clean up + + dir2 := filepath.Join(os.TempDir(), "dir2") + if err := os.Mkdir(dir2, 0755); err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir2) // clean up + tmpfile2, err := os.Create(filepath.Join(os.TempDir(), "dir2", "fool.tmpl")) + if err != nil { + t.Fatal(err) + } + defer os.Remove(tmpfile2.Name()) // clean up + + // Call createTemplates + _, err = createTemplates([]string{tmpfile1.Name(), tmpfile2.Name()}) + if err == nil { + t.Fatal("Expected error due to duplicate filenames, got nil") + } + + // Check that the error message contains "duplicate template file name" + if !strings.Contains(err.Error(), "duplicate template file name") { + t.Fatalf("Expected error message to contain 'duplicate template file name', got '%s'", err.Error()) + } +}