Alerting: Expose info about notification delivery errors in a new /receivers endpoint (#55429)

* (WIP) switch to fork AM, first implementation of the API, generate spec

* get receivers avoiding race conditions

* use latest version of our forked AM, tests

* make linter happy, delete TODO comment

* update number of expected paths to += 2

* delete unused endpoint code, code review comments, tests

* Update pkg/services/ngalert/notifier/alertmanager.go

Co-authored-by: Matthew Jacobson <matthew.jacobson@grafana.com>

* remove call to fmt.Println

* clear naming for fields

* shorter variable names in GetReceivers

Co-authored-by: Matthew Jacobson <matthew.jacobson@grafana.com>
This commit is contained in:
Santiago 2022-10-03 10:58:41 -03:00 committed by GitHub
parent 1e16dd5b7c
commit 09f8e026a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 667 additions and 454 deletions

14
go.mod
View File

@ -26,7 +26,7 @@ require (
github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f
github.com/aws/aws-sdk-go v1.44.9
github.com/beevik/etree v1.1.0
github.com/benbjohnson/clock v1.1.0
github.com/benbjohnson/clock v1.3.0
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b
github.com/centrifugal/centrifuge v0.25.0
github.com/cortexproject/cortex v1.10.1-0.20211014125347-85c378182d0d
@ -137,8 +137,6 @@ require (
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/FZambia/eagle v0.0.2 // indirect
github.com/FZambia/sentinel v1.1.0 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
github.com/andybalholm/brotli v1.0.3
github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40 // indirect
@ -162,12 +160,12 @@ require (
github.com/go-openapi/analysis v0.21.2 // indirect
github.com/go-openapi/errors v0.20.2 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/loads v0.21.1
github.com/go-openapi/runtime v0.23.1 // indirect
github.com/go-openapi/spec v0.20.4 // indirect
github.com/go-openapi/spec v0.20.6 // indirect
github.com/go-openapi/swag v0.21.1 // indirect
github.com/go-openapi/validate v0.21.0 // indirect
github.com/go-openapi/validate v0.22.0 // indirect
github.com/gogo/googleapis v1.4.1 // indirect
github.com/gogo/status v1.1.0 // indirect
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
@ -370,3 +368,7 @@ replace github.com/microcosm-cc/bluemonday => github.com/microcosm-cc/bluemonday
// happen, for example, during a read when the sqlite db is under heavy write load.
// This patch cherry picks compatible fixes from upstream xorm PR#1998 and can be reverted on upgrade to xorm v1.2.0+.
replace xorm.io/xorm => github.com/grafana/xorm v0.8.3-0.20220614223926-2fcda7565af6
// Use our fork of the upstream alertmanagers.
// This is required in order to get notification delivery errors from the receivers API.
replace github.com/prometheus/alertmanager => github.com/grafana/prometheus-alertmanager v0.24.0-rc.0.0.20220930143838-d75bdc5543c0

66
go.sum
View File

@ -259,10 +259,8 @@ github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C6
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/RoaringBitmap/gocroaring v0.4.0/go.mod h1:NieMwz7ZqwU2DD73/vvYwv7r4eWBKuPVSXZIpsaMwCI=
github.com/RoaringBitmap/real-roaring-datasets v0.0.0-20190726190000-eb7c87156f76/go.mod h1:oM0MHmQ3nDsq609SS36p+oYbRi16+oVvU2Bw4Ipv0SE=
@ -357,7 +355,6 @@ github.com/aws/aws-sdk-go v1.38.3/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zK
github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.38.60/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.38.68/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.40.11/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go v1.40.37/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go v1.43.11/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
@ -412,8 +409,9 @@ github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/immutable v0.2.1/go.mod h1:uc6OHo6PN2++n98KHLxW8ef4W42ylHiQSENghE1ezxI=
github.com/benbjohnson/tmpl v1.0.0/go.mod h1:igT620JFIi44B6awvU9IsDhR77IXWtFigTLil/RPdps=
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@ -475,11 +473,8 @@ github.com/caio/go-tdigest v3.1.0+incompatible h1:uoVMJ3Q5lXmVLCCqaMGHLBWnbGoN6L
github.com/caio/go-tdigest v3.1.0+incompatible/go.mod h1:sHQM/ubZStBUmF1WbB8FAm8q9GjDajLC5T7ydxE3JHI=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/casbin/casbin/v2 v2.31.6/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
github.com/cenkalti/backoff v0.0.0-20181003080854-62661b46c409/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff v1.0.0/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo=
github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
@ -490,7 +485,6 @@ github.com/centrifugal/centrifuge v0.25.0/go.mod h1:bFcSFalnROq/wcFeRiTG+wIbHsxE
github.com/centrifugal/protocol v0.8.10 h1:eezzBIU/4pWyl7a+NUnANYojJBASqbkPZcQh9b8YQRI=
github.com/centrifugal/protocol v0.8.10/go.mod h1:dlHBjKakr0r+f1pkfwSMfZ+cnpvidN7pQe1ZrsKfhtE=
github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/cespare/xxhash v0.0.0-20181017004759-096ff4a8a059/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@ -937,7 +931,6 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
github.com/go-openapi/analysis v0.17.2/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
@ -950,7 +943,6 @@ github.com/go-openapi/analysis v0.20.1/go.mod h1:BMchjvaHDykmRMsK40iPtvyOfFdMMxl
github.com/go-openapi/analysis v0.21.2 h1:hXFrOYFHUAMQdu6zwAiKKJHJQ8kqZs1ux/ru1P1wLJU=
github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY=
github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/errors v0.17.2/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
github.com/go-openapi/errors v0.19.3/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
@ -964,7 +956,6 @@ github.com/go-openapi/errors v0.20.2 h1:dxy7PGTqEh94zj2E3h1cUmQQWiM1+aeCROfAr02E
github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.17.2/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
@ -972,16 +963,15 @@ github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUe
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.17.2/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.17.2/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs=
@ -995,21 +985,17 @@ github.com/go-openapi/loads v0.20.2/go.mod h1:hTVUotJ+UonAMMZsvakEgmWKgtulweO9vY
github.com/go-openapi/loads v0.21.1 h1:Wb3nVZpdEzDTcly8S4HMkey6fjARRzb7iEaySimlDW0=
github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g=
github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
github.com/go-openapi/runtime v0.18.0/go.mod h1:uI6pHuxWYTy94zZxgcwJkUWa9wbIlhteGfloI10GD4U=
github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64=
github.com/go-openapi/runtime v0.19.3/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=
github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=
github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo=
github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98=
github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk=
github.com/go-openapi/runtime v0.19.26/go.mod h1:BvrQtn6iVb2QmiVXRsFAm6ZCAZBpbVKFfN6QWCp582M=
github.com/go-openapi/runtime v0.19.28/go.mod h1:BvrQtn6iVb2QmiVXRsFAm6ZCAZBpbVKFfN6QWCp582M=
github.com/go-openapi/runtime v0.19.29/go.mod h1:BvrQtn6iVb2QmiVXRsFAm6ZCAZBpbVKFfN6QWCp582M=
github.com/go-openapi/runtime v0.23.1 h1:/Drg9R96eMmgKJHVWZADz78XbE39/6QiIiB45mc+epo=
github.com/go-openapi/runtime v0.23.1/go.mod h1:AKurw9fNre+h3ELZfk6ILsfvPN+bvvlaU/M9q/r9hpk=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.17.2/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
@ -1021,10 +1007,10 @@ github.com/go-openapi/spec v0.19.15/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFu
github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU=
github.com/go-openapi/spec v0.20.1/go.mod h1:93x7oh+d+FQsmsieroS4cmR3u0p/ywH649a3qwC9OsQ=
github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
github.com/go-openapi/spec v0.20.6 h1:ich1RQ3WDbfoeTqTAb+5EIxNmpKVJZWBNah9RAT0jIQ=
github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
github.com/go-openapi/strfmt v0.17.2/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
@ -1041,7 +1027,6 @@ github.com/go-openapi/strfmt v0.21.2 h1:5NDNgadiX1Vhemth/TH4gCGopWSTdDjxl60H3B7f
github.com/go-openapi/strfmt v0.21.2/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.17.2/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.4/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
@ -1055,7 +1040,6 @@ github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU=
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-openapi/validate v0.17.2/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo=
@ -1066,8 +1050,9 @@ github.com/go-openapi/validate v0.19.14/go.mod h1:PdGrHe0rp6MG3A1SrAY/rIHATqzJEE
github.com/go-openapi/validate v0.19.15/go.mod h1:tbn/fdOwYHgrhPBzidZfJC2MIVvs9GA7monOmWBbeCI=
github.com/go-openapi/validate v0.20.1/go.mod h1:b60iJT+xNNLfaQJUqLI7946tYiFEOuE9E4k54HpKcJ0=
github.com/go-openapi/validate v0.20.2/go.mod h1:e7OJoKNgd0twXZwIn0A43tHbvIcr/rZIVCbJBpTUoY0=
github.com/go-openapi/validate v0.21.0 h1:+Wqk39yKOhfpLqNLEC0/eViCkzM5FVXVqrvt526+wcI=
github.com/go-openapi/validate v0.21.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg=
github.com/go-openapi/validate v0.22.0 h1:b0QecH6VslW/TxtpKgzpO1SNG7GU2FsaqKdP1E2T50Y=
github.com/go-openapi/validate v0.22.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
@ -1305,7 +1290,6 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -1385,6 +1369,8 @@ github.com/grafana/grafana-google-sdk-go v0.0.0-20211104130251-b190293eaf58/go.m
github.com/grafana/grafana-plugin-sdk-go v0.114.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk=
github.com/grafana/grafana-plugin-sdk-go v0.139.0 h1:2RQKM2QpSaWTtaGN6sK+R7LO7zykOeTYF0QkAMA7JsI=
github.com/grafana/grafana-plugin-sdk-go v0.139.0/go.mod h1:Y+Ps2sesZ62AyCnX+hzrYnyDQYe/ZZl+A8yKLOBm12c=
github.com/grafana/prometheus-alertmanager v0.24.0-rc.0.0.20220930143838-d75bdc5543c0 h1:Ifcxl2wKT+UoJE+d2hsEZjH5FVdF5nML+1dtMliFk78=
github.com/grafana/prometheus-alertmanager v0.24.0-rc.0.0.20220930143838-d75bdc5543c0/go.mod h1:xVHSIhcJ2xBqw8jSf7ZM+9NnTSV68dCLrj7MDiFEse8=
github.com/grafana/saml v0.4.9-0.20220727151557-61cd9c9353fc h1:1PY8n+rXuBNr3r1JQhoytWDCpc+pq+BibxV0SZv+Cr4=
github.com/grafana/saml v0.4.9-0.20220727151557-61cd9c9353fc/go.mod h1:9Zh6dWPtB3MSzTRt8fIFH60Z351QQ+s7hCU3J/tTlA4=
github.com/grafana/thema v0.0.0-20220817114012-ebeee841c104 h1:dYpwFYIChrMfpq3wDa/ZBxAbUGSW5NYmYBeSezhaoao=
@ -1498,7 +1484,6 @@ github.com/hashicorp/memberlist v0.1.5/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
github.com/hashicorp/memberlist v0.2.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/memberlist v0.2.3/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/memberlist v0.2.4/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/memberlist v0.3.1 h1:MXgUXLqva1QvpVEDQW1IQLG0wivQAtmFlHRQ+1vWZfM=
github.com/hashicorp/memberlist v0.3.1/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
@ -1626,7 +1611,6 @@ github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/U
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc=
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
github.com/jessevdk/go-flags v0.0.0-20180331124232-1c38ed7ad0cc/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
@ -1724,7 +1708,6 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE=
github.com/kylelemons/godebug v0.0.0-20160406211939-eadb3ce320cb/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
@ -1974,7 +1957,6 @@ github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtb
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
github.com/oklog/ulid v0.0.0-20170117200651-66bb6560562f/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
@ -2105,19 +2087,6 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI=
github.com/prometheus/alertmanager v0.18.0/go.mod h1:WcxHBl40VSPuOaqWae6l6HpnEOVRIycEJ7i9iYkadEE=
github.com/prometheus/alertmanager v0.19.0/go.mod h1:Eyp94Yi/T+kdeb2qvq66E3RGuph5T/jm/RBVh4yz1xo=
github.com/prometheus/alertmanager v0.20.0/go.mod h1:9g2i48FAyZW6BtbsnvHtMHQXl2aVtrORKwKVCQ+nbrg=
github.com/prometheus/alertmanager v0.21.0/go.mod h1:h7tJ81NA0VLWvWEayi1QltevFkLF3KxmC/malTcT8Go=
github.com/prometheus/alertmanager v0.21.1-0.20200911160112-1fdff6b3f939/go.mod h1:imXRHOP6QTsE0fFsIsAV/cXimS32m7gVZOiUj11m6Ig=
github.com/prometheus/alertmanager v0.21.1-0.20201106142418-c39b78780054/go.mod h1:imXRHOP6QTsE0fFsIsAV/cXimS32m7gVZOiUj11m6Ig=
github.com/prometheus/alertmanager v0.21.1-0.20210310093010-0f9cab6991e6/go.mod h1:MTqVn+vIupE0dzdgo+sMcNCp37SCAi8vPrvKTTnTz9g=
github.com/prometheus/alertmanager v0.21.1-0.20210422101724-8176f78a70e1/go.mod h1:gsEqwD5BHHW9RNKvCuPOrrTMiP5I+faJUyLXvnivHik=
github.com/prometheus/alertmanager v0.22.2/go.mod h1:rYinOWxFuCnNssc3iOjn2oMTlhLaPcUuqV5yk5JKUAE=
github.com/prometheus/alertmanager v0.23.0/go.mod h1:0MLTrjQI8EuVmvykEhcfr/7X0xmaDAZrqMgxIq3OXHk=
github.com/prometheus/alertmanager v0.23.1-0.20210914172521-e35efbddb66a/go.mod h1:U7pGu+z7A9ZKhK8lq1MvIOp5GdVlZjwOYk+S0h3LSbA=
github.com/prometheus/alertmanager v0.24.0 h1:HBWR3lk4uy3ys+naDZthDdV7yEsxpaNeZuUS+hJgrOw=
github.com/prometheus/alertmanager v0.24.0/go.mod h1:r6fy/D7FRuZh5YbnX6J3MBY0eI4Pb5yPYS7/bPSXXqI=
github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@ -2163,24 +2132,20 @@ github.com/prometheus/common v0.8.0/go.mod h1:PC/OgXc+UN7B4ALwvn1yzVZmVwvhXp5Jsb
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.11.1/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.12.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.20.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.21.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.23.0/go.mod h1:H6QK/N6XVT42whUeIdI3dp36w49c+/iMDk7UAI2qm7Q=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.31.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4=
github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI=
github.com/prometheus/exporter-toolkit v0.5.0/go.mod h1:OCkM4805mmisBhLmVFw858QYi3v0wKdY6/UxrT0pZVg=
github.com/prometheus/exporter-toolkit v0.5.1/go.mod h1:OCkM4805mmisBhLmVFw858QYi3v0wKdY6/UxrT0pZVg=
github.com/prometheus/exporter-toolkit v0.6.1/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g=
github.com/prometheus/exporter-toolkit v0.7.1 h1:c6RXaK8xBVercEeUQ4tRNL8UGWzDHfvj9dseo1FcK1Y=
@ -2207,7 +2172,6 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/prometheus/prometheus v0.0.0-20180315085919-58e2a31db8de/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
github.com/prometheus/prometheus v0.0.0-20190818123050-43acd0e2e93f/go.mod h1:rMTlmxGCvukf2KMu3fClMDKLLoJ5hl61MhcJ7xKakf0=
github.com/prometheus/prometheus v0.0.0-20200609090129-a6600f564e3c/go.mod h1:S5n0C6tSgdnwWshBUceRx5G1OsjLv/EeZ9t3wIfEtsY=
github.com/prometheus/prometheus v1.8.2-0.20200107122003-4708915ac6ef/go.mod h1:7U90zPoLkWjEIQcy/rweQla82OCTUzxVHE51G3OhJbI=
@ -2253,8 +2217,6 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM=
github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
@ -2278,7 +2240,6 @@ github.com/samuel/go-zookeeper v0.0.0-20200724154423-2164a8ac840e/go.mod h1:gi+0
github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sanity-io/litter v1.2.0/go.mod h1:JF6pZUFgu2Q0sBZ+HSV35P8TVPI1TTzEwyu9FXAw2W4=
github.com/santhosh-tekuri/jsonschema v1.2.4/go.mod h1:TEAUOeZSmIxTTuHatJzrvARHiuO9LYd+cIxzgEHCQI4=
github.com/satori/go.uuid v0.0.0-20160603004225-b111a074d5ef/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210223165440-c65ae3540d44 h1:3egqo0Vut6daANFm7tOXdNAa8v5/uLU+sgCJrc88Meo=
@ -2304,11 +2265,9 @@ github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNX
github.com/shirou/gopsutil v3.21.6+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk=
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/vfsgen v0.0.0-20180825020608-02ddb050ef6b/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
github.com/shurcooL/vfsgen v0.0.0-20200627165143-92b8a710ab6c/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 h1:pXY9qYc/MP5zdvqWEUH6SjNiu7VhSjuVFTFiTcphaLU=
@ -2506,7 +2465,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xlab/treeprint v1.0.0/go.mod h1:IoImgRak9i3zJyuxOKUP1v4UZd1tMoKkq/Cimt1uhCg=
github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/xorcare/pointer v1.1.0 h1:sFwXOhRF8QZ0tyVZrtxWGIoVZNEmRzBCaFWdONPQIUM=
@ -2871,7 +2829,6 @@ golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@ -3109,7 +3066,6 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180805044716-cb6730876b98/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@ -3142,7 +3098,6 @@ golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181112210238-4b1f3b6b1646/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190118193359-16909d206f00/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@ -3209,7 +3164,6 @@ golang.org/x/tools v0.0.0-20200422205258-72e4a01eba43/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200513201620-d5fe73897c97/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200603131246-cc40288be839/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=

View File

@ -49,7 +49,8 @@ type Alertmanager interface {
GetAlerts(active, silenced, inhibited bool, filter []string, receiver string) (apimodels.GettableAlerts, error)
GetAlertGroups(active, silenced, inhibited bool, filter []string, receiver string) (apimodels.AlertGroups, error)
// Testing
// Receivers
GetReceivers(ctx context.Context) apimodels.Receivers
TestReceivers(ctx context.Context, c apimodels.TestReceiversConfigBodyParams) (*notifier.TestReceiversResult, error)
}

View File

@ -248,6 +248,16 @@ func (srv AlertmanagerSrv) RoutePostAMAlerts(_ *models.ReqContext, _ apimodels.P
return NotImplementedResp
}
func (srv AlertmanagerSrv) RouteGetReceivers(c *models.ReqContext) response.Response {
am, errResp := srv.AlertmanagerFor(c.OrgID)
if errResp != nil {
return errResp
}
rcvs := am.GetReceivers(c.Req.Context())
return response.JSON(http.StatusOK, rcvs)
}
func (srv AlertmanagerSrv) RoutePostTestReceivers(c *models.ReqContext, body apimodels.TestReceiversConfigBodyParams) response.Response {
if err := srv.crypto.LoadSecureSettings(c.Req.Context(), c.OrgID, body.Receivers); err != nil {
var unknownReceiverError UnknownReceiverError

View File

@ -156,6 +156,8 @@ func (api *API) authorize(method, path string) web.Handler {
case http.MethodPost + "/api/alertmanager/grafana/config/api/v1/alerts":
// additional authorization is done in the request handler
eval = ac.EvalAny(ac.EvalPermission(ac.ActionAlertingNotificationsWrite))
case http.MethodGet + "/api/alertmanager/grafana/config/api/v1/receivers":
eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead)
case http.MethodPost + "/api/alertmanager/grafana/config/api/v1/receivers/test":
fallback = middleware.ReqEditorRole
eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead)

View File

@ -49,7 +49,7 @@ func TestAuthorize(t *testing.T) {
}
paths[p] = methods
}
require.Len(t, paths, 40)
require.Len(t, paths, 41)
ac := acmock.New()
api := &API{AccessControl: ac}

View File

@ -187,6 +187,10 @@ func (f *AlertmanagerApiHandler) handleRoutePostGrafanaAlertingConfig(ctx *model
return f.GrafanaSvc.RoutePostAlertingConfig(ctx, conf)
}
func (f *AlertmanagerApiHandler) handleRouteGetGrafanaReceivers(ctx *models.ReqContext) response.Response {
return f.GrafanaSvc.RouteGetReceivers(ctx)
}
func (f *AlertmanagerApiHandler) handleRoutePostTestGrafanaReceivers(ctx *models.ReqContext, conf apimodels.TestReceiversConfigBodyParams) response.Response {
return f.GrafanaSvc.RoutePostTestReceivers(ctx, conf)
}

View File

@ -33,6 +33,7 @@ type AlertmanagerApi interface {
RouteGetGrafanaAMAlerts(*models.ReqContext) response.Response
RouteGetGrafanaAMStatus(*models.ReqContext) response.Response
RouteGetGrafanaAlertingConfig(*models.ReqContext) response.Response
RouteGetGrafanaReceivers(*models.ReqContext) response.Response
RouteGetGrafanaSilence(*models.ReqContext) response.Response
RouteGetGrafanaSilences(*models.ReqContext) response.Response
RouteGetSilence(*models.ReqContext) response.Response
@ -114,6 +115,9 @@ func (f *AlertmanagerApiHandler) RouteGetGrafanaAMStatus(ctx *models.ReqContext)
func (f *AlertmanagerApiHandler) RouteGetGrafanaAlertingConfig(ctx *models.ReqContext) response.Response {
return f.handleRouteGetGrafanaAlertingConfig(ctx)
}
func (f *AlertmanagerApiHandler) RouteGetGrafanaReceivers(ctx *models.ReqContext) response.Response {
return f.handleRouteGetGrafanaReceivers(ctx)
}
func (f *AlertmanagerApiHandler) RouteGetGrafanaSilence(ctx *models.ReqContext) response.Response {
// Parse Path Parameters
silenceIdParam := web.Params(ctx.Req)[":SilenceId"]
@ -330,6 +334,16 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics
m,
),
)
group.Get(
toMacaronPath("/api/alertmanager/grafana/config/api/v1/receivers"),
api.authorize(http.MethodGet, "/api/alertmanager/grafana/config/api/v1/receivers"),
metrics.Instrument(
http.MethodGet,
"/api/alertmanager/grafana/config/api/v1/receivers",
srv.RouteGetGrafanaReceivers,
m,
),
)
group.Get(
toMacaronPath("/api/alertmanager/grafana/api/v2/silence/{SilenceId}"),
api.authorize(http.MethodGet, "/api/alertmanager/grafana/api/v2/silence/{SilenceId}"),

View File

@ -260,7 +260,7 @@
"type": "string"
},
"for": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"labels": {
"additionalProperties": {
@ -378,25 +378,6 @@
"title": "DataTopic is used to identify which topic the frame should be assigned to.",
"type": "string"
},
"DateTime": {
"description": "DateTime is a time but it serializes to ISO8601 format with millis\nIt knows how to read 3 different variations of a RFC3339 date time.\nMost APIs we encounter want either millisecond or second precision times.\nThis just tries to make it worry-free.",
"format": "date-time",
"type": "string"
},
"DayOfMonthRange": {
"properties": {
"Begin": {
"format": "int64",
"type": "integer"
},
"End": {
"format": "int64",
"type": "integer"
}
},
"title": "A DayOfMonthRange is an inclusive range that may have negative Beginning/End values that represent distance from the End of the month Beginning at -1.",
"type": "object"
},
"DiscoveryBase": {
"properties": {
"error": {
@ -625,16 +606,12 @@
"FieldConfig": {
"properties": {
"color": {
"additionalProperties": {
"type": "object"
},
"additionalProperties": {},
"description": "Map values to a display color\nNOTE: this interface is under development in the frontend... so simple map for now",
"type": "object"
},
"custom": {
"additionalProperties": {
"type": "object"
},
"additionalProperties": {},
"description": "Panel Specific Values",
"type": "object"
},
@ -742,8 +719,7 @@
"type": "string"
},
"custom": {
"description": "Custom datasource specific values.",
"type": "object"
"description": "Custom datasource specific values."
},
"dataTopic": {
"$ref": "#/definitions/DataTopic"
@ -939,7 +915,7 @@
"type": "string"
},
"for": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"grafana_alert": {
"$ref": "#/definitions/GettableGrafanaRule"
@ -1239,6 +1215,10 @@
"description": "The bearer token file for the targets. Deprecated in favour of\nAuthorization.CredentialsFile.",
"type": "string"
},
"enable_http2": {
"description": "EnableHTTP2 specifies whether the client should configure HTTP2.\nThe omitempty flag is not set, because it would be hidden from the\nmarshalled configuration when set to false.",
"type": "boolean"
},
"follow_redirects": {
"description": "FollowRedirects specifies whether the client should follow HTTP 3xx redirects.\nThe omitempty flag is not set, because it would be hidden from the\nmarshalled configuration when set to false.",
"type": "boolean"
@ -1268,20 +1248,6 @@
"title": "HostPort represents a \"host:port\" network address.",
"type": "object"
},
"InclusiveRange": {
"properties": {
"Begin": {
"format": "int64",
"type": "integer"
},
"End": {
"format": "int64",
"type": "integer"
}
},
"title": "InclusiveRange is used to hold the Beginning and End values of many time interval components.",
"type": "object"
},
"InhibitRule": {
"description": "InhibitRule defines an inhibition rule that mutes alerts that match the\ntarget labels if an alert matching the source labels exists.\nBoth alerts have to have a set of labels being equal.",
"properties": {
@ -1501,20 +1467,6 @@
},
"type": "array"
},
"MonthRange": {
"properties": {
"Begin": {
"format": "int64",
"type": "integer"
},
"End": {
"format": "int64",
"type": "integer"
}
},
"title": "A MonthRange is an inclusive range between [1, 12] where 1 = January.",
"type": "object"
},
"MultiStatus": {
"type": "object"
},
@ -1605,6 +1557,9 @@
},
"type": "object"
},
"proxy_url": {
"$ref": "#/definitions/URL"
},
"scopes": {
"items": {
"type": "string"
@ -1931,7 +1886,7 @@
"type": "string"
},
"for": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"grafana_alert": {
"$ref": "#/definitions/PostableGrafanaRule"
@ -2220,7 +2175,7 @@
"PushoverConfig": {
"properties": {
"expire": {
"$ref": "#/definitions/duration"
"type": "string"
},
"html": {
"type": "boolean"
@ -2235,7 +2190,7 @@
"type": "string"
},
"retry": {
"$ref": "#/definitions/duration"
"type": "string"
},
"send_resolved": {
"type": "boolean"
@ -2265,16 +2220,12 @@
"description": "The embedded FieldConfig's display name must be set.\nIt corresponds to the QueryResultMetaStat on the frontend (https://github.com/grafana/grafana/blob/master/packages/grafana-data/src/types/data.ts#L53).",
"properties": {
"color": {
"additionalProperties": {
"type": "object"
},
"additionalProperties": {},
"description": "Map values to a display color\nNOTE: this interface is under development in the frontend... so simple map for now",
"type": "object"
},
"custom": {
"additionalProperties": {
"type": "object"
},
"additionalProperties": {},
"description": "Panel Specific Values",
"type": "object"
},
@ -2462,10 +2413,10 @@
"type": "array"
},
"group_interval": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"group_wait": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"match": {
"additionalProperties": {
@ -2496,7 +2447,7 @@
"type": "string"
},
"repeat_interval": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"routes": {
"items": {
@ -2897,6 +2848,9 @@
"description": "The client key file for the targets.",
"type": "string"
},
"min_version": {
"$ref": "#/definitions/TLSVersion"
},
"server_name": {
"description": "Used to verify the hostname for the targets.",
"type": "string"
@ -2905,6 +2859,10 @@
"title": "TLSConfig configures the options for TLS connections.",
"type": "object"
},
"TLSVersion": {
"format": "uint16",
"type": "integer"
},
"TelegramConfig": {
"properties": {
"api_url": {
@ -3073,13 +3031,13 @@
"properties": {
"days_of_month": {
"items": {
"$ref": "#/definitions/DayOfMonthRange"
"type": "string"
},
"type": "array"
},
"months": {
"items": {
"$ref": "#/definitions/MonthRange"
"type": "string"
},
"type": "array"
},
@ -3091,13 +3049,13 @@
},
"weekdays": {
"items": {
"$ref": "#/definitions/WeekdayRange"
"type": "string"
},
"type": "array"
},
"years": {
"items": {
"$ref": "#/definitions/YearRange"
"type": "string"
},
"type": "array"
}
@ -3120,7 +3078,6 @@
"type": "object"
},
"URL": {
"description": "The general form represented is:\n\n[scheme:][//[userinfo@]host][/]path[?query][#fragment]\n\nURLs that do not start with a slash after the scheme are interpreted as:\n\nscheme:opaque[?query][#fragment]\n\nNote that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/.\nA consequence is that it is impossible to tell which slashes in the Path were\nslashes in the raw URL and which were %2f. This distinction is rarely important,\nbut when it is, the code should use RawPath, an optional field which only gets\nset if the default encoding is different from Path.\n\nURL's String method uses the EscapedPath method to obtain the path. See the\nEscapedPath method for more details.",
"properties": {
"ForceQuery": {
"type": "boolean"
@ -3131,6 +3088,9 @@
"Host": {
"type": "string"
},
"OmitHost": {
"type": "boolean"
},
"Opaque": {
"type": "string"
},
@ -3153,7 +3113,7 @@
"$ref": "#/definitions/Userinfo"
}
},
"title": "A URL represents a parsed URL (technically, a URI reference).",
"title": "URL is a custom URL type that allows validation at configuration load time.",
"type": "object"
},
"Userinfo": {
@ -3291,34 +3251,6 @@
"title": "WechatConfig configures notifications via Wechat.",
"type": "object"
},
"WeekdayRange": {
"properties": {
"Begin": {
"format": "int64",
"type": "integer"
},
"End": {
"format": "int64",
"type": "integer"
}
},
"title": "A WeekdayRange is an inclusive range between [0, 6] where 0 = Sunday.",
"type": "object"
},
"YearRange": {
"properties": {
"Begin": {
"format": "int64",
"type": "integer"
},
"End": {
"format": "int64",
"type": "integer"
}
},
"title": "A YearRange is a positive inclusive range.",
"type": "object"
},
"alert": {
"description": "Alert alert",
"properties": {
@ -3361,6 +3293,7 @@
"type": "object"
},
"alertGroups": {
"description": "AlertGroups alert groups",
"items": {
"$ref": "#/definitions/alertGroup"
},
@ -3464,10 +3397,8 @@
],
"type": "object"
},
"duration": {
"$ref": "#/definitions/Duration"
},
"gettableAlert": {
"description": "GettableAlert gettable alert",
"properties": {
"annotations": {
"$ref": "#/definitions/labelSet"
@ -3530,6 +3461,7 @@
"type": "array"
},
"gettableSilence": {
"description": "GettableSilence gettable silence",
"properties": {
"comment": {
"description": "comment",
@ -3578,11 +3510,42 @@
"type": "object"
},
"gettableSilences": {
"description": "GettableSilences gettable silences",
"items": {
"$ref": "#/definitions/gettableSilence"
},
"type": "array"
},
"integration": {
"properties": {
"lastNotifyAttempt": {
"description": "A timestamp indicating the last attempt to deliver a notification regardless of the outcome.\nFormat: date-time",
"format": "date-time",
"type": "string"
},
"lastNotifyAttemptDuration": {
"description": "Duration of the last attempt to deliver a notification in humanized format (`1s` or `15ms`, etc).",
"type": "string"
},
"lastNotifyAttemptError": {
"description": "Error string for the last attempt to deliver a notification. Empty if the last attempt was successful.",
"type": "string"
},
"name": {
"description": "name",
"type": "string"
},
"sendResolved": {
"description": "send resolved",
"type": "boolean"
}
},
"required": [
"name",
"sendResolved"
],
"type": "object"
},
"labelSet": {
"additionalProperties": {
"type": "string"
@ -3688,6 +3651,7 @@
"type": "array"
},
"postableSilence": {
"description": "PostableSilence postable silence",
"properties": {
"comment": {
"description": "comment",
@ -3725,14 +3689,26 @@
"type": "object"
},
"receiver": {
"description": "Receiver receiver",
"properties": {
"active": {
"description": "active",
"type": "boolean"
},
"integrations": {
"description": "integrations",
"items": {
"$ref": "#/definitions/integration"
},
"type": "array"
},
"name": {
"description": "name",
"type": "string"
}
},
"required": [
"active",
"integrations",
"name"
],
"type": "object"

View File

@ -142,6 +142,13 @@ import (
// 400: ValidationError
// 404: NotFound
// swagger:route GET /api/alertmanager/grafana/config/api/v1/receivers alertmanager RouteGetGrafanaReceivers
//
// Get a list of all receivers.
//
// Responses:
// 200: receivers
// swagger:route POST /api/alertmanager/grafana/config/api/v1/receivers/test alertmanager RoutePostTestGrafanaReceivers
//
// Test Grafana managed receivers without saving them.
@ -403,6 +410,12 @@ type AlertGroup = amv2.AlertGroup
// swagger:model receiver
type Receiver = amv2.Receiver
// swagger:model receivers
type Receivers = []amv2.Receiver
// swagger:model integration
type Integration = amv2.Integration
// swagger:parameters RouteGetAMAlerts RouteGetAMAlertGroups RouteGetGrafanaAMAlerts RouteGetGrafanaAMAlertGroups
type AlertsParams struct {

View File

@ -260,7 +260,7 @@
"type": "string"
},
"for": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"labels": {
"additionalProperties": {
@ -378,25 +378,6 @@
"title": "DataTopic is used to identify which topic the frame should be assigned to.",
"type": "string"
},
"DateTime": {
"description": "DateTime is a time but it serializes to ISO8601 format with millis\nIt knows how to read 3 different variations of a RFC3339 date time.\nMost APIs we encounter want either millisecond or second precision times.\nThis just tries to make it worry-free.",
"format": "date-time",
"type": "string"
},
"DayOfMonthRange": {
"properties": {
"Begin": {
"format": "int64",
"type": "integer"
},
"End": {
"format": "int64",
"type": "integer"
}
},
"title": "A DayOfMonthRange is an inclusive range that may have negative Beginning/End values that represent distance from the End of the month Beginning at -1.",
"type": "object"
},
"DiscoveryBase": {
"properties": {
"error": {
@ -625,16 +606,12 @@
"FieldConfig": {
"properties": {
"color": {
"additionalProperties": {
"type": "object"
},
"additionalProperties": {},
"description": "Map values to a display color\nNOTE: this interface is under development in the frontend... so simple map for now",
"type": "object"
},
"custom": {
"additionalProperties": {
"type": "object"
},
"additionalProperties": {},
"description": "Panel Specific Values",
"type": "object"
},
@ -742,8 +719,7 @@
"type": "string"
},
"custom": {
"description": "Custom datasource specific values.",
"type": "object"
"description": "Custom datasource specific values."
},
"dataTopic": {
"$ref": "#/definitions/DataTopic"
@ -939,7 +915,7 @@
"type": "string"
},
"for": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"grafana_alert": {
"$ref": "#/definitions/GettableGrafanaRule"
@ -1239,6 +1215,10 @@
"description": "The bearer token file for the targets. Deprecated in favour of\nAuthorization.CredentialsFile.",
"type": "string"
},
"enable_http2": {
"description": "EnableHTTP2 specifies whether the client should configure HTTP2.\nThe omitempty flag is not set, because it would be hidden from the\nmarshalled configuration when set to false.",
"type": "boolean"
},
"follow_redirects": {
"description": "FollowRedirects specifies whether the client should follow HTTP 3xx redirects.\nThe omitempty flag is not set, because it would be hidden from the\nmarshalled configuration when set to false.",
"type": "boolean"
@ -1268,20 +1248,6 @@
"title": "HostPort represents a \"host:port\" network address.",
"type": "object"
},
"InclusiveRange": {
"properties": {
"Begin": {
"format": "int64",
"type": "integer"
},
"End": {
"format": "int64",
"type": "integer"
}
},
"title": "InclusiveRange is used to hold the Beginning and End values of many time interval components.",
"type": "object"
},
"InhibitRule": {
"description": "InhibitRule defines an inhibition rule that mutes alerts that match the\ntarget labels if an alert matching the source labels exists.\nBoth alerts have to have a set of labels being equal.",
"properties": {
@ -1501,20 +1467,6 @@
},
"type": "array"
},
"MonthRange": {
"properties": {
"Begin": {
"format": "int64",
"type": "integer"
},
"End": {
"format": "int64",
"type": "integer"
}
},
"title": "A MonthRange is an inclusive range between [1, 12] where 1 = January.",
"type": "object"
},
"MultiStatus": {
"type": "object"
},
@ -1605,6 +1557,9 @@
},
"type": "object"
},
"proxy_url": {
"$ref": "#/definitions/URL"
},
"scopes": {
"items": {
"type": "string"
@ -1931,7 +1886,7 @@
"type": "string"
},
"for": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"grafana_alert": {
"$ref": "#/definitions/PostableGrafanaRule"
@ -2220,7 +2175,7 @@
"PushoverConfig": {
"properties": {
"expire": {
"$ref": "#/definitions/duration"
"type": "string"
},
"html": {
"type": "boolean"
@ -2235,7 +2190,7 @@
"type": "string"
},
"retry": {
"$ref": "#/definitions/duration"
"type": "string"
},
"send_resolved": {
"type": "boolean"
@ -2265,16 +2220,12 @@
"description": "The embedded FieldConfig's display name must be set.\nIt corresponds to the QueryResultMetaStat on the frontend (https://github.com/grafana/grafana/blob/master/packages/grafana-data/src/types/data.ts#L53).",
"properties": {
"color": {
"additionalProperties": {
"type": "object"
},
"additionalProperties": {},
"description": "Map values to a display color\nNOTE: this interface is under development in the frontend... so simple map for now",
"type": "object"
},
"custom": {
"additionalProperties": {
"type": "object"
},
"additionalProperties": {},
"description": "Panel Specific Values",
"type": "object"
},
@ -2462,10 +2413,10 @@
"type": "array"
},
"group_interval": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"group_wait": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"match": {
"additionalProperties": {
@ -2496,7 +2447,7 @@
"type": "string"
},
"repeat_interval": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"routes": {
"items": {
@ -2897,6 +2848,9 @@
"description": "The client key file for the targets.",
"type": "string"
},
"min_version": {
"$ref": "#/definitions/TLSVersion"
},
"server_name": {
"description": "Used to verify the hostname for the targets.",
"type": "string"
@ -2905,6 +2859,10 @@
"title": "TLSConfig configures the options for TLS connections.",
"type": "object"
},
"TLSVersion": {
"format": "uint16",
"type": "integer"
},
"TelegramConfig": {
"properties": {
"api_url": {
@ -3073,13 +3031,13 @@
"properties": {
"days_of_month": {
"items": {
"$ref": "#/definitions/DayOfMonthRange"
"type": "string"
},
"type": "array"
},
"months": {
"items": {
"$ref": "#/definitions/MonthRange"
"type": "string"
},
"type": "array"
},
@ -3091,13 +3049,13 @@
},
"weekdays": {
"items": {
"$ref": "#/definitions/WeekdayRange"
"type": "string"
},
"type": "array"
},
"years": {
"items": {
"$ref": "#/definitions/YearRange"
"type": "string"
},
"type": "array"
}
@ -3120,6 +3078,7 @@
"type": "object"
},
"URL": {
"description": "The general form represented is:\n\n[scheme:][//[userinfo@]host][/]path[?query][#fragment]\n\nURLs that do not start with a slash after the scheme are interpreted as:\n\nscheme:opaque[?query][#fragment]\n\nNote that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/.\nA consequence is that it is impossible to tell which slashes in the Path were\nslashes in the raw URL and which were %2f. This distinction is rarely important,\nbut when it is, the code should use RawPath, an optional field which only gets\nset if the default encoding is different from Path.\n\nURL's String method uses the EscapedPath method to obtain the path. See the\nEscapedPath method for more details.",
"properties": {
"ForceQuery": {
"type": "boolean"
@ -3130,6 +3089,9 @@
"Host": {
"type": "string"
},
"OmitHost": {
"type": "boolean"
},
"Opaque": {
"type": "string"
},
@ -3152,7 +3114,7 @@
"$ref": "#/definitions/Userinfo"
}
},
"title": "URL is a custom URL type that allows validation at configuration load time.",
"title": "A URL represents a parsed URL (technically, a URI reference).",
"type": "object"
},
"Userinfo": {
@ -3290,34 +3252,6 @@
"title": "WechatConfig configures notifications via Wechat.",
"type": "object"
},
"WeekdayRange": {
"properties": {
"Begin": {
"format": "int64",
"type": "integer"
},
"End": {
"format": "int64",
"type": "integer"
}
},
"title": "A WeekdayRange is an inclusive range between [0, 6] where 0 = Sunday.",
"type": "object"
},
"YearRange": {
"properties": {
"Begin": {
"format": "int64",
"type": "integer"
},
"End": {
"format": "int64",
"type": "integer"
}
},
"title": "A YearRange is a positive inclusive range.",
"type": "object"
},
"alert": {
"description": "Alert alert",
"properties": {
@ -3462,11 +3396,7 @@
],
"type": "object"
},
"duration": {
"$ref": "#/definitions/Duration"
},
"gettableAlert": {
"description": "GettableAlert gettable alert",
"properties": {
"annotations": {
"$ref": "#/definitions/labelSet"
@ -3522,6 +3452,7 @@
"type": "object"
},
"gettableAlerts": {
"description": "GettableAlerts gettable alerts",
"items": {
"$ref": "#/definitions/gettableAlert"
},
@ -3576,12 +3507,42 @@
"type": "object"
},
"gettableSilences": {
"description": "GettableSilences gettable silences",
"items": {
"$ref": "#/definitions/gettableSilence"
},
"type": "array"
},
"integration": {
"description": "Integration integration",
"properties": {
"lastNotifyAttempt": {
"description": "A timestamp indicating the last attempt to deliver a notification regardless of the outcome.\nFormat: date-time",
"format": "date-time",
"type": "string"
},
"lastNotifyAttemptDuration": {
"description": "Duration of the last attempt to deliver a notification in humanized format (`1s` or `15ms`, etc).",
"type": "string"
},
"lastNotifyAttemptError": {
"description": "Error string for the last attempt to deliver a notification. Empty if the last attempt was successful.",
"type": "string"
},
"name": {
"description": "name",
"type": "string"
},
"sendResolved": {
"description": "send resolved",
"type": "boolean"
}
},
"required": [
"name",
"sendResolved"
],
"type": "object"
},
"labelSet": {
"additionalProperties": {
"type": "string"
@ -3687,7 +3648,6 @@
"type": "array"
},
"postableSilence": {
"description": "PostableSilence postable silence",
"properties": {
"comment": {
"description": "comment",
@ -3725,13 +3685,27 @@
"type": "object"
},
"receiver": {
"description": "Receiver receiver",
"properties": {
"active": {
"description": "active",
"type": "boolean"
},
"integrations": {
"description": "integrations",
"items": {
"$ref": "#/definitions/integration"
},
"type": "array"
},
"name": {
"description": "name",
"type": "string"
}
},
"required": [
"active",
"integrations",
"name"
],
"type": "object"
@ -4206,6 +4180,20 @@
]
}
},
"/api/alertmanager/grafana/config/api/v1/receivers": {
"get": {
"operationId": "RouteGetGrafanaReceivers",
"responses": {
"200": {
"$ref": "#/responses/receivers"
}
},
"summary": "Get a list of all receivers.",
"tags": [
"alertmanager"
]
}
},
"/api/alertmanager/grafana/config/api/v1/receivers/test": {
"post": {
"operationId": "RoutePostTestGrafanaReceivers",
@ -5462,6 +5450,26 @@
]
}
},
"/api/v1/ngalert": {
"get": {
"description": "Get the status of the alerting engine",
"operationId": "RouteGetStatus",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "AlertingStatus",
"schema": {
"$ref": "#/definitions/AlertingStatus"
}
}
},
"tags": [
"configuration"
]
}
},
"/api/v1/ngalert/admin_config": {
"delete": {
"consumes": [
@ -5571,26 +5579,6 @@
]
}
},
"/api/v1/ngalert": {
"get": {
"description": "Get the status of the alerting engine",
"operationId": "RouteGetStatus",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "AlertingStatus",
"schema": {
"$ref": "#/definitions/AlertingStatus"
}
}
},
"tags": [
"configuration"
]
}
},
"/api/v1/provisioning/alert-rules": {
"post": {
"consumes": [

View File

@ -392,6 +392,20 @@
}
}
},
"/api/alertmanager/grafana/config/api/v1/receivers": {
"get": {
"tags": [
"alertmanager"
],
"summary": "Get a list of all receivers.",
"operationId": "RouteGetGrafanaReceivers",
"responses": {
"200": {
"$ref": "#/responses/receivers"
}
}
}
},
"/api/alertmanager/grafana/config/api/v1/receivers/test": {
"post": {
"tags": [
@ -1648,6 +1662,26 @@
}
}
},
"/api/v1/ngalert": {
"get": {
"description": "Get the status of the alerting engine",
"produces": [
"application/json"
],
"tags": [
"configuration"
],
"operationId": "RouteGetStatus",
"responses": {
"200": {
"description": "AlertingStatus",
"schema": {
"$ref": "#/definitions/AlertingStatus"
}
}
}
}
},
"/api/v1/ngalert/admin_config": {
"get": {
"produces": [
@ -1757,26 +1791,6 @@
}
}
},
"/api/v1/ngalert": {
"get": {
"description": "Get the status of the alerting engine",
"produces": [
"application/json"
],
"tags": [
"configuration"
],
"operationId": "RouteGetStatus",
"responses": {
"200": {
"description": "AlertingStatus",
"schema": {
"$ref": "#/definitions/AlertingStatus"
}
}
}
}
},
"/api/v1/provisioning/alert-rules": {
"post": {
"consumes": [
@ -2782,7 +2796,7 @@
"type": "string"
},
"for": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"labels": {
"type": "object",
@ -2899,25 +2913,6 @@
"type": "string",
"title": "DataTopic is used to identify which topic the frame should be assigned to."
},
"DateTime": {
"description": "DateTime is a time but it serializes to ISO8601 format with millis\nIt knows how to read 3 different variations of a RFC3339 date time.\nMost APIs we encounter want either millisecond or second precision times.\nThis just tries to make it worry-free.",
"type": "string",
"format": "date-time"
},
"DayOfMonthRange": {
"type": "object",
"title": "A DayOfMonthRange is an inclusive range that may have negative Beginning/End values that represent distance from the End of the month Beginning at -1.",
"properties": {
"Begin": {
"type": "integer",
"format": "int64"
},
"End": {
"type": "integer",
"format": "int64"
}
}
},
"DiscoveryBase": {
"type": "object",
"required": [
@ -3153,16 +3148,12 @@
"color": {
"description": "Map values to a display color\nNOTE: this interface is under development in the frontend... so simple map for now",
"type": "object",
"additionalProperties": {
"type": "object"
}
"additionalProperties": {}
},
"custom": {
"description": "Panel Specific Values",
"type": "object",
"additionalProperties": {
"type": "object"
}
"additionalProperties": {}
},
"decimals": {
"type": "integer",
@ -3268,8 +3259,7 @@
"type": "string"
},
"custom": {
"description": "Custom datasource specific values.",
"type": "object"
"description": "Custom datasource specific values."
},
"dataTopic": {
"$ref": "#/definitions/DataTopic"
@ -3464,7 +3454,7 @@
"type": "string"
},
"for": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"grafana_alert": {
"$ref": "#/definitions/GettableGrafanaRule"
@ -3765,6 +3755,10 @@
"description": "The bearer token file for the targets. Deprecated in favour of\nAuthorization.CredentialsFile.",
"type": "string"
},
"enable_http2": {
"description": "EnableHTTP2 specifies whether the client should configure HTTP2.\nThe omitempty flag is not set, because it would be hidden from the\nmarshalled configuration when set to false.",
"type": "boolean"
},
"follow_redirects": {
"description": "FollowRedirects specifies whether the client should follow HTTP 3xx redirects.\nThe omitempty flag is not set, because it would be hidden from the\nmarshalled configuration when set to false.",
"type": "boolean"
@ -3792,20 +3786,6 @@
}
}
},
"InclusiveRange": {
"type": "object",
"title": "InclusiveRange is used to hold the Beginning and End values of many time interval components.",
"properties": {
"Begin": {
"type": "integer",
"format": "int64"
},
"End": {
"type": "integer",
"format": "int64"
}
}
},
"InhibitRule": {
"description": "InhibitRule defines an inhibition rule that mutes alerts that match the\ntarget labels if an alert matching the source labels exists.\nBoth alerts have to have a set of labels being equal.",
"type": "object",
@ -4026,20 +4006,6 @@
"$ref": "#/definitions/MessageTemplate"
}
},
"MonthRange": {
"type": "object",
"title": "A MonthRange is an inclusive range between [1, 12] where 1 = January.",
"properties": {
"Begin": {
"type": "integer",
"format": "int64"
},
"End": {
"type": "integer",
"format": "int64"
}
}
},
"MultiStatus": {
"type": "object"
},
@ -4132,6 +4098,9 @@
"type": "string"
}
},
"proxy_url": {
"$ref": "#/definitions/URL"
},
"scopes": {
"type": "array",
"items": {
@ -4457,7 +4426,7 @@
"type": "string"
},
"for": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"grafana_alert": {
"$ref": "#/definitions/PostableGrafanaRule"
@ -4746,7 +4715,7 @@
"type": "object",
"properties": {
"expire": {
"$ref": "#/definitions/duration"
"type": "string"
},
"html": {
"type": "boolean"
@ -4761,7 +4730,7 @@
"type": "string"
},
"retry": {
"$ref": "#/definitions/duration"
"type": "string"
},
"send_resolved": {
"type": "boolean"
@ -4794,16 +4763,12 @@
"color": {
"description": "Map values to a display color\nNOTE: this interface is under development in the frontend... so simple map for now",
"type": "object",
"additionalProperties": {
"type": "object"
}
"additionalProperties": {}
},
"custom": {
"description": "Panel Specific Values",
"type": "object",
"additionalProperties": {
"type": "object"
}
"additionalProperties": {}
},
"decimals": {
"type": "integer",
@ -4988,10 +4953,10 @@
}
},
"group_interval": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"group_wait": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"match": {
"description": "Deprecated. Remove before v1.0 release.",
@ -5022,7 +4987,7 @@
"type": "string"
},
"repeat_interval": {
"$ref": "#/definitions/Duration"
"type": "string"
},
"routes": {
"type": "array",
@ -5424,12 +5389,19 @@
"description": "The client key file for the targets.",
"type": "string"
},
"min_version": {
"$ref": "#/definitions/TLSVersion"
},
"server_name": {
"description": "Used to verify the hostname for the targets.",
"type": "string"
}
}
},
"TLSVersion": {
"type": "integer",
"format": "uint16"
},
"TelegramConfig": {
"type": "object",
"title": "TelegramConfig configures notifications via Telegram.",
@ -5600,13 +5572,13 @@
"days_of_month": {
"type": "array",
"items": {
"$ref": "#/definitions/DayOfMonthRange"
"type": "string"
}
},
"months": {
"type": "array",
"items": {
"$ref": "#/definitions/MonthRange"
"type": "string"
}
},
"times": {
@ -5618,13 +5590,13 @@
"weekdays": {
"type": "array",
"items": {
"$ref": "#/definitions/WeekdayRange"
"type": "string"
}
},
"years": {
"type": "array",
"items": {
"$ref": "#/definitions/YearRange"
"type": "string"
}
}
}
@ -5645,8 +5617,9 @@
}
},
"URL": {
"description": "The general form represented is:\n\n[scheme:][//[userinfo@]host][/]path[?query][#fragment]\n\nURLs that do not start with a slash after the scheme are interpreted as:\n\nscheme:opaque[?query][#fragment]\n\nNote that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/.\nA consequence is that it is impossible to tell which slashes in the Path were\nslashes in the raw URL and which were %2f. This distinction is rarely important,\nbut when it is, the code should use RawPath, an optional field which only gets\nset if the default encoding is different from Path.\n\nURL's String method uses the EscapedPath method to obtain the path. See the\nEscapedPath method for more details.",
"type": "object",
"title": "URL is a custom URL type that allows validation at configuration load time.",
"title": "A URL represents a parsed URL (technically, a URI reference).",
"properties": {
"ForceQuery": {
"type": "boolean"
@ -5657,6 +5630,9 @@
"Host": {
"type": "string"
},
"OmitHost": {
"type": "boolean"
},
"Opaque": {
"type": "string"
},
@ -5815,34 +5791,6 @@
}
}
},
"WeekdayRange": {
"type": "object",
"title": "A WeekdayRange is an inclusive range between [0, 6] where 0 = Sunday.",
"properties": {
"Begin": {
"type": "integer",
"format": "int64"
},
"End": {
"type": "integer",
"format": "int64"
}
}
},
"YearRange": {
"type": "object",
"title": "A YearRange is a positive inclusive range.",
"properties": {
"Begin": {
"type": "integer",
"format": "int64"
},
"End": {
"type": "integer",
"format": "int64"
}
}
},
"alert": {
"description": "Alert alert",
"type": "object",
@ -5989,11 +5937,7 @@
}
}
},
"duration": {
"$ref": "#/definitions/Duration"
},
"gettableAlert": {
"description": "GettableAlert gettable alert",
"type": "object",
"required": [
"labels",
@ -6050,6 +5994,7 @@
"$ref": "#/definitions/gettableAlert"
},
"gettableAlerts": {
"description": "GettableAlerts gettable alerts",
"type": "array",
"items": {
"$ref": "#/definitions/gettableAlert"
@ -6106,13 +6051,44 @@
"$ref": "#/definitions/gettableSilence"
},
"gettableSilences": {
"description": "GettableSilences gettable silences",
"type": "array",
"items": {
"$ref": "#/definitions/gettableSilence"
},
"$ref": "#/definitions/gettableSilences"
},
"integration": {
"description": "Integration integration",
"type": "object",
"required": [
"name",
"sendResolved"
],
"properties": {
"lastNotifyAttempt": {
"description": "A timestamp indicating the last attempt to deliver a notification regardless of the outcome.\nFormat: date-time",
"type": "string",
"format": "date-time"
},
"lastNotifyAttemptDuration": {
"description": "Duration of the last attempt to deliver a notification in humanized format (`1s` or `15ms`, etc).",
"type": "string"
},
"lastNotifyAttemptError": {
"description": "Error string for the last attempt to deliver a notification. Empty if the last attempt was successful.",
"type": "string"
},
"name": {
"description": "name",
"type": "string"
},
"sendResolved": {
"description": "send resolved",
"type": "boolean"
}
},
"$ref": "#/definitions/integration"
},
"labelSet": {
"description": "LabelSet label set",
"type": "object",
@ -6218,7 +6194,6 @@
}
},
"postableSilence": {
"description": "PostableSilence postable silence",
"type": "object",
"required": [
"comment",
@ -6257,11 +6232,25 @@
"$ref": "#/definitions/postableSilence"
},
"receiver": {
"description": "Receiver receiver",
"type": "object",
"required": [
"active",
"integrations",
"name"
],
"properties": {
"active": {
"description": "active",
"type": "boolean"
},
"integrations": {
"description": "integrations",
"type": "array",
"items": {
"$ref": "#/definitions/integration"
}
},
"name": {
"description": "name",
"type": "string"

View File

@ -118,6 +118,8 @@ type Alertmanager struct {
silencer *silence.Silencer
silences *silence.Silences
receivers []*notify.Receiver
// muteTimes is a map where the key is the name of the mute_time_interval
// and the value represents all configured time_interval(s)
muteTimes map[string][]timeinterval.TimeInterval
@ -206,7 +208,7 @@ func newAlertmanager(ctx context.Context, orgID int64, cfg *setting.Cfg, store A
}()
// Initialize in-memory alerts
am.alerts, err = mem.NewAlerts(context.Background(), am.marker, memoryAlertsGCInterval, nil, am.logger)
am.alerts, err = mem.NewAlerts(context.Background(), am.marker, memoryAlertsGCInterval, nil, am.logger, m.Registerer)
if err != nil {
return nil, fmt.Errorf("unable to initialize the alert provider component of alerting: %w", err)
}
@ -421,14 +423,20 @@ func (am *Alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig
inhibitionStage := notify.NewMuteStage(am.inhibitor)
timeMuteStage := notify.NewTimeMuteStage(am.muteTimes)
silencingStage := notify.NewMuteStage(am.silencer)
for name := range integrationsMap {
stage := am.createReceiverStage(name, integrationsMap[name], am.waitFunc, am.notificationLog)
routingStage[name] = notify.MultiStage{meshStage, silencingStage, timeMuteStage, inhibitionStage, stage}
}
am.route = dispatch.NewRoute(cfg.AlertmanagerConfig.Route.AsAMRoute(), nil)
am.dispatcher = dispatch.NewDispatcher(am.alerts, am.route, routingStage, am.marker, am.timeoutFunc, &nilLimits{}, am.logger, am.dispatcherMetrics)
// Check which receivers are active and create the receiver stage.
activeReceivers := am.getActiveReceiversMap(am.route)
for name := range integrationsMap {
stage := am.createReceiverStage(name, integrationsMap[name], am.waitFunc, am.notificationLog)
routingStage[name] = notify.MultiStage{meshStage, silencingStage, timeMuteStage, inhibitionStage, stage}
_, isActive := activeReceivers[name]
am.receivers = append(am.receivers, notify.NewReceiver(name, isActive, integrationsMap[name]))
}
am.wg.Add(1)
go func() {
defer am.wg.Done()
@ -452,8 +460,8 @@ func (am *Alertmanager) WorkingDirPath() string {
}
// buildIntegrationsMap builds a map of name to the list of Grafana integration notifiers off of a list of receiver config.
func (am *Alertmanager) buildIntegrationsMap(receivers []*apimodels.PostableApiReceiver, templates *template.Template) (map[string][]notify.Integration, error) {
integrationsMap := make(map[string][]notify.Integration, len(receivers))
func (am *Alertmanager) buildIntegrationsMap(receivers []*apimodels.PostableApiReceiver, templates *template.Template) (map[string][]*notify.Integration, error) {
integrationsMap := make(map[string][]*notify.Integration, len(receivers))
for _, receiver := range receivers {
integrations, err := am.buildReceiverIntegrations(receiver, templates)
if err != nil {
@ -466,8 +474,8 @@ func (am *Alertmanager) buildIntegrationsMap(receivers []*apimodels.PostableApiR
}
// buildReceiverIntegrations builds a list of integration notifiers off of a receiver config.
func (am *Alertmanager) buildReceiverIntegrations(receiver *apimodels.PostableApiReceiver, tmpl *template.Template) ([]notify.Integration, error) {
var integrations []notify.Integration
func (am *Alertmanager) buildReceiverIntegrations(receiver *apimodels.PostableApiReceiver, tmpl *template.Template) ([]*notify.Integration, error) {
var integrations []*notify.Integration
for i, r := range receiver.GrafanaManagedReceivers {
n, err := am.buildReceiverIntegration(r, tmpl)
if err != nil {
@ -667,18 +675,18 @@ func (e AlertValidationError) Error() string {
}
// createReceiverStage creates a pipeline of stages for a receiver.
func (am *Alertmanager) createReceiverStage(name string, integrations []notify.Integration, wait func() time.Duration, notificationLog notify.NotificationLog) notify.Stage {
func (am *Alertmanager) createReceiverStage(name string, integrations []*notify.Integration, wait func() time.Duration, notificationLog notify.NotificationLog) notify.Stage {
var fs notify.FanoutStage
for i := range integrations {
for _, integration := range integrations {
recv := &nflogpb.Receiver{
GroupName: name,
Integration: integrations[i].Name(),
Idx: uint32(integrations[i].Index()),
Integration: integration.Name(),
Idx: uint32(integration.Index()),
}
var s notify.MultiStage
s = append(s, notify.NewWaitStage(wait))
s = append(s, notify.NewDedupStage(&integrations[i], notificationLog, recv))
s = append(s, notify.NewRetryStage(integrations[i], name, am.stageMetrics))
s = append(s, notify.NewDedupStage(integration, notificationLog, recv))
s = append(s, notify.NewRetryStage(integration, name, am.stageMetrics))
s = append(s, notify.NewSetNotifiesStage(notificationLog, recv))
fs = append(fs, s)
@ -686,6 +694,17 @@ func (am *Alertmanager) createReceiverStage(name string, integrations []notify.I
return fs
}
// getActiveReceiversMap returns all receivers that are in use by a route.
func (am *Alertmanager) getActiveReceiversMap(r *dispatch.Route) map[string]struct{} {
receiversMap := make(map[string]struct{})
visitFunc := func(r *dispatch.Route) {
receiversMap[r.RouteOpts.Receiver] = struct{}{}
}
r.Walk(visitFunc)
return receiversMap
}
func (am *Alertmanager) waitFunc() time.Duration {
return time.Duration(am.peer.Position()) * am.peerTimeout
}

View File

@ -314,7 +314,7 @@ func TestPutAlert(t *testing.T) {
t.Run(c.title, func(t *testing.T) {
r := prometheus.NewRegistry()
am.marker = types.NewMarker(r)
am.alerts, err = mem.NewAlerts(context.Background(), am.marker, 15*time.Minute, nil, am.logger)
am.alerts, err = mem.NewAlerts(context.Background(), am.marker, 15*time.Minute, nil, am.logger, r)
require.NoError(t, err)
alerts := []*types.Alert{}

View File

@ -85,7 +85,7 @@ func NewMultiOrgAlertmanager(cfg *setting.Cfg, configStore AlertingStore, orgSto
true,
cfg.UnifiedAlerting.HAPushPullInterval,
cfg.UnifiedAlerting.HAGossipInterval,
cluster.DefaultTcpTimeout,
cluster.DefaultTCPTimeout,
cluster.DefaultProbeTimeout,
cluster.DefaultProbeInterval,
nil,

View File

@ -8,7 +8,9 @@ import (
"sort"
"time"
"github.com/go-openapi/strfmt"
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
"github.com/prometheus/alertmanager/api/v2/models"
"github.com/prometheus/alertmanager/notify"
"github.com/prometheus/alertmanager/types"
"github.com/prometheus/common/model"
@ -197,6 +199,44 @@ func (am *Alertmanager) TestReceivers(ctx context.Context, c apimodels.TestRecei
return newTestReceiversResult(testAlert, append(invalid, results...), now), nil
}
func (am *Alertmanager) GetReceivers(ctx context.Context) apimodels.Receivers {
am.reloadConfigMtx.RLock()
defer am.reloadConfigMtx.RUnlock()
var apiReceivers apimodels.Receivers
for _, rcv := range am.receivers {
// Build integrations slice for each receiver.
var integrations []*models.Integration
for _, integration := range rcv.Integrations() {
name := integration.Name()
sendResolved := integration.SendResolved()
ts, d, err := integration.GetReport()
integrations = append(integrations, &apimodels.Integration{
Name: &name,
SendResolved: &sendResolved,
LastNotifyAttempt: strfmt.DateTime(ts),
LastNotifyAttemptDuration: d.String(),
LastNotifyAttemptError: func() string {
if err != nil {
return err.Error()
}
return ""
}(),
})
}
active := rcv.Active()
name := rcv.Name()
apiReceivers = append(apiReceivers, apimodels.Receiver{
Active: &active,
Integrations: integrations,
Name: &name,
})
}
return apiReceivers
}
func newTestAlert(c apimodels.TestReceiversConfigBodyParams, startsAt, updatedAt time.Time) types.Alert {
var (
defaultAnnotations = model.LabelSet{

View File

@ -728,7 +728,7 @@ func TestNotificationChannels(t *testing.T) {
channels.GetBoundary = func() string { return "abcd" }
env.NotificationService.EmailHandlerSync = mockEmail.sendEmailCommandHandlerSync
// As we are using a NotificationService mock here, but he test expects real NotificationService -
// As we are using a NotificationService mock here, but the test expects real NotificationService -
// we try to issue a real POST request here
env.NotificationService.WebhookHandler = func(_ context.Context, cmd *models.SendWebhookSync) error {
if res, err := http.Post(cmd.Url, "", strings.NewReader(cmd.Body)); err == nil {
@ -770,11 +770,31 @@ func TestNotificationChannels(t *testing.T) {
re := regexp.MustCompile(`"uid":"([\w|-]*)"`)
e := getExpAlertmanagerConfigFromAPI(mockChannel.server.Addr)
require.JSONEq(t, e, string(re.ReplaceAll([]byte(b), []byte(`"uid":""`))))
// Check the receivers API. No errors nor attempts to notify should be registered.
receiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers", grafanaListedAddr)
resp = getRequest(t, receiversURL, http.StatusOK) // nolint
b = getBody(t, resp.Body)
var receivers apimodels.Receivers
err := json.Unmarshal([]byte(b), &receivers)
require.NoError(t, err)
for _, rcv := range receivers {
require.NotNil(t, rcv.Name)
require.NotNil(t, rcv.Active)
require.NotEmpty(t, rcv.Integrations)
for _, integration := range rcv.Integrations {
require.NotNil(t, integration.Name)
require.NotNil(t, integration.SendResolved)
require.Equal(t, "", integration.LastNotifyAttemptError)
require.Zero(t, integration.LastNotifyAttempt)
require.Equal(t, "0s", integration.LastNotifyAttemptDuration)
}
}
}
{
// Create rules that will fire as quickly as possible
originalFunction := store.GenerateNewAlertRuleUID
t.Cleanup(func() {
store.GenerateNewAlertRuleUID = originalFunction
@ -791,6 +811,7 @@ func TestNotificationChannels(t *testing.T) {
// Eventually, we'll get all the desired alerts.
// nolint:gosec
require.Eventually(t, func() bool {
// TODO: not waiting for the failed notifications, flaky test?
return mockChannel.totalNotifications() >= len(nonEmailAlertNames) && len(mockEmail.emails) >= 1
}, 30*time.Second, 1*time.Second)
@ -798,6 +819,60 @@ func TestNotificationChannels(t *testing.T) {
require.Equal(t, expEmailNotifications, mockEmail.emails)
require.NoError(t, mockChannel.Close())
// Check the receivers API. Errors and inactive receivers are expected, attempts to deliver notifications should be registered.
receiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers", grafanaListedAddr)
resp := getRequest(t, receiversURL, http.StatusOK) // nolint
b := getBody(t, resp.Body)
var receivers apimodels.Receivers
err := json.Unmarshal([]byte(b), &receivers)
require.NoError(t, err)
for _, rcv := range receivers {
var expActive bool
if _, ok := expInactiveReceivers[*rcv.Name]; !ok {
expActive = true
}
var expErr bool
if _, ok := expNotificationErrors[*rcv.Name]; ok {
expErr = true
}
require.NotNil(t, rcv.Name)
require.NotNil(t, rcv.Active)
require.NotEmpty(t, rcv.Integrations)
if expActive {
require.True(t, *rcv.Active)
}
// We don't have test alerts for the default notifier, continue iterating.
if *rcv.Name == "grafana-default-email" {
continue
}
for _, integration := range rcv.Integrations {
require.NotNil(t, integration.Name)
require.NotNil(t, integration.SendResolved)
// If the receiver is not active, no attempts to send notifications should be registered.
if expActive {
require.NotZero(t, integration.LastNotifyAttempt)
require.NotEqual(t, "0s", integration.LastNotifyAttemptDuration)
} else {
require.Zero(t, integration.LastNotifyAttempt)
require.Equal(t, "0s", integration.LastNotifyAttemptDuration)
}
// Check whether we're expecting an error on this integration.
if expErr {
for _, integration := range rcv.Integrations {
require.Equal(t, expNotificationErrors[*rcv.Name], integration.LastNotifyAttemptError)
}
} else {
require.Equal(t, "", integration.LastNotifyAttemptError)
}
}
}
{
// Delete the configuration; so it returns the default configuration.
u := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/alerts", grafanaListedAddr)
@ -859,6 +934,10 @@ var emailAlertNames = []string{
"EmailAlert",
}
var failedAlertNames = []string{
"SlackFailedAlert",
}
func getRulesConfig(t *testing.T) string {
t.Helper()
interval, err := model.ParseDuration("10s")
@ -869,7 +948,10 @@ func getRulesConfig(t *testing.T) string {
}
// Create rules that will fire as quickly as possible for all the routes.
for _, alertName := range append(nonEmailAlertNames, emailAlertNames...) {
rulesToCreate := append(nonEmailAlertNames, emailAlertNames...)
rulesToCreate = append(rulesToCreate, failedAlertNames...)
for _, alertName := range rulesToCreate {
rules.Rules = append(rules.Rules, apimodels.PostableExtendedRuleNode{
GrafanaManagedAlert: &apimodels.PostableGrafanaRule{
Title: alertName,
@ -1124,6 +1206,26 @@ const alertmanagerConfig = `
"alertname=\"SlackAlert2\""
]
},
{
"receiver": "slack_failed_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"SlackFailedAlert\""
]
},
{
"receiver": "slack_inactive_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"Inactive\""
]
},
{
"receiver": "pagerduty_recv",
"group_wait": "0s",
@ -1273,7 +1375,7 @@ const alertmanagerConfig = `
"matchers": [
"alertname=\"TelegramAlert\""
]
}
}
]
},
"receivers": [
@ -1483,7 +1585,7 @@ const alertmanagerConfig = `
}
]
},
{
{
"name": "slack_recv1",
"grafana_managed_receiver_configs": [
{
@ -1506,8 +1608,8 @@ const alertmanagerConfig = `
}
}
]
},
{
},
{
"name": "slack_recv2",
"grafana_managed_receiver_configs": [
{
@ -1523,6 +1625,39 @@ const alertmanagerConfig = `
}
}
]
},
{
"name": "slack_failed_recv",
"grafana_managed_receiver_configs": [
{
"name": "slack_failed_test",
"type": "slack",
"settings": {
"recipient": "#test-channel",
"username": "test",
"text": "Integration Test"
},
"secureSettings": {
"url": "htt://127.0.0.1:8080/slack_failed_recv/slack_failed_test"
}
}
]
},
{
"name": "slack_inactive_recv",
"grafana_managed_receiver_configs": [
{
"name": "inactive",
"type": "slack",
"settings": {
"recipient": "#inactive-channel",
"username": "Integration Test"
},
"secureSettings": {
"token": "myfullysecrettoken"
}
}
]
},
{
"name": "pagerduty_recv",
@ -1589,7 +1724,26 @@ var expAlertmanagerConfigFromAPI = `
"alertname=\"SlackAlert2\""
]
},
{
{
"receiver": "slack_failed_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"SlackFailedAlert\""
]
},
{
"receiver": "slack_inactive_recv",
"group_wait": "0s",
"group_by": [
"alertname"
],
"matchers": [
"alertname=\"Inactive\""
]
}, {
"receiver": "pagerduty_recv",
"group_wait": "0s",
"group_by": [
@ -1738,7 +1892,7 @@ var expAlertmanagerConfigFromAPI = `
"matchers": [
"alertname=\"TelegramAlert\""
]
}
}
]
},
"templates": null,
@ -1986,7 +2140,7 @@ var expAlertmanagerConfigFromAPI = `
}
]
},
{
{
"name": "slack_recv1",
"grafana_managed_receiver_configs": [
{
@ -2031,6 +2185,43 @@ var expAlertmanagerConfigFromAPI = `
}
]
},
{
"name": "slack_failed_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "slack_failed_test",
"type": "slack",
"disableResolveMessage": false,
"settings": {
"recipient": "#test-channel",
"username": "test",
"text": "Integration Test"
},
"secureFields": {
"url": true
}
}
]
},
{
"name": "slack_inactive_recv",
"grafana_managed_receiver_configs": [
{
"uid": "",
"name": "inactive",
"type": "slack",
"disableResolveMessage": false,
"settings": {
"recipient": "#inactive-channel",
"username": "Integration Test"
},
"secureFields": {
"token": true
}
}
]
},
{
"name": "pagerduty_recv",
"grafana_managed_receiver_configs": [
@ -2435,3 +2626,13 @@ var expNonEmailNotifications = map[string][]string{
]`,
},
}
// expNotificationErrors maps a receiver name with its expected error string.
var expNotificationErrors = map[string]string{
"slack_failed_recv": `Post "htt://127.0.0.1:8080/slack_failed_recv/slack_failed_test": unsupported protocol scheme "htt"`,
}
// expNotificationErrors maps a receiver name with its expected error string.
var expInactiveReceivers = map[string]struct{}{
"slack_inactive_recv": {},
}