From 85344e30c0c5f4ccd3eae2eb2c529c10526f7bdc Mon Sep 17 00:00:00 2001 From: Yuri Tseretyan Date: Wed, 30 Apr 2025 10:23:56 -0400 Subject: [PATCH] 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 --- .github/CODEOWNERS | 2 +- apps/alerting/notifications/Makefile | 34 +++- apps/alerting/notifications/go.mod | 27 ++- apps/alerting/notifications/go.sum | 87 ++++++++-- .../pkg/apis/alerting/v0alpha1/ext.go} | 2 +- .../pkg/apis/alerting_manifest.go | 2 + .../pkg/apis/receiver/v0alpha1/ext.go | 14 +- .../receiver/v0alpha1/receiver_schema_gen.go | 2 +- .../pkg/apis/routingtree/v0alpha1/ext.go | 10 +- .../pkg/apis/templategroup/v0alpha1/ext.go | 10 +- .../v0alpha1/templategroup_schema_gen.go | 2 +- .../pkg/apis/timeinterval/v0alpha1/ext.go | 10 +- .../apis/timeinterval/v0alpha1/fakes/gen.go | 5 +- .../v0alpha1/timeinterval_schema_gen.go | 2 +- apps/alerting/notifications/pkg/apis/type.go | 39 ++++- apps/alerting/notifications/pkg/app/app.go | 43 +++++ .../notifications/receiver/storage.go | 31 ---- .../apis/alerting/notifications/register.go | 164 ------------------ .../notifications/templategroup/storage.go | 29 ---- .../notifications/timeinterval/storage.go | 29 ---- pkg/registry/apis/apis.go | 2 - pkg/registry/apis/wireset.go | 2 - .../notifications/receiver/authorize.go | 0 .../notifications/receiver/conversions.go | 0 .../notifications/receiver/legacy_storage.go | 0 .../notifications/receiver/storage.go | 19 ++ .../alerting/notifications/receiver/type.go | 26 --- .../apps/alerting/notifications/register.go | 80 +++++++++ .../notifications/routingtree/authorize.go | 0 .../notifications/routingtree/conversions.go | 0 .../routingtree/legacy_storage.go | 0 .../notifications/routingtree/storage.go | 7 +- .../notifications/routingtree/type.go | 11 -- .../notifications/templategroup/authorize.go | 0 .../templategroup/conversions.go | 0 .../templategroup/legacy_storage.go | 0 .../notifications/templategroup/storage.go | 17 ++ .../notifications/templategroup/type.go | 26 --- .../notifications/timeinterval/authorize.go | 0 .../notifications/timeinterval/conversions.go | 0 .../timeinterval/legacy_storage.go | 0 .../notifications/timeinterval/storage.go | 17 ++ .../notifications/timeinterval/type.go | 26 --- pkg/registry/apps/apps.go | 8 +- pkg/registry/apps/wireset.go | 2 + .../apiserver/builder/runner/builder.go | 26 +++ .../notifications/receivers/receiver_test.go | 2 +- .../routingtree/routing_tree_test.go | 2 +- .../timeinterval/timeinterval_test.go | 4 +- ...cations.alerting.grafana.app-v0alpha1.json | 41 ++++- 50 files changed, 449 insertions(+), 413 deletions(-) rename apps/alerting/{common/constants.go => notifications/pkg/apis/alerting/v0alpha1/ext.go} (89%) create mode 100644 apps/alerting/notifications/pkg/app/app.go delete mode 100644 pkg/registry/apis/alerting/notifications/receiver/storage.go delete mode 100644 pkg/registry/apis/alerting/notifications/register.go delete mode 100644 pkg/registry/apis/alerting/notifications/templategroup/storage.go delete mode 100644 pkg/registry/apis/alerting/notifications/timeinterval/storage.go rename pkg/registry/{apis => apps}/alerting/notifications/receiver/authorize.go (100%) rename pkg/registry/{apis => apps}/alerting/notifications/receiver/conversions.go (100%) rename pkg/registry/{apis => apps}/alerting/notifications/receiver/legacy_storage.go (100%) create mode 100644 pkg/registry/apps/alerting/notifications/receiver/storage.go rename pkg/registry/{apis => apps}/alerting/notifications/receiver/type.go (60%) create mode 100644 pkg/registry/apps/alerting/notifications/register.go rename pkg/registry/{apis => apps}/alerting/notifications/routingtree/authorize.go (100%) rename pkg/registry/{apis => apps}/alerting/notifications/routingtree/conversions.go (100%) rename pkg/registry/{apis => apps}/alerting/notifications/routingtree/legacy_storage.go (100%) rename pkg/registry/{apis => apps}/alerting/notifications/routingtree/storage.go (64%) rename pkg/registry/{apis => apps}/alerting/notifications/routingtree/type.go (61%) rename pkg/registry/{apis => apps}/alerting/notifications/templategroup/authorize.go (100%) rename pkg/registry/{apis => apps}/alerting/notifications/templategroup/conversions.go (100%) rename pkg/registry/{apis => apps}/alerting/notifications/templategroup/legacy_storage.go (100%) create mode 100644 pkg/registry/apps/alerting/notifications/templategroup/storage.go rename pkg/registry/{apis => apps}/alerting/notifications/templategroup/type.go (55%) rename pkg/registry/{apis => apps}/alerting/notifications/timeinterval/authorize.go (100%) rename pkg/registry/{apis => apps}/alerting/notifications/timeinterval/conversions.go (100%) rename pkg/registry/{apis => apps}/alerting/notifications/timeinterval/legacy_storage.go (100%) create mode 100644 pkg/registry/apps/alerting/notifications/timeinterval/storage.go rename pkg/registry/{apis => apps}/alerting/notifications/timeinterval/type.go (55%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a24c909abc9..699670c1071 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -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 diff --git a/apps/alerting/notifications/Makefile b/apps/alerting/notifications/Makefile index df1d9cd7797..8f884ec418c 100644 --- a/apps/alerting/notifications/Makefile +++ b/apps/alerting/notifications/Makefile @@ -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 + diff --git a/apps/alerting/notifications/go.mod b/apps/alerting/notifications/go.mod index 98ff5fa11d9..6b2585db762 100644 --- a/apps/alerting/notifications/go.mod +++ b/apps/alerting/notifications/go.mod @@ -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 diff --git a/apps/alerting/notifications/go.sum b/apps/alerting/notifications/go.sum index 6a20491f6c7..f16c559e0fb 100644 --- a/apps/alerting/notifications/go.sum +++ b/apps/alerting/notifications/go.sum @@ -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= diff --git a/apps/alerting/common/constants.go b/apps/alerting/notifications/pkg/apis/alerting/v0alpha1/ext.go similarity index 89% rename from apps/alerting/common/constants.go rename to apps/alerting/notifications/pkg/apis/alerting/v0alpha1/ext.go index 2cc7c413276..772e823528d 100644 --- a/apps/alerting/common/constants.go +++ b/apps/alerting/notifications/pkg/apis/alerting/v0alpha1/ext.go @@ -1,4 +1,4 @@ -package common +package v0alpha1 const InternalPrefix = "grafana.com/" const ProvenanceStatusAnnotationKey = InternalPrefix + "provenance" diff --git a/apps/alerting/notifications/pkg/apis/alerting_manifest.go b/apps/alerting/notifications/pkg/apis/alerting_manifest.go index 9a97a47f78a..9e40415b859 100644 --- a/apps/alerting/notifications/pkg/apis/alerting_manifest.go +++ b/apps/alerting/notifications/pkg/apis/alerting_manifest.go @@ -11,6 +11,8 @@ import ( "github.com/grafana/grafana-app-sdk/app" ) +var () + var appManifestData = app.ManifestData{ AppName: "alerting", Group: "notifications.alerting.grafana.app", diff --git a/apps/alerting/notifications/pkg/apis/receiver/v0alpha1/ext.go b/apps/alerting/notifications/pkg/apis/receiver/v0alpha1/ext.go index da17a9f55df..958fc3df310 100644 --- a/apps/alerting/notifications/pkg/apis/receiver/v0alpha1/ext.go +++ b/apps/alerting/notifications/pkg/apis/receiver/v0alpha1/ext.go @@ -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 { diff --git a/apps/alerting/notifications/pkg/apis/receiver/v0alpha1/receiver_schema_gen.go b/apps/alerting/notifications/pkg/apis/receiver/v0alpha1/receiver_schema_gen.go index d159d0d9cb9..48b5d72fbd9 100644 --- a/apps/alerting/notifications/pkg/apis/receiver/v0alpha1/receiver_schema_gen.go +++ b/apps/alerting/notifications/pkg/apis/receiver/v0alpha1/receiver_schema_gen.go @@ -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) diff --git a/apps/alerting/notifications/pkg/apis/routingtree/v0alpha1/ext.go b/apps/alerting/notifications/pkg/apis/routingtree/v0alpha1/ext.go index b913c8c5d56..174fc076bbf 100644 --- a/apps/alerting/notifications/pkg/apis/routingtree/v0alpha1/ext.go +++ b/apps/alerting/notifications/pkg/apis/routingtree/v0alpha1/ext.go @@ -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 } diff --git a/apps/alerting/notifications/pkg/apis/templategroup/v0alpha1/ext.go b/apps/alerting/notifications/pkg/apis/templategroup/v0alpha1/ext.go index a9934d3a110..0d0b937cc2b 100644 --- a/apps/alerting/notifications/pkg/apis/templategroup/v0alpha1/ext.go +++ b/apps/alerting/notifications/pkg/apis/templategroup/v0alpha1/ext.go @@ -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 { diff --git a/apps/alerting/notifications/pkg/apis/templategroup/v0alpha1/templategroup_schema_gen.go b/apps/alerting/notifications/pkg/apis/templategroup/v0alpha1/templategroup_schema_gen.go index 073e8eb9058..256fbab3116 100644 --- a/apps/alerting/notifications/pkg/apis/templategroup/v0alpha1/templategroup_schema_gen.go +++ b/apps/alerting/notifications/pkg/apis/templategroup/v0alpha1/templategroup_schema_gen.go @@ -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) diff --git a/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1/ext.go b/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1/ext.go index 481818c7471..5a4bd438107 100644 --- a/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1/ext.go +++ b/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1/ext.go @@ -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 { diff --git a/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1/fakes/gen.go b/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1/fakes/gen.go index 86b2fa427fe..602283d5c3b 100644 --- a/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1/fakes/gen.go +++ b/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1/fakes/gen.go @@ -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 { diff --git a/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1/timeinterval_schema_gen.go b/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1/timeinterval_schema_gen.go index af8ff6454a5..627e02a9572 100644 --- a/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1/timeinterval_schema_gen.go +++ b/apps/alerting/notifications/pkg/apis/timeinterval/v0alpha1/timeinterval_schema_gen.go @@ -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) diff --git a/apps/alerting/notifications/pkg/apis/type.go b/apps/alerting/notifications/pkg/apis/type.go index 464697370d9..a6ef85658d5 100644 --- a/apps/alerting/notifications/pkg/apis/type.go +++ b/apps/alerting/notifications/pkg/apis/type.go @@ -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 +} diff --git a/apps/alerting/notifications/pkg/app/app.go b/apps/alerting/notifications/pkg/app/app.go new file mode 100644 index 00000000000..b57ed0cd143 --- /dev/null +++ b/apps/alerting/notifications/pkg/app/app.go @@ -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 +} diff --git a/pkg/registry/apis/alerting/notifications/receiver/storage.go b/pkg/registry/apis/alerting/notifications/receiver/storage.go deleted file mode 100644 index 1d691fe30e3..00000000000 --- a/pkg/registry/apis/alerting/notifications/receiver/storage.go +++ /dev/null @@ -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 -} diff --git a/pkg/registry/apis/alerting/notifications/register.go b/pkg/registry/apis/alerting/notifications/register.go deleted file mode 100644 index 329bfb67202..00000000000 --- a/pkg/registry/apis/alerting/notifications/register.go +++ /dev/null @@ -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 - }) -} diff --git a/pkg/registry/apis/alerting/notifications/templategroup/storage.go b/pkg/registry/apis/alerting/notifications/templategroup/storage.go deleted file mode 100644 index d1f0a4c11ec..00000000000 --- a/pkg/registry/apis/alerting/notifications/templategroup/storage.go +++ /dev/null @@ -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 -} diff --git a/pkg/registry/apis/alerting/notifications/timeinterval/storage.go b/pkg/registry/apis/alerting/notifications/timeinterval/storage.go deleted file mode 100644 index cba2e236575..00000000000 --- a/pkg/registry/apis/alerting/notifications/timeinterval/storage.go +++ /dev/null @@ -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 -} diff --git a/pkg/registry/apis/apis.go b/pkg/registry/apis/apis.go index 0ba63af8484..9a255d4c1b8 100644 --- a/pkg/registry/apis/apis.go +++ b/pkg/registry/apis/apis.go @@ -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, diff --git a/pkg/registry/apis/wireset.go b/pkg/registry/apis/wireset.go index 3ff07823e1a..78dfc45c1b8 100644 --- a/pkg/registry/apis/wireset.go +++ b/pkg/registry/apis/wireset.go @@ -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, ) diff --git a/pkg/registry/apis/alerting/notifications/receiver/authorize.go b/pkg/registry/apps/alerting/notifications/receiver/authorize.go similarity index 100% rename from pkg/registry/apis/alerting/notifications/receiver/authorize.go rename to pkg/registry/apps/alerting/notifications/receiver/authorize.go diff --git a/pkg/registry/apis/alerting/notifications/receiver/conversions.go b/pkg/registry/apps/alerting/notifications/receiver/conversions.go similarity index 100% rename from pkg/registry/apis/alerting/notifications/receiver/conversions.go rename to pkg/registry/apps/alerting/notifications/receiver/conversions.go diff --git a/pkg/registry/apis/alerting/notifications/receiver/legacy_storage.go b/pkg/registry/apps/alerting/notifications/receiver/legacy_storage.go similarity index 100% rename from pkg/registry/apis/alerting/notifications/receiver/legacy_storage.go rename to pkg/registry/apps/alerting/notifications/receiver/legacy_storage.go diff --git a/pkg/registry/apps/alerting/notifications/receiver/storage.go b/pkg/registry/apps/alerting/notifications/receiver/storage.go new file mode 100644 index 00000000000..0c779eca0c8 --- /dev/null +++ b/pkg/registry/apps/alerting/notifications/receiver/storage.go @@ -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, + } +} diff --git a/pkg/registry/apis/alerting/notifications/receiver/type.go b/pkg/registry/apps/alerting/notifications/receiver/type.go similarity index 60% rename from pkg/registry/apis/alerting/notifications/receiver/type.go rename to pkg/registry/apps/alerting/notifications/receiver/type.go index a8b7fc91c50..d42a4cff451 100644 --- a/pkg/registry/apis/alerting/notifications/receiver/type.go +++ b/pkg/registry/apps/alerting/notifications/receiver/type.go @@ -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 -} diff --git a/pkg/registry/apps/alerting/notifications/register.go b/pkg/registry/apps/alerting/notifications/register.go new file mode 100644 index 00000000000..6f62d7a56ea --- /dev/null +++ b/pkg/registry/apps/alerting/notifications/register.go @@ -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()) + } +} diff --git a/pkg/registry/apis/alerting/notifications/routingtree/authorize.go b/pkg/registry/apps/alerting/notifications/routingtree/authorize.go similarity index 100% rename from pkg/registry/apis/alerting/notifications/routingtree/authorize.go rename to pkg/registry/apps/alerting/notifications/routingtree/authorize.go diff --git a/pkg/registry/apis/alerting/notifications/routingtree/conversions.go b/pkg/registry/apps/alerting/notifications/routingtree/conversions.go similarity index 100% rename from pkg/registry/apis/alerting/notifications/routingtree/conversions.go rename to pkg/registry/apps/alerting/notifications/routingtree/conversions.go diff --git a/pkg/registry/apis/alerting/notifications/routingtree/legacy_storage.go b/pkg/registry/apps/alerting/notifications/routingtree/legacy_storage.go similarity index 100% rename from pkg/registry/apis/alerting/notifications/routingtree/legacy_storage.go rename to pkg/registry/apps/alerting/notifications/routingtree/legacy_storage.go diff --git a/pkg/registry/apis/alerting/notifications/routingtree/storage.go b/pkg/registry/apps/alerting/notifications/routingtree/storage.go similarity index 64% rename from pkg/registry/apis/alerting/notifications/routingtree/storage.go rename to pkg/registry/apps/alerting/notifications/routingtree/storage.go index ecce2112284..a8dac996fd5 100644 --- a/pkg/registry/apis/alerting/notifications/routingtree/storage.go +++ b/pkg/registry/apps/alerting/notifications/routingtree/storage.go @@ -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 } diff --git a/pkg/registry/apis/alerting/notifications/routingtree/type.go b/pkg/registry/apps/alerting/notifications/routingtree/type.go similarity index 61% rename from pkg/registry/apis/alerting/notifications/routingtree/type.go rename to pkg/registry/apps/alerting/notifications/routingtree/type.go index 7f53c7d0332..dde41603e7f 100644 --- a/pkg/registry/apis/alerting/notifications/routingtree/type.go +++ b/pkg/registry/apps/alerting/notifications/routingtree/type.go @@ -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 -} diff --git a/pkg/registry/apis/alerting/notifications/templategroup/authorize.go b/pkg/registry/apps/alerting/notifications/templategroup/authorize.go similarity index 100% rename from pkg/registry/apis/alerting/notifications/templategroup/authorize.go rename to pkg/registry/apps/alerting/notifications/templategroup/authorize.go diff --git a/pkg/registry/apis/alerting/notifications/templategroup/conversions.go b/pkg/registry/apps/alerting/notifications/templategroup/conversions.go similarity index 100% rename from pkg/registry/apis/alerting/notifications/templategroup/conversions.go rename to pkg/registry/apps/alerting/notifications/templategroup/conversions.go diff --git a/pkg/registry/apis/alerting/notifications/templategroup/legacy_storage.go b/pkg/registry/apps/alerting/notifications/templategroup/legacy_storage.go similarity index 100% rename from pkg/registry/apis/alerting/notifications/templategroup/legacy_storage.go rename to pkg/registry/apps/alerting/notifications/templategroup/legacy_storage.go diff --git a/pkg/registry/apps/alerting/notifications/templategroup/storage.go b/pkg/registry/apps/alerting/notifications/templategroup/storage.go new file mode 100644 index 00000000000..dce13ff00dd --- /dev/null +++ b/pkg/registry/apps/alerting/notifications/templategroup/storage.go @@ -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(), + } +} diff --git a/pkg/registry/apis/alerting/notifications/templategroup/type.go b/pkg/registry/apps/alerting/notifications/templategroup/type.go similarity index 55% rename from pkg/registry/apis/alerting/notifications/templategroup/type.go rename to pkg/registry/apps/alerting/notifications/templategroup/type.go index 9c6e1739901..215c8be2538 100644 --- a/pkg/registry/apis/alerting/notifications/templategroup/type.go +++ b/pkg/registry/apps/alerting/notifications/templategroup/type.go @@ -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 -} diff --git a/pkg/registry/apis/alerting/notifications/timeinterval/authorize.go b/pkg/registry/apps/alerting/notifications/timeinterval/authorize.go similarity index 100% rename from pkg/registry/apis/alerting/notifications/timeinterval/authorize.go rename to pkg/registry/apps/alerting/notifications/timeinterval/authorize.go diff --git a/pkg/registry/apis/alerting/notifications/timeinterval/conversions.go b/pkg/registry/apps/alerting/notifications/timeinterval/conversions.go similarity index 100% rename from pkg/registry/apis/alerting/notifications/timeinterval/conversions.go rename to pkg/registry/apps/alerting/notifications/timeinterval/conversions.go diff --git a/pkg/registry/apis/alerting/notifications/timeinterval/legacy_storage.go b/pkg/registry/apps/alerting/notifications/timeinterval/legacy_storage.go similarity index 100% rename from pkg/registry/apis/alerting/notifications/timeinterval/legacy_storage.go rename to pkg/registry/apps/alerting/notifications/timeinterval/legacy_storage.go diff --git a/pkg/registry/apps/alerting/notifications/timeinterval/storage.go b/pkg/registry/apps/alerting/notifications/timeinterval/storage.go new file mode 100644 index 00000000000..91bd9c49a60 --- /dev/null +++ b/pkg/registry/apps/alerting/notifications/timeinterval/storage.go @@ -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(), + } +} diff --git a/pkg/registry/apis/alerting/notifications/timeinterval/type.go b/pkg/registry/apps/alerting/notifications/timeinterval/type.go similarity index 55% rename from pkg/registry/apis/alerting/notifications/timeinterval/type.go rename to pkg/registry/apps/alerting/notifications/timeinterval/type.go index 8f15204da28..2588c1459c7 100644 --- a/pkg/registry/apis/alerting/notifications/timeinterval/type.go +++ b/pkg/registry/apps/alerting/notifications/timeinterval/type.go @@ -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 -} diff --git a/pkg/registry/apps/apps.go b/pkg/registry/apps/apps.go index 9de8798d97e..40f7dfc64de 100644 --- a/pkg/registry/apps/apps.go +++ b/pkg/registry/apps/apps.go @@ -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 { diff --git a/pkg/registry/apps/wireset.go b/pkg/registry/apps/wireset.go index b18c0b57fb0..84b9d9b745f 100644 --- a/pkg/registry/apps/wireset.go +++ b/pkg/registry/apps/wireset.go @@ -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)), ) diff --git a/pkg/services/apiserver/builder/runner/builder.go b/pkg/services/apiserver/builder/runner/builder.go index 8a7b18a5fe2..ae9b1790bf4 100644 --- a/pkg/services/apiserver/builder/runner/builder.go +++ b/pkg/services/apiserver/builder/runner/builder.go @@ -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) diff --git a/pkg/tests/apis/alerting/notifications/receivers/receiver_test.go b/pkg/tests/apis/alerting/notifications/receivers/receiver_test.go index b4a38f582c1..6305bd82595 100644 --- a/pkg/tests/apis/alerting/notifications/receivers/receiver_test.go +++ b/pkg/tests/apis/alerting/notifications/receivers/receiver_test.go @@ -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" diff --git a/pkg/tests/apis/alerting/notifications/routingtree/routing_tree_test.go b/pkg/tests/apis/alerting/notifications/routingtree/routing_tree_test.go index e4861b2ce4d..3ba58007eaa 100644 --- a/pkg/tests/apis/alerting/notifications/routingtree/routing_tree_test.go +++ b/pkg/tests/apis/alerting/notifications/routingtree/routing_tree_test.go @@ -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" diff --git a/pkg/tests/apis/alerting/notifications/timeinterval/timeinterval_test.go b/pkg/tests/apis/alerting/notifications/timeinterval/timeinterval_test.go index bc5a48fed01..1a4ecf0ee5e 100644 --- a/pkg/tests/apis/alerting/notifications/timeinterval/timeinterval_test.go +++ b/pkg/tests/apis/alerting/notifications/timeinterval/timeinterval_test.go @@ -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" diff --git a/pkg/tests/apis/openapi_snapshots/notifications.alerting.grafana.app-v0alpha1.json b/pkg/tests/apis/openapi_snapshots/notifications.alerting.grafana.app-v0alpha1.json index 35c74ed9514..34d1bf08cda 100644 --- a/pkg/tests/apis/openapi_snapshots/notifications.alerting.grafana.app-v0alpha1.json +++ b/pkg/tests/apis/openapi_snapshots/notifications.alerting.grafana.app-v0alpha1.json @@ -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",