Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 852c7ea24a | |||
| bdf529c545 | |||
| 77e13f7ef8 |
@@ -48,7 +48,7 @@ jobs:
|
||||
analyze:
|
||||
needs: detect-changes
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-x64-large-io
|
||||
continue-on-error: true # doesn't block PRs from being merged if this fails
|
||||
if: github.repository == 'grafana/grafana'
|
||||
|
||||
|
||||
+2
-1
@@ -98,6 +98,7 @@ require (
|
||||
github.com/dolthub/vitess v0.0.0-20250930230441-70c2c6a98e33 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
|
||||
github.com/evanphx/json-patch v5.9.11+incompatible // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||
@@ -131,6 +132,7 @@ require (
|
||||
github.com/go-openapi/validate v0.25.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.9.3 // indirect
|
||||
github.com/go-stack/stack v1.8.1 // indirect
|
||||
github.com/go-test/deep v1.1.1 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
@@ -153,7 +155,6 @@ require (
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 // indirect
|
||||
github.com/grafana/grafana-aws-sdk v1.3.0 // indirect
|
||||
github.com/grafana/grafana-azure-sdk-go/v2 v2.3.1 // indirect
|
||||
github.com/grafana/grafana/apps/plugins v0.0.0 // indirect
|
||||
github.com/grafana/grafana/apps/provisioning v0.0.0 // indirect
|
||||
github.com/grafana/grafana/pkg/apiserver v0.0.0 // indirect
|
||||
github.com/grafana/otel-profiling-go v0.5.1 // indirect
|
||||
|
||||
@@ -230,7 +230,6 @@ require (
|
||||
github.com/grafana/grafana-azure-sdk-go/v2 v2.3.1 // indirect
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.284.0 // indirect
|
||||
github.com/grafana/grafana/apps/dashboard v0.0.0 // indirect
|
||||
github.com/grafana/grafana/apps/plugins v0.0.0 // indirect
|
||||
github.com/grafana/grafana/apps/provisioning v0.0.0 // indirect
|
||||
github.com/grafana/grafana/apps/secret v0.0.0 // indirect
|
||||
github.com/grafana/grafana/pkg/aggregator v0.0.0 // indirect
|
||||
|
||||
+25
-3
@@ -9,7 +9,7 @@ replace github.com/grafana/grafana/pkg/apimachinery => ../../pkg/apimachinery
|
||||
replace github.com/grafana/grafana/pkg/apiserver => ../../pkg/apiserver
|
||||
|
||||
require (
|
||||
github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4
|
||||
github.com/emicklei/go-restful/v3 v3.13.0
|
||||
github.com/grafana/grafana v0.0.0-00010101000000-000000000000
|
||||
github.com/grafana/grafana-app-sdk v0.48.4
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3
|
||||
@@ -17,11 +17,15 @@ require (
|
||||
github.com/stretchr/testify v1.11.1
|
||||
k8s.io/apimachinery v0.34.2
|
||||
k8s.io/apiserver v0.34.2
|
||||
k8s.io/client-go v0.34.2
|
||||
k8s.io/klog/v2 v2.130.1
|
||||
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912
|
||||
)
|
||||
|
||||
require (
|
||||
cel.dev/expr v0.24.0 // indirect
|
||||
github.com/NYTimes/gziphandler v1.1.1 // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
|
||||
github.com/apache/arrow-go/v18 v18.4.1 // indirect
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.39.1 // indirect
|
||||
@@ -39,11 +43,13 @@ require (
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cheekybits/genny v1.0.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.13.0 // indirect
|
||||
github.com/evanphx/json-patch v5.9.11+incompatible // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||
github.com/getkin/kin-openapi v0.133.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
|
||||
@@ -64,12 +70,14 @@ require (
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/cel-go v0.26.1 // indirect
|
||||
github.com/google/flatbuffers v25.2.10+incompatible // indirect
|
||||
github.com/google/gnostic-models v0.7.0 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/grafana/alerting v0.0.0-20251119204204-77fa75125181 // indirect
|
||||
github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f // indirect
|
||||
github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4 // indirect
|
||||
github.com/grafana/dataplane/sdata v0.0.9 // indirect
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 // indirect
|
||||
github.com/grafana/grafana-aws-sdk v1.3.0 // indirect
|
||||
@@ -81,6 +89,7 @@ require (
|
||||
github.com/grafana/sqlds/v4 v4.2.7 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||
@@ -94,6 +103,7 @@ require (
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/hashicorp/memberlist v0.5.2 // indirect
|
||||
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jaegertracing/jaeger-idl v0.5.0 // indirect
|
||||
github.com/jmespath-community/go-jmespath v1.1.1 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
@@ -102,6 +112,7 @@ require (
|
||||
github.com/jszwedko/go-datemath v0.1.1-0.20230526204004-640a500621d6 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/mattetti/filebuffer v1.0.1 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
@@ -140,15 +151,21 @@ require (
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
|
||||
github.com/spf13/cobra v1.10.1 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/stoewer/go-strcase v1.3.1 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/tjhop/slog-gokit v0.1.5 // indirect
|
||||
github.com/woodsbury/decimal128 v1.3.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/zeebo/xxh3 v1.0.2 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.6.4 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.4 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.6.4 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.63.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.38.0 // indirect
|
||||
go.opentelemetry.io/contrib/samplers/jaegerremote v0.32.0 // indirect
|
||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||
@@ -159,6 +176,8 @@ require (
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.1 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.45.0 // indirect
|
||||
@@ -179,15 +198,18 @@ require (
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
|
||||
google.golang.org/grpc v1.77.0 // indirect
|
||||
google.golang.org/protobuf v1.36.10 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/api v0.34.2 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.34.2 // indirect
|
||||
k8s.io/client-go v0.34.2 // indirect
|
||||
k8s.io/component-base v0.34.2 // indirect
|
||||
k8s.io/kms v0.34.2 // indirect
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.1 // indirect
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
|
||||
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
||||
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
@@ -9,6 +14,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
|
||||
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
|
||||
github.com/apache/arrow-go/v18 v18.4.1 h1:q/jVkBWCJOB9reDgaIZIdruLQUb1kbkvOnOFezVH1C4=
|
||||
github.com/apache/arrow-go/v18 v18.4.1/go.mod h1:tLyFubsAl17bvFdUAy24bsSvA/6ww95Iqi67fTpGu3E=
|
||||
github.com/apache/thrift v0.22.0 h1:r7mTJdj51TMDe6RtcmNdQxgn9XcyfGDOzegMDRg47uc=
|
||||
@@ -52,12 +59,18 @@ github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitf
|
||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
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=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=
|
||||
github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8=
|
||||
@@ -67,6 +80,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
|
||||
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/getkin/kin-openapi v0.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ=
|
||||
@@ -89,6 +104,8 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
|
||||
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
|
||||
github.com/go-openapi/jsonpointer v0.22.1 h1:sHYI1He3b9NqJ4wXLoJDKmUmHkWy/L7rtEo92JUxBNk=
|
||||
github.com/go-openapi/jsonpointer v0.22.1/go.mod h1:pQT9OsLkfz1yWoMgYFy4x3U5GY5nUlsOn1qSBH5MkCM=
|
||||
github.com/go-openapi/jsonreference v0.21.2 h1:Wxjda4M/BBQllegefXrY/9aq1fxBA8sI5M/lFU6tSWU=
|
||||
@@ -118,6 +135,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||
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.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -134,6 +153,8 @@ github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
|
||||
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
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/cel-go v0.26.1 h1:iPbVVEdkhTX++hpe3lzSk7D3G3QSYqLGoHOcEio+UXQ=
|
||||
github.com/google/cel-go v0.26.1/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM=
|
||||
github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q=
|
||||
github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
|
||||
@@ -151,6 +172,8 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||
github.com/grafana/alerting v0.0.0-20251119204204-77fa75125181 h1:nbxKRtrbuhvOYmI2RhOYauHRJCtpR+vTNIgg1lFUCws=
|
||||
github.com/grafana/alerting v0.0.0-20251119204204-77fa75125181/go.mod h1:VtPNIFlEOJPPEc13Ax6ZTbNV3M/sAzLID72YjgzOPVA=
|
||||
github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f h1:Cbm6OKkOcJ+7CSZsGsEJzktC/SIa5bxVeYKQLuYK86o=
|
||||
@@ -181,6 +204,8 @@ github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 h1:uGoIog/wiQHI9GAxXO5TJbT0wWKH3O9HhOJW1F9c3fY=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@@ -215,12 +240,16 @@ github.com/hashicorp/memberlist v0.5.2 h1:rJoNPWZ0juJBgqn48gjy59K5H4rNgvUoM1kUD7
|
||||
github.com/hashicorp/memberlist v0.5.2/go.mod h1:Ri9p/tRShbjYnpNf4FFPXG7wxEGY4Nrcn6E7jrVa//4=
|
||||
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
|
||||
github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jaegertracing/jaeger-idl v0.5.0 h1:zFXR5NL3Utu7MhPg8ZorxtCBjHrL3ReM1VoB65FOFGE=
|
||||
github.com/jaegertracing/jaeger-idl v0.5.0/go.mod h1:ON90zFo9eoyXrt9F/KN8YeF3zxcnujaisMweFY/rg5k=
|
||||
github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94=
|
||||
github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8=
|
||||
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.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
|
||||
github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
||||
@@ -342,6 +371,7 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
|
||||
github.com/prometheus/alertmanager v0.28.0 h1:sLN+6HhZet8hrbmGHLAHWsTXgZSVCvq9Ix3U3wvivqc=
|
||||
github.com/prometheus/alertmanager v0.28.0/go.mod h1:/okSnb2LlodbMlRoOWQEKtqI/coOo2NKZDm2Hu9QHLQ=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
@@ -353,6 +383,7 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
@@ -362,6 +393,7 @@ github.com/prometheus/common v0.67.3/go.mod h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwk
|
||||
github.com/prometheus/exporter-toolkit v0.14.0 h1:NMlswfibpcZZ+H0sZBiTjrA3/aBFHkNZqE+iCj5EmRg=
|
||||
github.com/prometheus/exporter-toolkit v0.14.0/go.mod h1:Gu5LnVvt7Nr/oqTBUC23WILZepW0nffNo10XdhQcwWA=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
@@ -375,13 +407,23 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
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/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
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=
|
||||
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
|
||||
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
|
||||
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
|
||||
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs=
|
||||
github.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
|
||||
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/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
@@ -394,11 +436,14 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/tjhop/slog-gokit v0.1.5 h1:ayloIUi5EK2QYB8eY4DOPO95/mRtMW42lUkp3quJohc=
|
||||
github.com/tjhop/slog-gokit v0.1.5/go.mod h1:yA48zAHvV+Sg4z4VRyeFyFUNNXd3JY5Zg84u3USICq0=
|
||||
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/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
@@ -406,12 +451,28 @@ github.com/woodsbury/decimal128 v1.3.0 h1:8pffMNWIlC0O5vbyHWFZAt5yWvWcrHA+3ovIIj
|
||||
github.com/woodsbury/decimal128 v1.3.0/go.mod h1:C5UTmyTjW3JftjUFzOVhC20BEQa2a4ZKOB5I6Zjb+ds=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chqDkyE9Z4N61UnQd+KOfgp5Iu53llk=
|
||||
github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
|
||||
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
|
||||
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
|
||||
go.etcd.io/bbolt v1.4.2 h1:IrUHp260R8c+zYx/Tm8QZr04CX+qWS5PGfPdevhdm1I=
|
||||
go.etcd.io/bbolt v1.4.2/go.mod h1:Is8rSHO/b4f3XigBC0lL0+4FwAQv3HXEEIgFMuKHceM=
|
||||
go.etcd.io/etcd/api/v3 v3.6.4 h1:7F6N7toCKcV72QmoUKa23yYLiiljMrT4xCeBL9BmXdo=
|
||||
go.etcd.io/etcd/api/v3 v3.6.4/go.mod h1:eFhhvfR8Px1P6SEuLT600v+vrhdDTdcfMzmnxVXXSbk=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.4 h1:9HBYrjppeOfFjBjaMTRxT3R7xT0GLK8EJMVC4xg6ok0=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.4/go.mod h1:sbdzr2cl3HzVmxNw//PH7aLGVtY4QySjQFuaCgcRFAI=
|
||||
go.etcd.io/etcd/client/v3 v3.6.4 h1:YOMrCfMhRzY8NgtzUsHl8hC2EBSnuqbR3dh84Uryl7A=
|
||||
go.etcd.io/etcd/client/v3 v3.6.4/go.mod h1:jaNNHCyg2FdALyKWnd7hxZXZxZANb0+KGY+YQaEMISo=
|
||||
go.etcd.io/etcd/pkg/v3 v3.6.4 h1:fy8bmXIec1Q35/jRZ0KOes8vuFxbvdN0aAFqmEfJZWA=
|
||||
go.etcd.io/etcd/pkg/v3 v3.6.4/go.mod h1:kKcYWP8gHuBRcteyv6MXWSN0+bVMnfgqiHueIZnKMtE=
|
||||
go.etcd.io/etcd/server/v3 v3.6.4 h1:LsCA7CzjVt+8WGrdsnh6RhC0XqCsLkBly3ve5rTxMAU=
|
||||
go.etcd.io/etcd/server/v3 v3.6.4/go.mod h1:aYCL/h43yiONOv0QIR82kH/2xZ7m+IWYjzRmyQfnCAg=
|
||||
go.etcd.io/raft/v3 v3.6.0 h1:5NtvbDVYpnfZWcIHgGRk9DyzkBIXOi8j+DDp1IcnUWQ=
|
||||
go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo=
|
||||
@@ -448,6 +509,10 @@ go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjce
|
||||
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
|
||||
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.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
@@ -460,13 +525,17 @@ golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
|
||||
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
|
||||
golang.org/x/exp v0.0.0-20251002181428-27f1f14c8bb9 h1:TQwNpfvNkxAVlItJf6Cr5JTsVZoC/Sj7K3OZv2Pc14A=
|
||||
golang.org/x/exp v0.0.0-20251002181428-27f1f14c8bb9/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
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/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
|
||||
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
|
||||
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-20181114220301-adae6a3d119a/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-20190108225652-1e06a53dbb7e/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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@@ -475,9 +544,11 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -486,6 +557,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -519,6 +591,7 @@ golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
||||
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||
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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
@@ -535,11 +608,14 @@ gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
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/googleapis/api v0.0.0-20251022142026-3a174f9686a8 h1:mepRgnBZa07I4TRuomDE4sTIYieg/osKmzIf4USdWS4=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
|
||||
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM=
|
||||
google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
@@ -562,6 +638,8 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
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.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@@ -572,6 +650,7 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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=
|
||||
k8s.io/api v0.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY=
|
||||
k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw=
|
||||
k8s.io/apiextensions-apiserver v0.34.2 h1:WStKftnGeoKP4AZRz/BaAAEJvYp4mlZGN0UCv+uvsqo=
|
||||
@@ -586,10 +665,14 @@ k8s.io/component-base v0.34.2 h1:HQRqK9x2sSAsd8+R4xxRirlTjowsg6fWCPwWYeSvogQ=
|
||||
k8s.io/component-base v0.34.2/go.mod h1:9xw2FHJavUHBFpiGkZoKuYZ5pdtLKe97DEByaA+hHbM=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kms v0.34.2 h1:91rj4MDZLyIT9KxG8J5/CcMH666Z88CF/xJQeuPfJc8=
|
||||
k8s.io/kms v0.34.2/go.mod h1:s1CFkLG7w9eaTYvctOxosx88fl4spqmixnNpys0JAtM=
|
||||
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
|
||||
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||
|
||||
@@ -5,17 +5,22 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/app"
|
||||
"github.com/grafana/grafana-app-sdk/k8s"
|
||||
appsdkapiserver "github.com/grafana/grafana-app-sdk/k8s/apiserver"
|
||||
"github.com/grafana/grafana-app-sdk/operator"
|
||||
"github.com/grafana/grafana-app-sdk/simple"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
pluginsappapis "github.com/grafana/grafana/apps/plugins/pkg/apis"
|
||||
pluginsv0alpha1 "github.com/grafana/grafana/apps/plugins/pkg/apis/plugins/v0alpha1"
|
||||
"github.com/grafana/grafana/apps/plugins/pkg/app/meta"
|
||||
)
|
||||
|
||||
func New(cfg app.Config) (app.App, error) {
|
||||
cfg.KubeConfig.APIPath = "apis"
|
||||
|
||||
specificConfig, ok := cfg.SpecificConfig.(*PluginAppConfig)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid config type")
|
||||
@@ -60,3 +65,77 @@ func New(cfg app.Config) (app.App, error) {
|
||||
type PluginAppConfig struct {
|
||||
MetaProviderManager *meta.ProviderManager
|
||||
}
|
||||
|
||||
func ProvideAppInstaller(
|
||||
metaProviderManager *meta.ProviderManager,
|
||||
) (appsdkapiserver.AppInstaller, error) {
|
||||
specificConfig := &PluginAppConfig{
|
||||
MetaProviderManager: metaProviderManager,
|
||||
}
|
||||
provider := simple.NewAppProvider(pluginsappapis.LocalManifest(), specificConfig, New)
|
||||
appConfig := app.Config{
|
||||
KubeConfig: restclient.Config{}, // this will be overridden by the installer's InitializeApp method
|
||||
ManifestData: *pluginsappapis.LocalManifest().ManifestData,
|
||||
SpecificConfig: specificConfig,
|
||||
}
|
||||
defaultInstaller, err := appsdkapiserver.NewDefaultAppInstaller(provider, appConfig, pluginsappapis.NewGoTypeAssociator())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
appInstaller := &pluginAppInstaller{
|
||||
AppInstaller: defaultInstaller,
|
||||
metaManager: metaProviderManager,
|
||||
ready: make(chan struct{}),
|
||||
}
|
||||
return appInstaller, nil
|
||||
}
|
||||
|
||||
type pluginAppInstaller struct {
|
||||
appsdkapiserver.AppInstaller
|
||||
metaManager *meta.ProviderManager
|
||||
|
||||
// restConfig is set during InitializeApp and used by the client factory
|
||||
restConfig *restclient.Config
|
||||
ready chan struct{}
|
||||
}
|
||||
|
||||
func (p *pluginAppInstaller) InitializeApp(restConfig restclient.Config) error {
|
||||
if p.restConfig == nil {
|
||||
p.restConfig = &restConfig
|
||||
close(p.ready)
|
||||
}
|
||||
return p.AppInstaller.InitializeApp(restConfig)
|
||||
}
|
||||
|
||||
func (p *pluginAppInstaller) InstallAPIs(
|
||||
server appsdkapiserver.GenericAPIServer,
|
||||
restOptsGetter generic.RESTOptionsGetter,
|
||||
) error {
|
||||
// Create a client factory function that will be called lazily when the client is needed.
|
||||
// This uses the rest config from the app, which is set during InitializeApp.
|
||||
clientFactory := func(ctx context.Context) (*pluginsv0alpha1.PluginClient, error) {
|
||||
<-p.ready
|
||||
if p.restConfig == nil {
|
||||
return nil, fmt.Errorf("rest config not yet initialized, app must be initialized before client can be created")
|
||||
}
|
||||
|
||||
clientGenerator := k8s.NewClientRegistry(*p.restConfig, k8s.DefaultClientConfig())
|
||||
client, err := pluginsv0alpha1.NewPluginClientFromGenerator(clientGenerator)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create plugin client: %w", err)
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
pluginMetaGVR := pluginsv0alpha1.PluginMetaKind().GroupVersionResource()
|
||||
replacedStorage := map[schema.GroupVersionResource]rest.Storage{
|
||||
pluginMetaGVR: NewPluginMetaStorage(p.metaManager, clientFactory),
|
||||
}
|
||||
wrappedServer := &customStorageWrapper{
|
||||
wrapped: server,
|
||||
replace: replacedStorage,
|
||||
}
|
||||
return p.AppInstaller.InstallAPIs(wrappedServer, restOptsGetter)
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
|
||||
claims "github.com/grafana/authlib/types"
|
||||
|
||||
pluginsv0alpha1 "github.com/grafana/grafana/apps/plugins/pkg/apis/plugins/v0alpha1"
|
||||
"github.com/grafana/grafana/apps/plugins/pkg/app/meta"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
||||
@@ -40,14 +38,12 @@ type PluginMetaStorage struct {
|
||||
clientOnce sync.Once
|
||||
|
||||
gr schema.GroupResource
|
||||
namespacer claims.NamespaceFormatter
|
||||
tableConverter rest.TableConvertor
|
||||
}
|
||||
|
||||
func NewPluginMetaStorage(
|
||||
metaManager *meta.ProviderManager,
|
||||
clientFactory func(context.Context) (*pluginsv0alpha1.PluginClient, error),
|
||||
namespacer claims.NamespaceFormatter,
|
||||
) *PluginMetaStorage {
|
||||
gr := schema.GroupResource{
|
||||
Group: pluginsv0alpha1.APIGroup,
|
||||
@@ -58,7 +54,6 @@ func NewPluginMetaStorage(
|
||||
metaManager: metaManager,
|
||||
clientFactory: clientFactory,
|
||||
gr: gr,
|
||||
namespacer: namespacer,
|
||||
tableConverter: rest.NewDefaultTableConvertor(gr),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package plugins
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -48,6 +48,7 @@ The decrypters field is an allowlist that lets the secure value know which servi
|
||||
Currently available decrypters:
|
||||
|
||||
- `synthetic-monitoring` (for Synthetic Monitoring checks)
|
||||
- `k6-cloud` (for k6 performance tests)
|
||||
- `provisioning.grafana.app` (for GitSync/Provisioning)
|
||||
|
||||
## Create a secure value
|
||||
|
||||
@@ -40,7 +40,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/org/orgtest"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/installsync/installsyncfakes"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/managedplugins"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginassets"
|
||||
@@ -528,7 +527,7 @@ func callGetPluginAsset(sc *scenarioContext) {
|
||||
func pluginAssetScenario(t *testing.T, desc string, url string, urlPattern string,
|
||||
cfg *setting.Cfg, pluginRegistry registry.Service, fn scenarioFunc) {
|
||||
t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) {
|
||||
store, err := pluginstore.NewPluginStoreForTest(pluginRegistry, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{}, installsyncfakes.NewFakeSyncer())
|
||||
store, err := pluginstore.NewPluginStoreForTest(pluginRegistry, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{})
|
||||
require.NoError(t, err)
|
||||
|
||||
hs := HTTPServer{
|
||||
@@ -643,7 +642,7 @@ func Test_PluginsList_AccessControl(t *testing.T) {
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
server := SetupAPITestServer(t, func(hs *HTTPServer) {
|
||||
store, err := pluginstore.NewPluginStoreForTest(pluginRegistry, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{}, installsyncfakes.NewFakeSyncer())
|
||||
store, err := pluginstore.NewPluginStoreForTest(pluginRegistry, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{})
|
||||
require.NoError(t, err)
|
||||
|
||||
hs.Cfg = setting.NewCfg()
|
||||
@@ -833,7 +832,7 @@ func Test_PluginsSettings(t *testing.T) {
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
server := SetupAPITestServer(t, func(hs *HTTPServer) {
|
||||
store, err := pluginstore.NewPluginStoreForTest(pluginRegistry, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{}, installsyncfakes.NewFakeSyncer())
|
||||
store, err := pluginstore.NewPluginStoreForTest(pluginRegistry, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{})
|
||||
require.NoError(t, err)
|
||||
|
||||
hs.Cfg = setting.NewCfg()
|
||||
@@ -903,7 +902,7 @@ func Test_UpdatePluginSetting(t *testing.T) {
|
||||
|
||||
t.Run("should return an error when trying to disable an auto-enabled plugin", func(t *testing.T) {
|
||||
server := SetupAPITestServer(t, func(hs *HTTPServer) {
|
||||
store, err := pluginstore.NewPluginStoreForTest(pluginRegistry, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{}, installsyncfakes.NewFakeSyncer())
|
||||
store, err := pluginstore.NewPluginStoreForTest(pluginRegistry, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{})
|
||||
require.NoError(t, err)
|
||||
|
||||
hs.Cfg = setting.NewCfg()
|
||||
|
||||
@@ -1,29 +1,15 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/k8s"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/app"
|
||||
appsdkapiserver "github.com/grafana/grafana-app-sdk/k8s/apiserver"
|
||||
"github.com/grafana/grafana-app-sdk/simple"
|
||||
|
||||
pluginsappapis "github.com/grafana/grafana/apps/plugins/pkg/apis"
|
||||
pluginsv0alpha1 "github.com/grafana/grafana/apps/plugins/pkg/apis/plugins/v0alpha1"
|
||||
pluginsapp "github.com/grafana/grafana/apps/plugins/pkg/app"
|
||||
"github.com/grafana/grafana/apps/plugins/pkg/app/meta"
|
||||
"github.com/grafana/grafana/pkg/configprovider"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/appinstaller"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -32,17 +18,10 @@ var (
|
||||
)
|
||||
|
||||
type AppInstaller struct {
|
||||
metaManager *meta.ProviderManager
|
||||
cfgProvider configprovider.ConfigProvider
|
||||
restConfigProvider apiserver.RestConfigProvider
|
||||
|
||||
appsdkapiserver.AppInstaller
|
||||
}
|
||||
|
||||
func RegisterAppInstaller(
|
||||
cfgProvider configprovider.ConfigProvider,
|
||||
restConfigProvider apiserver.RestConfigProvider,
|
||||
) (*AppInstaller, error) {
|
||||
func ProvideAppInstaller() (*AppInstaller, error) {
|
||||
grafanaComAPIURL := os.Getenv("GRAFANA_COM_API_URL")
|
||||
if grafanaComAPIURL == "" {
|
||||
grafanaComAPIURL = "https://grafana.com/api/plugins"
|
||||
@@ -51,66 +30,17 @@ func RegisterAppInstaller(
|
||||
coreProvider := meta.NewCoreProvider()
|
||||
cloudProvider := meta.NewCloudProvider(grafanaComAPIURL)
|
||||
metaProviderManager := meta.NewProviderManager(coreProvider, cloudProvider)
|
||||
specificConfig := &pluginsapp.PluginAppConfig{
|
||||
MetaProviderManager: metaProviderManager,
|
||||
}
|
||||
provider := simple.NewAppProvider(pluginsappapis.LocalManifest(), specificConfig, pluginsapp.New)
|
||||
appConfig := app.Config{
|
||||
KubeConfig: restclient.Config{}, // this will be overridden by the installer's InitializeApp method
|
||||
ManifestData: *pluginsappapis.LocalManifest().ManifestData,
|
||||
SpecificConfig: specificConfig,
|
||||
}
|
||||
i, err := appsdkapiserver.NewDefaultAppInstaller(provider, appConfig, pluginsappapis.NewGoTypeAssociator())
|
||||
|
||||
i, err := pluginsapp.ProvideAppInstaller(metaProviderManager)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &AppInstaller{
|
||||
metaManager: metaProviderManager,
|
||||
cfgProvider: cfgProvider,
|
||||
restConfigProvider: restConfigProvider,
|
||||
AppInstaller: i,
|
||||
AppInstaller: i,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *AppInstaller) InstallAPIs(
|
||||
server appsdkapiserver.GenericAPIServer,
|
||||
restOptsGetter generic.RESTOptionsGetter,
|
||||
) error {
|
||||
ctx := context.Background()
|
||||
cfg, err := p.cfgProvider.Get(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create a client factory function that will be called lazily when the client is needed.
|
||||
// This avoids deadlock issues since the restConfigProvider/API server will not be ready during API installation.
|
||||
clientFactory := func(ctx context.Context) (*pluginsv0alpha1.PluginClient, error) {
|
||||
kubeConfig, err := p.restConfigProvider.GetRestConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get rest config: %w", err)
|
||||
}
|
||||
|
||||
clientGenerator := k8s.NewClientRegistry(*kubeConfig, k8s.DefaultClientConfig())
|
||||
client, err := pluginsv0alpha1.NewPluginClientFromGenerator(clientGenerator)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create plugin client: %w", err)
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
pluginMetaGVR := pluginsv0alpha1.PluginMetaKind().GroupVersionResource()
|
||||
replacedStorage := map[schema.GroupVersionResource]rest.Storage{
|
||||
pluginMetaGVR: pluginsapp.NewPluginMetaStorage(p.metaManager, clientFactory, request.GetNamespaceMapper(cfg)),
|
||||
}
|
||||
wrappedServer := &customStorageWrapper{
|
||||
wrapped: server,
|
||||
replace: replacedStorage,
|
||||
}
|
||||
return p.AppInstaller.InstallAPIs(wrappedServer, restOptsGetter)
|
||||
}
|
||||
|
||||
// GetAuthorizer returns the authorizer for the plugins app.
|
||||
func (p *AppInstaller) GetAuthorizer() authorizer.Authorizer {
|
||||
return pluginsapp.GetAuthorizer()
|
||||
|
||||
@@ -21,7 +21,7 @@ var WireSet = wire.NewSet(
|
||||
ProvideBuilderRunners,
|
||||
playlist.RegisterAppInstaller,
|
||||
investigations.RegisterApp,
|
||||
plugins.RegisterAppInstaller,
|
||||
plugins.ProvideAppInstaller,
|
||||
shorturl.RegisterAppInstaller,
|
||||
correlations.RegisterAppInstaller,
|
||||
rules.RegisterAppInstaller,
|
||||
|
||||
@@ -4,12 +4,16 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/modules"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/installsync"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugininstaller"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/provisioning"
|
||||
)
|
||||
|
||||
const (
|
||||
// InstallSync is the module name for the install sync service.
|
||||
InstallSync = installsync.ServiceName
|
||||
|
||||
// PluginStore is the module name for the plugin store service.
|
||||
PluginStore = pluginstore.ServiceName
|
||||
|
||||
@@ -46,10 +50,11 @@ func dependencyMap() map[string][]string {
|
||||
Tracing: {},
|
||||
GrafanaAPIServer: {Tracing},
|
||||
PluginStore: {GrafanaAPIServer},
|
||||
PluginInstaller: {PluginStore},
|
||||
InstallSync: {PluginStore},
|
||||
PluginInstaller: {InstallSync},
|
||||
FixedRolesLoader: {PluginInstaller},
|
||||
Provisioning: {PluginStore, PluginInstaller, FixedRolesLoader},
|
||||
Core: {GrafanaAPIServer, PluginStore, PluginInstaller, FixedRolesLoader, Provisioning},
|
||||
Core: {GrafanaAPIServer, PluginStore, PluginInstaller, FixedRolesLoader, Provisioning, InstallSync},
|
||||
BackgroundServices: {Core},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
plugindashboardsservice "github.com/grafana/grafana/pkg/services/plugindashboards/service"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/angulardetectorsprovider"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/installsync"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/keyretriever/dynamic"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginexternal"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugininstaller"
|
||||
@@ -73,6 +74,7 @@ func ProvideBackgroundServiceRegistry(
|
||||
dashboardServiceImpl *service.DashboardServiceImpl,
|
||||
secretsGarbageCollectionWorker *secretsgarbagecollectionworker.Worker,
|
||||
fixedRolesLoader *accesscontrol.FixedRolesLoader,
|
||||
installSync installsync.Syncer,
|
||||
// Need to make sure these are initialized, is there a better place to put them?
|
||||
_ dashboardsnapshots.Service,
|
||||
_ serviceaccounts.Service,
|
||||
@@ -121,6 +123,7 @@ func ProvideBackgroundServiceRegistry(
|
||||
dashboardServiceImpl,
|
||||
secretsGarbageCollectionWorker,
|
||||
fixedRolesLoader,
|
||||
installSync,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Generated
+16
-16
@@ -579,12 +579,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api
|
||||
}
|
||||
errorRegistry := pluginerrs.ProvideErrorTracker()
|
||||
loaderLoader := loader.ProvideService(pluginManagementCfg, discovery, bootstrap, validate, initialize, terminate, errorRegistry)
|
||||
clientGenerator := apiserver.ProvideClientGenerator(eventualRestConfigProvider)
|
||||
syncer, err := installsync.ProvideSyncer(featureToggles, clientGenerator, orgService, configProvider, serverLockService)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pluginstoreService, err := pluginstore.ProvideService(inMemory, sourcesService, loaderLoader, syncer, featureToggles)
|
||||
pluginstoreService, err := pluginstore.ProvideService(inMemory, sourcesService, loaderLoader, featureToggles)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -789,7 +784,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
appInstaller, err := plugins.RegisterAppInstaller(configProvider, eventualRestConfigProvider)
|
||||
appInstaller, err := plugins.ProvideAppInstaller()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -854,6 +849,11 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api
|
||||
dashboardUpdater := service8.ProvideDashboardUpdater(inProcBus, pluginstoreService, service14, importDashboardService, service13, pluginService, dashboardService)
|
||||
worker := garbagecollectionworker.ProvideWorker(cfg, secureValueMetadataStorage, keeperMetadataStorage, ossKeeperService)
|
||||
fixedRolesLoader := accesscontrol.ProvideFixedRolesLoader(acimplService, featureToggles)
|
||||
clientGenerator := apiserver.ProvideClientGenerator(eventualRestConfigProvider)
|
||||
syncer, err := installsync.ProvideSyncer(featureToggles, clientGenerator, orgService, configProvider, serverLockService, eventualRestConfigProvider, pluginstoreService)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
healthService, err := grpcserver.ProvideHealthService(cfg, grpcserverProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -935,7 +935,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api
|
||||
}
|
||||
ossUserProtectionImpl := authinfoimpl.ProvideOSSUserProtectionService()
|
||||
registration := authnimpl.ProvideRegistration(cfg, authnService, orgService, userAuthTokenService, acimplService, permissionRegistry, apikeyService, userService, authService, ossUserProtectionImpl, loginattemptimplService, quotaService, authinfoimplService, renderingService, featureToggles, oauthtokenService, socialService, remoteCache, ldapImpl, ossImpl, tracingService, tempuserService, notificationService)
|
||||
backgroundServiceRegistry := backgroundsvcs.ProvideBackgroundServiceRegistry(httpServer, alertNG, cleanUpService, grafanaLive, gateway, notificationService, pluginstoreService, renderingService, userAuthTokenService, tracingService, provisioningServiceImpl, usageStats, statscollectorService, grafanaService, pluginsService, internalMetricsService, secretsService, remoteCache, storageService, searchService, entityEventsService, serviceAccountsService, grpcserverProvider, secretMigrationProviderImpl, loginattemptimplService, supportbundlesimplService, metricService, keyRetriever, angulardetectorsproviderDynamic, apiserverService, anonDeviceService, ssosettingsimplService, pluginexternalService, plugininstallerService, zanzanaReconciler, appregistryService, dashboardUpdater, dashboardServiceImpl, worker, fixedRolesLoader, serviceImpl, serviceAccountsProxy, healthService, reflectionService, apiService, apiregistryService, idimplService, teamAPI, ssosettingsimplService, cloudmigrationService, registration)
|
||||
backgroundServiceRegistry := backgroundsvcs.ProvideBackgroundServiceRegistry(httpServer, alertNG, cleanUpService, grafanaLive, gateway, notificationService, pluginstoreService, renderingService, userAuthTokenService, tracingService, provisioningServiceImpl, usageStats, statscollectorService, grafanaService, pluginsService, internalMetricsService, secretsService, remoteCache, storageService, searchService, entityEventsService, serviceAccountsService, grpcserverProvider, secretMigrationProviderImpl, loginattemptimplService, supportbundlesimplService, metricService, keyRetriever, angulardetectorsproviderDynamic, apiserverService, anonDeviceService, ssosettingsimplService, pluginexternalService, plugininstallerService, zanzanaReconciler, appregistryService, dashboardUpdater, dashboardServiceImpl, worker, fixedRolesLoader, syncer, serviceImpl, serviceAccountsProxy, healthService, reflectionService, apiService, apiregistryService, idimplService, teamAPI, ssosettingsimplService, cloudmigrationService, registration)
|
||||
usageStatsProvidersRegistry := usagestatssvcs.ProvideUsageStatsProvidersRegistry(acimplService, userService)
|
||||
server, err := New(opts, cfg, httpServer, acimplService, provisioningServiceImpl, backgroundServiceRegistry, usageStatsProvidersRegistry, statscollectorService, tracingService, featureToggles, registerer)
|
||||
if err != nil {
|
||||
@@ -1231,12 +1231,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac
|
||||
}
|
||||
errorRegistry := pluginerrs.ProvideErrorTracker()
|
||||
loaderLoader := loader.ProvideService(pluginManagementCfg, discovery, bootstrap, validate, initialize, terminate, errorRegistry)
|
||||
clientGenerator := apiserver.ProvideClientGenerator(eventualRestConfigProvider)
|
||||
syncer, err := installsync.ProvideSyncer(featureToggles, clientGenerator, orgService, configProvider, serverLockService)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pluginstoreService, err := pluginstore.ProvideService(inMemory, sourcesService, loaderLoader, syncer, featureToggles)
|
||||
pluginstoreService, err := pluginstore.ProvideService(inMemory, sourcesService, loaderLoader, featureToggles)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1443,7 +1438,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
appInstaller, err := plugins.RegisterAppInstaller(configProvider, eventualRestConfigProvider)
|
||||
appInstaller, err := plugins.ProvideAppInstaller()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1508,6 +1503,11 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac
|
||||
dashboardUpdater := service8.ProvideDashboardUpdater(inProcBus, pluginstoreService, service14, importDashboardService, service13, pluginService, dashboardService)
|
||||
worker := garbagecollectionworker.ProvideWorker(cfg, secureValueMetadataStorage, keeperMetadataStorage, ossKeeperService)
|
||||
fixedRolesLoader := accesscontrol.ProvideFixedRolesLoader(acimplService, featureToggles)
|
||||
clientGenerator := apiserver.ProvideClientGenerator(eventualRestConfigProvider)
|
||||
syncer, err := installsync.ProvideSyncer(featureToggles, clientGenerator, orgService, configProvider, serverLockService, eventualRestConfigProvider, pluginstoreService)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
healthService, err := grpcserver.ProvideHealthService(cfg, grpcserverProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1589,7 +1589,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac
|
||||
}
|
||||
ossUserProtectionImpl := authinfoimpl.ProvideOSSUserProtectionService()
|
||||
registration := authnimpl.ProvideRegistration(cfg, authnService, orgService, userAuthTokenService, acimplService, permissionRegistry, apikeyService, userService, authService, ossUserProtectionImpl, loginattemptimplService, quotaService, authinfoimplService, renderingService, featureToggles, oauthtokentestService, socialService, remoteCache, ldapImpl, ossImpl, tracingService, tempuserService, notificationServiceMock)
|
||||
backgroundServiceRegistry := backgroundsvcs.ProvideBackgroundServiceRegistry(httpServer, alertNG, cleanUpService, grafanaLive, gateway, notificationService, pluginstoreService, renderingService, userAuthTokenService, tracingService, provisioningServiceImpl, usageStats, statscollectorService, grafanaService, pluginsService, internalMetricsService, secretsService, remoteCache, storageService, searchService, entityEventsService, serviceAccountsService, grpcserverProvider, secretMigrationProviderImpl, loginattemptimplService, supportbundlesimplService, metricService, keyRetriever, angulardetectorsproviderDynamic, apiserverService, anonDeviceService, ssosettingsimplService, pluginexternalService, plugininstallerService, zanzanaReconciler, appregistryService, dashboardUpdater, dashboardServiceImpl, worker, fixedRolesLoader, serviceImpl, serviceAccountsProxy, healthService, reflectionService, apiService, apiregistryService, idimplService, teamAPI, ssosettingsimplService, cloudmigrationService, registration)
|
||||
backgroundServiceRegistry := backgroundsvcs.ProvideBackgroundServiceRegistry(httpServer, alertNG, cleanUpService, grafanaLive, gateway, notificationService, pluginstoreService, renderingService, userAuthTokenService, tracingService, provisioningServiceImpl, usageStats, statscollectorService, grafanaService, pluginsService, internalMetricsService, secretsService, remoteCache, storageService, searchService, entityEventsService, serviceAccountsService, grpcserverProvider, secretMigrationProviderImpl, loginattemptimplService, supportbundlesimplService, metricService, keyRetriever, angulardetectorsproviderDynamic, apiserverService, anonDeviceService, ssosettingsimplService, pluginexternalService, plugininstallerService, zanzanaReconciler, appregistryService, dashboardUpdater, dashboardServiceImpl, worker, fixedRolesLoader, syncer, serviceImpl, serviceAccountsProxy, healthService, reflectionService, apiService, apiregistryService, idimplService, teamAPI, ssosettingsimplService, cloudmigrationService, registration)
|
||||
usageStatsProvidersRegistry := usagestatssvcs.ProvideUsageStatsProvidersRegistry(acimplService, userService)
|
||||
server, err := New(opts, cfg, httpServer, acimplService, provisioningServiceImpl, backgroundServiceRegistry, usageStatsProvidersRegistry, statscollectorService, tracingService, featureToggles, registerer)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,20 +1,29 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultPollInterval = 500 * time.Millisecond
|
||||
defaultAvailabilityTimeout = 30 * time.Second
|
||||
)
|
||||
|
||||
type DiscoveryClient interface {
|
||||
discovery.DiscoveryInterface
|
||||
GetResourceForKind(gvk schema.GroupVersionKind) (schema.GroupVersionResource, error)
|
||||
GetKindForResource(gvr schema.GroupVersionResource) (schema.GroupVersionKind, error)
|
||||
GetPreferredVesion(gr schema.GroupResource) (schema.GroupVersionResource, schema.GroupVersionKind, error)
|
||||
GetPreferredVersionForKind(gk schema.GroupKind) (schema.GroupVersionResource, schema.GroupVersionKind, error)
|
||||
WaitForAvailability(ctx context.Context, gv schema.GroupVersion) error
|
||||
}
|
||||
|
||||
type DiscoveryClientImpl struct {
|
||||
@@ -134,3 +143,13 @@ func (d *DiscoveryClientImpl) GetPreferredVersionForKind(gk schema.GroupKind) (s
|
||||
}
|
||||
return schema.GroupVersionResource{}, schema.GroupVersionKind{}, fmt.Errorf("preferred version not found for kind %s in group %s", gk.Kind, gk.Group)
|
||||
}
|
||||
|
||||
func (d *DiscoveryClientImpl) WaitForAvailability(ctx context.Context, gv schema.GroupVersion) error {
|
||||
return wait.PollUntilContextTimeout(ctx, defaultPollInterval, defaultAvailabilityTimeout, true, func(ctx context.Context) (bool, error) {
|
||||
_, err := d.ServerResourcesForGroupVersion(gv.String())
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -4,21 +4,29 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/apps/plugins/pkg/app/install"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/installsync"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
)
|
||||
|
||||
var _ installsync.Syncer = &FakeSyncer{}
|
||||
|
||||
type FakeSyncer struct {
|
||||
SyncFunc func(ctx context.Context, source install.Source, installedPlugins []*plugins.Plugin) error
|
||||
SyncFunc func(ctx context.Context, source install.Source, installedPlugins []pluginstore.Plugin) error
|
||||
}
|
||||
|
||||
func NewFakeSyncer() *FakeSyncer {
|
||||
return &FakeSyncer{}
|
||||
}
|
||||
|
||||
func (f *FakeSyncer) Sync(ctx context.Context, source install.Source, installedPlugins []*plugins.Plugin) error {
|
||||
func (f *FakeSyncer) IsDisabled() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *FakeSyncer) Run(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FakeSyncer) Sync(ctx context.Context, source install.Source, installedPlugins []pluginstore.Plugin) error {
|
||||
if f.SyncFunc != nil {
|
||||
return f.SyncFunc(ctx, source, installedPlugins)
|
||||
}
|
||||
|
||||
@@ -4,18 +4,25 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/dskit/services"
|
||||
"github.com/grafana/grafana-app-sdk/logging"
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
|
||||
pluginsv0alpha1 "github.com/grafana/grafana/apps/plugins/pkg/apis/plugins/v0alpha1"
|
||||
"github.com/grafana/grafana/apps/plugins/pkg/app/install"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/configprovider"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/client"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
)
|
||||
|
||||
const (
|
||||
ServiceName = "plugins.installsync"
|
||||
syncerLockActionName = "plugin-install-api-sync"
|
||||
)
|
||||
|
||||
@@ -25,7 +32,9 @@ var (
|
||||
|
||||
// Syncer is the interface for syncing plugin installations to the Kubernetes-style API.
|
||||
type Syncer interface {
|
||||
Sync(ctx context.Context, source install.Source, installedPlugins []*plugins.Plugin) error
|
||||
registry.BackgroundService
|
||||
registry.CanBeDisabled
|
||||
Sync(ctx context.Context, source install.Source, installedPlugins []pluginstore.Plugin) error
|
||||
}
|
||||
|
||||
// ServerLock is the interface for acquiring distributed locks.
|
||||
@@ -34,14 +43,22 @@ type ServerLock interface {
|
||||
}
|
||||
|
||||
type syncer struct {
|
||||
featureToggles featuremgmt.FeatureToggles
|
||||
clientGenerator resource.ClientGenerator
|
||||
installRegistrar *install.InstallRegistrar
|
||||
orgService org.Service
|
||||
namespaceMapper request.NamespaceMapper
|
||||
serverLock ServerLock
|
||||
services.NamedService
|
||||
featureToggles featuremgmt.FeatureToggles
|
||||
clientGenerator resource.ClientGenerator
|
||||
installRegistrar *install.InstallRegistrar
|
||||
orgService org.Service
|
||||
namespaceMapper request.NamespaceMapper
|
||||
serverLock ServerLock
|
||||
restConfigProvider apiserver.RestConfigProvider
|
||||
pluginsStoreService pluginstore.Store
|
||||
}
|
||||
|
||||
var _ Syncer = (*syncer)(nil)
|
||||
var _ registry.BackgroundService = (*syncer)(nil)
|
||||
var _ registry.CanBeDisabled = (*syncer)(nil)
|
||||
var _ services.NamedService = (*syncer)(nil)
|
||||
|
||||
// newSyncer creates a new syncer with the provided dependencies.
|
||||
func newSyncer(
|
||||
featureToggles featuremgmt.FeatureToggles,
|
||||
@@ -50,15 +67,21 @@ func newSyncer(
|
||||
orgService org.Service,
|
||||
namespaceMapper request.NamespaceMapper,
|
||||
serverLock ServerLock,
|
||||
restConfigProvider apiserver.RestConfigProvider,
|
||||
pluginsStoreService pluginstore.Store,
|
||||
) *syncer {
|
||||
return &syncer{
|
||||
clientGenerator: clientGenerator,
|
||||
featureToggles: featureToggles,
|
||||
installRegistrar: installRegistrar,
|
||||
orgService: orgService,
|
||||
namespaceMapper: namespaceMapper,
|
||||
serverLock: serverLock,
|
||||
s := syncer{
|
||||
clientGenerator: clientGenerator,
|
||||
featureToggles: featureToggles,
|
||||
installRegistrar: installRegistrar,
|
||||
orgService: orgService,
|
||||
namespaceMapper: namespaceMapper,
|
||||
serverLock: serverLock,
|
||||
restConfigProvider: restConfigProvider,
|
||||
pluginsStoreService: pluginsStoreService,
|
||||
}
|
||||
s.NamedService = services.NewBasicService(nil, s.running, nil).WithName(ServiceName)
|
||||
return &s
|
||||
}
|
||||
|
||||
// ProvideSyncer creates a new Syncer for syncing plugin installations to the API.
|
||||
@@ -68,6 +91,8 @@ func ProvideSyncer(
|
||||
orgService org.Service,
|
||||
cfgProvider configprovider.ConfigProvider,
|
||||
serverLock ServerLock,
|
||||
restConfigProvider apiserver.RestConfigProvider,
|
||||
pluginsStoreService pluginstore.Store,
|
||||
) (Syncer, error) {
|
||||
cfg, err := cfgProvider.Get(context.Background())
|
||||
if err != nil {
|
||||
@@ -83,18 +108,49 @@ func ProvideSyncer(
|
||||
orgService,
|
||||
namespaceMapper,
|
||||
serverLock,
|
||||
restConfigProvider,
|
||||
pluginsStoreService,
|
||||
), nil
|
||||
}
|
||||
|
||||
func (s *syncer) Sync(ctx context.Context, source install.Source, installedPlugins []*plugins.Plugin) error {
|
||||
func (s *syncer) IsDisabled() bool {
|
||||
//nolint:staticcheck // not yet migrated to OpenFeature
|
||||
if !s.featureToggles.IsEnabled(ctx, featuremgmt.FlagPluginInstallAPISync) {
|
||||
return nil
|
||||
syncEnabled := s.featureToggles.IsEnabled(context.Background(), featuremgmt.FlagPluginInstallAPISync)
|
||||
//nolint:staticcheck // not yet migrated to OpenFeature
|
||||
serviceLoadingEnabled := s.featureToggles.IsEnabled(context.Background(), featuremgmt.FlagPluginStoreServiceLoading)
|
||||
return !syncEnabled || !serviceLoadingEnabled
|
||||
}
|
||||
|
||||
func (s *syncer) Run(ctx context.Context) error {
|
||||
if err := s.StartAsync(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.AwaitTerminated(context.Background())
|
||||
}
|
||||
|
||||
func (s *syncer) running(ctx context.Context) error {
|
||||
ctxLog := logging.FromContext(ctx)
|
||||
restConfig, err := s.restConfigProvider.GetRestConfig(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
discoveryClient, err := client.NewDiscoveryClient(restConfig)
|
||||
if err != nil {
|
||||
ctxLog.Warn("Failed to create discovery client, skipping plugin sync", "error", err)
|
||||
}
|
||||
if err := discoveryClient.WaitForAvailability(ctx, pluginsv0alpha1.PluginKind().GroupVersionKind().GroupVersion()); err != nil {
|
||||
ctxLog.Warn("Failed to wait for plugin API availability, skipping plugin sync", "error", err)
|
||||
}
|
||||
|
||||
//nolint:staticcheck // not yet migrated to OpenFeature
|
||||
if !s.featureToggles.IsEnabled(ctx, featuremgmt.FlagPluginStoreServiceLoading) {
|
||||
logging.DefaultLogger.Warn("pluginInstallAPISync is enabled, but pluginStoreServiceLoading is disabled. skipping plugin sync.")
|
||||
if err := s.Sync(ctx, install.SourcePluginStore, s.pluginsStoreService.Plugins(ctx)); err != nil {
|
||||
ctxLog.Warn("Failed to sync plugins", "error", err)
|
||||
}
|
||||
<-ctx.Done()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *syncer) Sync(ctx context.Context, source install.Source, installedPlugins []pluginstore.Plugin) error {
|
||||
if s.IsDisabled() {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -113,13 +169,14 @@ func (s *syncer) Sync(ctx context.Context, source install.Source, installedPlugi
|
||||
return syncErr
|
||||
}
|
||||
|
||||
func (s *syncer) syncAllNamespaces(ctx context.Context, source install.Source, installedPlugins []*plugins.Plugin) error {
|
||||
func (s *syncer) syncAllNamespaces(ctx context.Context, source install.Source, installedPlugins []pluginstore.Plugin) error {
|
||||
orgs, err := s.orgService.Search(ctx, &org.SearchOrgsQuery{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, org := range orgs {
|
||||
ctx = identity.WithServiceIdentityForSingleNamespaceContext(ctx, s.namespaceMapper(org.ID))
|
||||
err := s.syncNamespace(ctx, s.namespaceMapper(org.ID), source, installedPlugins)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -129,7 +186,7 @@ func (s *syncer) syncAllNamespaces(ctx context.Context, source install.Source, i
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *syncer) syncNamespace(ctx context.Context, namespace string, source install.Source, installedPlugins []*plugins.Plugin) error {
|
||||
func (s *syncer) syncNamespace(ctx context.Context, namespace string, source install.Source, installedPlugins []pluginstore.Plugin) error {
|
||||
client, err := s.installRegistrar.GetClient()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -140,9 +197,9 @@ func (s *syncer) syncNamespace(ctx context.Context, namespace string, source ins
|
||||
return err
|
||||
}
|
||||
|
||||
installedMap := make(map[string]*plugins.Plugin)
|
||||
installedMap := make(map[string]struct{})
|
||||
for _, p := range installedPlugins {
|
||||
installedMap[p.ID] = p
|
||||
installedMap[p.ID] = struct{}{}
|
||||
}
|
||||
|
||||
// unregister plugins that are not installed
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/org/orgtest"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
)
|
||||
|
||||
func TestSyncer_Sync(t *testing.T) {
|
||||
@@ -25,7 +26,7 @@ func TestSyncer_Sync(t *testing.T) {
|
||||
name string
|
||||
pluginInstallAPISyncEnabled bool
|
||||
pluginStoreServiceEnabled bool
|
||||
installedPlugins []*plugins.Plugin
|
||||
installedPlugins []pluginstore.Plugin
|
||||
orgs []*org.OrgDTO
|
||||
orgServiceError error
|
||||
serverLockError error
|
||||
@@ -36,7 +37,7 @@ func TestSyncer_Sync(t *testing.T) {
|
||||
name: "plugin install API sync feature toggle disabled",
|
||||
pluginInstallAPISyncEnabled: false,
|
||||
pluginStoreServiceEnabled: true,
|
||||
installedPlugins: []*plugins.Plugin{{JSONData: plugins.JSONData{ID: "test-plugin", Info: plugins.Info{Version: "1.0.0"}}, Class: plugins.ClassCore}},
|
||||
installedPlugins: []pluginstore.Plugin{{JSONData: plugins.JSONData{ID: "test-plugin"}, Class: plugins.ClassCore}},
|
||||
orgs: []*org.OrgDTO{{ID: 1, Name: "Org 1"}},
|
||||
expectedError: nil,
|
||||
expectSyncCalls: 0,
|
||||
@@ -45,7 +46,7 @@ func TestSyncer_Sync(t *testing.T) {
|
||||
name: "plugin store service feature toggle disabled",
|
||||
pluginInstallAPISyncEnabled: true,
|
||||
pluginStoreServiceEnabled: false,
|
||||
installedPlugins: []*plugins.Plugin{{JSONData: plugins.JSONData{ID: "test-plugin", Info: plugins.Info{Version: "1.0.0"}}, Class: plugins.ClassCore}},
|
||||
installedPlugins: []pluginstore.Plugin{{JSONData: plugins.JSONData{ID: "test-plugin"}, Class: plugins.ClassCore}},
|
||||
orgs: []*org.OrgDTO{{ID: 1, Name: "Org 1"}},
|
||||
expectedError: nil,
|
||||
expectSyncCalls: 0,
|
||||
@@ -54,7 +55,7 @@ func TestSyncer_Sync(t *testing.T) {
|
||||
name: "both feature toggles enabled, no orgs",
|
||||
pluginInstallAPISyncEnabled: true,
|
||||
pluginStoreServiceEnabled: true,
|
||||
installedPlugins: []*plugins.Plugin{{JSONData: plugins.JSONData{ID: "test-plugin", Info: plugins.Info{Version: "1.0.0"}}, Class: plugins.ClassCore}},
|
||||
installedPlugins: []pluginstore.Plugin{{JSONData: plugins.JSONData{ID: "test-plugin"}, Class: plugins.ClassCore}},
|
||||
orgs: []*org.OrgDTO{},
|
||||
expectedError: nil,
|
||||
expectSyncCalls: 0,
|
||||
@@ -63,7 +64,7 @@ func TestSyncer_Sync(t *testing.T) {
|
||||
name: "both feature toggles enabled, empty installed plugins",
|
||||
pluginInstallAPISyncEnabled: true,
|
||||
pluginStoreServiceEnabled: true,
|
||||
installedPlugins: []*plugins.Plugin{},
|
||||
installedPlugins: []pluginstore.Plugin{},
|
||||
orgs: []*org.OrgDTO{{ID: 1, Name: "Org 1"}},
|
||||
expectedError: nil,
|
||||
expectSyncCalls: 0,
|
||||
@@ -72,7 +73,7 @@ func TestSyncer_Sync(t *testing.T) {
|
||||
name: "both feature toggles enabled, single org",
|
||||
pluginInstallAPISyncEnabled: true,
|
||||
pluginStoreServiceEnabled: true,
|
||||
installedPlugins: []*plugins.Plugin{{JSONData: plugins.JSONData{ID: "test-plugin", Info: plugins.Info{Version: "1.0.0"}}, Class: plugins.ClassCore}},
|
||||
installedPlugins: []pluginstore.Plugin{{JSONData: plugins.JSONData{ID: "test-plugin"}, Class: plugins.ClassCore}},
|
||||
orgs: []*org.OrgDTO{{ID: 1, Name: "Org 1"}},
|
||||
expectedError: nil,
|
||||
expectSyncCalls: 1,
|
||||
@@ -81,7 +82,7 @@ func TestSyncer_Sync(t *testing.T) {
|
||||
name: "both feature toggles enabled, multiple orgs",
|
||||
pluginInstallAPISyncEnabled: true,
|
||||
pluginStoreServiceEnabled: true,
|
||||
installedPlugins: []*plugins.Plugin{{JSONData: plugins.JSONData{ID: "test-plugin", Info: plugins.Info{Version: "1.0.0"}}, Class: plugins.ClassCore}},
|
||||
installedPlugins: []pluginstore.Plugin{{JSONData: plugins.JSONData{ID: "test-plugin"}, Class: plugins.ClassCore}},
|
||||
orgs: []*org.OrgDTO{
|
||||
{ID: 1, Name: "Org 1"},
|
||||
{ID: 2, Name: "Org 2"},
|
||||
@@ -94,7 +95,7 @@ func TestSyncer_Sync(t *testing.T) {
|
||||
name: "org service error",
|
||||
pluginInstallAPISyncEnabled: true,
|
||||
pluginStoreServiceEnabled: true,
|
||||
installedPlugins: []*plugins.Plugin{{JSONData: plugins.JSONData{ID: "test-plugin", Info: plugins.Info{Version: "1.0.0"}}, Class: plugins.ClassCore}},
|
||||
installedPlugins: []pluginstore.Plugin{{JSONData: plugins.JSONData{ID: "test-plugin"}, Class: plugins.ClassCore}},
|
||||
orgs: nil,
|
||||
orgServiceError: errors.New("org service error"),
|
||||
expectedError: errors.New("org service error"),
|
||||
@@ -104,7 +105,7 @@ func TestSyncer_Sync(t *testing.T) {
|
||||
name: "server lock error",
|
||||
pluginInstallAPISyncEnabled: true,
|
||||
pluginStoreServiceEnabled: true,
|
||||
installedPlugins: []*plugins.Plugin{{JSONData: plugins.JSONData{ID: "test-plugin", Info: plugins.Info{Version: "1.0.0"}}, Class: plugins.ClassCore}},
|
||||
installedPlugins: []pluginstore.Plugin{{JSONData: plugins.JSONData{ID: "test-plugin"}, Class: plugins.ClassCore}},
|
||||
orgs: []*org.OrgDTO{{ID: 1, Name: "Org 1"}},
|
||||
serverLockError: errors.New("lock error"),
|
||||
expectedError: errors.New("lock error"),
|
||||
@@ -156,6 +157,8 @@ func TestSyncer_Sync(t *testing.T) {
|
||||
orgService,
|
||||
func(orgID int64) string { return "org-1" },
|
||||
serverLock,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
// Execute
|
||||
@@ -177,7 +180,7 @@ func TestSyncer_Sync(t *testing.T) {
|
||||
func TestSyncer_syncNamespace(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
installedPlugins []*plugins.Plugin
|
||||
installedPlugins []pluginstore.Plugin
|
||||
apiPlugins []pluginsv0alpha1.Plugin
|
||||
clientListError error
|
||||
expectedError error
|
||||
@@ -188,7 +191,7 @@ func TestSyncer_syncNamespace(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "no installed plugins, no API plugins",
|
||||
installedPlugins: []*plugins.Plugin{},
|
||||
installedPlugins: []pluginstore.Plugin{},
|
||||
apiPlugins: []pluginsv0alpha1.Plugin{},
|
||||
expectedError: nil,
|
||||
expectedRegCalls: 0,
|
||||
@@ -196,7 +199,7 @@ func TestSyncer_syncNamespace(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "installed plugins only",
|
||||
installedPlugins: []*plugins.Plugin{
|
||||
installedPlugins: []pluginstore.Plugin{
|
||||
{JSONData: plugins.JSONData{ID: "plugin-1", Info: plugins.Info{Version: "1.0.0"}}, Class: plugins.ClassCore},
|
||||
{JSONData: plugins.JSONData{ID: "plugin-2", Info: plugins.Info{Version: "2.0.0"}}, Class: plugins.ClassExternal},
|
||||
},
|
||||
@@ -208,7 +211,7 @@ func TestSyncer_syncNamespace(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "API plugins only",
|
||||
installedPlugins: []*plugins.Plugin{},
|
||||
installedPlugins: []pluginstore.Plugin{},
|
||||
apiPlugins: []pluginsv0alpha1.Plugin{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -236,7 +239,7 @@ func TestSyncer_syncNamespace(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "mixed - some match",
|
||||
installedPlugins: []*plugins.Plugin{
|
||||
installedPlugins: []pluginstore.Plugin{
|
||||
{JSONData: plugins.JSONData{ID: "plugin-1", Info: plugins.Info{Version: "1.0.0"}}, Class: plugins.ClassCore},
|
||||
{JSONData: plugins.JSONData{ID: "plugin-2", Info: plugins.Info{Version: "2.0.0"}}, Class: plugins.ClassExternal},
|
||||
{JSONData: plugins.JSONData{ID: "plugin-3", Info: plugins.Info{Version: "3.0.0"}}, Class: plugins.ClassExternal},
|
||||
@@ -269,7 +272,7 @@ func TestSyncer_syncNamespace(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "list error",
|
||||
installedPlugins: []*plugins.Plugin{},
|
||||
installedPlugins: []pluginstore.Plugin{},
|
||||
apiPlugins: []pluginsv0alpha1.Plugin{},
|
||||
clientListError: errors.New("list error"),
|
||||
expectedError: errors.New("list error"),
|
||||
@@ -327,6 +330,8 @@ func TestSyncer_syncNamespace(t *testing.T) {
|
||||
orgtest.NewOrgServiceFake(),
|
||||
func(orgID int64) string { return "org-1" },
|
||||
&fakeServerLock{},
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
// Execute
|
||||
@@ -378,6 +383,8 @@ func TestInstallRegistrar_GetClient(t *testing.T) {
|
||||
orgtest.NewOrgServiceFake(),
|
||||
func(orgID int64) string { return "org-1" },
|
||||
&fakeServerLock{},
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
// First call
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/registry"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
fakeDatasources "github.com/grafana/grafana/pkg/services/datasources/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/installsync/installsyncfakes"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginconfig"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||
@@ -42,7 +41,7 @@ func TestGet(t *testing.T) {
|
||||
cfg := setting.NewCfg()
|
||||
ds := &fakeDatasources.FakeDataSourceService{}
|
||||
db := &dbtest.FakeDB{ExpectedError: pluginsettings.ErrPluginSettingNotFound}
|
||||
store, err := pluginstore.NewPluginStoreForTest(preg, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{}, installsyncfakes.NewFakeSyncer())
|
||||
store, err := pluginstore.NewPluginStoreForTest(preg, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{})
|
||||
require.NoError(t, err)
|
||||
pcp := plugincontext.ProvideService(cfg, localcache.ProvideService(),
|
||||
store, &fakeDatasources.FakeCacheService{},
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/pluginfakes"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/registry"
|
||||
"github.com/grafana/grafana/pkg/plugins/repo"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/installsync/installsyncfakes"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/managedplugins"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginchecker"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
@@ -27,7 +26,7 @@ func TestService_IsDisabled(t *testing.T) {
|
||||
&setting.Cfg{
|
||||
PreinstallPluginsAsync: []setting.InstallPlugin{{ID: "myplugin"}},
|
||||
},
|
||||
pluginstore.New(registry.NewInMemory(), &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{}, installsyncfakes.NewFakeSyncer()),
|
||||
pluginstore.New(registry.NewInMemory(), &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{}),
|
||||
&pluginfakes.FakePluginInstaller{},
|
||||
prometheus.NewRegistry(),
|
||||
&pluginfakes.FakePluginRepo{},
|
||||
@@ -160,7 +159,7 @@ func TestService_Run(t *testing.T) {
|
||||
}
|
||||
installed := 0
|
||||
installedFromURL := 0
|
||||
store, err := pluginstore.NewPluginStoreForTest(preg, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{}, installsyncfakes.NewFakeSyncer())
|
||||
store, err := pluginstore.NewPluginStoreForTest(preg, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{})
|
||||
require.NoError(t, err)
|
||||
s, err := ProvideService(
|
||||
&setting.Cfg{
|
||||
|
||||
@@ -8,14 +8,12 @@ import (
|
||||
"github.com/grafana/dskit/services"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/grafana/grafana/apps/plugins/pkg/app/install"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/loader"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/registry"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/sources"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/installsync"
|
||||
)
|
||||
|
||||
var _ Store = (*Service)(nil)
|
||||
@@ -34,18 +32,17 @@ type Store interface {
|
||||
type Service struct {
|
||||
services.NamedService
|
||||
|
||||
pluginRegistry registry.Service
|
||||
pluginLoader loader.Service
|
||||
pluginSources sources.Registry
|
||||
installsRegistrar installsync.Syncer
|
||||
loadOnStartup bool
|
||||
pluginRegistry registry.Service
|
||||
pluginLoader loader.Service
|
||||
pluginSources sources.Registry
|
||||
loadOnStartup bool
|
||||
}
|
||||
|
||||
func ProvideService(pluginRegistry registry.Service, pluginSources sources.Registry,
|
||||
pluginLoader loader.Service, installsRegistrar installsync.Syncer, features featuremgmt.FeatureToggles) (*Service, error) {
|
||||
pluginLoader loader.Service, features featuremgmt.FeatureToggles) (*Service, error) {
|
||||
//nolint:staticcheck // not yet migrated to OpenFeature
|
||||
if features.IsEnabledGlobally(featuremgmt.FlagPluginStoreServiceLoading) {
|
||||
s := New(pluginRegistry, pluginLoader, pluginSources, installsRegistrar)
|
||||
s := New(pluginRegistry, pluginLoader, pluginSources)
|
||||
s.loadOnStartup = true
|
||||
return s, nil
|
||||
}
|
||||
@@ -56,24 +53,18 @@ func ProvideService(pluginRegistry registry.Service, pluginSources sources.Regis
|
||||
logger := log.New("plugin.store")
|
||||
logger.Info("Loading plugins...")
|
||||
|
||||
loadedPluginsToSync := make([]*plugins.Plugin, 0)
|
||||
for _, ps := range pluginSources.List(ctx) {
|
||||
loadedPlugins, err := pluginLoader.Load(ctx, ps)
|
||||
if err != nil {
|
||||
logger.Error("Loading plugin source failed", "source", ps.PluginClass(ctx), "error", err)
|
||||
return nil, err
|
||||
}
|
||||
loadedPluginsToSync = append(loadedPluginsToSync, loadedPlugins...)
|
||||
totalPlugins += len(loadedPlugins)
|
||||
}
|
||||
|
||||
if err := installsRegistrar.Sync(ctx, install.SourcePluginStore, loadedPluginsToSync); err != nil {
|
||||
logger.Error("Syncing plugin installations failed", "error", err)
|
||||
}
|
||||
|
||||
logger.Info("Plugins loaded", "count", totalPlugins, "duration", time.Since(start))
|
||||
|
||||
return New(pluginRegistry, pluginLoader, pluginSources, installsRegistrar), nil
|
||||
return New(pluginRegistry, pluginLoader, pluginSources), nil
|
||||
}
|
||||
|
||||
func (s *Service) Run(ctx context.Context) error {
|
||||
@@ -84,8 +75,8 @@ func (s *Service) Run(ctx context.Context) error {
|
||||
return s.AwaitTerminated(stopCtx)
|
||||
}
|
||||
|
||||
func NewPluginStoreForTest(pluginRegistry registry.Service, pluginLoader loader.Service, pluginSources sources.Registry, installsRegistrar installsync.Syncer) (*Service, error) {
|
||||
s := New(pluginRegistry, pluginLoader, pluginSources, installsRegistrar)
|
||||
func NewPluginStoreForTest(pluginRegistry registry.Service, pluginLoader loader.Service, pluginSources sources.Registry) (*Service, error) {
|
||||
s := New(pluginRegistry, pluginLoader, pluginSources)
|
||||
s.loadOnStartup = true
|
||||
if err := s.StartAsync(context.Background()); err != nil {
|
||||
return nil, err
|
||||
@@ -96,12 +87,11 @@ func NewPluginStoreForTest(pluginRegistry registry.Service, pluginLoader loader.
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func New(pluginRegistry registry.Service, pluginLoader loader.Service, pluginSources sources.Registry, installsRegistrar installsync.Syncer) *Service {
|
||||
func New(pluginRegistry registry.Service, pluginLoader loader.Service, pluginSources sources.Registry) *Service {
|
||||
s := &Service{
|
||||
pluginRegistry: pluginRegistry,
|
||||
pluginLoader: pluginLoader,
|
||||
pluginSources: pluginSources,
|
||||
installsRegistrar: installsRegistrar,
|
||||
pluginRegistry: pluginRegistry,
|
||||
pluginLoader: pluginLoader,
|
||||
pluginSources: pluginSources,
|
||||
}
|
||||
s.NamedService = services.NewBasicService(s.starting, s.running, s.stopping).WithName(ServiceName)
|
||||
return s
|
||||
@@ -116,21 +106,15 @@ func (s *Service) starting(ctx context.Context) error {
|
||||
logger := log.New(ServiceName)
|
||||
logger.Info("Loading plugins...")
|
||||
|
||||
loadedPluginsToSync := make([]*plugins.Plugin, 0)
|
||||
for _, ps := range s.pluginSources.List(ctx) {
|
||||
loadedPlugins, err := s.pluginLoader.Load(ctx, ps)
|
||||
if err != nil {
|
||||
logger.Error("Loading plugin source failed", "source", ps.PluginClass(ctx), "error", err)
|
||||
return err
|
||||
}
|
||||
loadedPluginsToSync = append(loadedPluginsToSync, loadedPlugins...)
|
||||
totalPlugins += len(loadedPlugins)
|
||||
}
|
||||
|
||||
if err := s.installsRegistrar.Sync(ctx, install.SourcePluginStore, loadedPluginsToSync); err != nil {
|
||||
logger.Error("Syncing plugin installations failed", "error", err)
|
||||
}
|
||||
|
||||
logger.Info("Plugins loaded", "count", totalPlugins, "duration", time.Since(start))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,13 +7,11 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/apps/plugins/pkg/app/install"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/log"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/pluginfakes"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/installsync/installsyncfakes"
|
||||
)
|
||||
|
||||
func TestStore_ProvideService(t *testing.T) {
|
||||
@@ -78,7 +76,7 @@ func TestStore_ProvideService(t *testing.T) {
|
||||
features = featuremgmt.WithFeatures()
|
||||
}
|
||||
|
||||
service, err := ProvideService(pluginfakes.NewFakePluginRegistry(), srcs, l, installsyncfakes.NewFakeSyncer(), features)
|
||||
service, err := ProvideService(pluginfakes.NewFakePluginRegistry(), srcs, l, features)
|
||||
require.Equal(t, tt.expectedLoadOnStartup, service.loadOnStartup)
|
||||
require.Equal(t, tt.expectedBeforeStart, loadedSrcs)
|
||||
require.NoError(t, err)
|
||||
@@ -91,47 +89,6 @@ func TestStore_ProvideService(t *testing.T) {
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Plugin installs are synced", func(t *testing.T) {
|
||||
registrar := installsyncfakes.NewFakeSyncer()
|
||||
registered := []*plugins.Plugin{}
|
||||
registrar.SyncFunc = func(ctx context.Context, source install.Source, installedPlugins []*plugins.Plugin) error {
|
||||
registered = append(registered, installedPlugins...)
|
||||
return nil
|
||||
}
|
||||
srcs := &pluginfakes.FakeSourceRegistry{ListFunc: func(_ context.Context) []plugins.PluginSource {
|
||||
return []plugins.PluginSource{
|
||||
&pluginfakes.FakePluginSource{
|
||||
PluginClassFunc: func(ctx context.Context) plugins.Class {
|
||||
return plugins.ClassExternal
|
||||
},
|
||||
DiscoverFunc: func(ctx context.Context) ([]*plugins.FoundBundle, error) {
|
||||
return []*plugins.FoundBundle{
|
||||
{
|
||||
Primary: plugins.FoundPlugin{JSONData: plugins.JSONData{ID: "test-plugin"}},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
DefaultSignatureFunc: func(ctx context.Context) (plugins.Signature, bool) {
|
||||
return plugins.Signature{}, false
|
||||
},
|
||||
},
|
||||
}
|
||||
}}
|
||||
l := &pluginfakes.FakeLoader{
|
||||
LoadFunc: func(ctx context.Context, src plugins.PluginSource) ([]*plugins.Plugin, error) {
|
||||
return []*plugins.Plugin{{JSONData: plugins.JSONData{ID: "test-plugin"}}}, nil
|
||||
},
|
||||
}
|
||||
service, err := ProvideService(pluginfakes.NewFakePluginRegistry(), srcs, l, registrar, featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
ctx := context.Background()
|
||||
err = service.StartAsync(ctx)
|
||||
require.NoError(t, err)
|
||||
err = service.AwaitRunning(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, registered, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestStore_Plugin(t *testing.T) {
|
||||
@@ -145,7 +102,7 @@ func TestStore_Plugin(t *testing.T) {
|
||||
p1.ID: p1,
|
||||
p2.ID: p2,
|
||||
},
|
||||
}, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{}, installsyncfakes.NewFakeSyncer())
|
||||
}, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{})
|
||||
require.NoError(t, err)
|
||||
|
||||
p, exists := ps.Plugin(context.Background(), p1.ID)
|
||||
@@ -175,7 +132,7 @@ func TestStore_Plugins(t *testing.T) {
|
||||
p4.ID: p4,
|
||||
p5.ID: p5,
|
||||
},
|
||||
}, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{}, installsyncfakes.NewFakeSyncer())
|
||||
}, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{})
|
||||
require.NoError(t, err)
|
||||
|
||||
ToGrafanaDTO(p1)
|
||||
@@ -219,7 +176,7 @@ func TestStore_Routes(t *testing.T) {
|
||||
p5.ID: p5,
|
||||
p6.ID: p6,
|
||||
},
|
||||
}, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{}, installsyncfakes.NewFakeSyncer())
|
||||
}, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{})
|
||||
require.NoError(t, err)
|
||||
|
||||
sr := func(p *plugins.Plugin) *plugins.StaticRoute {
|
||||
@@ -249,7 +206,7 @@ func TestProcessManager_shutdown(t *testing.T) {
|
||||
unloaded = true
|
||||
return nil, nil
|
||||
},
|
||||
}, &pluginfakes.FakeSourceRegistry{}, installsyncfakes.NewFakeSyncer())
|
||||
}, &pluginfakes.FakeSourceRegistry{})
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
@@ -282,7 +239,7 @@ func TestProcessManager_shutdown(t *testing.T) {
|
||||
UnloadFunc: func(_ context.Context, plugin *plugins.Plugin) (*plugins.Plugin, error) {
|
||||
return nil, expectedErr
|
||||
},
|
||||
}, &pluginfakes.FakeSourceRegistry{}, installsyncfakes.NewFakeSyncer())
|
||||
}, &pluginfakes.FakeSourceRegistry{})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = ps.stopping(nil)
|
||||
@@ -302,7 +259,7 @@ func TestStore_availablePlugins(t *testing.T) {
|
||||
p1.ID: p1,
|
||||
p2.ID: p2,
|
||||
},
|
||||
}, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{}, installsyncfakes.NewFakeSyncer())
|
||||
}, &pluginfakes.FakeLoader{}, &pluginfakes.FakeSourceRegistry{})
|
||||
require.NoError(t, err)
|
||||
|
||||
aps := ps.availablePlugins(context.Background())
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/sources"
|
||||
"github.com/grafana/grafana/pkg/plugins/pluginassets"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/installsync/installsyncfakes"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pipeline"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginconfig"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs"
|
||||
@@ -65,7 +64,7 @@ func CreateIntegrationTestCtx(t *testing.T, cfg *setting.Cfg, coreRegistry *core
|
||||
Terminator: term,
|
||||
})
|
||||
|
||||
ps, err := pluginstore.NewPluginStoreForTest(reg, l, sources.ProvideService(cfg, pCfg), installsyncfakes.NewFakeSyncer())
|
||||
ps, err := pluginstore.NewPluginStoreForTest(reg, l, sources.ProvideService(cfg, pCfg))
|
||||
require.NoError(t, err)
|
||||
|
||||
return &IntegrationTestCtx{
|
||||
|
||||
Reference in New Issue
Block a user