Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alertmanager: Fix custom Grafana templates not defined #9438

Merged

Conversation

santihernandezc
Copy link
Contributor

@santihernandezc santihernandezc commented Sep 26, 2024

As we're using []io.Reader for templates, we can read them only once. This is a problem because we use different structs to execute templates for Mimir and Grafana integrations, and both need the same templates. When we create the Grafana template struct, the templates have already been read, resulting in "template not defined" errors when trying to send notifications with custom templates.

Since we stopped reading templates from disk, there's no advantage in using an io.Reader besides using the interface
github.com/prometheus/alertmanager/template expects in template.Parse().

This PR replaces []io.Reader for templates in favor of []TemplateDefinition, converting them into an io.Reader when calling template.Parse().

Fixes https://github.com/grafana/alerting-squad/issues/929

@santihernandezc santihernandezc added the bug Something isn't working label Sep 26, 2024
@santihernandezc santihernandezc requested review from a team as code owners September 26, 2024 18:32
@@ -95,7 +96,7 @@ func WithCustomFunctions(userID string) template.Option {

// loadTemplates produces a template.Template from several in-memory template files.
// It is adapted from FromGlobs in prometheus/alertmanager: https://github.com/prometheus/alertmanager/blob/9de8ef36755298a68b6ab20244d4369d38bdea99/template/template.go#L67-L95
func loadTemplates(tmpls []io.Reader, options ...template.Option) (*template.Template, error) {
func loadTemplates(tmpls []alertingTemplates.TemplateDefinition, options ...template.Option) (*template.Template, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] I don't think the grafana/alerting types need to leak in here, I think this is cleaner.

Suggested change
func loadTemplates(tmpls []alertingTemplates.TemplateDefinition, options ...template.Option) (*template.Template, error) {
func loadTemplates(tmpls []string, options ...template.Option) (*template.Template, error) {

@santihernandezc santihernandezc force-pushed the santihernandezc/fix_custom_grafana_templates_not_defined branch from f36c7f4 to a9a6969 Compare September 27, 2024 19:01
Copy link
Contributor

@titolins titolins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just added a possible different approach. Will try to test this later today before approving 👍

@@ -433,9 +432,9 @@ func clusterWait(position func() int, timeout time.Duration) func() time.Duratio

// ApplyConfig applies a new configuration to an Alertmanager.
func (am *Alertmanager) ApplyConfig(conf *definition.PostableApiAlertingConfig, tmpls []alertingTemplates.TemplateDefinition, rawCfg string, tmplExternalURL *url.URL, staticHeaders map[string]string) error {
templates := make([]io.Reader, 0, len(tmpls))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is not really the io.Reader, that's just an interface. You could also keep the type signature and create a wrapper that implements Reader - e.g.:

type unlimitedStringReader struct {
    s string
}

func (r *unlimitedStringReader) Read(p []byte) (n int, err error) {
    return strings.NewReader(r.s).Read(p)
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but we don't need this level of abstraction.
We're currently using readers just because we need to pass readers down the pipeline, it's a relic from reading templates from disk. We can do perfectly fine using plain strings.

Copy link
Contributor

@titolins titolins Sep 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a relic from reading templates from disk

Ahh, tks for the context. It does make more sense that we'd like to get rid of it.

I'm testing it now and should approve in a bit 👍

Copy link
Contributor

@rwwiv rwwiv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to see a test that illustrates the fix, but changes LGTM

@santihernandezc santihernandezc force-pushed the santihernandezc/fix_custom_grafana_templates_not_defined branch from d288f39 to a75e0dc Compare September 30, 2024 19:23
@santihernandezc santihernandezc force-pushed the santihernandezc/fix_custom_grafana_templates_not_defined branch from 629ff41 to 71d22dd Compare September 30, 2024 20:19
@santihernandezc santihernandezc merged commit a9f9dc5 into main Sep 30, 2024
29 checks passed
@santihernandezc santihernandezc deleted the santihernandezc/fix_custom_grafana_templates_not_defined branch September 30, 2024 21:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working component/alertmanager
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants