Skip to content

Commit d903963

Browse files
Changes related to supporting Pager Duty as a receiver
Signed-off-by: Anand Rajagopal <anrajag@amazon.com>
1 parent f2f2f07 commit d903963

17 files changed

+2060
-67
lines changed

cmd/alertmanager/main.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ import (
3030
"syscall"
3131
"time"
3232

33+
"github.com/prometheus/alertmanager/secrets"
34+
"github.com/prometheus/alertmanager/secrets/providers"
35+
3336
"github.com/KimMachineGun/automemlimit/memlimit"
3437
"github.com/alecthomas/kingpin/v2"
3538
"github.com/prometheus/client_golang/prometheus"
@@ -402,8 +405,9 @@ func run() int {
402405
}
403406

404407
var (
405-
inhibitor *inhibit.Inhibitor
406-
tmpl *template.Template
408+
inhibitor *inhibit.Inhibitor
409+
tmpl *template.Template
410+
secretsProviderRegistry *secrets.SecretsProviderRegistry
407411
)
408412

409413
dispMetrics := dispatch.NewDispatcherMetrics(false, prometheus.DefaultRegisterer)
@@ -414,6 +418,9 @@ func run() int {
414418
prometheus.DefaultRegisterer,
415419
configLogger,
416420
)
421+
defer func() {
422+
secretsProviderRegistry.Stop()
423+
}()
417424
configCoordinator.Subscribe(func(conf *config.Config) error {
418425
tmpl, err = template.FromGlobs(conf.Templates)
419426
if err != nil {
@@ -428,6 +435,15 @@ func run() int {
428435
activeReceivers[r.RouteOpts.Receiver] = struct{}{}
429436
})
430437

438+
if secretsProviderRegistry == nil {
439+
secretsProviderRegistry = secrets.NewSecretsProviderRegistry(logger, prometheus.NewRegistry())
440+
// currently only one secrets provider is registered. Inline secrets provider is always available
441+
if secretsProviderRegistry.Register(providers.AWSSecretsManagerSecretProviderDiscoveryConfig{}) != nil {
442+
configLogger.Error("failed to register secrets provider", "err", err)
443+
}
444+
secretsProviderRegistry.Init()
445+
}
446+
431447
// Build the map of receiver to integrations.
432448
receivers := make(map[string][]notify.Integration, len(activeReceivers))
433449
var integrationsNum int
@@ -437,7 +453,7 @@ func run() int {
437453
configLogger.Info("skipping creation of receiver not referenced by any route", "receiver", rcv.Name)
438454
continue
439455
}
440-
integrations, err := receiver.BuildReceiverIntegrations(rcv, tmpl, logger)
456+
integrations, err := receiver.BuildReceiverIntegrations(rcv, tmpl, logger, secretsProviderRegistry)
441457
if err != nil {
442458
return err
443459
}
@@ -463,7 +479,6 @@ func run() int {
463479

464480
inhibitor = inhibit.NewInhibitor(alerts, conf.InhibitRules, marker, logger)
465481
silencer := silence.NewSilencer(silences, marker, logger)
466-
467482
// An interface value that holds a nil concrete value is non-nil.
468483
// Therefore we explicly pass an empty interface, to detect if the
469484
// cluster is not enabled in notify.
@@ -522,7 +537,7 @@ func run() int {
522537

523538
go disp.Run()
524539
go inhibitor.Run()
525-
540+
secretsProviderRegistry.UpdateComplete()
526541
return nil
527542
})
528543

config/config_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323
"testing"
2424
"time"
2525

26+
"github.com/prometheus/alertmanager/secrets"
27+
2628
commoncfg "github.com/prometheus/common/config"
2729
"github.com/prometheus/common/model"
2830
"github.com/prometheus/common/promslog"
@@ -528,6 +530,8 @@ func TestHideConfigSecrets(t *testing.T) {
528530
func TestShowMarshalSecretValues(t *testing.T) {
529531
MarshalSecretValue = true
530532
defer func() { MarshalSecretValue = false }()
533+
secrets.MarshalSecretValue = true
534+
defer func() { secrets.MarshalSecretValue = false }()
531535

532536
c, err := LoadFile("testdata/conf.good.yml")
533537
if err != nil {

config/notifiers.go

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"text/template"
2323
"time"
2424

25+
"github.com/prometheus/alertmanager/secrets"
26+
2527
commoncfg "github.com/prometheus/common/config"
2628
"github.com/prometheus/common/model"
2729
"github.com/prometheus/sigv4"
@@ -328,22 +330,22 @@ type PagerdutyConfig struct {
328330

329331
HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
330332

331-
ServiceKey Secret `yaml:"service_key,omitempty" json:"service_key,omitempty"`
332-
ServiceKeyFile string `yaml:"service_key_file,omitempty" json:"service_key_file,omitempty"`
333-
RoutingKey Secret `yaml:"routing_key,omitempty" json:"routing_key,omitempty"`
334-
RoutingKeyFile string `yaml:"routing_key_file,omitempty" json:"routing_key_file,omitempty"`
335-
URL *URL `yaml:"url,omitempty" json:"url,omitempty"`
336-
Client string `yaml:"client,omitempty" json:"client,omitempty"`
337-
ClientURL string `yaml:"client_url,omitempty" json:"client_url,omitempty"`
338-
Description string `yaml:"description,omitempty" json:"description,omitempty"`
339-
Details map[string]string `yaml:"details,omitempty" json:"details,omitempty"`
340-
Images []PagerdutyImage `yaml:"images,omitempty" json:"images,omitempty"`
341-
Links []PagerdutyLink `yaml:"links,omitempty" json:"links,omitempty"`
342-
Source string `yaml:"source,omitempty" json:"source,omitempty"`
343-
Severity string `yaml:"severity,omitempty" json:"severity,omitempty"`
344-
Class string `yaml:"class,omitempty" json:"class,omitempty"`
345-
Component string `yaml:"component,omitempty" json:"component,omitempty"`
346-
Group string `yaml:"group,omitempty" json:"group,omitempty"`
333+
ServiceKey secrets.GenericSecret `yaml:"service_key,omitempty" json:"service_key,omitempty"`
334+
ServiceKeyFile string `yaml:"service_key_file,omitempty" json:"service_key_file,omitempty"`
335+
RoutingKey secrets.GenericSecret `yaml:"routing_key,omitempty" json:"routing_key,omitempty"`
336+
RoutingKeyFile string `yaml:"routing_key_file,omitempty" json:"routing_key_file,omitempty"`
337+
URL *URL `yaml:"url,omitempty" json:"url,omitempty"`
338+
Client string `yaml:"client,omitempty" json:"client,omitempty"`
339+
ClientURL string `yaml:"client_url,omitempty" json:"client_url,omitempty"`
340+
Description string `yaml:"description,omitempty" json:"description,omitempty"`
341+
Details map[string]string `yaml:"details,omitempty" json:"details,omitempty"`
342+
Images []PagerdutyImage `yaml:"images,omitempty" json:"images,omitempty"`
343+
Links []PagerdutyLink `yaml:"links,omitempty" json:"links,omitempty"`
344+
Source string `yaml:"source,omitempty" json:"source,omitempty"`
345+
Severity string `yaml:"severity,omitempty" json:"severity,omitempty"`
346+
Class string `yaml:"class,omitempty" json:"class,omitempty"`
347+
Component string `yaml:"component,omitempty" json:"component,omitempty"`
348+
Group string `yaml:"group,omitempty" json:"group,omitempty"`
347349
}
348350

349351
// PagerdutyLink is a link.
@@ -359,20 +361,24 @@ type PagerdutyImage struct {
359361
Href string `yaml:"href,omitempty" json:"href,omitempty"`
360362
}
361363

364+
func (c *PagerdutyConfig) isKeyZero() bool {
365+
return c.ServiceKey.IsZero() && c.RoutingKey.IsZero()
366+
}
367+
362368
// UnmarshalYAML implements the yaml.Unmarshaler interface.
363369
func (c *PagerdutyConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
364370
*c = DefaultPagerdutyConfig
365371
type plain PagerdutyConfig
366372
if err := unmarshal((*plain)(c)); err != nil {
367373
return err
368374
}
369-
if c.RoutingKey == "" && c.ServiceKey == "" && c.RoutingKeyFile == "" && c.ServiceKeyFile == "" {
375+
if c.isKeyZero() && c.RoutingKeyFile == "" && c.ServiceKeyFile == "" {
370376
return errors.New("missing service or routing key in PagerDuty config")
371377
}
372-
if len(c.RoutingKey) > 0 && len(c.RoutingKeyFile) > 0 {
378+
if !c.RoutingKey.IsZero() && len(c.RoutingKeyFile) > 0 {
373379
return errors.New("at most one of routing_key & routing_key_file must be configured")
374380
}
375-
if len(c.ServiceKey) > 0 && len(c.ServiceKeyFile) > 0 {
381+
if !c.ServiceKey.IsZero() && len(c.ServiceKeyFile) > 0 {
376382
return errors.New("at most one of service_key & service_key_file must be configured")
377383
}
378384
if c.Details == nil {

config/notifiers_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ routing_key_file: 'xyz'
142142
func TestPagerdutyServiceKey(t *testing.T) {
143143
t.Run("error if no service key or key file", func(t *testing.T) {
144144
in := `
145-
service_key: ''
145+
service_key:
146146
`
147147
var cfg PagerdutyConfig
148148
err := yaml.UnmarshalStrict([]byte(in), &cfg)

config/receiver/receiver.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ package receiver
1616
import (
1717
"log/slog"
1818

19+
"github.com/prometheus/alertmanager/secrets"
20+
1921
commoncfg "github.com/prometheus/common/config"
2022
"github.com/prometheus/common/promslog"
2123

@@ -43,7 +45,7 @@ import (
4345

4446
// BuildReceiverIntegrations builds a list of integration notifiers off of a
4547
// receiver config.
46-
func BuildReceiverIntegrations(nc config.Receiver, tmpl *template.Template, logger *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) ([]notify.Integration, error) {
48+
func BuildReceiverIntegrations(nc config.Receiver, tmpl *template.Template, logger *slog.Logger, spRegistry *secrets.SecretsProviderRegistry, httpOpts ...commoncfg.HTTPClientOption) ([]notify.Integration, error) {
4749
if logger == nil {
4850
logger = promslog.NewNopLogger()
4951
}
@@ -68,7 +70,9 @@ func BuildReceiverIntegrations(nc config.Receiver, tmpl *template.Template, logg
6870
add("email", i, c, func(l *slog.Logger) (notify.Notifier, error) { return email.New(c, tmpl, l), nil })
6971
}
7072
for i, c := range nc.PagerdutyConfigs {
71-
add("pagerduty", i, c, func(l *slog.Logger) (notify.Notifier, error) { return pagerduty.New(c, tmpl, l, httpOpts...) })
73+
add("pagerduty", i, c, func(l *slog.Logger) (notify.Notifier, error) {
74+
return pagerduty.New(c, tmpl, l, spRegistry, httpOpts...)
75+
})
7276
}
7377
for i, c := range nc.OpsGenieConfigs {
7478
add("opsgenie", i, c, func(l *slog.Logger) (notify.Notifier, error) { return opsgenie.New(c, tmpl, l, httpOpts...) })

config/receiver/receiver_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ package receiver
1616
import (
1717
"testing"
1818

19+
"github.com/prometheus/client_golang/prometheus"
20+
"github.com/prometheus/common/promslog"
21+
22+
"github.com/prometheus/alertmanager/secrets"
23+
1924
commoncfg "github.com/prometheus/common/config"
2025
"github.com/stretchr/testify/require"
2126

@@ -71,7 +76,8 @@ func TestBuildReceiverIntegrations(t *testing.T) {
7176
} {
7277
tc := tc
7378
t.Run("", func(t *testing.T) {
74-
integrations, err := BuildReceiverIntegrations(tc.receiver, nil, nil)
79+
sp := secrets.NewSecretsProviderRegistry(promslog.NewNopLogger(), prometheus.DefaultRegisterer)
80+
integrations, err := BuildReceiverIntegrations(tc.receiver, nil, nil, sp)
7581
if tc.err {
7682
require.Error(t, err)
7783
return

go.mod

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ require (
77
github.com/alecthomas/kingpin/v2 v2.4.0
88
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b
99
github.com/aws/aws-sdk-go v1.55.5
10+
github.com/aws/aws-sdk-go-v2 v1.36.4
11+
github.com/aws/aws-sdk-go-v2/config v1.29.16
12+
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.6
1013
github.com/cenkalti/backoff/v4 v4.3.0
1114
github.com/cespare/xxhash/v2 v2.3.0
1215
github.com/coder/quartz v0.1.2
@@ -53,6 +56,17 @@ require (
5356
require (
5457
github.com/armon/go-metrics v0.3.10 // indirect
5558
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
59+
github.com/aws/aws-sdk-go-v2/credentials v1.17.69 // indirect
60+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.31 // indirect
61+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35 // indirect
62+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35 // indirect
63+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
64+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect
65+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.16 // indirect
66+
github.com/aws/aws-sdk-go-v2/service/sso v1.25.4 // indirect
67+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.2 // indirect
68+
github.com/aws/aws-sdk-go-v2/service/sts v1.33.21 // indirect
69+
github.com/aws/smithy-go v1.22.2 // indirect
5670
github.com/beorn7/perks v1.0.1 // indirect
5771
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
5872
github.com/davecgh/go-spew v1.1.1 // indirect

go.sum

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,34 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d
8080
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
8181
github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
8282
github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
83+
github.com/aws/aws-sdk-go-v2 v1.36.4 h1:GySzjhVvx0ERP6eyfAbAuAXLtAda5TEy19E5q5W8I9E=
84+
github.com/aws/aws-sdk-go-v2 v1.36.4/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
85+
github.com/aws/aws-sdk-go-v2/config v1.29.16 h1:XkruGnXX1nEZ+Nyo9v84TzsX+nj86icbFAeust6uo8A=
86+
github.com/aws/aws-sdk-go-v2/config v1.29.16/go.mod h1:uCW7PNjGwZ5cOGZ5jr8vCWrYkGIhPoTNV23Q/tpHKzg=
87+
github.com/aws/aws-sdk-go-v2/credentials v1.17.69 h1:8B8ZQboRc3uaIKjshve/XlvJ570R7BKNy3gftSbS178=
88+
github.com/aws/aws-sdk-go-v2/credentials v1.17.69/go.mod h1:gPME6I8grR1jCqBFEGthULiolzf/Sexq/Wy42ibKK9c=
89+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.31 h1:oQWSGexYasNpYp4epLGZxxjsDo8BMBh6iNWkTXQvkwk=
90+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.31/go.mod h1:nc332eGUU+djP3vrMI6blS0woaCfHTe3KiSQUVTMRq0=
91+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35 h1:o1v1VFfPcDVlK3ll1L5xHsaQAFdNtZ5GXnNR7SwueC4=
92+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35/go.mod h1:rZUQNYMNG+8uZxz9FOerQJ+FceCiodXvixpeRtdESrU=
93+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35 h1:R5b82ubO2NntENm3SAm0ADME+H630HomNJdgv+yZ3xw=
94+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35/go.mod h1:FuA+nmgMRfkzVKYDNEqQadvEMxtxl9+RLT9ribCwEMs=
95+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
96+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
97+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE=
98+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA=
99+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.16 h1:/ldKrPPXTC421bTNWrUIpq3CxwHwRI/kpc+jPUTJocM=
100+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.16/go.mod h1:5vkf/Ws0/wgIMJDQbjI4p2op86hNW6Hie5QtebrDgT8=
101+
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.6 h1:l4mxH8imZoflVEWWa8VT8skwObm+t0KEveqEskyiKEo=
102+
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.6/go.mod h1:1qwmvfRBGTQ5shUxu+eQO/S2+O6o6SxbvcvtN62kmc0=
103+
github.com/aws/aws-sdk-go-v2/service/sso v1.25.4 h1:EU58LP8ozQDVroOEyAfcq0cGc5R/FTZjVoYJ6tvby3w=
104+
github.com/aws/aws-sdk-go-v2/service/sso v1.25.4/go.mod h1:CrtOgCcysxMvrCoHnvNAD7PHWclmoFG78Q2xLK0KKcs=
105+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.2 h1:XB4z0hbQtpmBnb1FQYvKaCM7UsS6Y/u8jVBwIUGeCTk=
106+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.2/go.mod h1:hwRpqkRxnQ58J9blRDrB4IanlXCpcKmsC83EhG77upg=
107+
github.com/aws/aws-sdk-go-v2/service/sts v1.33.21 h1:nyLjs8sYJShFYj6aiyjCBI3EcLn1udWrQTjEF+SOXB0=
108+
github.com/aws/aws-sdk-go-v2/service/sts v1.33.21/go.mod h1:EhdxtZ+g84MSGrSrHzZiUm9PYiZkrADNja15wtRJSJo=
109+
github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
110+
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
83111
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
84112
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
85113
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=

0 commit comments

Comments
 (0)