mirror of
https://github.com/grafana/grafana.git
synced 2025-01-26 08:16:59 -06:00
Chore: Add grafana-apiserver (#70721)
* add grafana-apiserver * remove watchset & move provisioning and http server to background services * remove scheme * otel fixes (#70874) * remove module ProvideRegistry test * use certgenerator from apiserver package * Control collector/pdata from going to v1.0.0-rc8 (as Tempo 1.5.1 would have it)
This commit is contained in:
parent
8ced4343f3
commit
52121b7165
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@ -99,6 +99,7 @@
|
||||
/pkg/server/ @grafana/backend-platform
|
||||
/pkg/services/annotations/ @grafana/backend-platform
|
||||
/pkg/services/apikey/ @grafana/grafana-authnz-team
|
||||
/pkg/services/certgenerator @grafana/grafana-app-platform-squad
|
||||
/pkg/services/cleanup/ @grafana/backend-platform
|
||||
/pkg/services/contexthandler/ @grafana/backend-platform
|
||||
/pkg/services/correlations/ @grafana/backend-platform
|
||||
@ -108,6 +109,7 @@
|
||||
/pkg/services/dashboardversion/ @grafana/backend-platform
|
||||
/pkg/services/encryption/ @grafana/backend-platform
|
||||
/pkg/services/folder/ @grafana/backend-platform
|
||||
/pkg/services/grafana-apiserver @grafana/grafana-app-platform-squad
|
||||
/pkg/services/hooks/ @grafana/backend-platform
|
||||
/pkg/services/kmsproviders/ @grafana/backend-platform
|
||||
/pkg/services/licensing/ @grafana/backend-platform
|
||||
|
@ -82,6 +82,11 @@ linters = ["stylecheck"]
|
||||
text = "ST1001"
|
||||
|
||||
# Enable when appropriate
|
||||
# http.CloseNotifier has been deprecated since Go 1.11 and an alternative has been available since Go 1.7: We currently need it in pkg/web/response_writer.go.
|
||||
[[issues.exclude-rules]]
|
||||
linters = ["staticcheck"]
|
||||
text = "SA1019: http.CloseNotifier"
|
||||
|
||||
# strings.Title has been deprecated since Go 1.18 and an alternative has been available since Go 1.0: The rule Title uses for word boundaries does not handle Unicode punctuation properly.
|
||||
# Use golang.org/x/text/cases instead.
|
||||
[[issues.exclude-rules]]
|
||||
|
@ -128,6 +128,7 @@ Experimental features might be changed or removed without prior notice.
|
||||
| `transformationsRedesign` | Enables the transformations redesign |
|
||||
| `mlExpressions` | Enable support for Machine Learning in server-side expressions |
|
||||
| `disableTraceQLStreaming` | Disables the option to stream the response of TraceQL queries of the Tempo data source |
|
||||
| `grafanaAPIServer` | Enable Kubernetes API Server for Grafana resources |
|
||||
|
||||
## Development feature toggles
|
||||
|
||||
|
107
go.mod
107
go.mod
@ -13,13 +13,19 @@ replace github.com/denisenkom/go-mssqldb => github.com/grafana/go-mssqldb v0.9.2
|
||||
replace github.com/docker/docker => github.com/moby/moby v23.0.4+incompatible
|
||||
|
||||
// contains openapi encoder fixes. remove ASAP
|
||||
replace cuelang.org/go => github.com/sdboyer/cue v0.5.0-beta.2.0.20230712135403-bdc4772ae055
|
||||
replace cuelang.org/go => github.com/sdboyer/cue v0.5.0-beta.2.0.20230712135403-bdc4772ae055 // @grafana/grafana-as-code
|
||||
|
||||
// For some insane reason, client-go seems to have a broken v12.0.0 tag on it that forces us to
|
||||
// hoist a replace statement.
|
||||
replace k8s.io/client-go => k8s.io/client-go v0.25.3
|
||||
// TODO: following otel replaces to pin the libraries so k8s.io/apiserver doesn't downgrade us inadvertantly
|
||||
// will need bumps as we upgrade otel in Grafana
|
||||
replace go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp => go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 // @grafana/backend-platform
|
||||
|
||||
require k8s.io/apimachinery v0.26.2 // @grafana/backend-platform
|
||||
replace go.opentelemetry.io/otel => go.opentelemetry.io/otel v1.16.0 // @grafana/backend-platform
|
||||
|
||||
replace go.opentelemetry.io/otel/trace => go.opentelemetry.io/otel/trace v1.16.0 // @grafana/backend-platform
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => go.opentelemetry.io/otel/metric v1.16.0 // @grafana/backend-platform
|
||||
|
||||
replace go.opentelemetry.io/collector/pdata => go.opentelemetry.io/collector/pdata v0.50.0 // @grafana/backend-platform
|
||||
|
||||
// Override Prometheus version because Prometheus v2.X is tagged as v0.X for Go modules purposes and Go assumes
|
||||
// that v1.Y is higher than v0.X, so when we resolve dependencies if any dependency imports v1.Y we'd
|
||||
@ -99,16 +105,16 @@ require (
|
||||
github.com/vectordotdev/go-datemath v0.1.1-0.20220323213446-f3954d0b18ae // @grafana/backend-platform
|
||||
github.com/yalue/merged_fs v1.2.2 // @grafana/grafana-as-code
|
||||
github.com/yudai/gojsondiff v1.0.0 // @grafana/backend-platform
|
||||
go.opentelemetry.io/collector/model v0.46.0 // @grafana/backend-platform
|
||||
go.opentelemetry.io/collector/model v0.50.0 // @grafana/backend-platform
|
||||
go.opentelemetry.io/collector/pdata v1.0.0-rc8 // @grafana/backend-platform
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.37.0 // @grafana/grafana-operator-experience-squad
|
||||
go.opentelemetry.io/otel v1.14.0 // @grafana/alerting-squad-backend
|
||||
go.opentelemetry.io/otel/exporters/jaeger v1.10.0 // @grafana/backend-platform
|
||||
go.opentelemetry.io/otel/sdk v1.14.0 // @grafana/backend-platform
|
||||
go.opentelemetry.io/otel/trace v1.14.0 // @grafana/backend-platform
|
||||
go.opentelemetry.io/otel/sdk v1.16.0 // @grafana/backend-platform
|
||||
go.opentelemetry.io/otel/trace v1.16.0 // @grafana/backend-platform
|
||||
golang.org/x/crypto v0.11.0 // @grafana/backend-platform
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // @grafana/alerting-squad-backend
|
||||
golang.org/x/net v0.10.0 // @grafana/grafana-bi-squad
|
||||
golang.org/x/oauth2 v0.7.0 // @grafana/grafana-authnz-team
|
||||
golang.org/x/oauth2 v0.8.0 // @grafana/grafana-authnz-team
|
||||
golang.org/x/sync v0.3.0 // @grafana/alerting-squad-backend
|
||||
golang.org/x/time v0.3.0 // @grafana/backend-platform
|
||||
golang.org/x/tools v0.7.0 // @grafana/grafana-as-code
|
||||
@ -121,7 +127,7 @@ require (
|
||||
gopkg.in/mail.v2 v2.3.1 // @grafana/backend-platform
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // @grafana/alerting-squad-backend
|
||||
xorm.io/builder v0.3.6 // indirect
|
||||
xorm.io/builder v0.3.6 // indirect; @grafana/backend-platform
|
||||
xorm.io/core v0.7.3 // @grafana/backend-platform
|
||||
xorm.io/xorm v0.8.2 // @grafana/alerting-squad-backend
|
||||
)
|
||||
@ -134,14 +140,13 @@ require (
|
||||
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/FZambia/eagle v0.0.2 // indirect
|
||||
github.com/FZambia/eagle v0.1.0 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // @grafana/partner-datasources
|
||||
github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/centrifugal/protocol v0.10.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cheekybits/genny v1.0.0 // indirect
|
||||
github.com/cockroachdb/apd/v2 v2.0.2 // indirect
|
||||
@ -164,7 +169,7 @@ require (
|
||||
github.com/go-openapi/validate v0.22.1 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // @grafana/backend-platform
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
|
||||
github.com/golang/glog v1.0.0 // indirect
|
||||
github.com/golang/glog v1.1.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // @grafana/backend-platform
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
@ -175,7 +180,7 @@ require (
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-msgpack v0.5.5 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect; @grafana/grafana-as-code
|
||||
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
|
||||
github.com/hashicorp/golang-lru v0.6.0 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
@ -220,7 +225,7 @@ require (
|
||||
golang.org/x/text v0.11.0 // @grafana/backend-platform
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect; @grafana/backend-platform
|
||||
google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e // indirect; @grafana/backend-platform
|
||||
)
|
||||
|
||||
require (
|
||||
@ -239,15 +244,15 @@ require (
|
||||
github.com/golang-migrate/migrate/v4 v4.7.0 // @grafana/backend-platform
|
||||
github.com/google/go-github/v45 v45.2.0 // @grafana/grafana-delivery
|
||||
github.com/grafana/codejen v0.0.3 // @grafana/dataviz-squad
|
||||
github.com/grafana/dskit v0.0.0-20230620150242-3dc2113b720d // @grafana/backend-platform
|
||||
github.com/grafana/dskit v0.0.0-20230706162620-5081d8ed53e6 // @grafana/backend-platform
|
||||
github.com/grafana/phlare/api v0.1.4-0.20230426005640-f90edba05413 // @grafana/observability-traces-and-profiling
|
||||
github.com/huandu/xstrings v1.3.1 // @grafana/partner-datasources
|
||||
github.com/jmoiron/sqlx v1.3.5 // @grafana/backend-platform
|
||||
github.com/matryer/is v1.4.0 // @grafana/grafana-as-code
|
||||
github.com/urfave/cli v1.22.12 // @grafana/backend-platform
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.40.0 // @grafana/plugins-platform-backend
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0 // @grafana/plugins-platform-backend
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.15.0 // @grafana/backend-platform
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.14.0 // @grafana/backend-platform
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 // @grafana/backend-platform
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.14.0 // @grafana/backend-platform
|
||||
gocloud.dev v0.25.0 // @grafana/grafana-app-platform-squad
|
||||
)
|
||||
@ -263,7 +268,7 @@ require (
|
||||
github.com/grafana/dataplane/sdata v0.0.6 // @grafana/observability-metrics
|
||||
github.com/grafana/go-mssqldb v0.9.1 // @grafana/grafana-bi-squad
|
||||
github.com/grafana/kindsys v0.0.0-20230508162304-452481b63482 // @grafana/grafana-as-code
|
||||
github.com/grafana/tempo v1.5.1-0.20230524121406-1dc1bfe7085b
|
||||
github.com/grafana/tempo v1.5.1-0.20230524121406-1dc1bfe7085b // @grafana/observability-traces-and-profiling
|
||||
github.com/grafana/thema v0.0.0-20230712153715-375c1b45f3ed // @grafana/grafana-as-code
|
||||
github.com/ory/fosite v0.44.1-0.20230317114349-45a6785cc54f // @grafana/grafana-authnz-team
|
||||
github.com/redis/go-redis/v9 v9.0.2 // @grafana/alerting-squad-backend
|
||||
@ -271,8 +276,17 @@ require (
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // @grafana/grafana-as-code
|
||||
go.opentelemetry.io/contrib/samplers/jaegerremote v0.9.0 // @grafana/backend-platform
|
||||
golang.org/x/mod v0.9.0 // @grafana/backend-platform
|
||||
gopkg.in/square/go-jose.v2 v2.5.2-0.20210529014059-a5c7eec3c614 // @grafana/grafana-authnz-team
|
||||
k8s.io/utils v0.0.0-20230308161112-d77c459e9343 // @grafana/partner-datasources
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // @grafana/grafana-authnz-team
|
||||
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // @grafana/partner-datasources
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/grafana/grafana-apiserver v0.0.0-20230713001719-88a9ed41992d // @grafana/grafana-app-platform-squad
|
||||
go.opentelemetry.io/otel v1.16.0 // @grafana/backend-platform
|
||||
k8s.io/apiserver v0.27.1 // @grafana/grafana-app-platform-squad
|
||||
k8s.io/apimachinery v0.27.1 // @grafana/grafana-app-platform-squad
|
||||
k8s.io/client-go v0.27.1 // @grafana/grafana-app-platform-squad
|
||||
k8s.io/klog/v2 v2.90.1 // @grafana/grafana-app-platform-squad
|
||||
)
|
||||
|
||||
require (
|
||||
@ -281,11 +295,16 @@ require (
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/NYTimes/gziphandler v1.1.1 // indirect
|
||||
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/bmatcuk/doublestar v1.1.1 // indirect
|
||||
github.com/buildkite/yaml v2.1.0+incompatible // indirect
|
||||
github.com/bwmarrin/snowflake v0.3.0 // indirect
|
||||
github.com/centrifugal/protocol v0.10.0 // indirect
|
||||
github.com/cloudflare/circl v1.1.0 // indirect
|
||||
github.com/cockroachdb/errors v1.9.1 // indirect
|
||||
github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f // indirect
|
||||
@ -296,6 +315,7 @@ require (
|
||||
github.com/dave/jennifer v1.5.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.0 // indirect
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
|
||||
github.com/docker/distribution v2.8.1+incompatible // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/drone-runners/drone-runner-docker v1.8.2 // indirect
|
||||
@ -304,9 +324,14 @@ require (
|
||||
github.com/drone/runner-go v1.12.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/ecordell/optgen v0.0.6 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.10.1 // indirect
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/getsentry/sentry-go v0.12.0 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
|
||||
github.com/google/cel-go v0.12.6 // indirect
|
||||
github.com/google/gnostic v0.6.9 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
|
||||
@ -318,7 +343,7 @@ require (
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.2 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/memberlist v0.5.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/invopop/yaml v0.1.0 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
@ -330,6 +355,8 @@ require (
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/onsi/gomega v1.27.6 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.3-0.20220512140940-7b36cea86235 // indirect
|
||||
github.com/ory/go-acc v0.2.6 // indirect
|
||||
@ -341,15 +368,16 @@ require (
|
||||
github.com/perimeterx/marshmallow v1.1.4 // indirect
|
||||
github.com/rivo/uniseg v0.3.4 // indirect
|
||||
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
||||
github.com/rueian/rueidis v0.0.100-go1.18 // indirect
|
||||
github.com/rueian/rueidis v0.0.100 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/segmentio/asm v1.2.0 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/spf13/afero v1.9.2 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/cobra v1.6.1 // indirect
|
||||
github.com/spf13/cobra v1.7.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stoewer/go-strcase v1.2.0 // indirect
|
||||
github.com/subosito/gotenv v1.4.1 // indirect
|
||||
github.com/unknwon/bra v0.0.0-20200517080246-1e3013ecaff8 // indirect
|
||||
github.com/unknwon/com v1.0.1 // indirect
|
||||
@ -357,13 +385,27 @@ require (
|
||||
github.com/weaveworks/promrus v1.2.0 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
github.com/yuin/gopher-lua v1.1.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v0.37.0 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.7 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.5.7 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.16.0 // indirect
|
||||
go.starlark.net v0.0.0-20221020143700-22309ac47eac // indirect
|
||||
go.uber.org/multierr v1.10.0 // indirect
|
||||
go.uber.org/zap v1.24.0 // indirect
|
||||
golang.org/x/term v0.10.0 // indirect
|
||||
gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
k8s.io/klog/v2 v2.90.1 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||
k8s.io/api v0.27.1 // indirect
|
||||
k8s.io/component-base v0.27.1 // indirect
|
||||
k8s.io/kms v0.27.1 // indirect
|
||||
k8s.io/kube-aggregator v0.27.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
@ -388,6 +430,7 @@ require (
|
||||
github.com/blugelabs/ice v1.0.0 // indirect
|
||||
github.com/caio/go-tdigest v3.1.0+incompatible // indirect
|
||||
github.com/chromedp/cdproto v0.0.0-20220208224320-6efb837e6bc2 // indirect
|
||||
github.com/coreos/go-semver v0.3.0 // indirect
|
||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
|
||||
github.com/docker/docker v23.0.4+incompatible // @grafana/grafana-delivery
|
||||
github.com/elazarl/goproxy v0.0.0-20220115173737-adb46da277ac // indirect
|
||||
@ -395,10 +438,10 @@ require (
|
||||
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 // indirect
|
||||
github.com/go-git/gcfg v1.5.0 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.3.1 // indirect
|
||||
github.com/go-logr/logr v1.2.4 // indirect
|
||||
github.com/go-logr/logr v1.2.4 // @grafana/grafana-app-platform-squad
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/google/go-github v17.0.0+incompatible // @grafana/grafana-app-platform-squad
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
|
||||
github.com/hmarr/codeowners v1.1.2 // @grafana/grafana-as-code
|
||||
github.com/imdario/mergo v0.3.13 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
@ -415,8 +458,8 @@ require (
|
||||
github.com/wk8/go-ordered-map v1.0.0 // @grafana/backend-platform
|
||||
github.com/xanzy/ssh-agent v0.3.0 // indirect
|
||||
github.com/xlab/treeprint v1.1.0 // @grafana/observability-traces-and-profiling
|
||||
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.14.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v0.20.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
)
|
||||
|
||||
@ -442,6 +485,8 @@ replace github.com/prometheus/alertmanager => github.com/grafana/prometheus-aler
|
||||
// grpc v1.46.0 removed "WithBalancerName()" API, still in use by weaveworks/commons.
|
||||
replace google.golang.org/grpc => google.golang.org/grpc v1.45.0
|
||||
|
||||
replace google.golang.org/genproto => google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3
|
||||
|
||||
// Use 1.10.6 of pq to avoid a change in 1.10.7 that has certificate validation issues. https://github.com/grafana/grafana/issues/65816
|
||||
replace github.com/lib/pq => github.com/lib/pq v1.10.6
|
||||
|
||||
|
@ -115,4 +115,5 @@ export interface FeatureToggles {
|
||||
transformationsRedesign?: boolean;
|
||||
mlExpressions?: boolean;
|
||||
disableTraceQLStreaming?: boolean;
|
||||
grafanaAPIServer?: boolean;
|
||||
}
|
||||
|
@ -11,8 +11,9 @@ import (
|
||||
"time"
|
||||
|
||||
om "github.com/wk8/go-ordered-map"
|
||||
otlp "go.opentelemetry.io/collector/model/otlp"
|
||||
otelpdata "go.opentelemetry.io/collector/model/pdata"
|
||||
"go.opentelemetry.io/collector/model/otlp"
|
||||
"go.opentelemetry.io/collector/pdata/pcommon"
|
||||
"go.opentelemetry.io/collector/pdata/ptrace"
|
||||
)
|
||||
|
||||
// KeyVal is an ordered map of string to interface
|
||||
@ -142,7 +143,7 @@ func (tc TraceContext) KeyVal() *KeyVal {
|
||||
|
||||
// Traces wraps the otel traces model.
|
||||
type Traces struct {
|
||||
otelpdata.Traces
|
||||
ptrace.Traces
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals Traces model.
|
||||
@ -163,12 +164,12 @@ func (t Traces) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
// SpanSlice unpacks Traces entity into a slice of Spans.
|
||||
func (t Traces) SpanSlice() []otelpdata.Span {
|
||||
spans := make([]otelpdata.Span, 0)
|
||||
func (t Traces) SpanSlice() []ptrace.Span {
|
||||
spans := make([]ptrace.Span, 0)
|
||||
rss := t.ResourceSpans()
|
||||
for i := 0; i < rss.Len(); i++ {
|
||||
rs := rss.At(i)
|
||||
ilss := rs.InstrumentationLibrarySpans()
|
||||
ilss := rs.ScopeSpans()
|
||||
for j := 0; j < ilss.Len(); j++ {
|
||||
s := ilss.At(j).Spans()
|
||||
for si := 0; si < s.Len(); si++ {
|
||||
@ -180,7 +181,7 @@ func (t Traces) SpanSlice() []otelpdata.Span {
|
||||
}
|
||||
|
||||
// SpanToKeyVal returns KeyVal representation of a Span.
|
||||
func SpanToKeyVal(s otelpdata.Span) *KeyVal {
|
||||
func SpanToKeyVal(s ptrace.Span) *KeyVal {
|
||||
kv := NewKeyVal()
|
||||
if s.StartTimestamp() > 0 {
|
||||
KeyValAdd(kv, "timestamp", s.StartTimestamp().AsTime().String())
|
||||
@ -194,7 +195,7 @@ func SpanToKeyVal(s otelpdata.Span) *KeyVal {
|
||||
KeyValAdd(kv, "span_kind", s.Kind().String())
|
||||
KeyValAdd(kv, "name", s.Name())
|
||||
KeyValAdd(kv, "parent_spanID", s.ParentSpanID().HexString())
|
||||
s.Attributes().Range(func(k string, v otelpdata.AttributeValue) bool {
|
||||
s.Attributes().Range(func(k string, v pcommon.Value) bool {
|
||||
KeyValAdd(kv, "attr_"+k, fmt.Sprintf("%v", v))
|
||||
return true
|
||||
})
|
||||
|
@ -5,9 +5,18 @@ const (
|
||||
All string = "all"
|
||||
// BackgroundServices includes all Grafana services that run in the background
|
||||
BackgroundServices string = "background-services"
|
||||
// CertGenerator generates certificates for grafana-apiserver
|
||||
CertGenerator string = "cert-generator"
|
||||
// GrafanaAPIServer is the Kubertenes API server for Grafana Resources
|
||||
GrafanaAPIServer string = "grafana-apiserver"
|
||||
)
|
||||
|
||||
// dependencyMap defines Module Targets => Dependencies
|
||||
var dependencyMap = map[string][]string{
|
||||
BackgroundServices: {},
|
||||
|
||||
CertGenerator: {},
|
||||
GrafanaAPIServer: {CertGenerator},
|
||||
|
||||
All: {BackgroundServices},
|
||||
}
|
||||
|
@ -3,11 +3,13 @@ package modules
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/dskit/modules"
|
||||
"github.com/grafana/dskit/services"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/systemd"
|
||||
)
|
||||
@ -35,9 +37,14 @@ type service struct {
|
||||
moduleManager *modules.Manager
|
||||
serviceManager *services.Manager
|
||||
serviceMap map[string]services.Service
|
||||
|
||||
features *featuremgmt.FeatureManager
|
||||
}
|
||||
|
||||
func ProvideService(cfg *setting.Cfg) *service {
|
||||
func ProvideService(
|
||||
cfg *setting.Cfg,
|
||||
features *featuremgmt.FeatureManager,
|
||||
) *service {
|
||||
logger := log.New("modules")
|
||||
|
||||
return &service{
|
||||
@ -47,6 +54,8 @@ func ProvideService(cfg *setting.Cfg) *service {
|
||||
|
||||
moduleManager: modules.NewManager(logger),
|
||||
serviceMap: map[string]services.Service{},
|
||||
|
||||
features: features,
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,6 +63,11 @@ func ProvideService(cfg *setting.Cfg) *service {
|
||||
func (m *service) Init(_ context.Context) error {
|
||||
var err error
|
||||
|
||||
if err = m.processFeatureFlags(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.log.Debug("Initializing module manager", "targets", m.targets)
|
||||
for mod, targets := range dependencyMap {
|
||||
if err := m.moduleManager.AddDependency(mod, targets...); err != nil {
|
||||
return err
|
||||
@ -93,6 +107,7 @@ func (m *service) Run(ctx context.Context) error {
|
||||
listener := newServiceListener(m.log, m)
|
||||
m.serviceManager.AddListener(listener)
|
||||
|
||||
m.log.Debug("Starting module service manager")
|
||||
// wait until a service fails or stop signal was received
|
||||
err := m.serviceManager.StartAsync(ctx)
|
||||
if err != nil {
|
||||
@ -149,3 +164,31 @@ func (m *service) RegisterInvisibleModule(name string, initFn func() (services.S
|
||||
func (m *service) IsModuleEnabled(name string) bool {
|
||||
return stringsContain(m.targets, name)
|
||||
}
|
||||
|
||||
// processFeatureFlags adds or removes targets based on feature flags.
|
||||
func (m *service) processFeatureFlags() error {
|
||||
// add GrafanaAPIServer to targets if feature is enabled
|
||||
if m.features.IsEnabled(featuremgmt.FlagGrafanaAPIServer) {
|
||||
m.targets = append(m.targets, GrafanaAPIServer)
|
||||
}
|
||||
|
||||
if !m.features.IsEnabled(featuremgmt.FlagGrafanaAPIServer) {
|
||||
// error if GrafanaAPIServer is in targets
|
||||
for _, t := range m.targets {
|
||||
if t == GrafanaAPIServer {
|
||||
return fmt.Errorf("feature flag %s is disabled, but target %s is still enabled", featuremgmt.FlagGrafanaAPIServer, GrafanaAPIServer)
|
||||
}
|
||||
}
|
||||
|
||||
// error if GrafanaAPIServer is a dependency of a target
|
||||
for parent, targets := range dependencyMap {
|
||||
for _, t := range targets {
|
||||
if t == GrafanaAPIServer && m.IsModuleEnabled(parent) {
|
||||
return fmt.Errorf("feature flag %s is disabled, but target %s is enabled with dependency on %s", featuremgmt.FlagGrafanaAPIServer, parent, GrafanaAPIServer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -3,9 +3,11 @@ package registry
|
||||
import (
|
||||
"github.com/grafana/dskit/services"
|
||||
|
||||
"github.com/grafana/grafana-apiserver/pkg/certgenerator"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/modules"
|
||||
"github.com/grafana/grafana/pkg/server/backgroundsvcs"
|
||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
||||
)
|
||||
|
||||
type Registry interface{}
|
||||
@ -17,12 +19,16 @@ type registry struct {
|
||||
|
||||
func ProvideRegistry(
|
||||
moduleManager modules.Manager,
|
||||
apiServer grafanaapiserver.Service,
|
||||
backgroundServiceRunner *backgroundsvcs.BackgroundServiceRunner,
|
||||
certGenerator certgenerator.ServiceInterface,
|
||||
) *registry {
|
||||
return newRegistry(
|
||||
log.New("modules.registry"),
|
||||
moduleManager,
|
||||
apiServer,
|
||||
backgroundServiceRunner,
|
||||
certGenerator,
|
||||
)
|
||||
}
|
||||
|
||||
@ -41,7 +47,6 @@ func newRegistry(logger log.Logger, moduleManager modules.Manager, svcs ...servi
|
||||
})
|
||||
}
|
||||
|
||||
// Register module targets
|
||||
logger.Debug("Registering module", "name", modules.All)
|
||||
r.moduleManager.RegisterModule(modules.All, nil)
|
||||
|
||||
|
@ -9,31 +9,8 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/modules"
|
||||
"github.com/grafana/grafana/pkg/server/backgroundsvcs"
|
||||
)
|
||||
|
||||
func TestProvideRegistry(t *testing.T) {
|
||||
var registeredInvisibleModules []string
|
||||
var registeredModules []string
|
||||
|
||||
moduleManager := &modules.MockModuleManager{
|
||||
RegisterModuleFunc: func(name string, initFn func() (services.Service, error)) {
|
||||
registeredModules = append(registeredModules, name)
|
||||
},
|
||||
RegisterInvisibleModuleFunc: func(name string, initFn func() (services.Service, error)) {
|
||||
registeredInvisibleModules = append(registeredInvisibleModules, name)
|
||||
},
|
||||
}
|
||||
|
||||
svcRegistry := backgroundsvcs.NewBackgroundServiceRegistry()
|
||||
svcRunner := backgroundsvcs.ProvideBackgroundServiceRunner(svcRegistry)
|
||||
|
||||
r := ProvideRegistry(moduleManager, svcRunner)
|
||||
require.NotNil(t, r)
|
||||
require.Equal(t, []string{modules.BackgroundServices}, registeredInvisibleModules)
|
||||
require.Equal(t, []string{modules.All}, registeredModules)
|
||||
}
|
||||
|
||||
func TestNewRegistry(t *testing.T) {
|
||||
var registeredInvisibleModules []string
|
||||
var registeredModules []string
|
||||
|
@ -44,6 +44,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/apikey/apikeyimpl"
|
||||
"github.com/grafana/grafana/pkg/services/auth/jwt"
|
||||
"github.com/grafana/grafana/pkg/services/authn/authnimpl"
|
||||
"github.com/grafana/grafana/pkg/services/certgenerator"
|
||||
"github.com/grafana/grafana/pkg/services/cleanup"
|
||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||
"github.com/grafana/grafana/pkg/services/contexthandler/authproxy"
|
||||
@ -64,6 +65,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/folder/folderimpl"
|
||||
"github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/grpcserver"
|
||||
grpccontext "github.com/grafana/grafana/pkg/services/grpcserver/context"
|
||||
"github.com/grafana/grafana/pkg/services/grpcserver/interceptors"
|
||||
@ -204,6 +206,7 @@ var wireBasicSet = wire.NewSet(
|
||||
wire.Bind(new(httpclient.Provider), new(*sdkhttpclient.Provider)),
|
||||
serverlock.ProvideService,
|
||||
annotationsimpl.ProvideCleanupService,
|
||||
certgenerator.WireSet,
|
||||
wire.Bind(new(annotations.Cleaner), new(*annotationsimpl.CleanupServiceImpl)),
|
||||
cleanup.ProvideService,
|
||||
shorturlimpl.ProvideService,
|
||||
@ -355,6 +358,7 @@ var wireBasicSet = wire.NewSet(
|
||||
wire.Bind(new(tag.Service), new(*tagimpl.Service)),
|
||||
authnimpl.ProvideService,
|
||||
supportbundlesimpl.ProvideService,
|
||||
grafanaapiserver.WireSet,
|
||||
oasimpl.ProvideService,
|
||||
wire.Bind(new(oauthserver.OAuth2Server), new(*oasimpl.OAuth2ServiceImpl)),
|
||||
loggermw.Provide,
|
||||
|
14
pkg/services/certgenerator/service.go
Normal file
14
pkg/services/certgenerator/service.go
Normal file
@ -0,0 +1,14 @@
|
||||
package certgenerator
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/grafana/grafana/pkg/modules"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
|
||||
"github.com/grafana/grafana-apiserver/pkg/certgenerator"
|
||||
)
|
||||
|
||||
func ProvideService(cfg *setting.Cfg) (*certgenerator.Service, error) {
|
||||
return certgenerator.CreateService(modules.CertGenerator, filepath.Join(cfg.DataPath, "k8s"))
|
||||
}
|
11
pkg/services/certgenerator/wire.go
Normal file
11
pkg/services/certgenerator/wire.go
Normal file
@ -0,0 +1,11 @@
|
||||
package certgenerator
|
||||
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
"github.com/grafana/grafana-apiserver/pkg/certgenerator"
|
||||
)
|
||||
|
||||
var WireSet = wire.NewSet(
|
||||
ProvideService,
|
||||
wire.Bind(new(certgenerator.ServiceInterface), new(*certgenerator.Service)),
|
||||
)
|
@ -115,3 +115,9 @@ func (mw mockWriter) Before(web.BeforeFunc) {}
|
||||
func (mw mockWriter) Push(target string, opts *http.PushOptions) error {
|
||||
return nil
|
||||
}
|
||||
func (mw mockWriter) CloseNotify() <-chan bool {
|
||||
return make(<-chan bool)
|
||||
}
|
||||
func (mw mockWriter) Unwrap() http.ResponseWriter {
|
||||
return mw
|
||||
}
|
||||
|
@ -661,5 +661,12 @@ var (
|
||||
FrontendOnly: true,
|
||||
Owner: grafanaObservabilityTracesAndProfilingSquad,
|
||||
},
|
||||
{
|
||||
Name: "grafanaAPIServer",
|
||||
Description: "Enable Kubernetes API Server for Grafana resources",
|
||||
Stage: FeatureStageExperimental,
|
||||
FrontendOnly: false,
|
||||
Owner: grafanaAppPlatformSquad,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
@ -96,3 +96,4 @@ awsDatasourcesTempCredentials,experimental,@grafana/aws-datasources,false,false,
|
||||
transformationsRedesign,experimental,@grafana/observability-metrics,false,false,false,true
|
||||
mlExpressions,experimental,@grafana/alerting-squad,false,false,false,false
|
||||
disableTraceQLStreaming,experimental,@grafana/observability-traces-and-profiling,false,false,false,true
|
||||
grafanaAPIServer,experimental,@grafana/grafana-app-platform-squad,false,false,false,false
|
||||
|
|
@ -394,4 +394,8 @@ const (
|
||||
// FlagDisableTraceQLStreaming
|
||||
// Disables the option to stream the response of TraceQL queries of the Tempo data source
|
||||
FlagDisableTraceQLStreaming = "disableTraceQLStreaming"
|
||||
|
||||
// FlagGrafanaAPIServer
|
||||
// Enable Kubernetes API Server for Grafana resources
|
||||
FlagGrafanaAPIServer = "grafanaAPIServer"
|
||||
)
|
||||
|
50
pkg/services/grafana-apiserver/log.go
Normal file
50
pkg/services/grafana-apiserver/log.go
Normal file
@ -0,0 +1,50 @@
|
||||
package grafanaapiserver
|
||||
|
||||
import (
|
||||
"cuelang.org/go/pkg/strings"
|
||||
"github.com/go-logr/logr"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
)
|
||||
|
||||
var _ logr.LogSink = (*logAdapter)(nil)
|
||||
|
||||
type logAdapter struct {
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func newLogAdapter() *logAdapter {
|
||||
return &logAdapter{log: log.New("k8s.apiserver")}
|
||||
}
|
||||
|
||||
func (l *logAdapter) WithName(name string) logr.LogSink {
|
||||
l.log = l.log.New("name", name)
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *logAdapter) WithValues(keysAndValues ...interface{}) logr.LogSink {
|
||||
l.log = l.log.New(keysAndValues...)
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *logAdapter) Init(_ logr.RuntimeInfo) {
|
||||
// TODO: shrug emoji
|
||||
}
|
||||
|
||||
func (l *logAdapter) Enabled(level int) bool {
|
||||
return level <= 5
|
||||
}
|
||||
|
||||
func (l *logAdapter) Info(level int, msg string, keysAndValues ...interface{}) {
|
||||
msg = strings.TrimSpace(msg)
|
||||
if level < 1 {
|
||||
l.log.Info(msg, keysAndValues...)
|
||||
return
|
||||
}
|
||||
l.log.Debug(msg, keysAndValues...)
|
||||
}
|
||||
|
||||
func (l *logAdapter) Error(err error, msg string, keysAndValues ...interface{}) {
|
||||
msg = strings.TrimSpace(msg)
|
||||
l.log.Error(msg, keysAndValues...)
|
||||
}
|
248
pkg/services/grafana-apiserver/service.go
Normal file
248
pkg/services/grafana-apiserver/service.go
Normal file
@ -0,0 +1,248 @@
|
||||
package grafanaapiserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
"cuelang.org/go/pkg/strings"
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/grafana/dskit/services"
|
||||
grafanaapiserveroptions "github.com/grafana/grafana-apiserver/pkg/cmd/server/options"
|
||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||
"k8s.io/apiserver/pkg/authentication/request/headerrequest"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/endpoints/responsewriter"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/server/options"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"github.com/grafana/grafana-apiserver/pkg/certgenerator"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/infra/appcontext"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/modules"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultAPIServerHost = "https://" + certgenerator.DefaultAPIServerIp + ":6443"
|
||||
)
|
||||
|
||||
var (
|
||||
_ Service = (*service)(nil)
|
||||
_ RestConfigProvider = (*service)(nil)
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
services.NamedService
|
||||
}
|
||||
|
||||
type RestConfigProvider interface {
|
||||
GetRestConfig() *rest.Config
|
||||
}
|
||||
|
||||
type service struct {
|
||||
*services.BasicService
|
||||
|
||||
restConfig *rest.Config
|
||||
rr routing.RouteRegister
|
||||
|
||||
handler web.Handler
|
||||
dataPath string
|
||||
stopCh chan struct{}
|
||||
stoppedCh chan error
|
||||
}
|
||||
|
||||
func ProvideService(cfg *setting.Cfg, rr routing.RouteRegister) (*service, error) {
|
||||
s := &service{
|
||||
rr: rr,
|
||||
dataPath: path.Join(cfg.DataPath, "k8s"),
|
||||
stopCh: make(chan struct{}),
|
||||
}
|
||||
|
||||
s.BasicService = services.NewBasicService(s.start, s.running, nil).WithName(modules.GrafanaAPIServer)
|
||||
|
||||
s.rr.Group("/k8s", func(k8sRoute routing.RouteRegister) {
|
||||
handler := func(c *contextmodel.ReqContext) {
|
||||
if s.handler == nil {
|
||||
c.Resp.WriteHeader(404)
|
||||
_, _ = c.Resp.Write([]byte("Not found"))
|
||||
return
|
||||
}
|
||||
|
||||
if handle, ok := s.handler.(func(c *contextmodel.ReqContext)); ok {
|
||||
handle(c)
|
||||
return
|
||||
}
|
||||
}
|
||||
k8sRoute.Any("/", middleware.ReqSignedIn, handler)
|
||||
k8sRoute.Any("/*", middleware.ReqSignedIn, handler)
|
||||
})
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *service) GetRestConfig() *rest.Config {
|
||||
return s.restConfig
|
||||
}
|
||||
|
||||
func (s *service) start(ctx context.Context) error {
|
||||
logger := logr.New(newLogAdapter())
|
||||
logger.V(9)
|
||||
klog.SetLoggerWithOptions(logger, klog.ContextualLogger(true))
|
||||
|
||||
o := grafanaapiserveroptions.NewGrafanaAPIServerOptions(os.Stdout, os.Stderr)
|
||||
o.RecommendedOptions.SecureServing.BindPort = 6443
|
||||
o.RecommendedOptions.Authentication.RemoteKubeConfigFileOptional = true
|
||||
o.RecommendedOptions.Authorization.RemoteKubeConfigFileOptional = true
|
||||
o.RecommendedOptions.Authorization.AlwaysAllowPaths = []string{"*"}
|
||||
o.RecommendedOptions.Authorization.AlwaysAllowGroups = []string{user.SystemPrivilegedGroup, "grafana"}
|
||||
o.RecommendedOptions.Etcd = nil
|
||||
// TODO: setting CoreAPI to nil currently segfaults in grafana-apiserver
|
||||
o.RecommendedOptions.CoreAPI = nil
|
||||
|
||||
// Get the util to get the paths to pre-generated certs
|
||||
certUtil := certgenerator.CertUtil{
|
||||
K8sDataPath: s.dataPath,
|
||||
}
|
||||
|
||||
o.RecommendedOptions.SecureServing.BindAddress = net.ParseIP(certgenerator.DefaultAPIServerIp)
|
||||
o.RecommendedOptions.SecureServing.ServerCert.CertKey = options.CertKey{
|
||||
CertFile: certUtil.APIServerCertFile(),
|
||||
KeyFile: certUtil.APIServerKeyFile(),
|
||||
}
|
||||
|
||||
if err := o.Complete(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := o.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serverConfig, err := o.Config()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rootCert, err := certUtil.GetK8sCACert()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authenticator, err := newAuthenticator(rootCert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serverConfig.GenericConfig.Authentication.Authenticator = authenticator
|
||||
|
||||
server, err := serverConfig.Complete().New(genericapiserver.NewEmptyDelegate())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.restConfig = server.GenericAPIServer.LoopbackClientConfig
|
||||
err = s.writeKubeConfiguration(s.restConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
prepared := server.GenericAPIServer.PrepareRun()
|
||||
|
||||
s.handler = func(c *contextmodel.ReqContext) {
|
||||
req := c.Req
|
||||
req.URL.Path = strings.TrimPrefix(req.URL.Path, "/k8s")
|
||||
if req.URL.Path == "" {
|
||||
req.URL.Path = "/"
|
||||
}
|
||||
ctx := req.Context()
|
||||
signedInUser := appcontext.MustUser(ctx)
|
||||
|
||||
req.Header.Set("X-Remote-User", strconv.FormatInt(signedInUser.UserID, 10))
|
||||
req.Header.Set("X-Remote-Group", "grafana")
|
||||
req.Header.Set("X-Remote-Extra-token-name", signedInUser.Name)
|
||||
req.Header.Set("X-Remote-Extra-org-role", string(signedInUser.OrgRole))
|
||||
req.Header.Set("X-Remote-Extra-org-id", strconv.FormatInt(signedInUser.OrgID, 10))
|
||||
req.Header.Set("X-Remote-Extra-user-id", strconv.FormatInt(signedInUser.UserID, 10))
|
||||
|
||||
resp := responsewriter.WrapForHTTP1Or2(c.Resp)
|
||||
prepared.GenericAPIServer.Handler.ServeHTTP(resp, req)
|
||||
}
|
||||
|
||||
go func() {
|
||||
s.stoppedCh <- prepared.Run(s.stopCh)
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *service) running(ctx context.Context) error {
|
||||
select {
|
||||
case err := <-s.stoppedCh:
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case <-ctx.Done():
|
||||
close(s.stopCh)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *service) writeKubeConfiguration(restConfig *rest.Config) error {
|
||||
clusters := make(map[string]*clientcmdapi.Cluster)
|
||||
clusters["default-cluster"] = &clientcmdapi.Cluster{
|
||||
Server: restConfig.Host,
|
||||
InsecureSkipTLSVerify: true,
|
||||
}
|
||||
|
||||
contexts := make(map[string]*clientcmdapi.Context)
|
||||
contexts["default-context"] = &clientcmdapi.Context{
|
||||
Cluster: "default-cluster",
|
||||
Namespace: "default",
|
||||
AuthInfo: "default",
|
||||
}
|
||||
|
||||
authinfos := make(map[string]*clientcmdapi.AuthInfo)
|
||||
authinfos["default"] = &clientcmdapi.AuthInfo{
|
||||
Token: restConfig.BearerToken,
|
||||
}
|
||||
|
||||
clientConfig := clientcmdapi.Config{
|
||||
Kind: "Config",
|
||||
APIVersion: "v1",
|
||||
Clusters: clusters,
|
||||
Contexts: contexts,
|
||||
CurrentContext: "default-context",
|
||||
AuthInfos: authinfos,
|
||||
}
|
||||
return clientcmd.WriteToFile(clientConfig, path.Join(s.dataPath, "grafana.kubeconfig"))
|
||||
}
|
||||
|
||||
func newAuthenticator(cert *x509.Certificate) (authenticator.Request, error) {
|
||||
reqHeaderOptions := options.RequestHeaderAuthenticationOptions{
|
||||
UsernameHeaders: []string{"X-Remote-User"},
|
||||
GroupHeaders: []string{"X-Remote-Group"},
|
||||
ExtraHeaderPrefixes: []string{"X-Remote-Extra-"},
|
||||
}
|
||||
|
||||
requestHeaderAuthenticator, err := headerrequest.New(
|
||||
reqHeaderOptions.UsernameHeaders,
|
||||
reqHeaderOptions.GroupHeaders,
|
||||
reqHeaderOptions.ExtraHeaderPrefixes,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return requestHeaderAuthenticator, nil
|
||||
}
|
11
pkg/services/grafana-apiserver/wire.go
Normal file
11
pkg/services/grafana-apiserver/wire.go
Normal file
@ -0,0 +1,11 @@
|
||||
package grafanaapiserver
|
||||
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
var WireSet = wire.NewSet(
|
||||
ProvideService,
|
||||
wire.Bind(new(Service), new(*service)),
|
||||
wire.Bind(new(RestConfigProvider), new(*service)),
|
||||
)
|
@ -15,7 +15,7 @@
|
||||
package tempo
|
||||
|
||||
import (
|
||||
"go.opentelemetry.io/collector/model/pdata"
|
||||
"go.opentelemetry.io/collector/pdata/ptrace"
|
||||
)
|
||||
|
||||
// Some of the keys used to represent OTLP constructs as tags or annotations in other formats.
|
||||
@ -55,9 +55,9 @@ const (
|
||||
|
||||
// StatusCodeFromHTTP takes an HTTP status code and return the appropriate OpenTelemetry status code
|
||||
// See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#status
|
||||
func StatusCodeFromHTTP(httpStatusCode int) pdata.StatusCode {
|
||||
func StatusCodeFromHTTP(httpStatusCode int) ptrace.StatusCode {
|
||||
if httpStatusCode >= 100 && httpStatusCode < 399 {
|
||||
return pdata.StatusCodeUnset
|
||||
return ptrace.StatusCodeUnset
|
||||
}
|
||||
return pdata.StatusCodeError
|
||||
return ptrace.StatusCodeError
|
||||
}
|
||||
|
@ -7,7 +7,10 @@ import (
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"go.opentelemetry.io/collector/model/pdata"
|
||||
semconv "go.opentelemetry.io/collector/model/semconv/v1.8.0"
|
||||
"go.opentelemetry.io/collector/pdata/pcommon"
|
||||
"go.opentelemetry.io/collector/pdata/ptrace"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.15.0"
|
||||
)
|
||||
|
||||
type KeyValue struct {
|
||||
@ -27,7 +30,7 @@ type TraceReference struct {
|
||||
Tags []*KeyValue `json:"tags"`
|
||||
}
|
||||
|
||||
func TraceToFrame(td pdata.Traces) (*data.Frame, error) {
|
||||
func TraceToFrame(td ptrace.Traces) (*data.Frame, error) {
|
||||
// In open telemetry format the spans are grouped first by resource/service they originated in and inside that
|
||||
// resource they are grouped by the instrumentation library which created them.
|
||||
|
||||
@ -80,9 +83,9 @@ func TraceToFrame(td pdata.Traces) (*data.Frame, error) {
|
||||
}
|
||||
|
||||
// resourceSpansToRows processes all the spans for a particular resource/service
|
||||
func resourceSpansToRows(rs pdata.ResourceSpans) ([][]interface{}, error) {
|
||||
func resourceSpansToRows(rs ptrace.ResourceSpans) ([][]interface{}, error) {
|
||||
resource := rs.Resource()
|
||||
ilss := rs.InstrumentationLibrarySpans()
|
||||
ilss := rs.ScopeSpans()
|
||||
|
||||
if resource.Attributes().Len() == 0 || ilss.Len() == 0 {
|
||||
return [][]interface{}{}, nil
|
||||
@ -100,7 +103,7 @@ func resourceSpansToRows(rs pdata.ResourceSpans) ([][]interface{}, error) {
|
||||
|
||||
for j := 0; j < spans.Len(); j++ {
|
||||
span := spans.At(j)
|
||||
row, err := spanToSpanRow(span, ils.InstrumentationLibrary(), resource)
|
||||
row, err := spanToSpanRow(span, ils.Scope(), resource)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -113,7 +116,7 @@ func resourceSpansToRows(rs pdata.ResourceSpans) ([][]interface{}, error) {
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
func spanToSpanRow(span pdata.Span, libraryTags pdata.InstrumentationLibrary, resource pdata.Resource) ([]interface{}, error) {
|
||||
func spanToSpanRow(span ptrace.Span, libraryTags pcommon.InstrumentationScope, resource pcommon.Resource) ([]interface{}, error) {
|
||||
// If the id representation changed from hexstring to something else we need to change the transformBase64IDToHexString in the frontend code
|
||||
traceID := span.TraceID().HexString()
|
||||
traceID = strings.TrimPrefix(traceID, strings.Repeat("0", 16))
|
||||
@ -175,7 +178,7 @@ func spanToSpanRow(span pdata.Span, libraryTags pdata.InstrumentationLibrary, re
|
||||
}, nil
|
||||
}
|
||||
|
||||
func resourceToProcess(resource pdata.Resource) (string, []*KeyValue) {
|
||||
func resourceToProcess(resource pcommon.Resource) (string, []*KeyValue) {
|
||||
attrs := resource.Attributes()
|
||||
serviceName := ResourceNoServiceName
|
||||
if attrs.Len() == 0 {
|
||||
@ -183,8 +186,8 @@ func resourceToProcess(resource pdata.Resource) (string, []*KeyValue) {
|
||||
}
|
||||
|
||||
tags := make([]*KeyValue, 0, attrs.Len()-1)
|
||||
attrs.Range(func(key string, attr pdata.AttributeValue) bool {
|
||||
if key == semconv.AttributeServiceName {
|
||||
attrs.Range(func(key string, attr pcommon.Value) bool {
|
||||
if attribute.Key(key) == semconv.ServiceNameKey {
|
||||
serviceName = attr.StringVal()
|
||||
}
|
||||
tags = append(tags, &KeyValue{Key: key, Value: getAttributeVal(attr)})
|
||||
@ -194,44 +197,44 @@ func resourceToProcess(resource pdata.Resource) (string, []*KeyValue) {
|
||||
return serviceName, tags
|
||||
}
|
||||
|
||||
func getAttributeVal(attr pdata.AttributeValue) interface{} {
|
||||
func getAttributeVal(attr pcommon.Value) interface{} {
|
||||
switch attr.Type() {
|
||||
case pdata.AttributeValueTypeString:
|
||||
case pcommon.ValueTypeString:
|
||||
return attr.StringVal()
|
||||
case pdata.AttributeValueTypeInt:
|
||||
case pcommon.ValueTypeInt:
|
||||
return attr.IntVal()
|
||||
case pdata.AttributeValueTypeBool:
|
||||
case pcommon.ValueTypeBool:
|
||||
return attr.BoolVal()
|
||||
case pdata.AttributeValueTypeDouble:
|
||||
case pcommon.ValueTypeDouble:
|
||||
return attr.DoubleVal()
|
||||
case pdata.AttributeValueTypeMap, pdata.AttributeValueTypeArray:
|
||||
case pcommon.ValueTypeMap, pcommon.ValueTypeSlice:
|
||||
return attr.AsString()
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func getSpanTags(span pdata.Span) []*KeyValue {
|
||||
func getSpanTags(span ptrace.Span) []*KeyValue {
|
||||
var tags []*KeyValue
|
||||
span.Attributes().Range(func(key string, attr pdata.AttributeValue) bool {
|
||||
span.Attributes().Range(func(key string, attr pcommon.Value) bool {
|
||||
tags = append(tags, &KeyValue{Key: key, Value: getAttributeVal(attr)})
|
||||
return true
|
||||
})
|
||||
return tags
|
||||
}
|
||||
|
||||
func getSpanKind(spanKind pdata.SpanKind) string {
|
||||
func getSpanKind(spanKind ptrace.SpanKind) string {
|
||||
var tagStr string
|
||||
switch spanKind {
|
||||
case pdata.SpanKindClient:
|
||||
case ptrace.SpanKindClient:
|
||||
tagStr = string(OpenTracingSpanKindClient)
|
||||
case pdata.SpanKindServer:
|
||||
case ptrace.SpanKindServer:
|
||||
tagStr = string(OpenTracingSpanKindServer)
|
||||
case pdata.SpanKindProducer:
|
||||
case ptrace.SpanKindProducer:
|
||||
tagStr = string(OpenTracingSpanKindProducer)
|
||||
case pdata.SpanKindConsumer:
|
||||
case ptrace.SpanKindConsumer:
|
||||
tagStr = string(OpenTracingSpanKindConsumer)
|
||||
case pdata.SpanKindInternal:
|
||||
case ptrace.SpanKindInternal:
|
||||
tagStr = string(OpenTracingSpanKindInternal)
|
||||
default:
|
||||
return ""
|
||||
@ -240,14 +243,11 @@ func getSpanKind(spanKind pdata.SpanKind) string {
|
||||
return tagStr
|
||||
}
|
||||
|
||||
func getTraceState(traceState pdata.TraceState) string {
|
||||
if traceState != pdata.TraceStateEmpty {
|
||||
return string(traceState)
|
||||
}
|
||||
return ""
|
||||
func getTraceState(traceState ptrace.TraceState) string {
|
||||
return string(traceState)
|
||||
}
|
||||
|
||||
func spanEventsToLogs(events pdata.SpanEventSlice) []*TraceLog {
|
||||
func spanEventsToLogs(events ptrace.SpanEventSlice) []*TraceLog {
|
||||
if events.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
@ -259,10 +259,10 @@ func spanEventsToLogs(events pdata.SpanEventSlice) []*TraceLog {
|
||||
if event.Name() != "" {
|
||||
fields = append(fields, &KeyValue{
|
||||
Key: TagMessage,
|
||||
Value: event.Name(),
|
||||
Value: attribute.StringValue(event.Name()),
|
||||
})
|
||||
}
|
||||
event.Attributes().Range(func(key string, attr pdata.AttributeValue) bool {
|
||||
event.Attributes().Range(func(key string, attr pcommon.Value) bool {
|
||||
fields = append(fields, &KeyValue{Key: key, Value: getAttributeVal(attr)})
|
||||
return true
|
||||
})
|
||||
@ -290,7 +290,7 @@ func spanLinksToReferences(links pdata.SpanLinkSlice) []*TraceReference {
|
||||
spanId := link.SpanID().HexString()
|
||||
|
||||
tags := make([]*KeyValue, 0, link.Attributes().Len())
|
||||
link.Attributes().Range(func(key string, attr pdata.AttributeValue) bool {
|
||||
link.Attributes().Range(func(key string, attr pcommon.Value) bool {
|
||||
tags = append(tags, &KeyValue{Key: key, Value: getAttributeVal(attr)})
|
||||
return true
|
||||
})
|
||||
|
@ -5,15 +5,17 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"go.opentelemetry.io/collector/pdata/pcommon"
|
||||
"go.opentelemetry.io/collector/pdata/ptrace"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/stretchr/testify/require"
|
||||
otlp "go.opentelemetry.io/collector/model/otlp"
|
||||
"go.opentelemetry.io/collector/model/pdata"
|
||||
"go.opentelemetry.io/collector/model/otlp"
|
||||
)
|
||||
|
||||
func TestTraceToFrame(t *testing.T) {
|
||||
t.Run("should transform tempo protobuf response into dataframe", func(t *testing.T) {
|
||||
// For what ever reason you cannot easily create pdata.Traces for the TraceToFrame from something more readable
|
||||
// For what ever reason you cannot easily create ptrace.Traces for the TraceToFrame from something more readable
|
||||
// like json. You could tediously create the structures manually using all the setters for everything or use
|
||||
// https://github.com/grafana/tempo/tree/master/pkg/tempopb to create the protobuf structs from something like
|
||||
// json. At the moment just saving some real tempo proto response into file and loading was the easiest and
|
||||
@ -60,14 +62,14 @@ func TestTraceToFrame(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var index int
|
||||
otTrace.ResourceSpans().RemoveIf(func(rsp pdata.ResourceSpans) bool {
|
||||
rsp.InstrumentationLibrarySpans().RemoveIf(func(sp pdata.InstrumentationLibrarySpans) bool {
|
||||
sp.Spans().RemoveIf(func(span pdata.Span) bool {
|
||||
otTrace.ResourceSpans().RemoveIf(func(rsp ptrace.ResourceSpans) bool {
|
||||
rsp.ScopeSpans().RemoveIf(func(sp ptrace.ScopeSpans) bool {
|
||||
sp.Spans().RemoveIf(func(span ptrace.Span) bool {
|
||||
if index == 0 {
|
||||
span.SetTraceID(pdata.NewTraceID([16]byte{0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7}))
|
||||
span.SetTraceID(pcommon.NewTraceID([16]byte{0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7}))
|
||||
}
|
||||
if index == 1 {
|
||||
span.SetTraceID(pdata.NewTraceID([16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7}))
|
||||
span.SetTraceID(pcommon.NewTraceID([16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7}))
|
||||
}
|
||||
index++
|
||||
return false
|
||||
|
@ -19,11 +19,15 @@ import (
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"k8s.io/apiserver/pkg/endpoints/responsewriter"
|
||||
)
|
||||
|
||||
var (
|
||||
_ http.ResponseWriter = &responseWriter{}
|
||||
_ http.Hijacker = &responseWriter{}
|
||||
_ http.ResponseWriter = &responseWriter{}
|
||||
_ http.Hijacker = &responseWriter{}
|
||||
_ responsewriter.CloseNotifierFlusher = &responseWriter{}
|
||||
_ responsewriter.UserProvidedDecorator = &responseWriter{}
|
||||
)
|
||||
|
||||
// ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about
|
||||
@ -41,6 +45,10 @@ type ResponseWriter interface {
|
||||
// Before allows for a function to be called before the ResponseWriter has been written to. This is
|
||||
// useful for setting headers or any other operations that must happen before a response has been written.
|
||||
Before(BeforeFunc)
|
||||
|
||||
// Needed to support https://pkg.go.dev/k8s.io/apiserver@v0.27.2/pkg/endpoints/responsewriter#WrapForHTTP1Or2
|
||||
http.CloseNotifier
|
||||
Unwrap() http.ResponseWriter
|
||||
}
|
||||
|
||||
// BeforeFunc is a function that is called before the ResponseWriter has been written to.
|
||||
@ -139,3 +147,16 @@ func (rw *responseWriter) Flush() {
|
||||
flusher.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
func (rw *responseWriter) Unwrap() http.ResponseWriter {
|
||||
return rw.ResponseWriter
|
||||
}
|
||||
|
||||
func (rw *responseWriter) CloseNotify() <-chan bool {
|
||||
notifier, ok := rw.ResponseWriter.(http.CloseNotifier)
|
||||
if ok {
|
||||
return notifier.CloseNotify()
|
||||
}
|
||||
// TODO: this is probably not the right thing to do here
|
||||
return make(<-chan bool)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user