Alerting: Migrate notifications API to app-platform SDK application (#104424)

* introduce alerting notification app
* move code as is and remove from old registry
* update api server registration
* update make file and remove unnecessary args, copy some useful make commands from dashboards
* update codeowners

* move constants inside module and remove dependency from grafana
* add support for selectors to the app builder
This commit is contained in:
Yuri Tseretyan
2025-04-30 10:23:56 -04:00
committed by GitHub
parent 454e260207
commit 85344e30c0
50 changed files with 449 additions and 413 deletions
+1 -1
View File
@@ -732,11 +732,11 @@ embed.go @grafana/grafana-as-code
/pkg/kinds/ @grafana/grafana-as-code
/pkg/registry/ @grafana/grafana-as-code
/pkg/registry/apis/ @grafana/grafana-app-platform-squad
/pkg/registry/apis/alerting @grafana/grafana-app-platform-squad @grafana/alerting-backend
/pkg/registry/apis/query @grafana/grafana-datasources-core-services
/pkg/registry/apis/secret @grafana/grafana-operator-experience-squad
/pkg/registry/apis/userstorage @grafana/grafana-app-platform-squad @grafana/plugins-platform-backend
/pkg/registry/apps/advisor @grafana/plugins-platform-backend
/pkg/registry/apps/alerting @grafana/alerting-backend
/pkg/codegen/ @grafana/grafana-as-code
/pkg/codegen/generators @grafana/grafana-as-code
/pkg/kinds/*/*_gen.go @grafana/grafana-as-code
+27 -7
View File
@@ -1,8 +1,28 @@
APP_SDK_VERSION := v0.35.1
APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION)
APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk
.PHONY: install-app-sdk
install-app-sdk: $(APP_SDK_BIN) ## Install the Grafana App SDK
$(APP_SDK_BIN):
@echo "Installing Grafana App SDK version $(APP_SDK_VERSION)"
@mkdir -p $(APP_SDK_DIR)
# The only way to install specific versions of binaries using `go install`
# is by setting GOBIN to the directory you want to install the binary to.
GOBIN=$(APP_SDK_DIR) go install github.com/grafana/grafana-app-sdk/cmd/grafana-app-sdk@$(APP_SDK_VERSION)
@touch $@
.PHONY: update-app-sdk
update-app-sdk: ## Update the Grafana App SDK dependency in go.mod
go get github.com/grafana/grafana-app-sdk@$(APP_SDK_VERSION)
go mod tidy
.PHONY: generate
generate:
## --defencoding=none is needed to avoid infinite loop while generating recursive models (see routingtree.cue)
@grafana-app-sdk generate \
--gogenpath=./pkg/apis \
--source=./kinds/ \
--defencoding=none \
--noschemasinmanifest
generate: do-generate ## Run Grafana App SDK code generation
.PHONY: do-generate
do-generate: install-app-sdk update-app-sdk
## --defencoding=none and noschemasinmanifest are needed to avoid infinite loop while generating recursive models (see routingtree.cue)
@$(APP_SDK_BIN) generate --gogenpath=./pkg/apis --defencoding=none --noschemasinmanifest
+18 -9
View File
@@ -2,11 +2,9 @@ module github.com/grafana/grafana/apps/alerting/notifications
go 1.24.2
replace github.com/grafana/grafana => ../../..
require (
github.com/grafana/grafana v11.4.0-00010101000000-000000000000+incompatible
github.com/grafana/grafana-app-sdk v0.35.1
github.com/grafana/grafana-app-sdk/logging v0.35.1
k8s.io/apimachinery v0.32.3
k8s.io/apiserver v0.32.3
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
@@ -15,13 +13,14 @@ require (
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/getkin/kin-openapi v0.131.0 // indirect
@@ -31,17 +30,20 @@ require (
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/grafana/grafana-app-sdk/logging v0.35.1 // indirect
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250422074709-7c8433fbb2c2 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmespath-community/go-jmespath v1.1.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.18.0 // indirect
@@ -61,9 +63,12 @@ require (
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.63.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/spf13/cobra v1.9.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.etcd.io/bbolt v1.4.0 // indirect
go.etcd.io/etcd/api/v3 v3.5.16 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.16 // indirect
go.etcd.io/etcd/client/v3 v3.5.16 // indirect
@@ -73,20 +78,23 @@ require (
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
go.opentelemetry.io/otel/sdk v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
golang.org/x/net v0.39.0 // indirect
golang.org/x/oauth2 v0.29.0 // indirect
golang.org/x/sync v0.13.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/term v0.31.0 // indirect
golang.org/x/text v0.24.0 // indirect
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.32.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect
google.golang.org/grpc v1.71.1 // indirect
@@ -95,6 +103,7 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.32.3 // indirect
k8s.io/apiextensions-apiserver v0.32.3 // indirect
k8s.io/client-go v0.32.3 // indirect
k8s.io/component-base v0.32.3 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
+77 -10
View File
@@ -1,16 +1,20 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
@@ -24,12 +28,20 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/getkin/kin-openapi v0.131.0 h1:NO2UeHnFKRYhZ8wg6Nyh5Cq7dHk4suQQr72a4pMrDxE=
github.com/getkin/kin-openapi v0.131.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -41,6 +53,7 @@ github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
@@ -53,12 +66,15 @@ github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
@@ -75,8 +91,6 @@ github.com/grafana/grafana-app-sdk v0.35.1 h1:zEXubzsQrxGBOzXJJMBwhEClC/tvPi0sfK
github.com/grafana/grafana-app-sdk v0.35.1/go.mod h1:Zx5MkVppYK+ElSDUAR6+fjzOVo6I/cIgk+ty+LmNOxI=
github.com/grafana/grafana-app-sdk/logging v0.35.1 h1:taVpl+RoixTYl0JBJGhH+fPVmwA9wvdwdzJTZsv9buM=
github.com/grafana/grafana-app-sdk/logging v0.35.1/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250422074709-7c8433fbb2c2 h1:kvG92f3XbJlQPUcZfXlTNLziI4e8LYeA9Jv2ixmM5Ic=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250422074709-7c8433fbb2c2/go.mod h1:ll14OJrUGYgXApz3YX6zmxYjRMZHL+pgQjoKBuRzaRs=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 h1:uGoIog/wiQHI9GAxXO5TJbT0wWKH3O9HhOJW1F9c3fY=
@@ -85,10 +99,13 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jmespath-community/go-jmespath v1.1.1 h1:bFikPhsi/FdmlZhVgSCd2jj1e7G/rw+zyQfyg5UF+L4=
github.com/jmespath-community/go-jmespath v1.1.1/go.mod h1:4gOyFJsR/Gk+05RgTKYrifT7tBPWD8Lubtb5jRrfy9I=
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -99,8 +116,12 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
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/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
@@ -125,8 +146,10 @@ github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU
github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -137,6 +160,7 @@ github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGC
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
@@ -145,9 +169,12 @@ github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
@@ -157,11 +184,13 @@ github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wx
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf h1:Z2X3Os7oRzpdJ75iPqWZc0HeJWFYNCvKsfpQwFpRNTA=
github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0=
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
@@ -200,6 +229,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0f
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk=
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
@@ -210,10 +241,14 @@ go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -221,14 +256,18 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -243,10 +282,14 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
@@ -259,6 +302,11 @@ golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
@@ -268,8 +316,13 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0=
gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 h1:Pw6WnI9W/LIdRxqK7T6XGugGbHIRl5Q7q3BssH6xk4s=
google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4/go.mod h1:qbZzneIOXSq+KFAFut9krLfRLZiFLzZL5u2t8SV83EE=
google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 h1:hE3bRWtU6uceqlh4fhrSnUyjKHMKB9KrTLLG+bc0ddM=
@@ -277,11 +330,17 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463/go.
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI=
google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
@@ -290,11 +349,19 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY=
k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss=
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/apiserver v0.32.3 h1:kOw2KBuHOA+wetX1MkmrxgBr648ksz653j26ESuWNY8=
@@ -1,4 +1,4 @@
package common
package v0alpha1
const InternalPrefix = "grafana.com/"
const ProvenanceStatusAnnotationKey = InternalPrefix + "provenance"
@@ -11,6 +11,8 @@ import (
"github.com/grafana/grafana-app-sdk/app"
)
var ()
var appManifestData = app.ManifestData{
AppName: "alerting",
Group: "notifications.alerting.grafana.app",
@@ -6,16 +6,16 @@ import (
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apiserver/pkg/registry/generic"
"github.com/grafana/grafana/apps/alerting/common"
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1"
)
func (o *Receiver) GetProvenanceStatus() string {
if o == nil || o.Annotations == nil {
return ""
}
s, ok := o.Annotations[common.ProvenanceStatusAnnotationKey]
s, ok := o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey]
if !ok || s == "" {
return common.ProvenanceStatusNone
return v0alpha1.ProvenanceStatusNone
}
return s
}
@@ -25,9 +25,9 @@ func (o *Receiver) SetProvenanceStatus(status string) {
o.Annotations = make(map[string]string, 1)
}
if status == "" {
status = common.ProvenanceStatusNone
status = v0alpha1.ProvenanceStatusNone
}
o.Annotations[common.ProvenanceStatusAnnotationKey] = status
o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey] = status
}
func (o *Receiver) SetAccessControl(action string) {
@@ -40,7 +40,7 @@ func (o *Receiver) SetAccessControl(action string) {
// AccessControlAnnotation returns the key for the access control annotation for the given action.
// Ex. grafana.com/access/canDelete.
func AccessControlAnnotation(action string) string {
return fmt.Sprintf("%s%s/%s", common.InternalPrefix, "access", action)
return fmt.Sprintf("%s%s/%s", v0alpha1.InternalPrefix, "access", action)
}
func (o *Receiver) SetInUse(routesCnt int, rules []string) {
@@ -54,7 +54,7 @@ func (o *Receiver) SetInUse(routesCnt int, rules []string) {
// InUseAnnotation returns the key for the in-use annotation for the given resource.
// Ex. grafana.com/inUse/routes, grafana.com/inUse/rules.
func InUseAnnotation(resource string) string {
return fmt.Sprintf("%s%s/%s", common.InternalPrefix, "inUse", resource)
return fmt.Sprintf("%s%s/%s", v0alpha1.InternalPrefix, "inUse", resource)
}
func SelectableFields(obj *Receiver) fields.Set {
@@ -13,7 +13,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaReceiver = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &Receiver{}, &ReceiverList{}, resource.WithKind("Receiver"),
resource.WithPlural("receivers"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{{
resource.WithPlural("receivers"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{resource.SelectableField{
FieldSelector: "spec.title",
FieldValueFunc: func(o resource.Object) (string, error) {
cast, ok := o.(*Receiver)
@@ -1,7 +1,7 @@
package v0alpha1
import (
"github.com/grafana/grafana/apps/alerting/common"
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1"
)
const UserDefinedRoutingTreeName = "user-defined"
@@ -10,9 +10,9 @@ func (o *RoutingTree) GetProvenanceStatus() string {
if o == nil || o.Annotations == nil {
return ""
}
s, ok := o.Annotations[common.ProvenanceStatusAnnotationKey]
s, ok := o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey]
if !ok || s == "" {
return common.ProvenanceStatusNone
return v0alpha1.ProvenanceStatusNone
}
return s
}
@@ -22,7 +22,7 @@ func (o *RoutingTree) SetProvenanceStatus(status string) {
o.Annotations = make(map[string]string, 1)
}
if status == "" {
status = common.ProvenanceStatusNone
status = v0alpha1.ProvenanceStatusNone
}
o.Annotations[common.ProvenanceStatusAnnotationKey] = status
o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey] = status
}
@@ -4,7 +4,7 @@ import (
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apiserver/pkg/registry/generic"
"github.com/grafana/grafana/apps/alerting/common"
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1"
)
const DefaultTemplateTitle = "Built-in Templates"
@@ -13,9 +13,9 @@ func (o *TemplateGroup) GetProvenanceStatus() string {
if o == nil || o.Annotations == nil {
return ""
}
s, ok := o.Annotations[common.ProvenanceStatusAnnotationKey]
s, ok := o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey]
if !ok || s == "" {
return common.ProvenanceStatusNone
return v0alpha1.ProvenanceStatusNone
}
return s
}
@@ -25,9 +25,9 @@ func (o *TemplateGroup) SetProvenanceStatus(status string) {
o.Annotations = make(map[string]string, 1)
}
if status == "" {
status = common.ProvenanceStatusNone
status = v0alpha1.ProvenanceStatusNone
}
o.Annotations[common.ProvenanceStatusAnnotationKey] = status
o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey] = status
}
func SelectableFields(obj *TemplateGroup) fields.Set {
@@ -13,7 +13,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaTemplateGroup = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &TemplateGroup{}, &TemplateGroupList{}, resource.WithKind("TemplateGroup"),
resource.WithPlural("templategroups"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{{
resource.WithPlural("templategroups"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{resource.SelectableField{
FieldSelector: "spec.title",
FieldValueFunc: func(o resource.Object) (string, error) {
cast, ok := o.(*TemplateGroup)
@@ -4,16 +4,16 @@ import (
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apiserver/pkg/registry/generic"
"github.com/grafana/grafana/apps/alerting/common"
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1"
)
func (o *TimeInterval) GetProvenanceStatus() string {
if o == nil || o.Annotations == nil {
return ""
}
s, ok := o.Annotations[common.ProvenanceStatusAnnotationKey]
s, ok := o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey]
if !ok || s == "" {
return common.ProvenanceStatusNone
return v0alpha1.ProvenanceStatusNone
}
return s
}
@@ -23,9 +23,9 @@ func (o *TimeInterval) SetProvenanceStatus(status string) {
o.Annotations = make(map[string]string, 1)
}
if status == "" {
status = common.ProvenanceStatusNone
status = v0alpha1.ProvenanceStatusNone
}
o.Annotations[common.ProvenanceStatusAnnotationKey] = status
o.Annotations[v0alpha1.ProvenanceStatusAnnotationKey] = status
}
func SelectableFields(obj *TimeInterval) fields.Set {
@@ -8,9 +8,10 @@ import (
"time"
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1"
"github.com/grafana/grafana/pkg/util"
)
var UTCLocation = "UTC"
// +k8s:openapi-gen=false
type IntervalMutator func(spec *v0alpha1.Interval)
@@ -62,7 +63,7 @@ func (t IntervalGenerator) generateLocation() *string {
if rand.Int()%3 == 0 {
return nil
}
return util.Pointer("UTC")
return &UTCLocation
}
func (t IntervalGenerator) generateMonth() string {
@@ -13,7 +13,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaTimeInterval = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &TimeInterval{}, &TimeIntervalList{}, resource.WithKind("TimeInterval"),
resource.WithPlural("timeintervals"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{{
resource.WithPlural("timeintervals"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{resource.SelectableField{
FieldSelector: "spec.name",
FieldValueFunc: func(o resource.Object) (string, error) {
cast, ok := o.(*TimeInterval)
+37 -2
View File
@@ -1,5 +1,40 @@
package apis
import "k8s.io/apimachinery/pkg/runtime/schema"
import (
"maps"
var GroupVersion = schema.GroupVersion{Group: "notifications.alerting.grafana.app", Version: "v0alpha1"}
sdkResource "github.com/grafana/grafana-app-sdk/resource"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kube-openapi/pkg/common"
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1"
receiverv0alpha1 "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/receiver/v0alpha1"
routingtreev0alpha1 "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/routingtree/v0alpha1"
templategroupv0alpha1 "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/templategroup/v0alpha1"
timeintervalv0alpha1 "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1"
)
func GetOpenAPIDefinitions(c common.ReferenceCallback) map[string]common.OpenAPIDefinition {
tmpl := templategroupv0alpha1.GetOpenAPIDefinitions(c)
tin := timeintervalv0alpha1.GetOpenAPIDefinitions(c)
recv := receiverv0alpha1.GetOpenAPIDefinitions(c)
rest := routingtreev0alpha1.GetOpenAPIDefinitions(c)
result := make(map[string]common.OpenAPIDefinition, len(tmpl)+len(tin)+len(recv)+len(rest))
maps.Copy(result, tmpl)
maps.Copy(result, tin)
maps.Copy(result, recv)
maps.Copy(result, rest)
return result
}
func GetKinds() map[schema.GroupVersion][]sdkResource.Kind {
result := map[schema.GroupVersion][]sdkResource.Kind{
v0alpha1.GroupVersion: {
receiverv0alpha1.Kind(),
routingtreev0alpha1.Kind(),
templategroupv0alpha1.Kind(),
timeintervalv0alpha1.Kind(),
},
}
return result
}
@@ -0,0 +1,43 @@
package app
import (
"context"
"github.com/grafana/grafana-app-sdk/app"
"github.com/grafana/grafana-app-sdk/logging"
"github.com/grafana/grafana-app-sdk/simple"
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis"
)
func New(cfg app.Config) (app.App, error) {
managedKinds := make([]simple.AppManagedKind, 0)
for _, kinds := range apis.GetKinds() {
for _, kind := range kinds {
managedKinds = append(managedKinds, simple.AppManagedKind{Kind: kind})
}
}
c := simple.AppConfig{
Name: "alerting.notification",
KubeConfig: cfg.KubeConfig,
InformerConfig: simple.AppInformerConfig{
ErrorHandler: func(ctx context.Context, err error) {
logging.DefaultLogger.With("error", err).Error("Informer processing error")
},
},
ManagedKinds: managedKinds,
}
a, err := simple.NewApp(c)
if err != nil {
return nil, err
}
err = a.ValidateManifest(cfg.ManifestData)
if err != nil {
return nil, err
}
return a, nil
}
@@ -1,31 +0,0 @@
package receiver
import (
"k8s.io/apiserver/pkg/registry/rest"
grafanaregistry "github.com/grafana/grafana/pkg/apiserver/registry/generic"
"github.com/grafana/grafana/pkg/services/apiserver/builder"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
)
func NewStorage(
legacySvc ReceiverService,
namespacer request.NamespaceMapper,
opts builder.APIGroupOptions,
metadata MetadataService,
) (rest.Storage, error) {
legacyStore := &legacyStorage{
service: legacySvc,
namespacer: namespacer,
tableConverter: ResourceInfo.TableConverter(),
metadata: metadata,
}
if opts.OptsGetter != nil && opts.DualWriteBuilder != nil {
store, err := grafanaregistry.NewRegistryStore(opts.Scheme, ResourceInfo, opts.OptsGetter)
if err != nil {
return nil, err
}
return opts.DualWriteBuilder(ResourceInfo.GroupResource(), legacyStore, store)
}
return legacyStore, nil
}
@@ -1,164 +0,0 @@
package notifications
import (
"context"
"fmt"
"maps"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/registry/rest"
genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/kube-openapi/pkg/common"
"k8s.io/kube-openapi/pkg/spec3"
resource "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis"
"github.com/grafana/grafana/pkg/registry/apis/alerting/notifications/receiver"
"github.com/grafana/grafana/pkg/registry/apis/alerting/notifications/routingtree"
"github.com/grafana/grafana/pkg/registry/apis/alerting/notifications/templategroup"
"github.com/grafana/grafana/pkg/registry/apis/alerting/notifications/timeinterval"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/apiserver/builder"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/ngalert"
ac "github.com/grafana/grafana/pkg/services/ngalert/accesscontrol"
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/setting"
)
var _ builder.APIGroupBuilder = (*NotificationsAPIBuilder)(nil)
// This is used just so wire has something unique to return
type NotificationsAPIBuilder struct {
authz accesscontrol.AccessControl
receiverAuth receiver.AccessControlService
ng *ngalert.AlertNG
namespacer request.NamespaceMapper
}
func RegisterAPIService(
features featuremgmt.FeatureToggles,
apiregistration builder.APIRegistrar,
cfg *setting.Cfg,
ng *ngalert.AlertNG,
) *NotificationsAPIBuilder {
if ng.IsDisabled() {
return nil
}
builder := &NotificationsAPIBuilder{
ng: ng,
namespacer: request.GetNamespaceMapper(cfg),
authz: ng.Api.AccessControl,
receiverAuth: ac.NewReceiverAccess[*ngmodels.Receiver](ng.Api.AccessControl, false),
}
apiregistration.RegisterAPI(builder)
return builder
}
func (t *NotificationsAPIBuilder) GetGroupVersion() schema.GroupVersion {
return resource.GroupVersion
}
func (t *NotificationsAPIBuilder) InstallSchema(scheme *runtime.Scheme) error {
if err := receiver.AddKnownTypes(scheme); err != nil {
return err
}
if err := routingtree.AddKnownTypes(scheme); err != nil {
return err
}
if err := templategroup.AddKnownTypes(scheme); err != nil {
return err
}
if err := timeinterval.AddKnownTypes(scheme); err != nil {
return err
}
return nil
}
func (t *NotificationsAPIBuilder) UpdateAPIGroupInfo(apiGroupInfo *genericapiserver.APIGroupInfo, opts builder.APIGroupOptions) error {
addStorage := func(gvr schema.GroupVersionResource, s rest.Storage) {
v, ok := apiGroupInfo.VersionedResourcesStorageMap[gvr.Version]
if !ok {
v = map[string]rest.Storage{}
apiGroupInfo.VersionedResourcesStorageMap[gvr.Version] = v
}
v[gvr.Resource] = s
}
intervals, err := timeinterval.NewStorage(t.ng.Api.MuteTimings, t.namespacer, opts)
if err != nil {
return fmt.Errorf("failed to initialize time-interval storage: %w", err)
}
addStorage(timeinterval.ResourceInfo.GroupVersionResource(), intervals)
recvStorage, err := receiver.NewStorage(t.ng.Api.ReceiverService, t.namespacer, opts, t.ng.Api.ReceiverService)
if err != nil {
return fmt.Errorf("failed to initialize receiver storage: %w", err)
}
addStorage(receiver.ResourceInfo.GroupVersionResource(), recvStorage)
templ, err := templategroup.NewStorage(t.ng.Api.Templates, t.namespacer, opts)
if err != nil {
return fmt.Errorf("failed to initialize templates group storage: %w", err)
}
addStorage(templategroup.ResourceInfo.GroupVersionResource(), templ)
routeStorage, err := routingtree.NewStorage(t.ng.Api.Policies, t.namespacer)
if err != nil {
return fmt.Errorf("failed to initialize route storage: %w", err)
}
addStorage(routingtree.ResourceInfo.GroupVersionResource(), routeStorage)
return nil
}
func (t *NotificationsAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefinitions {
return func(c common.ReferenceCallback) map[string]common.OpenAPIDefinition {
tmpl := templategroup.GetOpenAPIDefinitions(c)
tin := timeinterval.GetOpenAPIDefinitions(c)
recv := receiver.GetOpenAPIDefinitions(c)
rest := routingtree.GetOpenAPIDefinitions(c)
result := make(map[string]common.OpenAPIDefinition, len(tmpl)+len(tin)+len(recv)+len(rest))
maps.Copy(result, tmpl)
maps.Copy(result, tin)
maps.Copy(result, recv)
maps.Copy(result, rest)
return result
}
}
// PostProcessOpenAPI is a hook to alter OpenAPI3 specification of the API server.
func (t *NotificationsAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.OpenAPI, error) {
// The plugin description
oas.Info.Description = "Grafana Alerting Notification resources"
// The root api URL
root := "/apis/" + t.GetGroupVersion().String() + "/"
// Hide the ability to list or watch across all tenants
delete(oas.Paths.Paths, root+receiver.ResourceInfo.GroupResource().Resource)
delete(oas.Paths.Paths, root+timeinterval.ResourceInfo.GroupResource().Resource)
delete(oas.Paths.Paths, root+templategroup.ResourceInfo.GroupResource().Resource)
delete(oas.Paths.Paths, root+routingtree.ResourceInfo.GroupResource().Resource)
return oas, nil
}
func (t *NotificationsAPIBuilder) GetAuthorizer() authorizer.Authorizer {
return authorizer.AuthorizerFunc(
func(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
switch a.GetResource() {
case templategroup.ResourceInfo.GroupResource().Resource:
return templategroup.Authorize(ctx, t.authz, a)
case timeinterval.ResourceInfo.GroupResource().Resource:
return timeinterval.Authorize(ctx, t.authz, a)
case receiver.ResourceInfo.GroupResource().Resource:
return receiver.Authorize(ctx, t.receiverAuth, a)
case routingtree.ResourceInfo.GroupResource().Resource:
return routingtree.Authorize(ctx, t.authz, a)
}
return authorizer.DecisionNoOpinion, "", nil
})
}
@@ -1,29 +0,0 @@
package templategroup
import (
"k8s.io/apiserver/pkg/registry/rest"
grafanaregistry "github.com/grafana/grafana/pkg/apiserver/registry/generic"
"github.com/grafana/grafana/pkg/services/apiserver/builder"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
)
func NewStorage(
legacySvc TemplateService,
namespacer request.NamespaceMapper,
opts builder.APIGroupOptions,
) (rest.Storage, error) {
legacyStore := &legacyStorage{
service: legacySvc,
namespacer: namespacer,
tableConverter: ResourceInfo.TableConverter(),
}
if opts.OptsGetter != nil && opts.DualWriteBuilder != nil {
store, err := grafanaregistry.NewRegistryStore(opts.Scheme, ResourceInfo, opts.OptsGetter)
if err != nil {
return nil, err
}
return opts.DualWriteBuilder(ResourceInfo.GroupResource(), legacyStore, store)
}
return legacyStore, nil
}
@@ -1,29 +0,0 @@
package timeinterval
import (
"k8s.io/apiserver/pkg/registry/rest"
grafanaregistry "github.com/grafana/grafana/pkg/apiserver/registry/generic"
"github.com/grafana/grafana/pkg/services/apiserver/builder"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
)
func NewStorage(
legacySvc TimeIntervalService,
namespacer request.NamespaceMapper,
opts builder.APIGroupOptions,
) (rest.Storage, error) {
legacyStore := &legacyStorage{
service: legacySvc,
namespacer: namespacer,
tableConverter: ResourceInfo.TableConverter(),
}
if opts.OptsGetter != nil && opts.DualWriteBuilder != nil {
store, err := grafanaregistry.NewRegistryStore(opts.Scheme, ResourceInfo, opts.OptsGetter)
if err != nil {
return nil, err
}
return opts.DualWriteBuilder(ResourceInfo.GroupResource(), legacyStore, store)
}
return legacyStore, nil
}
-2
View File
@@ -1,7 +1,6 @@
package apiregistry
import (
"github.com/grafana/grafana/pkg/registry/apis/alerting/notifications"
dashboardinternal "github.com/grafana/grafana/pkg/registry/apis/dashboard"
"github.com/grafana/grafana/pkg/registry/apis/dashboardsnapshot"
"github.com/grafana/grafana/pkg/registry/apis/datasource"
@@ -26,7 +25,6 @@ func ProvideRegistryServiceSink(
_ *folders.FolderAPIBuilder,
_ *iam.IdentityAccessManagementAPIBuilder,
_ *query.QueryAPIBuilder,
_ *notifications.NotificationsAPIBuilder,
_ *userstorage.UserStorageAPIBuilder,
_ *secret.SecretAPIBuilder,
_ *provisioning.APIBuilder,
-2
View File
@@ -3,7 +3,6 @@ package apiregistry
import (
"github.com/google/wire"
"github.com/grafana/grafana/pkg/registry/apis/alerting/notifications"
dashboardinternal "github.com/grafana/grafana/pkg/registry/apis/dashboard"
"github.com/grafana/grafana/pkg/registry/apis/dashboardsnapshot"
"github.com/grafana/grafana/pkg/registry/apis/datasource"
@@ -36,7 +35,6 @@ var WireSet = wire.NewSet(
provisioning.RegisterAPIService,
service.RegisterAPIService,
query.RegisterAPIService,
notifications.RegisterAPIService,
secret.RegisterAPIService,
userstorage.RegisterAPIService,
)
@@ -0,0 +1,19 @@
package receiver
import (
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
)
func NewStorage(
legacySvc ReceiverService,
namespacer request.NamespaceMapper,
metadata MetadataService,
) grafanarest.Storage {
return &legacyStorage{
service: legacySvc,
namespacer: namespacer,
tableConverter: ResourceInfo.TableConverter(),
metadata: metadata,
}
}
@@ -12,7 +12,6 @@ import (
)
var kind = model.Kind()
var GetOpenAPIDefinitions = model.GetOpenAPIDefinitions
var ResourceInfo = utils.NewResourceInfo(kind.Group(), kind.Version(),
kind.GroupVersionResource().Resource, strings.ToLower(kind.Kind()), kind.Kind(),
func() runtime.Object { return kind.ZeroValue() },
@@ -35,28 +34,3 @@ var ResourceInfo = utils.NewResourceInfo(kind.Group(), kind.Version(),
},
},
)
func AddKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(ResourceInfo.GroupVersion(),
&model.Receiver{},
&model.ReceiverList{},
)
metav1.AddToGroupVersion(scheme, ResourceInfo.GroupVersion())
err := scheme.AddFieldLabelConversionFunc(
ResourceInfo.GroupVersionKind(),
func(label, value string) (string, string, error) {
fieldSet := model.SelectableFields(&model.Receiver{})
for key := range fieldSet {
if label == key {
return label, value, nil
}
}
return "", "", fmt.Errorf("field label not supported for %s: %s", ResourceInfo.GroupVersionKind(), label)
},
)
if err != nil {
return err
}
return nil
}
@@ -0,0 +1,80 @@
package notifications
import (
"context"
"github.com/grafana/grafana-app-sdk/app"
"github.com/grafana/grafana-app-sdk/simple"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/authorization/authorizer"
notificationsResource "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis"
notificationsApp "github.com/grafana/grafana/apps/alerting/notifications/pkg/app"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/registry/apps/alerting/notifications/receiver"
"github.com/grafana/grafana/pkg/registry/apps/alerting/notifications/routingtree"
"github.com/grafana/grafana/pkg/registry/apps/alerting/notifications/templategroup"
"github.com/grafana/grafana/pkg/registry/apps/alerting/notifications/timeinterval"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/apiserver/builder/runner"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
"github.com/grafana/grafana/pkg/services/ngalert"
ac "github.com/grafana/grafana/pkg/services/ngalert/accesscontrol"
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/setting"
)
type AlertingNotificationsAppProvider struct {
app.Provider
}
func RegisterApp(
cfg *setting.Cfg,
ng *ngalert.AlertNG,
) *AlertingNotificationsAppProvider {
if ng.IsDisabled() {
return nil
}
appCfg := &runner.AppBuilderConfig{
Authorizer: getAuthorizer(ng.Api.AccessControl),
LegacyStorageGetter: getLegacyStorage(request.GetNamespaceMapper(cfg), ng),
OpenAPIDefGetter: notificationsResource.GetOpenAPIDefinitions,
ManagedKinds: notificationsResource.GetKinds(),
}
return &AlertingNotificationsAppProvider{
Provider: simple.NewAppProvider(notificationsResource.LocalManifest(), appCfg, notificationsApp.New),
}
}
func getAuthorizer(authz accesscontrol.AccessControl) authorizer.Authorizer {
return authorizer.AuthorizerFunc(
func(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
switch a.GetResource() {
case templategroup.ResourceInfo.GroupResource().Resource:
return templategroup.Authorize(ctx, authz, a)
case timeinterval.ResourceInfo.GroupResource().Resource:
return timeinterval.Authorize(ctx, authz, a)
case receiver.ResourceInfo.GroupResource().Resource:
return receiver.Authorize(ctx, ac.NewReceiverAccess[*ngmodels.Receiver](authz, false), a)
case routingtree.ResourceInfo.GroupResource().Resource:
return routingtree.Authorize(ctx, authz, a)
}
return authorizer.DecisionNoOpinion, "", nil
})
}
func getLegacyStorage(namespacer request.NamespaceMapper, ng *ngalert.AlertNG) runner.LegacyStorageGetter {
return func(gvr schema.GroupVersionResource) grafanarest.Storage {
if gvr == receiver.ResourceInfo.GroupVersionResource() {
return receiver.NewStorage(ng.Api.ReceiverService, namespacer, ng.Api.ReceiverService)
} else if gvr == timeinterval.ResourceInfo.GroupVersionResource() {
return timeinterval.NewStorage(ng.Api.MuteTimings, namespacer)
} else if gvr == templategroup.ResourceInfo.GroupVersionResource() {
return templategroup.NewStorage(ng.Api.Templates, namespacer)
} else if gvr == routingtree.ResourceInfo.GroupVersionResource() {
return routingtree.NewStorage(ng.Api.Policies, namespacer)
}
panic("unknown legacy storage requested: " + gvr.String())
}
}
@@ -3,15 +3,14 @@ package routingtree
import (
"k8s.io/apiserver/pkg/registry/rest"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
)
func NewStorage(legacySvc RouteService, namespacer request.NamespaceMapper) (rest.Storage, error) {
legacyStore := &legacyStorage{
func NewStorage(legacySvc RouteService, namespacer request.NamespaceMapper) grafanarest.Storage {
return &legacyStorage{
service: legacySvc,
namespacer: namespacer,
tableConverter: rest.NewDefaultTableConvertor(ResourceInfo.GroupResource()),
}
// TODO implement dual write for routes. This API is a special beast - the resource is singleton.
return legacyStore, nil
}
@@ -3,7 +3,6 @@ package routingtree
import (
"strings"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
model "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/routingtree/v0alpha1"
@@ -11,19 +10,9 @@ import (
)
var kind = model.Kind()
var GetOpenAPIDefinitions = model.GetOpenAPIDefinitions
var ResourceInfo = utils.NewResourceInfo(kind.Group(), kind.Version(),
kind.GroupVersionResource().Resource, strings.ToLower(kind.Kind()), kind.Kind(),
func() runtime.Object { return kind.ZeroValue() },
func() runtime.Object { return kind.ZeroListValue() },
utils.TableColumns{},
)
func AddKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(ResourceInfo.GroupVersion(),
&model.RoutingTree{},
&model.RoutingTreeList{},
)
metav1.AddToGroupVersion(scheme, ResourceInfo.GroupVersion())
return nil
}
@@ -0,0 +1,17 @@
package templategroup
import (
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
)
func NewStorage(
legacySvc TemplateService,
namespacer request.NamespaceMapper,
) grafanarest.Storage {
return &legacyStorage{
service: legacySvc,
namespacer: namespacer,
tableConverter: ResourceInfo.TableConverter(),
}
}
@@ -12,7 +12,6 @@ import (
)
var kind = model.Kind()
var GetOpenAPIDefinitions = model.GetOpenAPIDefinitions
var ResourceInfo = utils.NewResourceInfo(kind.Group(), kind.Version(),
kind.GroupVersionResource().Resource, strings.ToLower(kind.Kind()), kind.Kind(),
func() runtime.Object { return kind.ZeroValue() },
@@ -32,28 +31,3 @@ var ResourceInfo = utils.NewResourceInfo(kind.Group(), kind.Version(),
},
},
)
func AddKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(ResourceInfo.GroupVersion(),
&model.TemplateGroup{},
&model.TemplateGroupList{},
)
metav1.AddToGroupVersion(scheme, ResourceInfo.GroupVersion())
err := scheme.AddFieldLabelConversionFunc(
ResourceInfo.GroupVersionKind(),
func(label, value string) (string, string, error) {
fieldSet := model.SelectableFields(&model.TemplateGroup{})
for key := range fieldSet {
if label == key {
return label, value, nil
}
}
return "", "", fmt.Errorf("field label not supported for %s: %s", ResourceInfo.GroupVersionKind(), label)
},
)
if err != nil {
return err
}
return nil
}
@@ -0,0 +1,17 @@
package timeinterval
import (
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
)
func NewStorage(
legacySvc TimeIntervalService,
namespacer request.NamespaceMapper,
) grafanarest.Storage {
return &legacyStorage{
service: legacySvc,
namespacer: namespacer,
tableConverter: ResourceInfo.TableConverter(),
}
}
@@ -12,7 +12,6 @@ import (
)
var kind = model.Kind()
var GetOpenAPIDefinitions = model.GetOpenAPIDefinitions
var ResourceInfo = utils.NewResourceInfo(kind.Group(), kind.Version(),
kind.GroupVersionResource().Resource, strings.ToLower(kind.Kind()), kind.Kind(),
func() runtime.Object { return kind.ZeroValue() },
@@ -32,28 +31,3 @@ var ResourceInfo = utils.NewResourceInfo(kind.Group(), kind.Version(),
},
},
)
func AddKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(ResourceInfo.GroupVersion(),
&model.TimeInterval{},
&model.TimeIntervalList{},
)
metav1.AddToGroupVersion(scheme, ResourceInfo.GroupVersion())
err := scheme.AddFieldLabelConversionFunc(
ResourceInfo.GroupVersionKind(),
func(label, value string) (string, string, error) {
fieldSet := model.SelectableFields(&model.TimeInterval{})
for key := range fieldSet {
if label == key {
return label, value, nil
}
}
return "", "", fmt.Errorf("field label not supported for %s: %s", ResourceInfo.GroupVersionKind(), label)
},
)
if err != nil {
return err
}
return nil
}
+7 -1
View File
@@ -5,9 +5,12 @@ import (
"slices"
"github.com/grafana/grafana-app-sdk/app"
"k8s.io/client-go/rest"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/registry"
"github.com/grafana/grafana/pkg/registry/apps/advisor"
"github.com/grafana/grafana/pkg/registry/apps/alerting/notifications"
"github.com/grafana/grafana/pkg/registry/apps/investigations"
"github.com/grafana/grafana/pkg/registry/apps/playlist"
"github.com/grafana/grafana/pkg/services/apiserver"
@@ -15,7 +18,6 @@ import (
"github.com/grafana/grafana/pkg/services/apiserver/builder/runner"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/setting"
"k8s.io/client-go/rest"
)
var (
@@ -35,6 +37,7 @@ func ProvideRegistryServiceSink(
playlistAppProvider *playlist.PlaylistAppProvider,
investigationAppProvider *investigations.InvestigationsAppProvider,
advisorAppProvider *advisor.AdvisorAppProvider,
alertingNotificationsAppProvider *notifications.AlertingNotificationsAppProvider,
grafanaCfg *setting.Cfg,
) (*Service, error) {
cfgWrapper := func(ctx context.Context) (*rest.Config, error) {
@@ -62,6 +65,9 @@ func ProvideRegistryServiceSink(
!slices.Contains(grafanaCfg.DisablePlugins, "grafana-advisor-app") {
providers = append(providers, advisorAppProvider)
}
if alertingNotificationsAppProvider != nil {
providers = append(providers, alertingNotificationsAppProvider)
}
apiGroupRunner, err = runner.NewAPIGroupRunner(cfg, providers...)
if err != nil {
+2
View File
@@ -5,6 +5,7 @@ import (
"github.com/grafana/grafana/apps/advisor/pkg/app/checkregistry"
"github.com/grafana/grafana/pkg/registry/apps/advisor"
"github.com/grafana/grafana/pkg/registry/apps/alerting/notifications"
"github.com/grafana/grafana/pkg/registry/apps/investigations"
"github.com/grafana/grafana/pkg/registry/apps/playlist"
)
@@ -15,5 +16,6 @@ var WireSet = wire.NewSet(
investigations.RegisterApp,
advisor.RegisterApp,
checkregistry.ProvideService,
notifications.RegisterApp,
wire.Bind(new(checkregistry.CheckService), new(*checkregistry.Service)),
)
@@ -1,6 +1,8 @@
package runner
import (
"fmt"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/authorization/authorizer"
@@ -10,6 +12,7 @@ import (
"github.com/grafana/grafana-app-sdk/app"
"github.com/grafana/grafana-app-sdk/resource"
"github.com/grafana/grafana/pkg/apimachinery/utils"
grafanaregistry "github.com/grafana/grafana/pkg/apiserver/registry/generic"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
@@ -74,6 +77,29 @@ func (b *appBuilder) InstallSchema(scheme *runtime.Scheme) error {
}
scheme.AddKnownTypeWithName(gvInternal.WithKind(kind.Kind()), kind.ZeroValue())
scheme.AddKnownTypeWithName(gvInternal.WithKind(kind.Kind()+"List"), kind.ZeroListValue())
if len(kind.SelectableFields()) == 0 {
continue
}
gvk := gv.WithKind(kind.Kind())
err := scheme.AddFieldLabelConversionFunc(
gvk,
func(label, value string) (string, string, error) {
if label == "metadata.name" || label == "metadata.namespace" {
return label, value, nil
}
fields := kind.SelectableFields()
for _, field := range fields {
if field.FieldSelector == label {
return label, value, nil
}
}
return "", "", fmt.Errorf("field label not supported for %s: %s", gvk, label)
},
)
if err != nil {
return err
}
}
}
return scheme.SetVersionPriority(gv)
@@ -24,7 +24,7 @@ import (
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/receiver/v0alpha1"
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
"github.com/grafana/grafana/pkg/registry/apis/alerting/notifications/routingtree"
"github.com/grafana/grafana/pkg/registry/apps/alerting/notifications/routingtree"
test_common "github.com/grafana/grafana/pkg/tests/apis/alerting/notifications/common"
@@ -18,7 +18,7 @@ import (
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/routingtree/v0alpha1"
v0alpha1_timeinterval "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1"
"github.com/grafana/grafana/pkg/registry/apis/alerting/notifications/routingtree"
"github.com/grafana/grafana/pkg/registry/apps/alerting/notifications/routingtree"
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1/fakes"
"github.com/grafana/grafana/pkg/bus"
@@ -21,8 +21,8 @@ import (
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1/fakes"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/registry/apis/alerting/notifications/routingtree"
"github.com/grafana/grafana/pkg/registry/apis/alerting/notifications/timeinterval"
"github.com/grafana/grafana/pkg/registry/apps/alerting/notifications/routingtree"
"github.com/grafana/grafana/pkg/registry/apps/alerting/notifications/timeinterval"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
@@ -1,7 +1,6 @@
{
"openapi": "3.0.0",
"info": {
"description": "Grafana Alerting Notification resources",
"title": "notifications.alerting.grafana.app/v0alpha1"
},
"paths": {
@@ -3434,6 +3433,11 @@
}
},
"x-kubernetes-group-version-kind": [
{
"group": "notifications.alerting.grafana.app",
"kind": "Receiver",
"version": "__internal"
},
{
"group": "notifications.alerting.grafana.app",
"kind": "Receiver",
@@ -3477,6 +3481,11 @@
}
},
"x-kubernetes-group-version-kind": [
{
"group": "notifications.alerting.grafana.app",
"kind": "ReceiverList",
"version": "__internal"
},
{
"group": "notifications.alerting.grafana.app",
"kind": "ReceiverList",
@@ -3715,6 +3724,11 @@
}
},
"x-kubernetes-group-version-kind": [
{
"group": "notifications.alerting.grafana.app",
"kind": "RoutingTree",
"version": "__internal"
},
{
"group": "notifications.alerting.grafana.app",
"kind": "RoutingTree",
@@ -3758,6 +3772,11 @@
}
},
"x-kubernetes-group-version-kind": [
{
"group": "notifications.alerting.grafana.app",
"kind": "RoutingTreeList",
"version": "__internal"
},
{
"group": "notifications.alerting.grafana.app",
"kind": "RoutingTreeList",
@@ -3961,6 +3980,11 @@
}
},
"x-kubernetes-group-version-kind": [
{
"group": "notifications.alerting.grafana.app",
"kind": "TemplateGroup",
"version": "__internal"
},
{
"group": "notifications.alerting.grafana.app",
"kind": "TemplateGroup",
@@ -4004,6 +4028,11 @@
}
},
"x-kubernetes-group-version-kind": [
{
"group": "notifications.alerting.grafana.app",
"kind": "TemplateGroupList",
"version": "__internal"
},
{
"group": "notifications.alerting.grafana.app",
"kind": "TemplateGroupList",
@@ -4179,6 +4208,11 @@
}
},
"x-kubernetes-group-version-kind": [
{
"group": "notifications.alerting.grafana.app",
"kind": "TimeInterval",
"version": "__internal"
},
{
"group": "notifications.alerting.grafana.app",
"kind": "TimeInterval",
@@ -4222,6 +4256,11 @@
}
},
"x-kubernetes-group-version-kind": [
{
"group": "notifications.alerting.grafana.app",
"kind": "TimeIntervalList",
"version": "__internal"
},
{
"group": "notifications.alerting.grafana.app",
"kind": "TimeIntervalList",