mirror of
https://github.com/grafana/grafana.git
synced 2024-11-21 00:24:46 -06:00
Core: Remove thema and kindsys dependencies (#84499)
* Move some thema code inside grafana * Use new codegen instead of thema for core kinds * Replace TS generator * Use new generator for go types * Remove thema from oapi generator * Remove thema from generators * Don't use kindsys/thema for core kinds * Remove kindsys/thema from plugins * Remove last thema related * Remove most of cuectx and move utils_ts into codegen. It also deletes wire dependency * Merge plugins generators * Delete thema dependency 🎉 * Fix CODEOWNERS * Fix package name * Fix TS output names * More path fixes * Fix mod codeowners * Use original plugin's name * Remove kindsys dependency 🎉 * Modify oapi schema and create an apply function to fix elasticsearch errors * cue.mod was deleted by mistake * Fix TS panels * sort imports * Fixing elasticsearch output * Downgrade oapi-codegen library * Update output ts files * More fixes * Restore old elasticsearch generated file and skip its generation. Remove core imports into plugins * More lint fixes * Add codeowners * restore embed.go file * Fix embed.go
This commit is contained in:
parent
856e410480
commit
473898e47c
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@ -624,10 +624,10 @@ playwright.config.ts @grafana/plugins-platform-frontend
|
||||
# Kind system and code generation
|
||||
embed.go @grafana/grafana-as-code
|
||||
/pkg/kinds/ @grafana/grafana-as-code
|
||||
/pkg/cuectx/ @grafana/grafana-as-code
|
||||
/pkg/registry/ @grafana/grafana-as-code
|
||||
/pkg/registry/apis/ @grafana/grafana-app-platform-squad
|
||||
/pkg/codegen/ @grafana/grafana-as-code
|
||||
/pkg/codegen/generators @grafana/grafana-as-code
|
||||
/pkg/kinds/*/*_gen.go @grafana/grafana-as-code
|
||||
/pkg/registry/schemas/ @grafana/grafana-as-code
|
||||
/public/app/plugins/*gen.go @grafana/grafana-as-code
|
||||
|
2
embed.go
2
embed.go
@ -6,5 +6,5 @@ import (
|
||||
|
||||
// CueSchemaFS embeds all schema-related CUE files in the Grafana project.
|
||||
//
|
||||
//go:embed cue.mod/module.cue kinds/*.cue kinds/*/*.cue packages/grafana-schema/src/common/*.cue public/app/plugins/*/*/*.cue public/app/plugins/*/*/plugin.json
|
||||
//go:embed cue.mod/module.cue
|
||||
var CueSchemaFS embed.FS
|
||||
|
48
go.mod
48
go.mod
@ -15,9 +15,6 @@ replace cuelang.org/go => github.com/grafana/cue v0.0.0-20230926092038-971951014
|
||||
// import that instead of v0.X even though v0.X is newer.
|
||||
replace github.com/prometheus/prometheus => github.com/prometheus/prometheus v0.49.0
|
||||
|
||||
// The v0.120.0 is needed for now to be compatible with grafana/thema.
|
||||
replace github.com/getkin/kin-openapi => github.com/getkin/kin-openapi v0.120.0
|
||||
|
||||
require (
|
||||
cloud.google.com/go/storage v1.36.0 // @grafana/backend-platform
|
||||
cuelang.org/go v0.6.0-0.dev // @grafana/grafana-as-code
|
||||
@ -90,7 +87,6 @@ require (
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect
|
||||
github.com/urfave/cli/v2 v2.25.0 // @grafana/backend-platform
|
||||
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/pdata v1.0.1 // @grafana/backend-platform
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.49.0 // @grafana/grafana-operator-experience-squad
|
||||
@ -103,7 +99,7 @@ require (
|
||||
golang.org/x/oauth2 v0.16.0 // @grafana/grafana-authnz-team
|
||||
golang.org/x/sync v0.6.0 // @grafana/alerting-squad-backend
|
||||
golang.org/x/time v0.5.0 // @grafana/backend-platform
|
||||
golang.org/x/tools v0.17.0 // indirect; @grafana/grafana-as-code
|
||||
golang.org/x/tools v0.17.0 // @grafana/grafana-as-code
|
||||
gonum.org/v1/gonum v0.12.0 // @grafana/observability-metrics
|
||||
google.golang.org/api v0.155.0 // @grafana/backend-platform
|
||||
google.golang.org/grpc v1.62.1 // @grafana/plugins-platform-backend
|
||||
@ -113,7 +109,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 // @grafana/backend-platform
|
||||
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
|
||||
)
|
||||
@ -135,7 +131,7 @@ require (
|
||||
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
|
||||
github.com/deepmap/oapi-codegen v1.12.4 // indirect
|
||||
github.com/deepmap/oapi-codegen v1.13.0 // @grafana/grafana-as-code
|
||||
github.com/dennwc/varint v1.0.0 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
@ -160,12 +156,12 @@ require (
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/flatbuffers v23.5.26+incompatible // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // @grafana/backend-platform
|
||||
github.com/gorilla/mux v1.8.0 // @grafana/backend-platform
|
||||
github.com/gorilla/mux v1.8.1 // @grafana/backend-platform
|
||||
github.com/grafana/grafana-google-sdk-go v0.1.0 // @grafana/partner-datasources
|
||||
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 // @grafana/alerting-squad
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect; @grafana/alerting-squad
|
||||
github.com/hashicorp/go-sockaddr v1.0.6 // indirect
|
||||
github.com/hashicorp/golang-lru v0.6.0 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
@ -177,7 +173,7 @@ require (
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
|
||||
github.com/mattetti/filebuffer v1.0.1 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/miekg/dns v1.1.57 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
@ -224,7 +220,6 @@ require (
|
||||
github.com/bufbuild/connect-go v1.10.0 // @grafana/observability-traces-and-profiling
|
||||
github.com/dlmiddlecote/sqlstats v1.0.2 // @grafana/backend-platform
|
||||
github.com/drone/drone-cli v1.6.1 // @grafana/grafana-release-guild
|
||||
github.com/getkin/kin-openapi v0.120.0 // @grafana/grafana-operator-experience-squad
|
||||
github.com/golang-migrate/migrate/v4 v4.7.0 // @grafana/backend-platform
|
||||
github.com/google/go-github v17.0.0+incompatible // @grafana/grafana-release-guild
|
||||
github.com/google/go-github/v45 v45.2.0 // @grafana/grafana-release-guild
|
||||
@ -250,11 +245,9 @@ require (
|
||||
github.com/go-jose/go-jose/v3 v3.0.3 // @grafana/grafana-authnz-team
|
||||
github.com/grafana/dataplane/examples v0.0.1 // @grafana/observability-metrics
|
||||
github.com/grafana/dataplane/sdata v0.0.7 // @grafana/observability-metrics
|
||||
github.com/grafana/kindsys v0.0.0-20230508162304-452481b63482 // @grafana/grafana-as-code
|
||||
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/microsoft/go-mssqldb v1.6.1-0.20240214161942-b65008136246 // @grafana/grafana-bi-squad
|
||||
github.com/redis/go-redis/v9 v9.0.2 // @grafana/alerting-squad-backend
|
||||
github.com/redis/go-redis/v9 v9.1.0 // @grafana/alerting-squad-backend
|
||||
go.opentelemetry.io/contrib/samplers/jaegerremote v0.18.0 // @grafana/backend-platform
|
||||
golang.org/x/mod v0.14.0 // @grafana/backend-platform
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // @grafana/partner-datasources
|
||||
@ -298,9 +291,6 @@ require (
|
||||
github.com/bwmarrin/snowflake v0.3.0 // @grafan/grafana-app-platform-squad
|
||||
github.com/centrifugal/protocol v0.10.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/cockroachdb/errors v1.9.1 // indirect
|
||||
github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f // indirect
|
||||
github.com/cockroachdb/redact v1.1.3 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
@ -315,7 +305,6 @@ require (
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/getsentry/sentry-go v0.12.0 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gogo/googleapis v1.4.1 // indirect
|
||||
@ -328,13 +317,12 @@ require (
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/grafana/regexp v0.0.0-20221123153739-15dc172cd2db // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // @grafana/alerting-squad-backend
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect; @grafana/alerting-squad-backend
|
||||
github.com/hashicorp/memberlist v0.5.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/invopop/yaml v0.2.0 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-ieproxy v0.0.3 // indirect
|
||||
@ -350,7 +338,6 @@ require (
|
||||
github.com/redis/rueidis v1.0.16 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.3.4 // indirect
|
||||
github.com/rogpeppe/go-internal v1.11.0 // 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
|
||||
@ -427,7 +414,7 @@ require (
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/labstack/echo/v4 v4.10.2 // indirect
|
||||
github.com/labstack/echo/v4 v4.11.1 // indirect
|
||||
github.com/labstack/gommon v0.4.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/mschoch/smat v0.2.0 // indirect
|
||||
@ -440,7 +427,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
|
||||
github.com/go-errors/errors v1.4.2 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79 // @grafana/backend-platform
|
||||
@ -486,9 +472,19 @@ require (
|
||||
|
||||
require github.com/jackc/pgx/v5 v5.5.5 // @grafana/oss-big-tent
|
||||
|
||||
require github.com/getkin/kin-openapi v0.120.0 // @grafana/grafana-as-code
|
||||
|
||||
require (
|
||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/bytedance/sonic v1.9.1 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/gin-gonic/gin v1.9.1 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/invopop/jsonschema v0.12.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
@ -500,7 +496,13 @@ require (
|
||||
github.com/jcmturner/goidentity/v6 v6.0.1 // indirect
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/yudai/pp v2.0.1+incompatible // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
)
|
||||
|
||||
// Use fork of crewjam/saml with fixes for some issues until changes get merged into upstream
|
||||
|
155
go.sum
155
go.sum
@ -1181,7 +1181,6 @@ gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zum
|
||||
git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
|
||||
github.com/99designs/basicauth-go v0.0.0-20160802081356-2a93ba0f464d/go.mod h1:3cARGAK9CfW3HoxCy1a0G4TKrdiKke8ftOMEOHyySYs=
|
||||
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e/go.mod h1:Xa6lInWHNQnuWoF0YPSsx+INFA9qk7/7pTjwb3PInkY=
|
||||
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
||||
github.com/Azure/azure-amqp-common-go/v3 v3.2.1/go.mod h1:O6X1iYHP7s2x7NjUKsXVhkwWrQhxrd+d8/3rRadj4CI=
|
||||
github.com/Azure/azure-amqp-common-go/v3 v3.2.2/go.mod h1:O6X1iYHP7s2x7NjUKsXVhkwWrQhxrd+d8/3rRadj4CI=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
|
||||
@ -1278,8 +1277,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
|
||||
github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo=
|
||||
github.com/Code-Hex/go-generics-cache v1.3.1 h1:i8rLwyhoyhaerr7JpjtYjJZUcCbWOdiYO3fZXLiEC4g=
|
||||
github.com/Code-Hex/go-generics-cache v1.3.1/go.mod h1:qxcC9kRVrct9rHeiYpFWSoW1vxyillCVzX13KZG8dl4=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
@ -1291,7 +1288,6 @@ github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob
|
||||
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
|
||||
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU=
|
||||
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
|
||||
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
@ -1320,7 +1316,6 @@ github.com/RoaringBitmap/real-roaring-datasets v0.0.0-20190726190000-eb7c87156f7
|
||||
github.com/RoaringBitmap/roaring v0.9.1/go.mod h1:h1B7iIUOmnAeb5ytYMvnHJwxMc6LUrwBnzXWRuqTQUc=
|
||||
github.com/RoaringBitmap/roaring v0.9.4 h1:ckvZSX5gwCRaJYBNe7syNawCU5oruY9gQmjXlp4riwo=
|
||||
github.com/RoaringBitmap/roaring v0.9.4/go.mod h1:icnadbWcNyfEHlYdr+tDlOTih1Bf/h+rzPpv4sbomAA=
|
||||
github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
@ -1329,7 +1324,6 @@ github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f/go.mod h1:f3H
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
|
||||
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
|
||||
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||
github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY=
|
||||
github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk=
|
||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||
@ -1447,7 +1441,6 @@ github.com/aws/smithy-go v1.11.2 h1:eG/N+CcUMAvsdffgMvjMKwfyDzIkjM6pfxMJ8Mzc6mE=
|
||||
github.com/aws/smithy-go v1.11.2/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM=
|
||||
github.com/axiomhq/hyperloglog v0.0.0-20191112132149-a4c4c47bc57f h1:y06x6vGnFYfXUoVMbrcP1Uzpj4JG01eB5vRps9G8agM=
|
||||
github.com/axiomhq/hyperloglog v0.0.0-20191112132149-a4c4c47bc57f/go.mod h1:2stgcRjl6QmW+gU2h5E7BQXg4HU0gzxKWDuT5HviN9s=
|
||||
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
|
||||
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
|
||||
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
|
||||
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
|
||||
@ -1493,10 +1486,10 @@ github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl
|
||||
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
||||
github.com/bsm/ginkgo/v2 v2.5.0 h1:aOAnND1T40wEdAtkGSkvSICWeQ8L3UASX7YVCqQx+eQ=
|
||||
github.com/bsm/ginkgo/v2 v2.5.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w=
|
||||
github.com/bsm/gomega v1.20.0 h1:JhAwLmtRzXFTx2AkALSLa8ijZafntmhSoU63Ok18Uq8=
|
||||
github.com/bsm/gomega v1.20.0/go.mod h1:JifAceMQ4crZIWYUKrlGcmbN3bqHogVTADMD2ATsbwk=
|
||||
github.com/bsm/ginkgo/v2 v2.9.5 h1:rtVBYPs3+TC5iLUVOis1B9tjLTup7Cj5IfzosKtvTJ0=
|
||||
github.com/bsm/ginkgo/v2 v2.9.5/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
|
||||
github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/bufbuild/connect-go v1.10.0 h1:QAJ3G9A1OYQW2Jbk3DeoJbkCxuKArrvZgDt47mjdTbg=
|
||||
github.com/bufbuild/connect-go v1.10.0/go.mod h1:CAIePUgkDR5pAFaylSMtNK45ANQjp9JvpluG20rhpV8=
|
||||
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
|
||||
@ -1508,6 +1501,9 @@ github.com/buildkite/yaml v2.1.0+incompatible/go.mod h1:UoU8vbcwu1+vjZq01+KrpSeL
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
|
||||
github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/caio/go-tdigest v3.1.0+incompatible h1:uoVMJ3Q5lXmVLCCqaMGHLBWnbGoN6Lpu7OAUPR60cds=
|
||||
github.com/caio/go-tdigest v3.1.0+incompatible/go.mod h1:sHQM/ubZStBUmF1WbB8FAm8q9GjDajLC5T7ydxE3JHI=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
@ -1530,6 +1526,9 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89 h1:aPflPkRFkVwbW6dmcVqfgwp1i+UWGFH6VgR1Jim5Ygc=
|
||||
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
|
||||
github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs=
|
||||
@ -1570,15 +1569,7 @@ github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b80
|
||||
github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw=
|
||||
github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
|
||||
github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8=
|
||||
github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk=
|
||||
github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f h1:6jduT9Hfc0njg5jJ1DdKCFPdMBrp/mdZfCpa5h+WM74=
|
||||
github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
|
||||
github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ=
|
||||
github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/containerd v1.3.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
@ -1621,16 +1612,14 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
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/dchest/uniuri v0.0.0-20160212164326-8902c56451e9/go.mod h1:GgB8SF9nRG+GqaDtLcwJZsQFhcogVCJ79j4EdT0c2V4=
|
||||
github.com/deepmap/oapi-codegen v1.12.4 h1:pPmn6qI9MuOtCz82WY2Xaw46EQjgvxednXXrP7g5Q2s=
|
||||
github.com/deepmap/oapi-codegen v1.12.4/go.mod h1:3lgHGMu6myQ2vqbbTXH2H1o4eXFTGnFiDaOaKKl5yas=
|
||||
github.com/deepmap/oapi-codegen v1.13.0 h1:cnFHelhsRQbYvanCUAbRSn/ZpkUb1HPRlQcu8YqSORQ=
|
||||
github.com/deepmap/oapi-codegen v1.13.0/go.mod h1:Amy7tbubKY9qkZOXqymI3Z6xSbndmu+atMJheLdyg44=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
|
||||
github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU=
|
||||
github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE=
|
||||
github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA=
|
||||
github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY=
|
||||
github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
|
||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 h1:y7y0Oa6UawqTFPCDw9JG6pdKt4F9pAhHv0B7FMGaGD0=
|
||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
|
||||
@ -1681,7 +1670,6 @@ github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ=
|
||||
github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
|
||||
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
|
||||
github.com/elazarl/goproxy v0.0.0-20230731152917-f99041a5c027 h1:1L0aalTpPz7YlMxETKpmQoWMBkeiuorElZIXoNmgiPE=
|
||||
github.com/elazarl/goproxy v0.0.0-20230731152917-f99041a5c027/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
|
||||
@ -1719,11 +1707,9 @@ github.com/envoyproxy/protoc-gen-validate v1.0.1/go.mod h1:0vj8bNkYbSTNS2PIyH87K
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
|
||||
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
@ -1732,7 +1718,6 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF
|
||||
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
@ -1754,27 +1739,23 @@ github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyT
|
||||
github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk=
|
||||
github.com/fullstorydev/grpchan v1.1.1 h1:heQqIJlAv5Cnks9a70GRL2EJke6QQoUB25VGR6TZQas=
|
||||
github.com/fullstorydev/grpchan v1.1.1/go.mod h1:f4HpiV8V6htfY/K44GWV1ESQzHBTq7DinhzqQ95lpgc=
|
||||
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||
github.com/gchaincl/sqlhooks v1.3.0 h1:yKPXxW9a5CjXaVf2HkQn6wn7TZARvbAOAelr3H8vK2Y=
|
||||
github.com/gchaincl/sqlhooks v1.3.0/go.mod h1:9BypXnereMT0+Ys8WGWHqzgkkOfHIhyeUCqXC24ra34=
|
||||
github.com/getkin/kin-openapi v0.120.0 h1:MqJcNJFrMDFNc07iwE8iFC5eT2k/NPUFDIpNeiZv8Jg=
|
||||
github.com/getkin/kin-openapi v0.120.0/go.mod h1:PCWw/lfBrJY4HcdqE3jj+QFkaFK8ABoqo7PvqVhXXqw=
|
||||
github.com/getsentry/sentry-go v0.12.0 h1:era7g0re5iY13bHSdN/xMkyV+5zZppjRVQhZrXCaEIk=
|
||||
github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew=
|
||||
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
|
||||
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/gin-gonic/gin v1.7.3/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
|
||||
github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks=
|
||||
github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY=
|
||||
@ -1817,7 +1798,6 @@ 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.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A=
|
||||
github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4=
|
||||
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
|
||||
github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY=
|
||||
github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo=
|
||||
github.com/go-openapi/analysis v0.21.5/go.mod h1:25YcZosX9Lwz2wBsrFrrsL8bmjjXdlyP6zsr2AMy29M=
|
||||
@ -1881,10 +1861,18 @@ github.com/go-openapi/validate v0.23.0/go.mod h1:EeiAZ5bmpSIOJV1WLfyYF9qp/B1ZgSa
|
||||
github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
|
||||
github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
||||
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||
github.com/go-resty/resty/v2 v2.9.1/go.mod h1:4/GYJVjh9nhkhGR6AUNW3XhpDYNUr+Uvy9gV/VGZIy4=
|
||||
@ -1961,11 +1949,9 @@ github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM=
|
||||
github.com/gogo/status v1.1.1 h1:DuHXlSFHNKqTQ+/ACf5Vs6r4X/dH2EgIzR9Vr+H65kg=
|
||||
github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci7oU=
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
@ -2033,7 +2019,6 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219 h1:utua3L2IbQJmauC5IXdEA547bcoU5dozgQAfc8Onsg4=
|
||||
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
||||
github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
@ -2163,9 +2148,11 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
|
||||
github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
@ -2190,8 +2177,6 @@ github.com/grafana/gofpdf v0.0.0-20231002120153-857cc45be447 h1:jxJJ5z0GxqhWFbQU
|
||||
github.com/grafana/gofpdf v0.0.0-20231002120153-857cc45be447/go.mod h1:IxsY6mns6Q5sAnWcrptrgUrSglTZJXH/kXr9nbpb/9I=
|
||||
github.com/grafana/grafana-aws-sdk v0.25.0 h1:XNi3iA/C/KPArmVbQfbwKQROaIotd38nCRjNE6P1UP0=
|
||||
github.com/grafana/grafana-aws-sdk v0.25.0/go.mod h1:3zghFF6edrxn0d6k6X9HpGZXDH+VfA+MwD2Pc/9X0ec=
|
||||
github.com/grafana/grafana-azure-sdk-go v1.13.1 h1:zYw5kNYf4zS4mG+yuB0Izn1Z4rsrPdLLivWF2JHUXPk=
|
||||
github.com/grafana/grafana-azure-sdk-go v1.13.1/go.mod h1:SAlwLdEuox4vw8ZaeQwnepYXnhznnQQdstJbcw8LH68=
|
||||
github.com/grafana/grafana-azure-sdk-go/v2 v2.0.1 h1:a/zb8uX7EvmS2YAFbYPyGEnZP8jMp7WppAm05Qtunok=
|
||||
github.com/grafana/grafana-azure-sdk-go/v2 v2.0.1/go.mod h1:nW7pr7POOGafhyOrq8V0ouXBcXTmpRCer3sDAfeSV+Y=
|
||||
github.com/grafana/grafana-google-sdk-go v0.1.0 h1:LKGY8z2DSxKjYfr2flZsWgTRTZ6HGQbTqewE3JvRaNA=
|
||||
@ -2209,8 +2194,6 @@ github.com/grafana/grafana/pkg/promlib v0.0.2 h1:yy7iwHlHH7Hl/n7ix9+RPIKg3CcKCAS
|
||||
github.com/grafana/grafana/pkg/promlib v0.0.2/go.mod h1:3El4NlsfALz8QQCbEGHGFvJUG+538QLMuALRhZ3pcoo=
|
||||
github.com/grafana/grafana/pkg/util/xorm v0.0.1 h1:72QZjxWIWpSeOF8ob4aMV058kfgZyeetkAB8dmeti2o=
|
||||
github.com/grafana/grafana/pkg/util/xorm v0.0.1/go.mod h1:eNfbB9f2jM8o9RfwqwjY8SYm5tvowJ8Ly+iE4P9rXII=
|
||||
github.com/grafana/kindsys v0.0.0-20230508162304-452481b63482 h1:1YNoeIhii4UIIQpCPU+EXidnqf449d0C3ZntAEt4KSo=
|
||||
github.com/grafana/kindsys v0.0.0-20230508162304-452481b63482/go.mod h1:GNcfpy5+SY6RVbNGQW264gC0r336Dm+0zgQ5vt6+M8Y=
|
||||
github.com/grafana/prometheus-alertmanager v0.25.1-0.20240208102907-e82436ce63e6 h1:CBm0rwLCPDyarg9/bHJ50rBLYmyMDoyCWpgRMITZhdA=
|
||||
github.com/grafana/prometheus-alertmanager v0.25.1-0.20240208102907-e82436ce63e6/go.mod h1:8Ia/R3urPmbzJ8OsdvmZvIprDwvwmYCmUbwBL+jlPOE=
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.6 h1:nEdZ8louGAplSvIJi1HVp7kWvFvdiiYg3COLlTwJiFo=
|
||||
@ -2226,8 +2209,6 @@ github.com/grafana/sqlds/v3 v3.2.0 h1:WXuYEaFfiCvgm8kK2ixx44/zAEjFzCylA2+RF3GBqZ
|
||||
github.com/grafana/sqlds/v3 v3.2.0/go.mod h1:kH0WuHUR3j0Q7IEymbm2JiaPckUhRCbqjV9ajaBAnmM=
|
||||
github.com/grafana/tempo v1.5.1-0.20230524121406-1dc1bfe7085b h1:mDlkqgTEJuK7vjPG44f3ZMtId5AAYLWHvBVbiGqIOOQ=
|
||||
github.com/grafana/tempo v1.5.1-0.20230524121406-1dc1bfe7085b/go.mod h1:UK7kTP5llPeRcGBOe5mm4QTNTd0k/mAqTVSOFdDH6AU=
|
||||
github.com/grafana/thema v0.0.0-20230712153715-375c1b45f3ed h1:TMtHc+B0SSNw2in6Ro1dAiBYSPRp4NzKgndFDfupt18=
|
||||
github.com/grafana/thema v0.0.0-20230712153715-375c1b45f3ed/go.mod h1:3zLJnssFRPCnebCBRlq53t5LgYv9P1mbj0XMozZMTww=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
|
||||
@ -2340,7 +2321,6 @@ github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw
|
||||
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
|
||||
github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE=
|
||||
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
@ -2351,7 +2331,6 @@ github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
@ -2368,11 +2347,6 @@ github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
|
||||
github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
|
||||
github.com/ionos-cloud/sdk-go/v6 v6.1.10 h1:3815Q2Hw/wc4cJ8wD7bwfsmDsdfIEp80B7BQMj0YP2w=
|
||||
github.com/ionos-cloud/sdk-go/v6 v6.1.10/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k=
|
||||
github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI=
|
||||
github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0=
|
||||
github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk=
|
||||
github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
|
||||
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
|
||||
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
|
||||
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
@ -2477,15 +2451,9 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
||||
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
|
||||
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||
github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8=
|
||||
github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE=
|
||||
github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE=
|
||||
github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro=
|
||||
github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
||||
@ -2494,8 +2462,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4=
|
||||
github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE=
|
||||
github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
@ -2505,7 +2471,6 @@ github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHU
|
||||
github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
|
||||
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
@ -2533,16 +2498,16 @@ github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLg
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y=
|
||||
github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
|
||||
github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
github.com/labstack/echo/v4 v4.11.1 h1:dEpLU2FLg4UVmvCGPuk/APjlH6GDpbEPti61srUUUs4=
|
||||
github.com/labstack/echo/v4 v4.11.1/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ=
|
||||
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
||||
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
|
||||
github.com/leesper/go_rng v0.0.0-20190531154944-a612b043e353 h1:X/79QL0b4YJVO5+OsPH9rF2u428CIrGL/jLmPsoOQQ4=
|
||||
github.com/leesper/go_rng v0.0.0-20190531154944-a612b043e353/go.mod h1:N0SVk0uhy+E1PZ3C9ctsPRlvOPAFPkCNlcPBDkt0N3U=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
@ -2583,7 +2548,6 @@ github.com/mattetti/filebuffer v1.0.1 h1:gG7pyfnSIZCxdoKq+cPa8T0hhYtD9NxCdI4D7PT
|
||||
github.com/mattetti/filebuffer v1.0.1/go.mod h1:YdMURNDOttIiruleeVr6f56OrMc+MydEnTcXwtkxNVs=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
@ -2600,7 +2564,6 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
@ -2611,22 +2574,19 @@ github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APP
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI=
|
||||
github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
|
||||
github.com/maxatome/go-testdeep v1.12.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM=
|
||||
github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
|
||||
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
|
||||
github.com/microsoft/go-mssqldb v1.6.1-0.20240214161942-b65008136246 h1:KT4vTYcHqj5C5hMK5kSpyAk7MnFqfHVWLL4VqMq66S8=
|
||||
github.com/microsoft/go-mssqldb v1.6.1-0.20240214161942-b65008136246/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
@ -2703,7 +2663,6 @@ github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
|
||||
github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de h1:D5x39vF5KCwKQaw+OC9ZPiLVHXz3UFw2+psEX+gYcto=
|
||||
github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de/go.mod h1:kJun4WP5gFuHZgRjZUWWuH1DTxCtxbHDOIJsudS8jzY=
|
||||
github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
|
||||
@ -2746,7 +2705,6 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
@ -2819,6 +2777,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
|
||||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM=
|
||||
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
|
||||
@ -2834,8 +2794,6 @@ github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuR
|
||||
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
|
||||
github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
||||
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
|
||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
||||
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||
@ -2924,8 +2882,8 @@ github.com/prometheus/prometheus v0.49.0/go.mod h1:aDogiyqmv3aBIWDb5z5Sdcxuuf2BO
|
||||
github.com/protocolbuffers/txtpbfmt v0.0.0-20220428173112-74888fd59c2b h1:zd/2RNzIRkoGGMjE+YIsZ85CnDIz672JK2F3Zl4vux4=
|
||||
github.com/protocolbuffers/txtpbfmt v0.0.0-20220428173112-74888fd59c2b/go.mod h1:KjY0wibdYKc4DYkerHSbguaf3JeIPGhNJBp2BNiFH78=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE=
|
||||
github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps=
|
||||
github.com/redis/go-redis/v9 v9.1.0 h1:137FnGdk+EQdCbye1FW+qOEcY5S+SpY9T0NiuqvtfMY=
|
||||
github.com/redis/go-redis/v9 v9.1.0/go.mod h1:urWj3He21Dj5k4TK1y59xH8Uj6ATueP8AH1cY3lZl4c=
|
||||
github.com/redis/rueidis v1.0.16 h1:ieB3AqZe9GcuTWZL8PFu1Mfn+pfqjBZAJEZh7zOcwSI=
|
||||
github.com/redis/rueidis v1.0.16/go.mod h1:8B+r5wdnjwK3lTFml5VtxjzGOQAC+5UmujoD12pDrEo=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
@ -2944,7 +2902,6 @@ github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
@ -2971,7 +2928,6 @@ github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21 h1:yWfiTPwYxB0l5fGMhl/G+liULugVIHD9AU77iNLrURQ=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
|
||||
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
|
||||
github.com/scottlepp/go-duck v0.0.15 h1:qrSF3pXlXAA4a7uxAfLYajqXLkeBjv8iW1wPdSfkMj0=
|
||||
github.com/scottlepp/go-duck v0.0.15/go.mod h1:GL+hHuKdueJRrFCduwBc7A7TQk+Tetc5BPXPVtduihY=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
|
||||
@ -2981,7 +2937,6 @@ github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
||||
github.com/segmentio/encoding v0.3.6 h1:E6lVLyDPseWEulBmCmAKPanDd3jiyGDo5gMcugCRwZQ=
|
||||
github.com/segmentio/encoding v0.3.6/go.mod h1:n0JeuIqEQrQoPDGsjo8UNd1iA0U8d8+oHAA4E3G3OxM=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
github.com/shoenig/test v0.6.6/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||
@ -3079,19 +3034,19 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1
|
||||
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/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ua-parser/uap-go v0.0.0-20211112212520-00c877edfe0f h1:A+MmlgpvrHLeUP8dkBVn4Pnf5Bp5Yk2OALm7SEJLLE8=
|
||||
github.com/ua-parser/uap-go v0.0.0-20211112212520-00c877edfe0f/go.mod h1:OBcG9bn7sHtXgarhUEb3OfCnNsgtGnkVf41ilSZ3K3E=
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
|
||||
github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=
|
||||
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
|
||||
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/unknwon/bra v0.0.0-20200517080246-1e3013ecaff8 h1:aVGB3YnaS/JNfOW3tiHIlmNmTDg618va+eT0mVomgyI=
|
||||
github.com/unknwon/bra v0.0.0-20200517080246-1e3013ecaff8/go.mod h1:fVle4kNr08ydeohzYafr20oZzbAkhQT39gKK/pFQ5M4=
|
||||
github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs=
|
||||
@ -3104,15 +3059,11 @@ github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk=
|
||||
github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA=
|
||||
github.com/urfave/cli/v2 v2.25.0 h1:ykdZKuQey2zq0yin/l7JOm9Mh+pg72ngYMeB0ABn6q8=
|
||||
github.com/urfave/cli/v2 v2.25.0/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
|
||||
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
github.com/vectordotdev/go-datemath v0.1.1-0.20220323213446-f3954d0b18ae h1:oyiy3uBj1F4O3AaFh7hUGBrJjAssJhKyAbwxtkslxqo=
|
||||
github.com/vectordotdev/go-datemath v0.1.1-0.20220323213446-f3954d0b18ae/go.mod h1:PnwzbSst7KD3vpBzzlntZU5gjVa455Uqa5QPiKSYJzQ=
|
||||
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
|
||||
@ -3145,9 +3096,6 @@ github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRT
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 h1:zzrxE1FKn5ryBNl9eKOeqQ58Y/Qpo3Q9QNxKHX5uzzQ=
|
||||
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2/go.mod h1:hzfGeIUDq/j97IG+FhNqkowIyEcD88LrW6fyU3K3WqY=
|
||||
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
|
||||
github.com/yalue/merged_fs v1.2.2 h1:vXHTpJBluJryju7BBpytr3PDIkzsPMpiEknxVGPhN/I=
|
||||
github.com/yalue/merged_fs v1.2.2/go.mod h1:WqqchfVYQyclV2tnR7wtRhBddzBvLVR83Cjw9BKQw0M=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
|
||||
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
|
||||
@ -3301,6 +3249,9 @@ go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||
gocloud.dev v0.25.0 h1:Y7vDq8xj7SyM848KXf32Krda2e6jQ4CLh/mTeCSqXtk=
|
||||
gocloud.dev v0.25.0/go.mod h1:7HegHVCYZrMiU3IE1qtnzf/vRrDwLYnRNR3EhWX8x9Y=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
@ -3316,7 +3267,6 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
@ -3326,7 +3276,6 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
@ -3441,7 +3390,6 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@ -3452,7 +3400,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@ -3490,7 +3437,6 @@ golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
@ -3622,7 +3568,6 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -3796,7 +3741,6 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@ -3809,14 +3753,12 @@ golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGm
|
||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
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-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
@ -4332,18 +4274,14 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
|
||||
gopkg.in/fsnotify/fsnotify.v1 v1.4.7 h1:XNNYLJHt73EyYiCZi6+xjupS9CpvmiDgjPTAjrBlQbo=
|
||||
gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE=
|
||||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
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.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
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/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk=
|
||||
gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
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/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
@ -4361,7 +4299,6 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
@ -1,7 +0,0 @@
|
||||
package kind
|
||||
|
||||
import "github.com/grafana/kindsys"
|
||||
|
||||
// In each child directory, the set of .cue files with 'package kind'
|
||||
// must be an instance of kindsys.Core - a declaration of a core kind.
|
||||
kindsys.Core
|
157
kinds/gen.go
157
kinds/gen.go
@ -15,37 +15,49 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"cuelang.org/go/cue/errors"
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/cuecontext"
|
||||
"cuelang.org/go/cue/load"
|
||||
"github.com/grafana/codejen"
|
||||
"github.com/grafana/cuetsy"
|
||||
"github.com/grafana/kindsys"
|
||||
|
||||
"github.com/grafana/grafana/pkg/codegen"
|
||||
"github.com/grafana/grafana/pkg/cuectx"
|
||||
)
|
||||
|
||||
// CoreDefParentPath is the path, relative to the repository root, where
|
||||
// each child directory is expected to contain .cue files defining one
|
||||
// Core kind.
|
||||
var CoreDefParentPath = "kinds"
|
||||
|
||||
// TSCoreKindParentPath is the path, relative to the repository root, to the directory that
|
||||
// contains one directory per kind, full of generated TS kind output: types and default consts.
|
||||
var TSCoreKindParentPath = filepath.Join("packages", "grafana-schema", "src", "raw")
|
||||
|
||||
func main() {
|
||||
if len(os.Args) > 1 {
|
||||
fmt.Fprintf(os.Stderr, "plugin thema code generator does not currently accept any arguments\n, got %q", os.Args)
|
||||
fmt.Fprintf(os.Stderr, "code generator does not currently accept any arguments\n, got %q", os.Args)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Core kinds composite code generator. Produces all generated code in
|
||||
// grafana/grafana that derives from core kinds.
|
||||
coreKindsGen := codejen.JennyListWithNamer(func(def kindsys.Kind) string {
|
||||
return def.Props().Common().MachineName
|
||||
coreKindsGen := codejen.JennyListWithNamer(func(def codegen.SchemaForGen) string {
|
||||
return def.Name
|
||||
})
|
||||
|
||||
// All the jennies that comprise the core kinds generator pipeline
|
||||
coreKindsGen.Append(
|
||||
&codegen.GoSpecJenny{},
|
||||
codegen.LatestMajorsOrXJenny(cuectx.TSCoreKindParentPath),
|
||||
&codegen.K8ResourcesJenny{},
|
||||
&codegen.CoreRegistryJenny{},
|
||||
codegen.LatestMajorsOrXJenny(TSCoreKindParentPath),
|
||||
codegen.TSVeneerIndexJenny(filepath.Join("packages", "grafana-schema", "src")),
|
||||
)
|
||||
|
||||
header := codegen.SlashHeaderMapper("kinds/gen.go")
|
||||
coreKindsGen.AddPostprocessors(header)
|
||||
|
||||
ctx := cuecontext.New()
|
||||
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "could not get working directory: %s", err)
|
||||
@ -53,29 +65,15 @@ func main() {
|
||||
}
|
||||
groot := filepath.Dir(cwd)
|
||||
|
||||
rt := cuectx.GrafanaThemaRuntime()
|
||||
var all []kindsys.Kind
|
||||
|
||||
f := os.DirFS(filepath.Join(groot, cuectx.CoreDefParentPath))
|
||||
f := os.DirFS(filepath.Join(groot, CoreDefParentPath))
|
||||
kinddirs := elsedie(fs.ReadDir(f, "."))("error reading core kind fs root directory")
|
||||
for _, kinddir := range kinddirs {
|
||||
if !kinddir.IsDir() {
|
||||
continue
|
||||
}
|
||||
rel := filepath.Join(cuectx.CoreDefParentPath, kinddir.Name())
|
||||
def, err := cuectx.LoadCoreKindDef(rel, rt.Context(), nil)
|
||||
if err != nil {
|
||||
die(fmt.Errorf("%s is not a valid kind: %s", rel, errors.Details(err, nil)))
|
||||
}
|
||||
if def.Properties.MachineName != kinddir.Name() {
|
||||
die(fmt.Errorf("%s: kind's machine name (%s) must equal parent dir name (%s)", rel, def.Properties.Name, kinddir.Name()))
|
||||
}
|
||||
|
||||
all = append(all, elsedie(kindsys.BindCore(rt, def))(rel))
|
||||
all, err := loadCueFiles(ctx, kinddirs)
|
||||
if err != nil {
|
||||
die(err)
|
||||
}
|
||||
|
||||
sort.Slice(all, func(i, j int) bool {
|
||||
return nameFor(all[i].Props()) < nameFor(all[j].Props())
|
||||
return all[i].Name < all[j].Name
|
||||
})
|
||||
|
||||
jfs, err := coreKindsGen.GenerateFS(all...)
|
||||
@ -83,22 +81,12 @@ func main() {
|
||||
die(fmt.Errorf("core kinddirs codegen failed: %w", err))
|
||||
}
|
||||
|
||||
commfsys := elsedie(genCommon(filepath.Join(groot, "pkg", "kindsys")))("common schemas failed")
|
||||
commfsys := elsedie(genCommon(ctx, groot))("common schemas failed")
|
||||
commfsys = elsedie(commfsys.Map(header))("failed gen header on common fsys")
|
||||
if err = jfs.Merge(commfsys); err != nil {
|
||||
die(err)
|
||||
}
|
||||
|
||||
// Merging k8 resources
|
||||
rawResources, err := genRawResources(kinddirs)
|
||||
if err != nil {
|
||||
die(err)
|
||||
}
|
||||
|
||||
if err = jfs.Merge(rawResources); err != nil {
|
||||
die(err)
|
||||
}
|
||||
|
||||
if _, set := os.LookupEnv("CODEGEN_VERIFY"); set {
|
||||
if err = jfs.Verify(context.Background(), groot); err != nil {
|
||||
die(fmt.Errorf("generated code is out of sync with inputs:\n%s\nrun `make gen-cue` to regenerate", err))
|
||||
@ -108,43 +96,28 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func nameFor(m kindsys.SomeKindProperties) string {
|
||||
switch x := m.(type) {
|
||||
case kindsys.CoreProperties:
|
||||
return x.Name
|
||||
case kindsys.CustomProperties:
|
||||
return x.Name
|
||||
case kindsys.ComposableProperties:
|
||||
return x.Name
|
||||
default:
|
||||
// unreachable so long as all the possibilities in KindProperties have switch branches
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
type dummyCommonJenny struct{}
|
||||
|
||||
func genCommon(kp string) (*codejen.FS, error) {
|
||||
func genCommon(ctx *cue.Context, groot string) (*codejen.FS, error) {
|
||||
fsys := codejen.NewFS()
|
||||
|
||||
// kp := filepath.Join("pkg", "kindsys")
|
||||
path := filepath.Join("packages", "grafana-schema", "src", "common")
|
||||
// Grab all the common_* files from kindsys and load them in
|
||||
dfsys := os.DirFS(kp)
|
||||
matches := elsedie(fs.Glob(dfsys, "common_*.cue"))("could not glob kindsys cue files")
|
||||
for _, fname := range matches {
|
||||
fpath := filepath.Join(path, strings.TrimPrefix(fname, "common_"))
|
||||
fpath = fpath[:len(fpath)-4] + "_gen.cue"
|
||||
data := elsedie(fs.ReadFile(dfsys, fname))("error reading " + fname)
|
||||
_ = fsys.Add(*codejen.NewFile(fpath, data, dummyCommonJenny{}))
|
||||
}
|
||||
fsys = elsedie(fsys.Map(packageMapper))("failed remapping fs")
|
||||
|
||||
v, err := cuectx.BuildGrafanaInstance(nil, path, "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
commonFiles := make([]string, 0)
|
||||
filepath.WalkDir(filepath.Join(groot, path), func(path string, d fs.DirEntry, err error) error {
|
||||
if d.IsDir() || filepath.Ext(d.Name()) != ".cue" {
|
||||
return nil
|
||||
}
|
||||
commonFiles = append(commonFiles, path)
|
||||
return nil
|
||||
})
|
||||
|
||||
instance := load.Instances(commonFiles, &load.Config{})[0]
|
||||
if instance.Err != nil {
|
||||
return nil, instance.Err
|
||||
}
|
||||
|
||||
v := ctx.BuildInstance(instance)
|
||||
b := elsedie(cuetsy.Generate(v, cuetsy.Config{
|
||||
Export: true,
|
||||
}))("failed to generate common schema TS")
|
||||
@ -186,26 +159,8 @@ func die(err error) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Resource generation without using Thema
|
||||
func genRawResources(dirs []os.DirEntry) (*codejen.FS, error) {
|
||||
jenny := codejen.JennyListWithNamer[[]codegen.CueSchema](func(_ []codegen.CueSchema) string {
|
||||
return "RawResources"
|
||||
})
|
||||
|
||||
jenny.Append(
|
||||
&codegen.K8ResourcesJenny{},
|
||||
&codegen.CoreRegistryJenny{},
|
||||
)
|
||||
|
||||
header := codegen.SlashHeaderMapper("kinds/gen.go")
|
||||
jenny.AddPostprocessors(header)
|
||||
|
||||
return jenny.GenerateFS(loadCueFiles(dirs))
|
||||
}
|
||||
|
||||
func loadCueFiles(dirs []os.DirEntry) []codegen.CueSchema {
|
||||
ctx := cuectx.GrafanaCUEContext()
|
||||
values := make([]codegen.CueSchema, 0)
|
||||
func loadCueFiles(ctx *cue.Context, dirs []os.DirEntry) ([]codegen.SchemaForGen, error) {
|
||||
values := make([]codegen.SchemaForGen, 0)
|
||||
for _, dir := range dirs {
|
||||
if !dir.IsDir() {
|
||||
continue
|
||||
@ -225,13 +180,33 @@ func loadCueFiles(dirs []os.DirEntry) []codegen.CueSchema {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
sch := codegen.CueSchema{
|
||||
FilePath: "./" + filepath.Join(cuectx.CoreDefParentPath, entry),
|
||||
CueFile: ctx.CompileBytes(cueFile),
|
||||
v := ctx.CompileBytes(cueFile)
|
||||
name, err := getSchemaName(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sch := codegen.SchemaForGen{
|
||||
Name: name,
|
||||
FilePath: "./" + filepath.Join(CoreDefParentPath, entry),
|
||||
CueFile: v,
|
||||
IsGroup: false,
|
||||
OutputName: strings.ToLower(name),
|
||||
}
|
||||
|
||||
values = append(values, sch)
|
||||
}
|
||||
|
||||
return values
|
||||
return values, nil
|
||||
}
|
||||
|
||||
func getSchemaName(v cue.Value) (string, error) {
|
||||
namePath := v.LookupPath(cue.ParsePath("name"))
|
||||
name, err := namePath.String()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("file doesn't have name field set: %s", err)
|
||||
}
|
||||
|
||||
name = strings.Replace(name, "-", "_", -1)
|
||||
return name, nil
|
||||
}
|
||||
|
@ -7,14 +7,12 @@ import (
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"github.com/grafana/codejen"
|
||||
"github.com/grafana/kindsys"
|
||||
"github.com/grafana/thema"
|
||||
)
|
||||
|
||||
type OneToOne codejen.OneToOne[kindsys.Kind]
|
||||
type OneToMany codejen.OneToMany[kindsys.Kind]
|
||||
type ManyToOne codejen.ManyToOne[kindsys.Kind]
|
||||
type ManyToMany codejen.ManyToMany[kindsys.Kind]
|
||||
type OneToOne codejen.OneToOne[SchemaForGen]
|
||||
type OneToMany codejen.OneToMany[SchemaForGen]
|
||||
type ManyToOne codejen.ManyToOne[SchemaForGen]
|
||||
type ManyToMany codejen.ManyToMany[SchemaForGen]
|
||||
|
||||
// SlashHeaderMapper produces a FileMapper that injects a comment header onto
|
||||
// a [codejen.File] indicating the main generator that produced it (via the provided
|
||||
@ -47,21 +45,10 @@ func SlashHeaderMapper(maingen string) codejen.FileMapper {
|
||||
}
|
||||
}
|
||||
|
||||
// SchemaForGen is an intermediate values type for jennies that holds both a thema.Schema,
|
||||
// and values relevant to generating the schema that should properly, eventually, be in
|
||||
// thema itself.
|
||||
//
|
||||
// TODO this will be replaced by thema-native constructs
|
||||
type SchemaForGen struct {
|
||||
// The PascalCase name of the schematized type.
|
||||
Name string
|
||||
// The schema to be rendered for the type itself.
|
||||
Schema thema.Schema
|
||||
// Whether the schema is grouped. See https://github.com/grafana/thema/issues/62
|
||||
IsGroup bool
|
||||
}
|
||||
|
||||
type CueSchema struct {
|
||||
CueFile cue.Value
|
||||
FilePath string
|
||||
Name string
|
||||
CueFile cue.Value
|
||||
FilePath string
|
||||
IsGroup bool
|
||||
OutputName string // Some TS output files are capitalised and others not.
|
||||
}
|
||||
|
282
pkg/codegen/generators/decorators.go
Normal file
282
pkg/codegen/generators/decorators.go
Normal file
@ -0,0 +1,282 @@
|
||||
package generators
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/dave/dst"
|
||||
"github.com/dave/dst/dstutil"
|
||||
)
|
||||
|
||||
// depointerizer returns an AST manipulator that removes redundant
|
||||
// pointer indirection from the defined types.
|
||||
func depointerizer() dstutil.ApplyFunc {
|
||||
return func(c *dstutil.Cursor) bool {
|
||||
switch x := c.Node().(type) {
|
||||
case *dst.Field:
|
||||
if s, is := x.Type.(*dst.StarExpr); is {
|
||||
switch deref := depoint(s).(type) {
|
||||
case *dst.ArrayType, *dst.MapType:
|
||||
x.Type = deref
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func depoint(e dst.Expr) dst.Expr {
|
||||
if star, is := e.(*dst.StarExpr); is {
|
||||
return star.X
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func setStar(e dst.Expr) string {
|
||||
if _, is := e.(*dst.StarExpr); is {
|
||||
return "*"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func fixTODOComments() dstutil.ApplyFunc {
|
||||
return func(cursor *dstutil.Cursor) bool {
|
||||
switch f := cursor.Node().(type) {
|
||||
case *dst.File:
|
||||
for _, d := range f.Decls {
|
||||
if isTypeSpec(d) {
|
||||
removeGoFieldComment(d.Decorations().Start.All())
|
||||
}
|
||||
fixTODOComment(d.Decorations().Start.All())
|
||||
}
|
||||
case *dst.Field:
|
||||
if len(f.Names) > 0 {
|
||||
removeGoFieldComment(f.Decorations().Start.All())
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func fixTODOComment(comments []string) {
|
||||
todoRegex := regexp.MustCompile("(//) (.*) (TODO.*)")
|
||||
if len(comments) > 0 {
|
||||
comments[0] = todoRegex.ReplaceAllString(comments[0], "$1 $3")
|
||||
}
|
||||
}
|
||||
|
||||
func removeGoFieldComment(comments []string) {
|
||||
todoRegex := regexp.MustCompile("(//) ([A-Z].*?) ([A-Z]?.*?) (.*)")
|
||||
if len(comments) > 0 {
|
||||
matches := todoRegex.FindAllStringSubmatch(comments[0], -1)
|
||||
if len(matches) > 0 {
|
||||
if strings.EqualFold(matches[0][3], matches[0][2]) {
|
||||
comments[0] = fmt.Sprintf("%s %s %s", matches[0][1], matches[0][3], matches[0][4])
|
||||
} else {
|
||||
r := []rune(matches[0][3])
|
||||
if !unicode.IsLower(r[0]) {
|
||||
comments[0] = fmt.Sprintf("%s %s %s", matches[0][1], matches[0][3], matches[0][4])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isTypeSpec(d dst.Decl) bool {
|
||||
gd, ok := d.(*dst.GenDecl)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
_, is := gd.Specs[0].(*dst.TypeSpec)
|
||||
return is
|
||||
}
|
||||
|
||||
// It fixes the "generic" fields. It happens when a value in cue could be different structs.
|
||||
// For Go it generates a struct with a json.RawMessage field inside and multiple functions to map it between the different possibilities.
|
||||
func fixRawData() dstutil.ApplyFunc {
|
||||
return func(c *dstutil.Cursor) bool {
|
||||
f, is := c.Node().(*dst.File)
|
||||
if !is {
|
||||
return false
|
||||
}
|
||||
|
||||
rawFields := make(map[string]bool)
|
||||
existingRawFields := make(map[string]bool)
|
||||
for _, decl := range f.Decls {
|
||||
switch x := decl.(type) {
|
||||
// Find the structs that only contains one json.RawMessage inside
|
||||
case *dst.GenDecl:
|
||||
for _, t := range x.Specs {
|
||||
if ts, ok := t.(*dst.TypeSpec); ok {
|
||||
if tp, ok := ts.Type.(*dst.StructType); ok && len(tp.Fields.List) == 1 {
|
||||
if fn, ok := tp.Fields.List[0].Type.(*dst.SelectorExpr); ok {
|
||||
if fmt.Sprintf("%s.%s", fn.X, fn.Sel.Name) == "json.RawMessage" {
|
||||
rawFields[ts.Name.Name] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Find the functions of the previous structs to verify that are the ones that we are looking for.
|
||||
case *dst.FuncDecl:
|
||||
for _, recv := range x.Recv.List {
|
||||
fnType := depoint(recv.Type).(*dst.Ident).Name
|
||||
if rawFields[fnType] {
|
||||
existingRawFields[fnType] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dstutil.Apply(f, func(c *dstutil.Cursor) bool {
|
||||
switch x := c.Node().(type) {
|
||||
// Delete the functions
|
||||
case *dst.FuncDecl:
|
||||
c.Delete()
|
||||
case *dst.GenDecl:
|
||||
// Deletes all "generics" generated for these json.RawMessage structs
|
||||
comments := x.Decorations().Start.All()
|
||||
if len(comments) > 0 {
|
||||
if strings.HasSuffix(comments[0], "defines model for .") {
|
||||
c.Delete()
|
||||
}
|
||||
}
|
||||
for _, spec := range x.Specs {
|
||||
if tp, ok := spec.(*dst.TypeSpec); ok {
|
||||
// Delete structs with only json.RawMessage
|
||||
if existingRawFields[tp.Name.Name] && tp.Name.Name != "MetricAggregation2" {
|
||||
c.Delete()
|
||||
continue
|
||||
}
|
||||
// Set types that was using these structs as interface{}
|
||||
if st, ok := tp.Type.(*dst.StructType); ok {
|
||||
iterateStruct(st, withoutRawData(existingRawFields))
|
||||
}
|
||||
if mt, ok := tp.Type.(*dst.MapType); ok {
|
||||
iterateMap(mt, withoutRawData(existingRawFields))
|
||||
}
|
||||
if at, ok := tp.Type.(*dst.ArrayType); ok {
|
||||
iterateArray(at, withoutRawData(existingRawFields))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}, nil)
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Fixes type name containing underscores in the generated Go files
|
||||
func fixUnderscoreInTypeName() dstutil.ApplyFunc {
|
||||
return func(c *dstutil.Cursor) bool {
|
||||
switch x := c.Node().(type) {
|
||||
case *dst.GenDecl:
|
||||
if specs, isType := x.Specs[0].(*dst.TypeSpec); isType {
|
||||
if strings.Contains(specs.Name.Name, "_") {
|
||||
oldName := specs.Name.Name
|
||||
specs.Name.Name = strings.ReplaceAll(specs.Name.Name, "_", "")
|
||||
x.Decs.Start[0] = strings.ReplaceAll(x.Decs.Start[0], oldName, specs.Name.Name)
|
||||
}
|
||||
if st, ok := specs.Type.(*dst.StructType); ok {
|
||||
iterateStruct(st, withoutUnderscore)
|
||||
}
|
||||
if mt, ok := specs.Type.(*dst.MapType); ok {
|
||||
iterateMap(mt, withoutUnderscore)
|
||||
}
|
||||
if at, ok := specs.Type.(*dst.ArrayType); ok {
|
||||
iterateArray(at, withoutUnderscore)
|
||||
}
|
||||
}
|
||||
case *dst.Field:
|
||||
findFieldsWithUnderscores(x)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func findFieldsWithUnderscores(x *dst.Field) {
|
||||
switch t := x.Type.(type) {
|
||||
case *dst.Ident:
|
||||
withoutUnderscore(t)
|
||||
case *dst.StarExpr:
|
||||
if i, is := t.X.(*dst.Ident); is {
|
||||
withoutUnderscore(i)
|
||||
}
|
||||
case *dst.ArrayType:
|
||||
iterateArray(t, withoutUnderscore)
|
||||
case *dst.MapType:
|
||||
iterateMap(t, withoutUnderscore)
|
||||
}
|
||||
}
|
||||
|
||||
func withoutUnderscore(i *dst.Ident) {
|
||||
if strings.Contains(i.Name, "_") {
|
||||
i.Name = strings.ReplaceAll(i.Name, "_", "")
|
||||
}
|
||||
}
|
||||
|
||||
func withoutRawData(existingFields map[string]bool) func(ident *dst.Ident) {
|
||||
return func(i *dst.Ident) {
|
||||
if existingFields[i.Name] {
|
||||
i.Name = setStar(i) + "any"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func iterateStruct(s *dst.StructType, fn func(i *dst.Ident)) {
|
||||
for i, f := range s.Fields.List {
|
||||
switch mx := depoint(f.Type).(type) {
|
||||
case *dst.Ident:
|
||||
fn(mx)
|
||||
case *dst.ArrayType:
|
||||
iterateArray(mx, fn)
|
||||
case *dst.MapType:
|
||||
iterateMap(mx, fn)
|
||||
case *dst.StructType:
|
||||
iterateStruct(mx, fn)
|
||||
case *dst.InterfaceType:
|
||||
s.Fields.List[i].Type = interfaceToAny(f.Type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func iterateMap(s *dst.MapType, fn func(i *dst.Ident)) {
|
||||
switch mx := s.Value.(type) {
|
||||
case *dst.Ident:
|
||||
fn(mx)
|
||||
case *dst.ArrayType:
|
||||
iterateArray(mx, fn)
|
||||
case *dst.MapType:
|
||||
iterateMap(mx, fn)
|
||||
case *dst.InterfaceType:
|
||||
s.Value = interfaceToAny(s.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func iterateArray(a *dst.ArrayType, fn func(i *dst.Ident)) {
|
||||
switch mx := a.Elt.(type) {
|
||||
case *dst.Ident:
|
||||
fn(mx)
|
||||
case *dst.ArrayType:
|
||||
iterateArray(mx, fn)
|
||||
case *dst.StructType:
|
||||
iterateStruct(mx, fn)
|
||||
case *dst.InterfaceType:
|
||||
a.Elt = interfaceToAny(a.Elt)
|
||||
}
|
||||
}
|
||||
|
||||
func interfaceToAny(i dst.Expr) dst.Expr {
|
||||
star := ""
|
||||
if _, is := i.(*dst.StarExpr); is {
|
||||
star = "*"
|
||||
}
|
||||
|
||||
return &dst.Ident{Name: star + "any"}
|
||||
}
|
193
pkg/codegen/generators/go_generator.go
Normal file
193
pkg/codegen/generators/go_generator.go
Normal file
@ -0,0 +1,193 @@
|
||||
package generators
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/pkg/encoding/yaml"
|
||||
"github.com/dave/dst/decorator"
|
||||
"github.com/dave/dst/dstutil"
|
||||
"github.com/deepmap/oapi-codegen/pkg/codegen"
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"golang.org/x/tools/imports"
|
||||
)
|
||||
|
||||
type GoConfig struct {
|
||||
Config *OpenApiConfig
|
||||
PackageName string
|
||||
ApplyFuncs []dstutil.ApplyFunc
|
||||
}
|
||||
|
||||
func GenerateTypesGo(v cue.Value, cfg *GoConfig) ([]byte, error) {
|
||||
if cfg == nil {
|
||||
return nil, fmt.Errorf("configuration cannot be nil")
|
||||
}
|
||||
|
||||
applyFuncs := []dstutil.ApplyFunc{depointerizer(), fixRawData(), fixUnderscoreInTypeName(), fixTODOComments()}
|
||||
applyFuncs = append(applyFuncs, cfg.ApplyFuncs...)
|
||||
|
||||
f, err := generateOpenAPI(v, cfg.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
str, err := yaml.Marshal(v.Context().BuildFile(f))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cue-yaml marshaling failed: %w", err)
|
||||
}
|
||||
|
||||
loader := openapi3.NewLoader()
|
||||
oT, err := loader.LoadFromData([]byte(str))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("loading generated openapi failed: %w", err)
|
||||
}
|
||||
|
||||
schemaName, err := getSchemaName(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cfg.PackageName == "" {
|
||||
cfg.PackageName = schemaName
|
||||
}
|
||||
|
||||
// Hack to fix https://github.com/grafana/thema/pull/127 issue without importing
|
||||
// to avoid to add the whole vendor in Grafana code
|
||||
if cfg.PackageName == "dataquery" {
|
||||
fixDataQuery(oT)
|
||||
}
|
||||
|
||||
ccfg := codegen.Configuration{
|
||||
PackageName: cfg.PackageName,
|
||||
Compatibility: codegen.CompatibilityOptions{
|
||||
AlwaysPrefixEnumValues: true,
|
||||
},
|
||||
Generate: codegen.GenerateOptions{
|
||||
Models: true,
|
||||
},
|
||||
OutputOptions: codegen.OutputOptions{
|
||||
SkipPrune: true,
|
||||
UserTemplates: map[string]string{
|
||||
"imports.tmpl": importstmpl,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
gostr, err := codegen.Generate(oT, ccfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("openapi generation failed: %w", err)
|
||||
}
|
||||
|
||||
return postprocessGoFile(genGoFile{
|
||||
path: fmt.Sprintf("%s_type_gen.go", schemaName),
|
||||
appliers: applyFuncs,
|
||||
in: []byte(gostr),
|
||||
})
|
||||
}
|
||||
|
||||
type genGoFile struct {
|
||||
path string
|
||||
appliers []dstutil.ApplyFunc
|
||||
in []byte
|
||||
}
|
||||
|
||||
func postprocessGoFile(cfg genGoFile) ([]byte, error) {
|
||||
fname := sanitizeLabelString(filepath.Base(cfg.path))
|
||||
buf := new(bytes.Buffer)
|
||||
fset := token.NewFileSet()
|
||||
gf, err := decorator.ParseFile(fset, fname, string(cfg.in), parser.ParseComments)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing generated file: %w", err)
|
||||
}
|
||||
|
||||
for _, af := range cfg.appliers {
|
||||
dstutil.Apply(gf, af, nil)
|
||||
}
|
||||
|
||||
err = decorator.Fprint(buf, gf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error formatting generated file: %w", err)
|
||||
}
|
||||
|
||||
byt, err := imports.Process(fname, buf.Bytes(), nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("goimports processing of generated file failed: %w", err)
|
||||
}
|
||||
|
||||
// Compare imports before and after; warn about performance if some were added
|
||||
gfa, _ := parser.ParseFile(fset, fname, string(byt), parser.ParseComments)
|
||||
imap := make(map[string]bool)
|
||||
for _, im := range gf.Imports {
|
||||
imap[im.Path.Value] = true
|
||||
}
|
||||
var added []string
|
||||
for _, im := range gfa.Imports {
|
||||
if !imap[im.Path.Value] {
|
||||
added = append(added, im.Path.Value)
|
||||
}
|
||||
}
|
||||
|
||||
if len(added) != 0 {
|
||||
// TODO improve the guidance in this error if/when we better abstract over imports to generate
|
||||
return nil, fmt.Errorf("goimports added the following import statements to %s: \n\t%s\nRelying on goimports to find imports significantly slows down code generation. Either add these imports with an AST manipulation in cfg.ApplyFuncs, or set cfg.IgnoreDiscoveredImports to true", cfg.path, strings.Join(added, "\n\t"))
|
||||
}
|
||||
return byt, nil
|
||||
}
|
||||
|
||||
// fixDataQuery extends the properties for the AllOf schemas when a DataQuery exists.
|
||||
// deep/oapi-codegen library ignores the properties of the models and only ones have references.
|
||||
// It doesn't apply this change https://github.com/grafana/thema/pull/154 since it modifies the
|
||||
// vendor implementation, and we don't import it.
|
||||
func fixDataQuery(spec *openapi3.T) *openapi3.T {
|
||||
for _, sch := range spec.Components.Schemas {
|
||||
if sch.Value != nil && len(sch.Value.AllOf) > 0 {
|
||||
for _, allOf := range sch.Value.AllOf {
|
||||
for n, p := range allOf.Value.Properties {
|
||||
sch.Value.Properties[n] = p
|
||||
}
|
||||
}
|
||||
sch.Value.AllOf = nil
|
||||
}
|
||||
}
|
||||
return spec
|
||||
}
|
||||
|
||||
// Almost all of the below imports are eliminated by dst transformers and calls
|
||||
// to goimports - but if they're not present in the template, then the internal
|
||||
// call to goimports that oapi-codegen makes will trigger a search for them,
|
||||
// which can slow down codegen by orders of magnitude.
|
||||
var importstmpl = `package {{ .PackageName }}
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/deepmap/oapi-codegen/pkg/runtime"
|
||||
openapi_types "github.com/deepmap/oapi-codegen/pkg/types"
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
`
|
199
pkg/codegen/generators/openapi_generator.go
Normal file
199
pkg/codegen/generators/openapi_generator.go
Normal file
@ -0,0 +1,199 @@
|
||||
package generators
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/ast"
|
||||
"cuelang.org/go/encoding/openapi"
|
||||
)
|
||||
|
||||
type OpenApiConfig struct {
|
||||
Config *openapi.Config
|
||||
IsGroup bool
|
||||
RootName string
|
||||
SubPath cue.Path
|
||||
}
|
||||
|
||||
func generateOpenAPI(v cue.Value, cfg *OpenApiConfig) (*ast.File, error) {
|
||||
if cfg == nil {
|
||||
return nil, fmt.Errorf("missing openapi configuration")
|
||||
}
|
||||
|
||||
if cfg.Config == nil {
|
||||
cfg.Config = &openapi.Config{}
|
||||
}
|
||||
|
||||
name, err := getSchemaName(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gen := &oapiGen{
|
||||
cfg: cfg,
|
||||
name: name,
|
||||
val: v.LookupPath(cue.ParsePath("lineage.schemas[0].schema")),
|
||||
subpath: cfg.SubPath,
|
||||
bpath: v.LookupPath(cue.ParsePath("lineage.schemas[0]")).Path(),
|
||||
}
|
||||
|
||||
declFunc := genSchema
|
||||
if cfg.IsGroup {
|
||||
declFunc = genGroup
|
||||
}
|
||||
|
||||
decls, err := declFunc(gen)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO recursively sort output to improve stability of output
|
||||
return &ast.File{
|
||||
Decls: []ast.Decl{
|
||||
ast.NewStruct(
|
||||
"openapi", ast.NewString("3.0.0"),
|
||||
"paths", ast.NewStruct(),
|
||||
"components", ast.NewStruct(
|
||||
"schemas", &ast.StructLit{Elts: decls},
|
||||
),
|
||||
),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
type oapiGen struct {
|
||||
cfg *OpenApiConfig
|
||||
val cue.Value
|
||||
subpath cue.Path
|
||||
|
||||
// overall name for the generated oapi doc
|
||||
name string
|
||||
|
||||
// original NameFunc
|
||||
onf func(cue.Value, cue.Path) string
|
||||
|
||||
// full prefix path that leads up to the #SchemaDef, e.g. lin._sortedSchemas[0]
|
||||
bpath cue.Path
|
||||
}
|
||||
|
||||
func genGroup(gen *oapiGen) ([]ast.Decl, error) {
|
||||
ctx := gen.val.Context()
|
||||
iter, err := gen.val.Fields(cue.Definitions(true), cue.Optional(true))
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("unreachable - should always be able to get iter for struct kinds: %w", err))
|
||||
}
|
||||
|
||||
var decls []ast.Decl
|
||||
for iter.Next() {
|
||||
val, sel := iter.Value(), iter.Selector()
|
||||
name := strings.Trim(sel.String(), "?#")
|
||||
|
||||
v := ctx.CompileString(fmt.Sprintf("#%s: _", name))
|
||||
defpath := cue.MakePath(cue.Def(name))
|
||||
defsch := v.FillPath(defpath, val)
|
||||
|
||||
cfgi := *gen.cfg.Config
|
||||
cfgi.NameFunc = func(val cue.Value, path cue.Path) string {
|
||||
return gen.nfSingle(val, path, defpath, name)
|
||||
}
|
||||
|
||||
part, err := openapi.Generate(defsch, &cfgi)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed generation for grouped field %s: %w", sel, err)
|
||||
}
|
||||
|
||||
decls = append(decls, getSchemas(part)...)
|
||||
}
|
||||
|
||||
return decls, nil
|
||||
}
|
||||
|
||||
func genSchema(gen *oapiGen) ([]ast.Decl, error) {
|
||||
hasSubpath := len(gen.cfg.SubPath.Selectors()) > 0
|
||||
name := sanitizeLabelString(gen.name)
|
||||
if gen.cfg.RootName != "" {
|
||||
name = gen.cfg.RootName
|
||||
} else if hasSubpath {
|
||||
sel := gen.cfg.SubPath.Selectors()
|
||||
name = sel[len(sel)-1].String()
|
||||
}
|
||||
|
||||
val := gen.val
|
||||
if hasSubpath {
|
||||
for i, sel := range gen.cfg.SubPath.Selectors() {
|
||||
if !gen.val.Allows(sel) {
|
||||
return nil, fmt.Errorf("subpath %q not present in schema", cue.MakePath(gen.cfg.SubPath.Selectors()[:i+1]...))
|
||||
}
|
||||
}
|
||||
val = val.LookupPath(gen.cfg.SubPath)
|
||||
}
|
||||
|
||||
v := gen.val.Context().CompileString(fmt.Sprintf("#%s: _", name))
|
||||
defpath := cue.MakePath(cue.Def(name))
|
||||
defsch := v.FillPath(defpath, val)
|
||||
|
||||
gen.cfg.Config.NameFunc = func(val cue.Value, path cue.Path) string {
|
||||
return gen.nfSingle(val, path, defpath, name)
|
||||
}
|
||||
|
||||
f, err := openapi.Generate(defsch.Eval(), gen.cfg.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return getSchemas(f), nil
|
||||
}
|
||||
|
||||
// For generating a single, our NameFunc must:
|
||||
// - Eliminate any path prefixes on the element, both internal lineage and wrapping
|
||||
// - Replace the name "_#schema" with the desired name
|
||||
// - Call the user-provided NameFunc, if any
|
||||
// - Remove CUE markers like #, !, ?
|
||||
func (gen *oapiGen) nfSingle(val cue.Value, path, defpath cue.Path, name string) string {
|
||||
tpath := trimPathPrefix(trimThemaPathPrefix(path, gen.bpath), defpath)
|
||||
|
||||
if path.String() == "" || tpath.String() == defpath.String() {
|
||||
return name
|
||||
}
|
||||
|
||||
if val == gen.val {
|
||||
return ""
|
||||
}
|
||||
|
||||
if gen.onf != nil {
|
||||
return gen.onf(val, tpath)
|
||||
}
|
||||
return strings.Trim(tpath.String(), "?#")
|
||||
}
|
||||
|
||||
func getSchemas(f *ast.File) []ast.Decl {
|
||||
compos := orp(getFieldByLabel(f, "components"))
|
||||
schemas := orp(getFieldByLabel(compos.Value, "schemas"))
|
||||
return schemas.Value.(*ast.StructLit).Elts
|
||||
}
|
||||
|
||||
func orp[T any](t T, err error) T {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func trimThemaPathPrefix(p, base cue.Path) cue.Path {
|
||||
if !pathHasPrefix(p, base) {
|
||||
return p
|
||||
}
|
||||
|
||||
rest := p.Selectors()[len(base.Selectors()):]
|
||||
if len(rest) == 0 {
|
||||
return cue.Path{}
|
||||
}
|
||||
switch rest[0].String() {
|
||||
case "schema", "_#schema", "_join", "joinSchema":
|
||||
return cue.MakePath(rest[1:]...)
|
||||
default:
|
||||
return cue.MakePath(rest...)
|
||||
}
|
||||
}
|
56
pkg/codegen/generators/ts_generator.go
Normal file
56
pkg/codegen/generators/ts_generator.go
Normal file
@ -0,0 +1,56 @@
|
||||
package generators
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/cuecontext"
|
||||
"github.com/grafana/cuetsy"
|
||||
"github.com/grafana/cuetsy/ts"
|
||||
"github.com/grafana/cuetsy/ts/ast"
|
||||
)
|
||||
|
||||
type TSConfig struct {
|
||||
CuetsyConfig *cuetsy.Config
|
||||
IsGroup bool
|
||||
RootName string
|
||||
}
|
||||
|
||||
// GenerateTypesTS generates native TypeScript types and defaults corresponding to
|
||||
// the provided Schema.
|
||||
func GenerateTypesTS(v cue.Value, cfg *TSConfig) (*ast.File, error) {
|
||||
if cfg == nil {
|
||||
return nil, fmt.Errorf("configuration cannot be empty")
|
||||
}
|
||||
if cfg.CuetsyConfig == nil {
|
||||
cfg.CuetsyConfig = &cuetsy.Config{
|
||||
Export: true,
|
||||
}
|
||||
}
|
||||
|
||||
// Thema #schema was a unification between the schema and cue.TopKind(_). For any reason, without this unification,
|
||||
// cuetsy fails finding some enums ¯\_(ツ)_/¯.
|
||||
oldSchema := cuecontext.New().CompileBytes([]byte("_"))
|
||||
schdef := v.LookupPath(cue.ParsePath("lineage.schemas[0].schema")).Unify(oldSchema)
|
||||
tf, err := cuetsy.GenerateAST(schdef, *cfg.CuetsyConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("generating TS for child elements of schema failed: %w", err)
|
||||
}
|
||||
|
||||
file := &ts.File{
|
||||
Nodes: tf.Nodes,
|
||||
}
|
||||
|
||||
if !cfg.IsGroup {
|
||||
top, err := cuetsy.GenerateSingleAST(cfg.RootName, schdef, cuetsy.TypeInterface)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("generating TS for schema root failed: %w", err)
|
||||
}
|
||||
file.Nodes = append(file.Nodes, top.T)
|
||||
if top.D != nil {
|
||||
file.Nodes = append(file.Nodes, top.D)
|
||||
}
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
130
pkg/codegen/generators/utils.go
Normal file
130
pkg/codegen/generators/utils.go
Normal file
@ -0,0 +1,130 @@
|
||||
package generators
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/ast"
|
||||
"cuelang.org/go/cue/token"
|
||||
)
|
||||
|
||||
// sanitizeLabelString strips characters from a string that are not allowed for
|
||||
// use in a CUE label.
|
||||
func sanitizeLabelString(s string) string {
|
||||
return strings.Map(func(r rune) rune {
|
||||
switch {
|
||||
case r >= 'a' && r <= 'z':
|
||||
fallthrough
|
||||
case r >= 'A' && r <= 'Z':
|
||||
fallthrough
|
||||
case r >= '0' && r <= '9':
|
||||
fallthrough
|
||||
case r == '_':
|
||||
return r
|
||||
default:
|
||||
return -1
|
||||
}
|
||||
}, s)
|
||||
}
|
||||
|
||||
// trimPathPrefix strips the provided prefix from the provided path, if the
|
||||
// prefix exists.
|
||||
//
|
||||
// If path and prefix are equivalent, and there is at least one additional
|
||||
// selector in the provided path.
|
||||
func trimPathPrefix(path, prefix cue.Path) cue.Path {
|
||||
sels, psels := path.Selectors(), prefix.Selectors()
|
||||
if len(sels) == 1 {
|
||||
return path
|
||||
}
|
||||
var i int
|
||||
for ; i < len(psels) && i < len(sels); i++ {
|
||||
if !selEq(psels[i], sels[i]) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return cue.MakePath(sels[i:]...)
|
||||
}
|
||||
|
||||
// selEq indicates whether two selectors are equivalent. Selectors are equivalent if
|
||||
// they are either exactly equal, or if they are equal ignoring path optionality.
|
||||
func selEq(s1, s2 cue.Selector) bool {
|
||||
return s1 == s2 || s1.Optional() == s2.Optional()
|
||||
}
|
||||
|
||||
// getFieldByLabel returns the ast.Field with a given label from a struct-ish input.
|
||||
func getFieldByLabel(n ast.Node, label string) (*ast.Field, error) {
|
||||
var d []ast.Decl
|
||||
switch x := n.(type) {
|
||||
case *ast.File:
|
||||
d = x.Decls
|
||||
case *ast.StructLit:
|
||||
d = x.Elts
|
||||
default:
|
||||
return nil, fmt.Errorf("not an *ast.File or *ast.StructLit")
|
||||
}
|
||||
|
||||
for _, el := range d {
|
||||
if isFieldWithLabel(el, label) {
|
||||
return el.(*ast.Field), nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no field with label %q", label)
|
||||
}
|
||||
|
||||
func isFieldWithLabel(n ast.Node, label string) bool {
|
||||
if x, is := n.(*ast.Field); is {
|
||||
if l, is := x.Label.(*ast.BasicLit); is {
|
||||
return strEq(l, label)
|
||||
}
|
||||
if l, is := x.Label.(*ast.Ident); is {
|
||||
return identStrEq(l, label)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func strEq(lit *ast.BasicLit, str string) bool {
|
||||
if lit.Kind != token.STRING {
|
||||
return false
|
||||
}
|
||||
ls, _ := strconv.Unquote(lit.Value)
|
||||
return str == ls || str == lit.Value
|
||||
}
|
||||
|
||||
func identStrEq(id *ast.Ident, str string) bool {
|
||||
if str == id.Name {
|
||||
return true
|
||||
}
|
||||
ls, _ := strconv.Unquote(id.Name)
|
||||
return str == ls
|
||||
}
|
||||
|
||||
// pathHasPrefix tests whether the [cue.Path] p begins with prefix.
|
||||
func pathHasPrefix(p, prefix cue.Path) bool {
|
||||
ps, pres := p.Selectors(), prefix.Selectors()
|
||||
if len(pres) > len(ps) {
|
||||
return false
|
||||
}
|
||||
return pathsAreEq(ps[:len(pres)], pres)
|
||||
}
|
||||
|
||||
func pathsAreEq(p1s, p2s []cue.Selector) bool {
|
||||
if len(p1s) != len(p2s) {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(p2s); i++ {
|
||||
if !selEq(p2s[i], p1s[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func getSchemaName(v cue.Value) (string, error) {
|
||||
nameValue := v.LookupPath(cue.ParsePath("name"))
|
||||
return nameValue.String()
|
||||
}
|
@ -7,7 +7,6 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"github.com/grafana/codejen"
|
||||
)
|
||||
|
||||
@ -21,10 +20,10 @@ func (jenny *CoreRegistryJenny) JennyName() string {
|
||||
return "CoreRegistryJenny"
|
||||
}
|
||||
|
||||
func (jenny *CoreRegistryJenny) Generate(cueFiles []CueSchema) (codejen.Files, error) {
|
||||
func (jenny *CoreRegistryJenny) Generate(cueFiles ...SchemaForGen) (codejen.Files, error) {
|
||||
schemas := make([]Schema, len(cueFiles))
|
||||
for i, v := range cueFiles {
|
||||
name, err := getSchemaName(v.CueFile)
|
||||
name, err := getSchemaName(v.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -51,12 +50,7 @@ func (jenny *CoreRegistryJenny) Generate(cueFiles []CueSchema) (codejen.Files, e
|
||||
return codejen.Files{*file}, nil
|
||||
}
|
||||
|
||||
func getSchemaName(v cue.Value) (string, error) {
|
||||
name, err := getPackageName(v)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
name = strings.Replace(name, "-", "_", -1)
|
||||
return strings.ToLower(name), nil
|
||||
func getSchemaName(pkg string) (string, error) {
|
||||
pkg = strings.Replace(pkg, "-", "_", -1)
|
||||
return strings.ToLower(pkg), nil
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"github.com/grafana/codejen"
|
||||
"github.com/grafana/cuetsy/ts"
|
||||
"github.com/grafana/cuetsy/ts/ast"
|
||||
"github.com/grafana/kindsys"
|
||||
)
|
||||
|
||||
// LatestMajorsOrXJenny returns a jenny that repeats the input for the latest in each major version.
|
||||
@ -27,28 +26,17 @@ func (j *lmox) JennyName() string {
|
||||
return "LatestMajorsOrXJenny"
|
||||
}
|
||||
|
||||
func (j *lmox) Generate(kind kindsys.Kind) (codejen.Files, error) {
|
||||
// TODO remove this once codejen catches nils https://github.com/grafana/codejen/issues/5
|
||||
if kind == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
comm := kind.Props().Common()
|
||||
sfg := SchemaForGen{
|
||||
Name: comm.Name,
|
||||
IsGroup: true,
|
||||
Schema: kind.Lineage().Latest(),
|
||||
}
|
||||
|
||||
func (j *lmox) Generate(sfg SchemaForGen) (codejen.Files, error) {
|
||||
sfg.IsGroup = true
|
||||
f, err := j.inner.Generate(sfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s jenny failed on %s schema for %s: %w", j.inner.JennyName(), sfg.Schema.Version(), kind.Props().Common().Name, err)
|
||||
return nil, fmt.Errorf("%s jenny failed for %s: %w", j.inner.JennyName(), sfg.Name, err)
|
||||
}
|
||||
if f == nil || !f.Exists() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
f.RelativePath = filepath.Join(j.parentdir, comm.MachineName, "x", f.RelativePath)
|
||||
f.RelativePath = filepath.Join(j.parentdir, sfg.OutputName, "x", f.RelativePath)
|
||||
f.From = append(f.From, j)
|
||||
return codejen.Files{*f}, nil
|
||||
}
|
||||
|
@ -2,13 +2,12 @@ package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"github.com/dave/dst/dstutil"
|
||||
"github.com/grafana/codejen"
|
||||
"github.com/grafana/kindsys"
|
||||
"github.com/grafana/thema/encoding/gocode"
|
||||
"github.com/grafana/thema/encoding/openapi"
|
||||
"github.com/grafana/grafana/pkg/codegen/generators"
|
||||
)
|
||||
|
||||
type GoSpecJenny struct {
|
||||
@ -19,19 +18,19 @@ func (jenny *GoSpecJenny) JennyName() string {
|
||||
return "GoResourceTypes"
|
||||
}
|
||||
|
||||
func (jenny *GoSpecJenny) Generate(kinds ...kindsys.Kind) (codejen.Files, error) {
|
||||
files := make(codejen.Files, len(kinds))
|
||||
for i, v := range kinds {
|
||||
name := v.Lineage().Name()
|
||||
b, err := gocode.GenerateTypesOpenAPI(v.Lineage().Latest(),
|
||||
&gocode.TypeConfigOpenAPI{
|
||||
Config: &openapi.Config{
|
||||
Group: false,
|
||||
func (jenny *GoSpecJenny) Generate(sfg ...SchemaForGen) (codejen.Files, error) {
|
||||
files := make(codejen.Files, len(sfg))
|
||||
for i, v := range sfg {
|
||||
packageName := strings.ToLower(v.Name)
|
||||
b, err := generators.GenerateTypesGo(v.CueFile,
|
||||
&generators.GoConfig{
|
||||
Config: &generators.OpenApiConfig{
|
||||
IsGroup: false,
|
||||
RootName: "Spec",
|
||||
Subpath: cue.MakePath(cue.Str("spec")),
|
||||
SubPath: cue.MakePath(cue.Str("spec")),
|
||||
},
|
||||
PackageName: name,
|
||||
ApplyFuncs: append(jenny.ApplyFuncs, PrefixDropper(v.Props().Common().Name)),
|
||||
PackageName: packageName,
|
||||
ApplyFuncs: append(jenny.ApplyFuncs, PrefixDropper(v.Name)),
|
||||
},
|
||||
)
|
||||
|
||||
@ -39,7 +38,7 @@ func (jenny *GoSpecJenny) Generate(kinds ...kindsys.Kind) (codejen.Files, error)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
files[i] = *codejen.NewFile(fmt.Sprintf("pkg/kinds/%s/%s_spec_gen.go", name, name), b, jenny)
|
||||
files[i] = *codejen.NewFile(fmt.Sprintf("pkg/kinds/%s/%s_spec_gen.go", packageName, packageName), b, jenny)
|
||||
}
|
||||
|
||||
return files, nil
|
||||
|
@ -18,25 +18,20 @@ func (jenny *K8ResourcesJenny) JennyName() string {
|
||||
return "K8ResourcesJenny"
|
||||
}
|
||||
|
||||
func (jenny *K8ResourcesJenny) Generate(cueFiles []CueSchema) (codejen.Files, error) {
|
||||
func (jenny *K8ResourcesJenny) Generate(cueFiles ...SchemaForGen) (codejen.Files, error) {
|
||||
files := make(codejen.Files, 0)
|
||||
for _, val := range cueFiles {
|
||||
pkg, err := getPackageName(val.CueFile)
|
||||
resource, err := jenny.genResource(val.Name, val.CueFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resource, err := jenny.genResource(pkg, val.CueFile)
|
||||
metadata, err := jenny.genMetadata(val.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
metadata, err := jenny.genMetadata(pkg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
status, err := jenny.genStatus(pkg)
|
||||
status, err := jenny.genStatus(val.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -100,15 +95,6 @@ func (jenny *K8ResourcesJenny) genStatus(pkg string) (codejen.File, error) {
|
||||
return *codejen.NewFile(fmt.Sprintf("pkg/kinds/%s/%s_status_gen.go", pkg, pkg), buf.Bytes(), jenny), nil
|
||||
}
|
||||
|
||||
func getPackageName(val cue.Value) (string, error) {
|
||||
name := val.LookupPath(cue.ParsePath("name"))
|
||||
pkg, err := name.String()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("file doesn't have name field set: %s", err)
|
||||
}
|
||||
return pkg, nil
|
||||
}
|
||||
|
||||
func getVersion(val cue.Value) (string, error) {
|
||||
val = val.LookupPath(cue.ParsePath("lineage.schemas[0].version"))
|
||||
versionValues, err := val.List()
|
||||
|
@ -4,17 +4,12 @@ import (
|
||||
"github.com/grafana/codejen"
|
||||
"github.com/grafana/cuetsy"
|
||||
"github.com/grafana/cuetsy/ts/ast"
|
||||
"github.com/grafana/grafana/pkg/cuectx"
|
||||
"github.com/grafana/thema/encoding/typescript"
|
||||
"github.com/grafana/grafana/pkg/codegen/generators"
|
||||
)
|
||||
|
||||
type ApplyFunc func(sfg SchemaForGen, file *ast.File)
|
||||
|
||||
// TSTypesJenny is a [OneToOne] that produces TypeScript types and
|
||||
// defaults for a Thema schema.
|
||||
//
|
||||
// Thema's generic TS jenny will be able to replace this one once
|
||||
// https://github.com/grafana/thema/issues/89 is complete.
|
||||
// TSTypesJenny is a [OneToOne] that produces TypeScript types and defaults.
|
||||
type TSTypesJenny struct {
|
||||
ApplyFuncs []ApplyFunc
|
||||
}
|
||||
@ -26,14 +21,13 @@ func (j TSTypesJenny) JennyName() string {
|
||||
}
|
||||
|
||||
func (j TSTypesJenny) Generate(sfg SchemaForGen) (*codejen.File, error) {
|
||||
// TODO allow using name instead of machine name in thema generator
|
||||
f, err := typescript.GenerateTypes(sfg.Schema, &typescript.TypeConfig{
|
||||
f, err := generators.GenerateTypesTS(sfg.CueFile, &generators.TSConfig{
|
||||
CuetsyConfig: &cuetsy.Config{
|
||||
Export: true,
|
||||
ImportMapper: cuectx.MapCUEImportToTS,
|
||||
ImportMapper: MapCUEImportToTS,
|
||||
},
|
||||
RootName: sfg.Name,
|
||||
Group: sfg.IsGroup,
|
||||
IsGroup: sfg.IsGroup,
|
||||
})
|
||||
|
||||
for _, renameFunc := range j.ApplyFuncs {
|
||||
@ -44,5 +38,10 @@ func (j TSTypesJenny) Generate(sfg SchemaForGen) (*codejen.File, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return codejen.NewFile(sfg.Schema.Lineage().Name()+"_types.gen.ts", []byte(f.String()), j), nil
|
||||
outputName := sfg.Name
|
||||
if sfg.OutputName != "" {
|
||||
outputName = sfg.OutputName
|
||||
}
|
||||
|
||||
return codejen.NewFile(outputName+"_types.gen.ts", []byte(f.String()), j), nil
|
||||
}
|
||||
|
@ -12,14 +12,9 @@ import (
|
||||
"github.com/grafana/cuetsy"
|
||||
"github.com/grafana/cuetsy/ts"
|
||||
"github.com/grafana/cuetsy/ts/ast"
|
||||
"github.com/grafana/grafana/pkg/cuectx"
|
||||
"github.com/grafana/kindsys"
|
||||
"github.com/grafana/thema"
|
||||
"github.com/grafana/thema/encoding/typescript"
|
||||
"github.com/grafana/grafana/pkg/codegen/generators"
|
||||
)
|
||||
|
||||
var schPath = cue.MakePath(cue.Hid("_#schema", "github.com/grafana/thema"))
|
||||
|
||||
// TSVeneerIndexJenny generates an index.gen.ts file with references to all
|
||||
// generated TS types. Elements with the attribute @grafana(TSVeneer="type") are
|
||||
// exported from a handwritten file, rather than the raw generated types.
|
||||
@ -43,19 +38,18 @@ func (gen *genTSVeneerIndex) JennyName() string {
|
||||
return "TSVeneerIndexJenny"
|
||||
}
|
||||
|
||||
func (gen *genTSVeneerIndex) Generate(kinds ...kindsys.Kind) (*codejen.File, error) {
|
||||
func (gen *genTSVeneerIndex) Generate(sfg ...SchemaForGen) (*codejen.File, error) {
|
||||
tsf := new(ast.File)
|
||||
for _, def := range kinds {
|
||||
sch := def.Lineage().Latest()
|
||||
f, err := typescript.GenerateTypes(sch, &typescript.TypeConfig{
|
||||
for _, def := range sfg {
|
||||
f, err := generators.GenerateTypesTS(def.CueFile, &generators.TSConfig{
|
||||
CuetsyConfig: &cuetsy.Config{
|
||||
ImportMapper: cuectx.MapCUEImportToTS,
|
||||
ImportMapper: MapCUEImportToTS,
|
||||
},
|
||||
RootName: def.Props().Common().Name,
|
||||
Group: def.Props().Common().LineageIsGroup,
|
||||
RootName: def.Name,
|
||||
IsGroup: def.IsGroup,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", def.Props().Common().Name, err)
|
||||
return nil, fmt.Errorf("%s: %w", def.Name, err)
|
||||
}
|
||||
// The obvious approach would be calling renameSpecNode() here, same as in the ts resource jenny,
|
||||
// to rename the "spec" field to the name of the kind. But that was causing extra
|
||||
@ -66,7 +60,7 @@ func (gen *genTSVeneerIndex) Generate(kinds ...kindsys.Kind) (*codejen.File, err
|
||||
|
||||
elems, err := gen.extractTSIndexVeneerElements(def, f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", def.Props().Common().Name, err)
|
||||
return nil, fmt.Errorf("%s: %w", def.Name, err)
|
||||
}
|
||||
tsf.Nodes = append(tsf.Nodes, elems...)
|
||||
}
|
||||
@ -74,12 +68,9 @@ func (gen *genTSVeneerIndex) Generate(kinds ...kindsys.Kind) (*codejen.File, err
|
||||
return codejen.NewFile(filepath.Join(gen.dir, "index.gen.ts"), []byte(tsf.String()), gen), nil
|
||||
}
|
||||
|
||||
func (gen *genTSVeneerIndex) extractTSIndexVeneerElements(def kindsys.Kind, tf *ast.File) ([]ast.Decl, error) {
|
||||
lin := def.Lineage()
|
||||
comm := def.Props().Common()
|
||||
|
||||
func (gen *genTSVeneerIndex) extractTSIndexVeneerElements(def SchemaForGen, tf *ast.File) ([]ast.Decl, error) {
|
||||
// Check the root, then walk the tree
|
||||
rootv := lin.Latest().Underlying().LookupPath(schPath)
|
||||
rootv := def.CueFile.LookupPath(cue.ParsePath("lineage.schemas[0].schema"))
|
||||
|
||||
var raw, custom, rawD, customD ast.Idents
|
||||
|
||||
@ -105,7 +96,7 @@ func (gen *genTSVeneerIndex) extractTSIndexVeneerElements(def kindsys.Kind, tf *
|
||||
}
|
||||
|
||||
// Search the generated TS AST for the type and default def nodes
|
||||
pair := findDeclNode(name, comm.Name, tf)
|
||||
pair := findDeclNode(name, def.Name, tf)
|
||||
if pair.T == nil {
|
||||
// No generated type for this item, skip it
|
||||
return false
|
||||
@ -152,29 +143,32 @@ func (gen *genTSVeneerIndex) extractTSIndexVeneerElements(def kindsys.Kind, tf *
|
||||
return nil, terr
|
||||
}
|
||||
|
||||
vpath := fmt.Sprintf("v%v", thema.Lineage.Latest(lin).Version())
|
||||
if def.Props().Common().Maturity.Less(kindsys.MaturityStable) {
|
||||
vpath = "x"
|
||||
}
|
||||
vpath := "x"
|
||||
machineName := strings.ToLower(def.Name)
|
||||
|
||||
ret := make([]ast.Decl, 0)
|
||||
if len(raw) > 0 {
|
||||
ret = append(ret, ast.ExportSet{
|
||||
CommentList: []ast.Comment{ts.CommentFromString(fmt.Sprintf("Raw generated types from %s kind.", comm.Name), 80, false)},
|
||||
CommentList: []ast.Comment{ts.CommentFromString(fmt.Sprintf("Raw generated types from %s kind.", def.Name), 80, false)},
|
||||
TypeOnly: true,
|
||||
Exports: raw,
|
||||
From: ast.Str{Value: fmt.Sprintf("./raw/%s/%s/%s_types.gen", comm.MachineName, vpath, comm.MachineName)},
|
||||
From: ast.Str{Value: fmt.Sprintf("./raw/%s/%s/%s_types.gen", machineName, vpath, machineName)},
|
||||
})
|
||||
}
|
||||
if len(rawD) > 0 {
|
||||
ret = append(ret, ast.ExportSet{
|
||||
CommentList: []ast.Comment{ts.CommentFromString(fmt.Sprintf("Raw generated enums and default consts from %s kind.", lin.Name()), 80, false)},
|
||||
CommentList: []ast.Comment{ts.CommentFromString(fmt.Sprintf("Raw generated enums and default consts from %s kind.", machineName), 80, false)},
|
||||
TypeOnly: false,
|
||||
Exports: rawD,
|
||||
From: ast.Str{Value: fmt.Sprintf("./raw/%s/%s/%s_types.gen", comm.MachineName, vpath, comm.MachineName)},
|
||||
From: ast.Str{Value: fmt.Sprintf("./raw/%s/%s/%s_types.gen", machineName, vpath, machineName)},
|
||||
})
|
||||
}
|
||||
vtfile := fmt.Sprintf("./veneer/%s.types", lin.Name())
|
||||
vtfile := fmt.Sprintf("./veneer/%s.types", machineName)
|
||||
version, err := getVersion(def.CueFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
customstr := fmt.Sprintf(`// The following exported declarations correspond to types in the %s@%s kind's
|
||||
// schema with attribute @grafana(TSVeneer="type").
|
||||
//
|
||||
@ -184,7 +178,7 @@ func (gen *genTSVeneerIndex) extractTSIndexVeneerElements(def kindsys.Kind, tf *
|
||||
// and exports all the symbols in the list.
|
||||
//
|
||||
// TODO generate code such that tsc enforces type compatibility between raw and veneer decls`,
|
||||
lin.Name(), thema.Lineage.Latest(lin).Version(), filepath.ToSlash(filepath.Join(gen.dir, vtfile)))
|
||||
machineName, strings.ReplaceAll(version, "-", "."), filepath.ToSlash(filepath.Join(gen.dir, vtfile)))
|
||||
|
||||
customComments := []ast.Comment{{Text: customstr}}
|
||||
if len(custom) > 0 {
|
||||
|
@ -27,21 +27,6 @@ func PrefixDropper(prefix string) dstutil.ApplyFunc {
|
||||
}).applyfunc
|
||||
}
|
||||
|
||||
// PrefixReplacer returns a dstutil.ApplyFunc that removes the provided prefix
|
||||
// string when it appears as a leading sequence in type names, var names, and
|
||||
// comments in a generated Go file.
|
||||
//
|
||||
// When an exact match for prefix is found, the provided replace string
|
||||
// is substituted.
|
||||
func PrefixReplacer(prefix, replace string) dstutil.ApplyFunc {
|
||||
return (&prefixmod{
|
||||
prefix: prefix,
|
||||
replace: replace,
|
||||
rxpsuff: regexp.MustCompile(fmt.Sprintf(`%s([a-zA-Z_]+)`, prefix)),
|
||||
rxp: regexp.MustCompile(fmt.Sprintf(`%s([\s.,;-])`, prefix)),
|
||||
}).applyfunc
|
||||
}
|
||||
|
||||
func depoint(e dst.Expr) dst.Expr {
|
||||
if star, is := e.(*dst.StarExpr); is {
|
||||
return star.X
|
||||
|
@ -1,4 +1,4 @@
|
||||
package cuectx
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -13,8 +13,6 @@ import (
|
||||
// indicates the import path should be dropped in the conversion to TS. Imports
|
||||
// not present in the list are not allowed, and code generation will fail.
|
||||
var importMap = map[string]string{
|
||||
"github.com/grafana/thema": "",
|
||||
"github.com/grafana/kindsys": "",
|
||||
"github.com/grafana/grafana/pkg/plugins/pfs": "",
|
||||
"github.com/grafana/grafana/packages/grafana-schema/src/common": "@grafana/schema",
|
||||
}
|
||||
@ -37,8 +35,6 @@ func init() {
|
||||
// Grafana kind definitions.
|
||||
func PermittedCUEImports() []string {
|
||||
return []string{
|
||||
"github.com/grafana/thema",
|
||||
"github.com/grafana/kindsys",
|
||||
"github.com/grafana/grafana/pkg/plugins/pfs",
|
||||
"github.com/grafana/grafana/packages/grafana-schema/src/common",
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
// Package cuectx provides a single, central ["cuelang.org/go/cue".Context] and
|
||||
// ["github.com/grafana/thema".Runtime] that can be used uniformly across
|
||||
// Grafana, and related helper functions for loading Thema lineages.
|
||||
|
||||
package cuectx
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/cuecontext"
|
||||
"github.com/grafana/thema"
|
||||
"github.com/grafana/thema/vmux"
|
||||
)
|
||||
|
||||
// CoreDefParentPath is the path, relative to the repository root, where
|
||||
// each child directory is expected to contain .cue files defining one
|
||||
// Core kind.
|
||||
var CoreDefParentPath = "kinds"
|
||||
|
||||
// GoCoreKindParentPath is the path, relative to the repository root, to the directory
|
||||
// containing one directory per kind, full of generated Go kind output: types and bindings.
|
||||
var GoCoreKindParentPath = filepath.Join("pkg", "kinds")
|
||||
|
||||
// TSCoreKindParentPath is the path, relative to the repository root, to the directory that
|
||||
// contains one directory per kind, full of generated TS kind output: types and default consts.
|
||||
var TSCoreKindParentPath = filepath.Join("packages", "grafana-schema", "src", "raw")
|
||||
|
||||
var (
|
||||
ctx *cue.Context
|
||||
rt *thema.Runtime
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
func initContext() {
|
||||
once.Do(func() {
|
||||
ctx = cuecontext.New()
|
||||
rt = thema.NewRuntime(ctx)
|
||||
})
|
||||
}
|
||||
|
||||
// GrafanaCUEContext returns Grafana's singleton instance of [cue.Context].
|
||||
//
|
||||
// All code within grafana/grafana that needs a *cue.Context should get it
|
||||
// from this function, when one was not otherwise provided.
|
||||
func GrafanaCUEContext() *cue.Context {
|
||||
initContext()
|
||||
return ctx
|
||||
}
|
||||
|
||||
// GrafanaThemaRuntime returns Grafana's singleton instance of [thema.Runtime].
|
||||
//
|
||||
// All code within grafana/grafana that needs a *thema.Runtime should get it
|
||||
// from this function, when one was not otherwise provided.
|
||||
func GrafanaThemaRuntime() *thema.Runtime {
|
||||
initContext()
|
||||
return rt
|
||||
}
|
||||
|
||||
// JSONtoCUE attempts to decode the given []byte into a cue.Value, relying on
|
||||
// the central Grafana cue.Context provided in this package.
|
||||
//
|
||||
// The provided path argument determines the name given to the input bytes if
|
||||
// later CUE operations (e.g. Thema validation) produce errors related to the
|
||||
// returned cue.Value.
|
||||
//
|
||||
// This is a convenience function for one-off JSON decoding. It's wasteful to
|
||||
// call it repeatedly. Most use cases should probably prefer making
|
||||
// their own Thema/CUE decoders.
|
||||
func JSONtoCUE(path string, b []byte) (cue.Value, error) {
|
||||
return vmux.NewJSONCodec(path).Decode(GrafanaCUEContext(), b)
|
||||
}
|
@ -1,239 +0,0 @@
|
||||
package cuectx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
"testing/fstest"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/build"
|
||||
"cuelang.org/go/cue/cuecontext"
|
||||
"github.com/grafana/kindsys"
|
||||
"github.com/grafana/thema"
|
||||
"github.com/grafana/thema/load"
|
||||
"github.com/yalue/merged_fs"
|
||||
|
||||
"github.com/grafana/grafana"
|
||||
)
|
||||
|
||||
// LoadGrafanaInstancesWithThema loads CUE files containing a lineage
|
||||
// representing some Grafana core model schema. It is expected to be used when
|
||||
// implementing a thema.LineageFactory.
|
||||
//
|
||||
// This function primarily juggles paths to make CUE's loader happy. Provide the
|
||||
// path from the grafana root to the directory containing the lineage.cue. The
|
||||
// lineage.cue file must be the sole contents of the provided fs.FS.
|
||||
//
|
||||
// More details on underlying behavior can be found in the docs for github.com/grafana/thema/load.InstanceWithThema.
|
||||
//
|
||||
// TODO this approach is complicated and confusing, refactor to something understandable
|
||||
func LoadGrafanaInstancesWithThema(path string, cueFS fs.FS, rt *thema.Runtime, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
prefix := filepath.FromSlash(path)
|
||||
fs, err := prefixWithGrafanaCUE(prefix, cueFS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inst, err := load.InstanceWithThema(fs, prefix)
|
||||
|
||||
// Need to trick loading by creating the embedded file and
|
||||
// making it look like a module in the root dir.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
val := rt.Context().BuildInstance(inst)
|
||||
|
||||
lin, err := thema.BindLineage(val, rt, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return lin, nil
|
||||
}
|
||||
|
||||
// prefixWithGrafanaCUE constructs an fs.FS that merges the provided fs.FS with
|
||||
// the embedded FS containing Grafana's core CUE files, [grafana.CueSchemaFS].
|
||||
// The provided prefix should be the relative path from the grafana repository
|
||||
// root to the directory root of the provided inputfs.
|
||||
//
|
||||
// The returned fs.FS is suitable for passing to a CUE loader, such as [load.InstanceWithThema].
|
||||
func prefixWithGrafanaCUE(prefix string, inputfs fs.FS) (fs.FS, error) {
|
||||
m, err := prefixFS(prefix, inputfs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return merged_fs.NewMergedFS(m, grafana.CueSchemaFS), nil
|
||||
}
|
||||
|
||||
// TODO such a waste, replace with stateless impl that just transforms paths on the fly
|
||||
func prefixFS(prefix string, fsys fs.FS) (fs.FS, error) {
|
||||
m := make(fstest.MapFS)
|
||||
|
||||
prefix = filepath.FromSlash(prefix)
|
||||
err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
b, err := fs.ReadFile(fsys, filepath.ToSlash(path))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// fstest can recognize only forward slashes.
|
||||
m[filepath.ToSlash(filepath.Join(prefix, path))] = &fstest.MapFile{Data: b}
|
||||
return nil
|
||||
})
|
||||
return m, err
|
||||
}
|
||||
|
||||
// LoadGrafanaInstance wraps [load.InstanceWithThema] to load a
|
||||
// [*build.Instance] corresponding to a particular path within the
|
||||
// github.com/grafana/grafana CUE module.
|
||||
//
|
||||
// This allows resolution of imports within the grafana or thema CUE modules to
|
||||
// work correctly and consistently by relying on the embedded FS at
|
||||
// [grafana.CueSchemaFS] and [thema.CueFS].
|
||||
//
|
||||
// relpath should be a relative path path within [grafana.CueSchemaFS] to be
|
||||
// loaded. Optionally, the caller may provide an additional fs.FS via the
|
||||
// overlay parameter, which will be merged with [grafana.CueSchemaFS] at
|
||||
// relpath, and loaded.
|
||||
//
|
||||
// pkg, if non-empty, is set as the value of
|
||||
// ["cuelang.org/go/cue/load".Config.Package]. If the CUE package to be loaded
|
||||
// is the same as the parent directory name, it should be omitted.
|
||||
//
|
||||
// NOTE this function will be deprecated in favor of a more generic loader
|
||||
func LoadGrafanaInstance(relpath string, pkg string, overlay fs.FS) (*build.Instance, error) {
|
||||
// notes about how this crap needs to work
|
||||
//
|
||||
// Within grafana/grafana, need:
|
||||
// - pass in an fs.FS that, in its root, contains the .cue files to load
|
||||
// - has no cue.mod
|
||||
// - gets prefixed with the appropriate path within grafana/grafana
|
||||
// - and merged with all the other .cue files from grafana/grafana
|
||||
// notes about how this crap needs to work
|
||||
//
|
||||
// Need a prefixing instance loader that:
|
||||
// - can take multiple fs.FS, each one representing a CUE module (nesting?)
|
||||
// - reconcile at most one of the provided fs with cwd
|
||||
// - behavior must differ depending on whether cwd is in a cue module
|
||||
// - behavior should(?) be controllable depending on
|
||||
relpath = filepath.ToSlash(relpath)
|
||||
|
||||
var f fs.FS = grafana.CueSchemaFS
|
||||
// merge the kindsys filesystem with ours for the kind categories
|
||||
f = merged_fs.NewMergedFS(kindsys.CueSchemaFS, f)
|
||||
|
||||
var err error
|
||||
if overlay != nil {
|
||||
f, err = prefixWithGrafanaCUE(relpath, overlay)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// merge the kindsys filesystem with ours for the kind categories
|
||||
f = merged_fs.NewMergedFS(kindsys.CueSchemaFS, f)
|
||||
}
|
||||
|
||||
if pkg != "" {
|
||||
return load.InstanceWithThema(f, relpath, load.Package(pkg))
|
||||
}
|
||||
return load.InstanceWithThema(f, relpath)
|
||||
}
|
||||
|
||||
// BuildGrafanaInstance wraps [LoadGrafanaInstance], additionally building
|
||||
// the returned [*build.Instance] into a [cue.Value].
|
||||
//
|
||||
// An error is returned if:
|
||||
// - The underlying call to [LoadGrafanaInstance] returns an error
|
||||
// - The built [cue.Value] has an error ([cue.Value.Err] returns non-nil)
|
||||
//
|
||||
// NOTE this function will be deprecated in favor of a more generic builder
|
||||
func BuildGrafanaInstance(ctx *cue.Context, relpath string, pkg string, overlay fs.FS) (cue.Value, error) {
|
||||
bi, err := LoadGrafanaInstance(relpath, pkg, overlay)
|
||||
if err != nil {
|
||||
return cue.Value{}, err
|
||||
}
|
||||
|
||||
if ctx == nil {
|
||||
ctx = GrafanaCUEContext()
|
||||
}
|
||||
v := ctx.BuildInstance(bi)
|
||||
if v.Err() != nil {
|
||||
return v, fmt.Errorf("%s not a valid CUE instance: %w", relpath, v.Err())
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// LoadInstanceWithGrafana loads a [*build.Instance] from .cue files
|
||||
// in the provided modFS as ["cuelang.org/go/cue/load".Instances], but
|
||||
// fulfilling any imports of CUE packages under:
|
||||
//
|
||||
// - github.com/grafana/grafana
|
||||
// - github.com/grafana/thema
|
||||
//
|
||||
// This function is modeled after [load.InstanceWithThema]. It has the same
|
||||
// signature and expectations for the modFS.
|
||||
//
|
||||
// Attempting to use this func to load files within the
|
||||
// github.com/grafana/grafana CUE module will result in an error. Use
|
||||
// [LoadGrafanaInstance] instead.
|
||||
//
|
||||
// NOTE This function will be deprecated in favor of a more generic loader
|
||||
func LoadInstanceWithGrafana(fsys fs.FS, dir string, opts ...load.Option) (*build.Instance, error) {
|
||||
if modf, err := fs.ReadFile(fsys, "cue.mod/module.cue"); err != nil {
|
||||
// delegate error handling
|
||||
return load.InstanceWithThema(fsys, dir, opts...)
|
||||
} else if modname, err := cuecontext.New().CompileBytes(modf).LookupPath(cue.MakePath(cue.Str("module"))).String(); err != nil {
|
||||
// delegate error handling
|
||||
return load.InstanceWithThema(fsys, dir, opts...)
|
||||
} else if modname == "github.com/grafana/grafana" {
|
||||
return nil, fmt.Errorf("use cuectx.LoadGrafanaInstance to load .cue files within github.com/grafana/grafana CUE module")
|
||||
}
|
||||
|
||||
// TODO wasteful, doing this every time - make that stateless prefixfs!
|
||||
depFS, err := prefixFS("cue.mod/pkg/github.com/grafana/grafana", grafana.CueSchemaFS)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// TODO wasteful, doing this every time - make that stateless prefixfs!
|
||||
kindsysFS, err := prefixFS("cue.mod/pkg/github.com/grafana/kindsys", kindsys.CueSchemaFS)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
allTheFs := merged_fs.MergeMultiple(kindsysFS, depFS, fsys)
|
||||
|
||||
// FIXME remove grafana from cue.mod/pkg if it exists, otherwise external thing can inject files to be loaded
|
||||
return load.InstanceWithThema(allTheFs, dir, opts...)
|
||||
}
|
||||
|
||||
// LoadCoreKindDef loads and validates a core kind definition of the kind
|
||||
// category indicated by the type parameter. On success, it returns a [Def]
|
||||
// which contains the entire contents of the kind definition.
|
||||
//
|
||||
// defpath is the path to the directory containing the core kind definition,
|
||||
// relative to the root of the caller's repository. For example, under
|
||||
// dashboards are in "kinds/dashboard".
|
||||
func LoadCoreKindDef(defpath string, ctx *cue.Context, overlay fs.FS) (kindsys.Def[kindsys.CoreProperties], error) {
|
||||
vk, err := BuildGrafanaInstance(ctx, defpath, "kind", overlay)
|
||||
if err != nil {
|
||||
return kindsys.Def[kindsys.CoreProperties]{}, err
|
||||
}
|
||||
|
||||
props, err := kindsys.ToKindProps[kindsys.CoreProperties](vk)
|
||||
if err != nil {
|
||||
return kindsys.Def[kindsys.CoreProperties]{}, err
|
||||
}
|
||||
|
||||
return kindsys.Def[kindsys.CoreProperties]{
|
||||
V: vk,
|
||||
Properties: props,
|
||||
}, nil
|
||||
}
|
@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/codejen"
|
||||
"github.com/grafana/grafana/pkg/plugins/pfs"
|
||||
)
|
||||
|
||||
var registryPath = filepath.Join("pkg", "registry", "schemas")
|
||||
@ -27,21 +28,22 @@ func (jenny *PluginRegistryJenny) JennyName() string {
|
||||
return "PluginRegistryJenny"
|
||||
}
|
||||
|
||||
func (jenny *PluginRegistryJenny) Generate(files []string) (*codejen.File, error) {
|
||||
if len(files) == 0 {
|
||||
func (jenny *PluginRegistryJenny) Generate(decls ...*pfs.PluginDecl) (*codejen.File, error) {
|
||||
if len(decls) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
schemas := make([]Schema, len(files))
|
||||
for i, file := range files {
|
||||
name, err := getSchemaName(file)
|
||||
schemas := make([]Schema, len(decls))
|
||||
for i, decl := range decls {
|
||||
variant := fmt.Sprintf("%s.cue", strings.ToLower(decl.SchemaInterface.Name))
|
||||
name, err := getSchemaName(decl.PluginPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to find schema name: %s", err)
|
||||
}
|
||||
|
||||
schemas[i] = Schema{
|
||||
Name: name,
|
||||
Filename: filepath.Base(file),
|
||||
FilePath: file,
|
||||
Filename: variant,
|
||||
FilePath: "./" + filepath.Join("public", "app", "plugins", decl.PluginPath, variant),
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +67,7 @@ func getSchemaName(path string) (string, error) {
|
||||
if len(parts) < 2 {
|
||||
return "", fmt.Errorf("path should contain more than 2 elements")
|
||||
}
|
||||
folderName := parts[len(parts)-2]
|
||||
folderName := parts[len(parts)-1]
|
||||
if renamed, ok := renamedPlugins[folderName]; ok {
|
||||
folderName = renamed
|
||||
}
|
||||
|
@ -6,12 +6,9 @@ import (
|
||||
"strings"
|
||||
|
||||
copenapi "cuelang.org/go/encoding/openapi"
|
||||
"github.com/dave/dst/dstutil"
|
||||
"github.com/grafana/codejen"
|
||||
corecodegen "github.com/grafana/grafana/pkg/codegen"
|
||||
"github.com/grafana/grafana/pkg/codegen/generators"
|
||||
"github.com/grafana/grafana/pkg/plugins/pfs"
|
||||
"github.com/grafana/thema/encoding/gocode"
|
||||
"github.com/grafana/thema/encoding/openapi"
|
||||
)
|
||||
|
||||
// TODO this is duplicative of other Go type jennies. Remove it in favor of a better-abstracted version in thema itself
|
||||
@ -30,22 +27,22 @@ func (j *pgoJenny) JennyName() string {
|
||||
}
|
||||
|
||||
func (j *pgoJenny) Generate(decl *pfs.PluginDecl) (*codejen.File, error) {
|
||||
b := decl.PluginMeta.Backend
|
||||
if b == nil || !*b || !decl.HasSchema() {
|
||||
hasBackend := decl.PluginMeta.Backend
|
||||
// We skip elasticsearch since we have problems with the generated file.
|
||||
// This is temporal until we migrate to the new system.
|
||||
if hasBackend == nil || !*hasBackend || decl.PluginMeta.Id == "elasticsearch" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
slotname := strings.ToLower(decl.SchemaInterface.Name)
|
||||
byt, err := gocode.GenerateTypesOpenAPI(decl.Lineage.Latest(), &gocode.TypeConfigOpenAPI{
|
||||
Config: &openapi.Config{
|
||||
Group: decl.SchemaInterface.IsGroup,
|
||||
byt, err := generators.GenerateTypesGo(decl.CueFile, &generators.GoConfig{
|
||||
Config: &generators.OpenApiConfig{
|
||||
Config: &copenapi.Config{
|
||||
MaxCycleDepth: 10,
|
||||
},
|
||||
SplitSchema: true,
|
||||
IsGroup: decl.SchemaInterface.IsGroup,
|
||||
},
|
||||
PackageName: slotname,
|
||||
ApplyFuncs: []dstutil.ApplyFunc{corecodegen.PrefixDropper(decl.Lineage.Name())},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
tsast "github.com/grafana/cuetsy/ts/ast"
|
||||
"github.com/grafana/grafana/pkg/build"
|
||||
"github.com/grafana/grafana/pkg/codegen"
|
||||
"github.com/grafana/grafana/pkg/cuectx"
|
||||
"github.com/grafana/grafana/pkg/plugins/pfs"
|
||||
)
|
||||
|
||||
@ -34,15 +33,11 @@ func (j *ptsJenny) JennyName() string {
|
||||
}
|
||||
|
||||
func (j *ptsJenny) Generate(decl *pfs.PluginDecl) (codejen.Files, error) {
|
||||
if !decl.HasSchema() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
genFile := &tsast.File{}
|
||||
versionedFile := &tsast.File{}
|
||||
|
||||
for _, im := range decl.Imports {
|
||||
if tsim, err := cuectx.ConvertImport(im); err != nil {
|
||||
if tsim, err := codegen.ConvertImport(im); err != nil {
|
||||
return nil, err
|
||||
} else if tsim.From.Value != "" {
|
||||
genFile.Imports = append(genFile.Imports, tsim)
|
||||
@ -94,18 +89,46 @@ func getPluginVersion(pluginVersion *string) string {
|
||||
|
||||
func adaptToPipeline(j codejen.OneToOne[codegen.SchemaForGen]) codejen.OneToOne[*pfs.PluginDecl] {
|
||||
return codejen.AdaptOneToOne(j, func(pd *pfs.PluginDecl) codegen.SchemaForGen {
|
||||
name := strings.ReplaceAll(pd.PluginMeta.Name, " ", "")
|
||||
if pd.SchemaInterface.Name == "DataQuery" {
|
||||
name = name + "DataQuery"
|
||||
}
|
||||
return codegen.SchemaForGen{
|
||||
Name: name,
|
||||
Schema: pd.Lineage.Latest(),
|
||||
Name: derivePascalName(pd.PluginMeta.Id, pd.PluginMeta.Name) + pd.SchemaInterface.Name,
|
||||
CueFile: pd.CueFile,
|
||||
IsGroup: pd.SchemaInterface.IsGroup,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func derivePascalName(id string, name string) string {
|
||||
sani := func(s string) string {
|
||||
ret := strings.Title(strings.Map(func(r rune) rune {
|
||||
switch {
|
||||
case r >= 'a' && r <= 'z':
|
||||
return r
|
||||
case r >= 'A' && r <= 'Z':
|
||||
return r
|
||||
default:
|
||||
return -1
|
||||
}
|
||||
}, strings.Title(strings.Map(func(r rune) rune {
|
||||
switch r {
|
||||
case '-', '_':
|
||||
return ' '
|
||||
default:
|
||||
return r
|
||||
}
|
||||
}, s))))
|
||||
if len(ret) > 63 {
|
||||
return ret[:63]
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
fromname := sani(name)
|
||||
if len(fromname) != 0 {
|
||||
return fromname
|
||||
}
|
||||
return sani(strings.Split(id, "-")[1])
|
||||
}
|
||||
|
||||
func getGrafanaVersion() string {
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
|
@ -1,30 +0,0 @@
|
||||
package corelist
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/grafana/grafana/pkg/cuectx"
|
||||
"github.com/grafana/grafana/pkg/plugins/pfs"
|
||||
"github.com/grafana/thema"
|
||||
)
|
||||
|
||||
var coreTrees []pfs.ParsedPlugin
|
||||
var coreOnce sync.Once
|
||||
|
||||
// New returns a pfs.PluginList containing the plugin trees for all core plugins
|
||||
// in the current version of Grafana.
|
||||
//
|
||||
// Go code within the grafana codebase should only ever call this with nil.
|
||||
func New(rt *thema.Runtime) []pfs.ParsedPlugin {
|
||||
var pl []pfs.ParsedPlugin
|
||||
if rt == nil {
|
||||
coreOnce.Do(func() {
|
||||
coreTrees = corePlugins(cuectx.GrafanaThemaRuntime())
|
||||
})
|
||||
pl = make([]pfs.ParsedPlugin, len(coreTrees))
|
||||
copy(pl, coreTrees)
|
||||
} else {
|
||||
return corePlugins(rt)
|
||||
}
|
||||
return pl
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||
//
|
||||
// Generated by:
|
||||
// public/app/plugins/gen.go
|
||||
// Using jennies:
|
||||
// PluginTreeListJenny
|
||||
//
|
||||
// Run 'make gen-cue' from repository root to regenerate.
|
||||
|
||||
package corelist
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
|
||||
"github.com/grafana/grafana"
|
||||
"github.com/grafana/grafana/pkg/plugins/pfs"
|
||||
"github.com/grafana/thema"
|
||||
)
|
||||
|
||||
func parsePluginOrPanic(path string, pkgname string, rt *thema.Runtime) pfs.ParsedPlugin {
|
||||
sub, err := fs.Sub(grafana.CueSchemaFS, path)
|
||||
if err != nil {
|
||||
panic("could not create fs sub to " + path)
|
||||
}
|
||||
pp, err := pfs.ParsePluginFS(sub, rt)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("error parsing plugin metadata for %s: %s", pkgname, err))
|
||||
}
|
||||
return pp
|
||||
}
|
||||
|
||||
func corePlugins(rt *thema.Runtime) []pfs.ParsedPlugin {
|
||||
return []pfs.ParsedPlugin{
|
||||
parsePluginOrPanic("public/app/plugins/datasource/alertmanager", "alertmanager", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/azuremonitor", "grafana_azure_monitor_datasource", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/cloud-monitoring", "stackdriver", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/cloudwatch", "cloudwatch", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/dashboard", "dashboard", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/elasticsearch", "elasticsearch", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/grafana", "grafana", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/grafana-postgresql-datasource", "grafana_postgresql_datasource", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/grafana-pyroscope-datasource", "grafana_pyroscope_datasource", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/grafana-testdata-datasource", "grafana_testdata_datasource", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/graphite", "graphite", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/jaeger", "jaeger", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/loki", "loki", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/mssql", "mssql", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/mysql", "mysql", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/parca", "parca", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/prometheus", "prometheus", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/tempo", "tempo", rt),
|
||||
parsePluginOrPanic("public/app/plugins/datasource/zipkin", "zipkin", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/alertlist", "alertlist", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/annolist", "annolist", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/barchart", "barchart", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/bargauge", "bargauge", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/candlestick", "candlestick", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/canvas", "canvas", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/dashlist", "dashlist", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/datagrid", "datagrid", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/debug", "debug", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/flamegraph", "flamegraph", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/gauge", "gauge", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/geomap", "geomap", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/gettingstarted", "gettingstarted", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/graph", "graph", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/heatmap", "heatmap", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/histogram", "histogram", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/live", "live", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/logs", "logs", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/news", "news", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/nodeGraph", "nodeGraph", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/piechart", "piechart", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/stat", "stat", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/state-timeline", "state_timeline", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/status-history", "status_history", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/table", "table", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/table-old", "table_old", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/text", "text", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/timeseries", "timeseries", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/traces", "traces", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/trend", "trend", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/welcome", "welcome", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/xychart", "xychart", rt),
|
||||
}
|
||||
}
|
@ -1,18 +1,16 @@
|
||||
package pfs
|
||||
|
||||
import (
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/ast"
|
||||
"github.com/grafana/kindsys"
|
||||
"github.com/grafana/thema"
|
||||
)
|
||||
|
||||
type PluginDecl struct {
|
||||
SchemaInterface *SchemaInterface
|
||||
Lineage thema.Lineage
|
||||
SchemaInterface SchemaInterface
|
||||
CueFile cue.Value
|
||||
Imports []*ast.ImportSpec
|
||||
PluginPath string
|
||||
PluginMeta Metadata
|
||||
KindDecl kindsys.Def[kindsys.ComposableProperties]
|
||||
}
|
||||
|
||||
type SchemaInterface struct {
|
||||
@ -26,15 +24,3 @@ type Metadata struct {
|
||||
Backend *bool
|
||||
Version *string
|
||||
}
|
||||
|
||||
func EmptyPluginDecl(path string, meta Metadata) *PluginDecl {
|
||||
return &PluginDecl{
|
||||
PluginPath: path,
|
||||
PluginMeta: meta,
|
||||
Imports: make([]*ast.ImportSpec, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (decl *PluginDecl) HasSchema() bool {
|
||||
return decl.Lineage != nil && decl.SchemaInterface != nil
|
||||
}
|
||||
|
@ -6,35 +6,22 @@ import (
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"github.com/grafana/thema"
|
||||
"cuelang.org/go/cue/cuecontext"
|
||||
)
|
||||
|
||||
type declParser struct {
|
||||
rt *thema.Runtime
|
||||
type DeclParser struct {
|
||||
skip map[string]bool
|
||||
}
|
||||
|
||||
// Extracted from kindsys repository
|
||||
var schemaInterfaces = map[string]*SchemaInterface{
|
||||
"PanelCfg": {
|
||||
Name: "PanelCfg",
|
||||
IsGroup: true,
|
||||
},
|
||||
"DataQuery": {
|
||||
Name: "DataQuery",
|
||||
IsGroup: false,
|
||||
},
|
||||
}
|
||||
|
||||
func NewDeclParser(rt *thema.Runtime, skip map[string]bool) *declParser {
|
||||
return &declParser{
|
||||
rt: rt,
|
||||
func NewDeclParser(skip map[string]bool) *DeclParser {
|
||||
return &DeclParser{
|
||||
skip: skip,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO convert this to be the new parser for Tree
|
||||
func (psr *declParser) Parse(root fs.FS) ([]*PluginDecl, error) {
|
||||
func (psr *DeclParser) Parse(root fs.FS) ([]*PluginDecl, error) {
|
||||
ctx := cuecontext.New()
|
||||
// TODO remove hardcoded tree structure assumption, work from root of provided fs
|
||||
plugins, err := fs.Glob(root, "**/**/plugin.json")
|
||||
if err != nil {
|
||||
@ -50,29 +37,22 @@ func (psr *declParser) Parse(root fs.FS) ([]*PluginDecl, error) {
|
||||
}
|
||||
|
||||
dir, _ := fs.Sub(root, path)
|
||||
pp, err := ParsePluginFS(dir, psr.rt)
|
||||
pp, err := ParsePluginFS(ctx, dir, path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing plugin failed for %s: %s", dir, err)
|
||||
}
|
||||
|
||||
if len(pp.ComposableKinds) == 0 {
|
||||
decls = append(decls, EmptyPluginDecl(path, pp.Properties))
|
||||
if !pp.CueFile.Exists() {
|
||||
continue
|
||||
}
|
||||
|
||||
for slotName, kind := range pp.ComposableKinds {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing plugin failed for %s: %s", dir, err)
|
||||
}
|
||||
decls = append(decls, &PluginDecl{
|
||||
SchemaInterface: schemaInterfaces[slotName],
|
||||
Lineage: kind.Lineage(),
|
||||
Imports: pp.CUEImports,
|
||||
PluginMeta: pp.Properties,
|
||||
PluginPath: path,
|
||||
KindDecl: kind.Def(),
|
||||
})
|
||||
}
|
||||
decls = append(decls, &PluginDecl{
|
||||
SchemaInterface: pp.Variant,
|
||||
CueFile: pp.CueFile,
|
||||
Imports: pp.CUEImports,
|
||||
PluginMeta: pp.Properties,
|
||||
PluginPath: path,
|
||||
})
|
||||
}
|
||||
|
||||
sort.Slice(decls, func(i, j int) bool {
|
||||
|
@ -4,29 +4,32 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing/fstest"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/cuecontext"
|
||||
"cuelang.org/go/cue/errors"
|
||||
"cuelang.org/go/cue/token"
|
||||
"github.com/grafana/kindsys"
|
||||
"github.com/grafana/thema"
|
||||
"github.com/grafana/thema/load"
|
||||
"github.com/yalue/merged_fs"
|
||||
|
||||
"github.com/grafana/grafana/pkg/cuectx"
|
||||
"cuelang.org/go/cue/load"
|
||||
"github.com/grafana/grafana/pkg/codegen"
|
||||
)
|
||||
|
||||
// PackageName is the name of the CUE package that Grafana will load when
|
||||
// looking for a Grafana plugin's kind declarations.
|
||||
const PackageName = "grafanaplugin"
|
||||
|
||||
var schemaInterface = map[string]SchemaInterface{
|
||||
"DataQuery": {
|
||||
Name: "DataQuery",
|
||||
IsGroup: false,
|
||||
},
|
||||
"PanelCfg": {
|
||||
Name: "PanelCfg",
|
||||
IsGroup: true,
|
||||
},
|
||||
}
|
||||
|
||||
// PermittedCUEImports returns the list of import paths that may be used in a
|
||||
// plugin's grafanaplugin cue package.
|
||||
var PermittedCUEImports = cuectx.PermittedCUEImports
|
||||
var PermittedCUEImports = codegen.PermittedCUEImports
|
||||
|
||||
func importAllowed(path string) bool {
|
||||
for _, p := range PermittedCUEImports() {
|
||||
@ -39,22 +42,12 @@ func importAllowed(path string) bool {
|
||||
|
||||
var allowedImportsStr string
|
||||
|
||||
var allsi []kindsys.SchemaInterface
|
||||
|
||||
func init() {
|
||||
all := make([]string, 0, len(PermittedCUEImports()))
|
||||
for _, im := range PermittedCUEImports() {
|
||||
all = append(all, fmt.Sprintf("\t%s", im))
|
||||
}
|
||||
allowedImportsStr = strings.Join(all, "\n")
|
||||
|
||||
for _, s := range kindsys.SchemaInterfaces(nil) {
|
||||
allsi = append(allsi, s)
|
||||
}
|
||||
|
||||
sort.Slice(allsi, func(i, j int) bool {
|
||||
return allsi[i].Name() < allsi[j].Name()
|
||||
})
|
||||
}
|
||||
|
||||
// ParsePluginFS takes a virtual filesystem and checks that it contains a valid
|
||||
@ -69,17 +62,17 @@ func init() {
|
||||
// This function parses exactly one plugin. It does not descend into
|
||||
// subdirectories to search for additional plugin.json or .cue files.
|
||||
//
|
||||
// Calling this with a nil [thema.Runtime] (the singleton returned from
|
||||
// [cuectx.GrafanaThemaRuntime] is used) will memoize certain CUE operations.
|
||||
// Prefer passing nil unless a different thema.Runtime is specifically required.
|
||||
//
|
||||
// [GrafanaPlugin]: https://github.com/grafana/grafana/blob/main/pkg/plugins/pfs/grafanaplugin.cue
|
||||
func ParsePluginFS(fsys fs.FS, rt *thema.Runtime) (ParsedPlugin, error) {
|
||||
func ParsePluginFS(ctx *cue.Context, fsys fs.FS, dir string) (ParsedPlugin, error) {
|
||||
if fsys == nil {
|
||||
return ParsedPlugin{}, ErrEmptyFS
|
||||
}
|
||||
if rt == nil {
|
||||
rt = cuectx.GrafanaThemaRuntime()
|
||||
|
||||
cuefiles, err := fs.Glob(fsys, "*.cue")
|
||||
if err != nil {
|
||||
return ParsedPlugin{}, fmt.Errorf("error globbing for cue files in fsys: %w", err)
|
||||
} else if len(cuefiles) == 0 {
|
||||
return ParsedPlugin{}, nil
|
||||
}
|
||||
|
||||
metadata, err := getPluginMetadata(fsys)
|
||||
@ -88,27 +81,19 @@ func ParsePluginFS(fsys fs.FS, rt *thema.Runtime) (ParsedPlugin, error) {
|
||||
}
|
||||
|
||||
pp := ParsedPlugin{
|
||||
ComposableKinds: make(map[string]kindsys.Composable),
|
||||
Properties: metadata,
|
||||
Properties: metadata,
|
||||
}
|
||||
|
||||
if cuefiles, err := fs.Glob(fsys, "*.cue"); err != nil {
|
||||
return ParsedPlugin{}, fmt.Errorf("error globbing for cue files in fsys: %w", err)
|
||||
} else if len(cuefiles) == 0 {
|
||||
return pp, nil
|
||||
}
|
||||
|
||||
fsys, err = ensureCueMod(fsys, pp.Properties)
|
||||
if err != nil {
|
||||
return ParsedPlugin{}, fmt.Errorf("%s has invalid cue.mod: %w", pp.Properties.Id, err)
|
||||
return ParsedPlugin{}, err
|
||||
}
|
||||
|
||||
bi, err := cuectx.LoadInstanceWithGrafana(fsys, "", load.Package(PackageName))
|
||||
if err != nil || bi.Err != nil {
|
||||
if err == nil {
|
||||
err = bi.Err
|
||||
}
|
||||
return ParsedPlugin{}, errors.Wrap(errors.Newf(token.NoPos, "%s did not load", pp.Properties.Id), err)
|
||||
bi := load.Instances(cuefiles, &load.Config{
|
||||
Package: PackageName,
|
||||
Dir: dir,
|
||||
})[0]
|
||||
if bi.Err != nil {
|
||||
return ParsedPlugin{}, bi.Err
|
||||
}
|
||||
|
||||
for _, f := range bi.Files {
|
||||
@ -132,105 +117,35 @@ func ParsePluginFS(fsys fs.FS, rt *thema.Runtime) (ParsedPlugin, error) {
|
||||
panic("Refactor required - upstream CUE implementation changed, bi.Files is no longer populated")
|
||||
}
|
||||
|
||||
gpi := rt.Context().BuildInstance(bi)
|
||||
gpi := ctx.BuildInstance(bi)
|
||||
if gpi.Err() != nil {
|
||||
return ParsedPlugin{}, errors.Wrap(errors.Promote(ErrInvalidGrafanaPluginInstance, pp.Properties.Id), gpi.Err())
|
||||
}
|
||||
|
||||
for _, si := range allsi {
|
||||
iv := gpi.LookupPath(cue.MakePath(cue.Str("composableKinds"), cue.Str(si.Name())))
|
||||
for name, si := range schemaInterface {
|
||||
iv := gpi.LookupPath(cue.MakePath(cue.Str("composableKinds"), cue.Str(name)))
|
||||
if !iv.Exists() {
|
||||
continue
|
||||
}
|
||||
|
||||
iv = iv.FillPath(cue.MakePath(cue.Str("schemaInterface")), si.Name())
|
||||
iv = iv.FillPath(cue.MakePath(cue.Str("name")), derivePascalName(pp.Properties.Id, pp.Properties.Name)+si.Name())
|
||||
iv = iv.FillPath(cue.MakePath(cue.Str("schemaInterface")), name)
|
||||
iv = iv.FillPath(cue.MakePath(cue.Str("name")), derivePascalName(pp.Properties.Id, pp.Properties.Name)+name)
|
||||
lineageNamePath := iv.LookupPath(cue.MakePath(cue.Str("lineage"), cue.Str("name")))
|
||||
if !lineageNamePath.Exists() {
|
||||
iv = iv.FillPath(cue.MakePath(cue.Str("lineage"), cue.Str("name")), derivePascalName(pp.Properties.Id, pp.Properties.Name)+si.Name())
|
||||
iv = iv.FillPath(cue.MakePath(cue.Str("lineage"), cue.Str("name")), derivePascalName(pp.Properties.Id, pp.Properties.Name)+name)
|
||||
}
|
||||
|
||||
validSchema := iv.LookupPath(cue.ParsePath("lineage.schemas[0].schema"))
|
||||
if !validSchema.Exists() {
|
||||
return ParsedPlugin{}, errors.Wrap(errors.Promote(ErrInvalidGrafanaPluginInstance, pp.Properties.Id), validSchema.Err())
|
||||
}
|
||||
|
||||
props, err := kindsys.ToKindProps[kindsys.ComposableProperties](iv)
|
||||
if err != nil {
|
||||
return ParsedPlugin{}, err
|
||||
}
|
||||
|
||||
compo, err := kindsys.BindComposable(rt, kindsys.Def[kindsys.ComposableProperties]{
|
||||
Properties: props,
|
||||
V: iv,
|
||||
})
|
||||
if err != nil {
|
||||
return ParsedPlugin{}, err
|
||||
}
|
||||
pp.ComposableKinds[si.Name()] = compo
|
||||
pp.Variant = si
|
||||
pp.CueFile = iv
|
||||
}
|
||||
|
||||
return pp, nil
|
||||
}
|
||||
|
||||
// LoadComposableKindDef loads and validates a composable kind definition.
|
||||
// On success, it returns a [Def] which contains the entire contents of the kind definition.
|
||||
//
|
||||
// defpath is the path to the directory containing the composable kind definition,
|
||||
// relative to the root of the caller's repository.
|
||||
//
|
||||
// NOTE This function will be deprecated in favor of a more generic loader when kind
|
||||
// providers will be implemented.
|
||||
func LoadComposableKindDef(fsys fs.FS, rt *thema.Runtime, defpath string) (kindsys.Def[kindsys.ComposableProperties], error) {
|
||||
pp := ParsedPlugin{
|
||||
ComposableKinds: make(map[string]kindsys.Composable),
|
||||
Properties: Metadata{
|
||||
Id: defpath,
|
||||
},
|
||||
}
|
||||
|
||||
fsys, err := ensureCueMod(fsys, pp.Properties)
|
||||
if err != nil {
|
||||
return kindsys.Def[kindsys.ComposableProperties]{}, fmt.Errorf("%s has invalid cue.mod: %w", pp.Properties.Id, err)
|
||||
}
|
||||
|
||||
bi, err := cuectx.LoadInstanceWithGrafana(fsys, "", load.Package(PackageName))
|
||||
if err != nil {
|
||||
return kindsys.Def[kindsys.ComposableProperties]{}, err
|
||||
}
|
||||
|
||||
ctx := rt.Context()
|
||||
v := ctx.BuildInstance(bi)
|
||||
if v.Err() != nil {
|
||||
return kindsys.Def[kindsys.ComposableProperties]{}, fmt.Errorf("%s not a valid CUE instance: %w", defpath, v.Err())
|
||||
}
|
||||
|
||||
props, err := kindsys.ToKindProps[kindsys.ComposableProperties](v)
|
||||
if err != nil {
|
||||
return kindsys.Def[kindsys.ComposableProperties]{}, err
|
||||
}
|
||||
|
||||
return kindsys.Def[kindsys.ComposableProperties]{
|
||||
V: v,
|
||||
Properties: props,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ensureCueMod(fsys fs.FS, metadata Metadata) (fs.FS, error) {
|
||||
if modf, err := fs.ReadFile(fsys, "cue.mod/module.cue"); err != nil {
|
||||
if !errors.Is(err, fs.ErrNotExist) {
|
||||
return nil, err
|
||||
}
|
||||
return merged_fs.NewMergedFS(fsys, fstest.MapFS{
|
||||
"cue.mod/module.cue": &fstest.MapFile{Data: []byte(fmt.Sprintf(`module: "grafana.com/grafana/plugins/%s"`, metadata.Id))},
|
||||
}), nil
|
||||
} else if _, err := cuecontext.New().CompileBytes(modf).LookupPath(cue.MakePath(cue.Str("module"))).String(); err != nil {
|
||||
return nil, fmt.Errorf("error reading cue module name: %w", err)
|
||||
}
|
||||
|
||||
return fsys, nil
|
||||
}
|
||||
|
||||
func getPluginMetadata(fsys fs.FS) (Metadata, error) {
|
||||
b, err := fs.ReadFile(fsys, "plugin.json")
|
||||
if err != nil {
|
||||
|
@ -1,297 +0,0 @@
|
||||
package pfs
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/grafana/grafana/pkg/cuectx"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParsePluginTestdata(t *testing.T) {
|
||||
type tt struct {
|
||||
tfs fs.FS
|
||||
// TODO could remove this by getting rid of inconsistent subdirs
|
||||
subpath string
|
||||
skip string
|
||||
err error
|
||||
// TODO could remove this by expecting that dirname == id
|
||||
rootid string
|
||||
}
|
||||
tab := map[string]tt{
|
||||
"app-with-child": {
|
||||
rootid: "myorgid-simple-app",
|
||||
subpath: "dist",
|
||||
skip: "schema violation, weirdness in info.version field",
|
||||
},
|
||||
"duplicate-plugins": {
|
||||
rootid: "test-app",
|
||||
subpath: "nested",
|
||||
skip: "schema violation, dependencies don't follow naming constraints",
|
||||
},
|
||||
"includes-symlinks": {
|
||||
skip: "schema violation, dependencies don't follow naming constraints",
|
||||
},
|
||||
"installer": {
|
||||
rootid: "test-datasource",
|
||||
subpath: "plugin",
|
||||
},
|
||||
"invalid-plugin-json": {
|
||||
rootid: "test-app",
|
||||
err: ErrInvalidRootFile,
|
||||
},
|
||||
"invalid-v1-signature": {
|
||||
rootid: "test-datasource",
|
||||
subpath: "plugin",
|
||||
},
|
||||
"invalid-v2-extra-file": {
|
||||
rootid: "test-datasource",
|
||||
subpath: "plugin",
|
||||
},
|
||||
"invalid-v2-missing-file": {
|
||||
rootid: "test-datasource",
|
||||
subpath: "plugin",
|
||||
},
|
||||
"lacking-files": {
|
||||
rootid: "test-datasource",
|
||||
subpath: "plugin",
|
||||
},
|
||||
"nested-plugins": {
|
||||
rootid: "test-datasource",
|
||||
subpath: "parent",
|
||||
},
|
||||
"non-pvt-with-root-url": {
|
||||
rootid: "test-datasource",
|
||||
subpath: "plugin",
|
||||
},
|
||||
"renderer-added-file": {
|
||||
rootid: "test-renderer",
|
||||
subpath: "plugin",
|
||||
},
|
||||
"symbolic-plugin-dirs": {
|
||||
skip: "io/fs-based scanner will not traverse symlinks; caller of ParsePluginFS() must do it",
|
||||
},
|
||||
"test-app": {
|
||||
skip: "schema violation, dependencies don't follow naming constraints",
|
||||
rootid: "test-app",
|
||||
},
|
||||
"test-app-with-includes": {
|
||||
rootid: "test-app",
|
||||
skip: "has a 'page'-type include which isn't a known part of spec",
|
||||
},
|
||||
"test-app-with-roles": {
|
||||
rootid: "test-app",
|
||||
},
|
||||
"unsigned-datasource": {
|
||||
rootid: "test-datasource",
|
||||
subpath: "plugin",
|
||||
},
|
||||
"unsigned-panel": {
|
||||
rootid: "test-panel",
|
||||
subpath: "plugin",
|
||||
},
|
||||
"valid-v2-pvt-signature": {
|
||||
rootid: "test-datasource",
|
||||
subpath: "plugin",
|
||||
},
|
||||
"valid-v2-pvt-signature-root-url-uri": {
|
||||
rootid: "test-datasource",
|
||||
subpath: "plugin",
|
||||
},
|
||||
"valid-v2-signature": {
|
||||
rootid: "test-datasource",
|
||||
subpath: "plugin",
|
||||
},
|
||||
"plugin-with-dist": {
|
||||
rootid: "test-datasource",
|
||||
subpath: "plugin",
|
||||
},
|
||||
"no-rootfile": {
|
||||
err: ErrNoRootFile,
|
||||
},
|
||||
"valid-model-panel": {},
|
||||
"valid-model-datasource": {},
|
||||
"missing-kind-datasource": {},
|
||||
"panel-conflicting-joinschema": {
|
||||
err: ErrInvalidLineage,
|
||||
skip: "TODO implement BindOption in thema, SatisfiesJoinSchema, then use it here",
|
||||
},
|
||||
"panel-does-not-follow-slot-joinschema": {
|
||||
err: ErrInvalidLineage,
|
||||
skip: "TODO implement BindOption in thema, SatisfiesJoinSchema, then use it here",
|
||||
},
|
||||
"pluginRootWithDist": {
|
||||
err: ErrNoRootFile,
|
||||
skip: "This folder is used to test multiple plugins in the same folder",
|
||||
},
|
||||
"name-mismatch-panel": {
|
||||
err: ErrInvalidGrafanaPluginInstance,
|
||||
},
|
||||
"disallowed-cue-import": {
|
||||
err: ErrDisallowedCUEImport,
|
||||
},
|
||||
"cdn": {
|
||||
rootid: "grafana-worldmap-panel",
|
||||
subpath: "plugin",
|
||||
},
|
||||
"external-registration": {
|
||||
rootid: "grafana-test-datasource",
|
||||
},
|
||||
}
|
||||
|
||||
staticRootPath, err := filepath.Abs(filepath.Join("..", "manager", "testdata"))
|
||||
require.NoError(t, err)
|
||||
dfs := os.DirFS(staticRootPath)
|
||||
ents, err := fs.ReadDir(dfs, ".")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Ensure table test and dir list are ==
|
||||
var dirs, tts []string
|
||||
for k := range tab {
|
||||
tts = append(tts, k)
|
||||
}
|
||||
for _, ent := range ents {
|
||||
dirs = append(dirs, ent.Name())
|
||||
}
|
||||
sort.Strings(tts)
|
||||
sort.Strings(dirs)
|
||||
if !cmp.Equal(tts, dirs) {
|
||||
t.Fatalf("table test map (-) and pkg/plugins/manager/testdata dirs (+) differ: %s", cmp.Diff(tts, dirs))
|
||||
}
|
||||
|
||||
for _, ent := range ents {
|
||||
tst := tab[ent.Name()]
|
||||
tst.tfs, err = fs.Sub(dfs, filepath.Join(ent.Name(), tst.subpath))
|
||||
require.NoError(t, err)
|
||||
tab[ent.Name()] = tst
|
||||
}
|
||||
|
||||
lib := cuectx.GrafanaThemaRuntime()
|
||||
for name, otst := range tab {
|
||||
tst := otst // otherwise var is shadowed within func by looping
|
||||
t.Run(name, func(t *testing.T) {
|
||||
if tst.skip != "" {
|
||||
t.Skip(tst.skip)
|
||||
}
|
||||
|
||||
pp, err := ParsePluginFS(tst.tfs, lib)
|
||||
if tst.err == nil {
|
||||
require.NoError(t, err, "unexpected error while parsing plugin tree")
|
||||
} else {
|
||||
require.Error(t, err)
|
||||
t.Logf("%T %s", err, err)
|
||||
require.ErrorIs(t, err, tst.err, "unexpected error type while parsing plugin tree")
|
||||
return
|
||||
}
|
||||
|
||||
if tst.rootid == "" {
|
||||
tst.rootid = name
|
||||
}
|
||||
|
||||
require.Equal(t, tst.rootid, pp.Properties.Id, "expected plugin id and actual plugin id differ")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseTreeZips(t *testing.T) {
|
||||
type tt struct {
|
||||
tfs fs.FS
|
||||
// TODO could remove this by getting rid of inconsistent subdirs
|
||||
subpath string
|
||||
skip string
|
||||
err error
|
||||
// TODO could remove this by expecting that dirname == id
|
||||
rootid string
|
||||
}
|
||||
|
||||
tab := map[string]tt{
|
||||
"grafana-simple-json-datasource-ec18fa4da8096a952608a7e4c7782b4260b41bcf.zip": {
|
||||
skip: "binary plugin",
|
||||
},
|
||||
"plugin-with-absolute-member.zip": {
|
||||
skip: "not actually a plugin, no plugin.json?",
|
||||
},
|
||||
"plugin-with-absolute-symlink-dir.zip": {
|
||||
skip: "not actually a plugin, no plugin.json?",
|
||||
},
|
||||
"plugin-with-absolute-symlink.zip": {
|
||||
skip: "not actually a plugin, no plugin.json?",
|
||||
},
|
||||
"plugin-with-parent-member.zip": {
|
||||
skip: "not actually a plugin, no plugin.json?",
|
||||
},
|
||||
"plugin-with-symlink-dir.zip": {
|
||||
skip: "not actually a plugin, no plugin.json?",
|
||||
},
|
||||
"plugin-with-symlink.zip": {
|
||||
skip: "not actually a plugin, no plugin.json?",
|
||||
},
|
||||
"plugin-with-symlinks.zip": {
|
||||
subpath: "test-app",
|
||||
rootid: "test-app",
|
||||
},
|
||||
}
|
||||
|
||||
staticRootPath, err := filepath.Abs(filepath.Join("..", "storage", "testdata"))
|
||||
require.NoError(t, err)
|
||||
ents, err := os.ReadDir(staticRootPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Ensure table test and dir list are ==
|
||||
var dirs, tts []string
|
||||
for k := range tab {
|
||||
tts = append(tts, k)
|
||||
}
|
||||
for _, ent := range ents {
|
||||
dirs = append(dirs, ent.Name())
|
||||
}
|
||||
sort.Strings(tts)
|
||||
sort.Strings(dirs)
|
||||
if !cmp.Equal(tts, dirs) {
|
||||
t.Fatalf("table test map (-) and pkg/plugins/installer/testdata dirs (+) differ: %s", cmp.Diff(tts, dirs))
|
||||
}
|
||||
|
||||
for _, ent := range ents {
|
||||
tst := tab[ent.Name()]
|
||||
r, err := zip.OpenReader(filepath.Join(staticRootPath, ent.Name()))
|
||||
require.NoError(t, err)
|
||||
defer r.Close() //nolint:errcheck
|
||||
if tst.subpath != "" {
|
||||
tst.tfs, err = fs.Sub(r, tst.subpath)
|
||||
require.NoError(t, err)
|
||||
} else {
|
||||
tst.tfs = r
|
||||
}
|
||||
|
||||
tab[ent.Name()] = tst
|
||||
}
|
||||
|
||||
lib := cuectx.GrafanaThemaRuntime()
|
||||
for name, otst := range tab {
|
||||
tst := otst // otherwise var is shadowed within func by looping
|
||||
t.Run(name, func(t *testing.T) {
|
||||
if tst.skip != "" {
|
||||
t.Skip(tst.skip)
|
||||
}
|
||||
|
||||
pp, err := ParsePluginFS(tst.tfs, lib)
|
||||
if tst.err == nil {
|
||||
require.NoError(t, err, "unexpected error while parsing plugin fs")
|
||||
} else {
|
||||
require.ErrorIs(t, err, tst.err, "unexpected error type while parsing plugin fs")
|
||||
return
|
||||
}
|
||||
|
||||
if tst.rootid == "" {
|
||||
tst.rootid = name
|
||||
}
|
||||
|
||||
require.Equal(t, tst.rootid, pp.Properties.Id, "expected plugin id and actual plugin id differ")
|
||||
})
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package pfs
|
||||
|
||||
import (
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/ast"
|
||||
"github.com/grafana/kindsys"
|
||||
)
|
||||
|
||||
// ParsedPlugin represents everything knowable about a single plugin from static
|
||||
@ -13,35 +13,10 @@ import (
|
||||
type ParsedPlugin struct {
|
||||
// Properties contains the plugin's definition, as declared in plugin.json.
|
||||
Properties Metadata
|
||||
|
||||
// ComposableKinds is a map of all the composable kinds declared in this plugin.
|
||||
// Keys are the name of the [kindsys.SchemaInterface] implemented by the value.
|
||||
//
|
||||
// Composable kind defs are only populated in this map by [ParsePluginFS] if
|
||||
// they are implementations of a known schema interface, or are for
|
||||
// an unknown schema interface.
|
||||
ComposableKinds map[string]kindsys.Composable
|
||||
|
||||
// CustomKinds is a map of all the custom kinds declared in this plugin.
|
||||
// Keys are the machineName of the custom kind.
|
||||
// CustomKinds map[string]kindsys.Custom
|
||||
CueFile cue.Value
|
||||
Variant SchemaInterface
|
||||
|
||||
// CUEImports lists the CUE import statements in the plugin's grafanaplugin CUE
|
||||
// package, if any.
|
||||
CUEImports []*ast.ImportSpec
|
||||
}
|
||||
|
||||
// TODO is this static approach worth using, akin to core generated registries? instead of the ParsedPlugins.ComposableKinds map? in addition to it?
|
||||
// ComposableKinds represents all the possible composable kinds that may be
|
||||
// defined in a Grafana plugin.
|
||||
//
|
||||
// The value of each field, if non-nil, is a standard [kindsys.Def]
|
||||
// representing a CUE definition of a composable kind that implements the
|
||||
// schema interface corresponding to the field's name. (This invariant is
|
||||
// only enforced in [ComposableKinds] returned from [ParsePluginFS].)
|
||||
//
|
||||
// type ComposableKinds struct {
|
||||
// PanelCfg kindsys.Def[kindsys.ComposableProperties]
|
||||
// Queries kindsys.Def[kindsys.ComposableProperties]
|
||||
// DSCfg kindsys.Def[kindsys.ComposableProperties]
|
||||
// }
|
||||
|
@ -1,31 +0,0 @@
|
||||
package pfs
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/grafana/kindsys"
|
||||
)
|
||||
|
||||
// This is a brick-dumb test that just ensures known schema interfaces are being
|
||||
// loaded correctly from their declarations in .cue files.
|
||||
//
|
||||
// If this test fails, it's either because:
|
||||
// - They're not being loaded correctly - there's a bug in kindsys or pfs somewhere, fix it
|
||||
// - The set of schema interfaces has been modified - update the static list here
|
||||
func TestSchemaInterfacesAreLoaded(t *testing.T) {
|
||||
knownSI := []string{"PanelCfg", "DataQuery", "DataSourceCfg"}
|
||||
all := kindsys.SchemaInterfaces(nil)
|
||||
var loadedSI []string
|
||||
for k := range all {
|
||||
loadedSI = append(loadedSI, k)
|
||||
}
|
||||
|
||||
sort.Strings(knownSI)
|
||||
sort.Strings(loadedSI)
|
||||
|
||||
if diff := cmp.Diff(knownSI, loadedSI); diff != "" {
|
||||
t.Fatalf("kindsys cue-declared schema interfaces differ from ComposableKinds go struct:\n%s", diff)
|
||||
}
|
||||
}
|
@ -8,14 +8,13 @@ package server
|
||||
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
|
||||
|
||||
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
||||
|
||||
|
||||
"github.com/grafana/grafana/pkg/api"
|
||||
"github.com/grafana/grafana/pkg/api/avatar"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/cuectx"
|
||||
"github.com/grafana/grafana/pkg/expr"
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
@ -306,8 +305,6 @@ var wireBasicSet = wire.NewSet(
|
||||
secretsStore.ProvideService,
|
||||
avatar.ProvideAvatarCacheServer,
|
||||
statscollector.ProvideService,
|
||||
cuectx.GrafanaCUEContext,
|
||||
cuectx.GrafanaThemaRuntime,
|
||||
csrf.ProvideCSRFFilter,
|
||||
wire.Bind(new(csrf.Service), new(*csrf.CSRF)),
|
||||
ossaccesscontrol.ProvideTeamPermissions,
|
||||
|
@ -98,10 +98,9 @@ const (
|
||||
|
||||
// AppInsightsGroupByQuery defines model for AppInsightsGroupByQuery.
|
||||
type AppInsightsGroupByQuery struct {
|
||||
BaseGrafanaTemplateVariableQuery
|
||||
Kind AppInsightsGroupByQueryKind `json:"kind"`
|
||||
MetricName string `json:"metricName"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
Kind *AppInsightsGroupByQueryKind `json:"kind,omitempty"`
|
||||
MetricName *string `json:"metricName,omitempty"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
}
|
||||
|
||||
// AppInsightsGroupByQueryKind defines model for AppInsightsGroupByQuery.Kind.
|
||||
@ -109,9 +108,8 @@ type AppInsightsGroupByQueryKind string
|
||||
|
||||
// AppInsightsMetricNameQuery defines model for AppInsightsMetricNameQuery.
|
||||
type AppInsightsMetricNameQuery struct {
|
||||
BaseGrafanaTemplateVariableQuery
|
||||
Kind AppInsightsMetricNameQueryKind `json:"kind"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
Kind *AppInsightsMetricNameQueryKind `json:"kind,omitempty"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
}
|
||||
|
||||
// AppInsightsMetricNameQueryKind defines model for AppInsightsMetricNameQuery.Kind.
|
||||
@ -221,20 +219,35 @@ type AzureMonitorDataQuery = map[string]any
|
||||
|
||||
// AzureMonitorQuery defines model for AzureMonitorQuery.
|
||||
type AzureMonitorQuery struct {
|
||||
// DataQuery These are the common properties available to all queries in all datasources.
|
||||
// Specific implementations will *extend* this interface, adding the required
|
||||
// properties for the given context.
|
||||
DataQuery
|
||||
|
||||
// Azure Monitor Logs sub-query properties
|
||||
AzureLogAnalytics *AzureLogsQuery `json:"azureLogAnalytics,omitempty"`
|
||||
AzureMonitor *AzureMetricQuery `json:"azureMonitor,omitempty"`
|
||||
AzureResourceGraph *AzureResourceGraphQuery `json:"azureResourceGraph,omitempty"`
|
||||
|
||||
// Application Insights Traces sub-query properties
|
||||
AzureTraces *AzureTracesQuery `json:"azureTraces,omitempty"`
|
||||
GrafanaTemplateVariableFn *any `json:"grafanaTemplateVariableFn,omitempty"`
|
||||
Namespace *string `json:"namespace,omitempty"`
|
||||
AzureTraces *AzureTracesQuery `json:"azureTraces,omitempty"`
|
||||
|
||||
// For mixed data sources the selected datasource is on the query level.
|
||||
// For non mixed scenarios this is undefined.
|
||||
// TODO find a better way to do this ^ that's friendly to schema
|
||||
// TODO this shouldn't be unknown but DataSourceRef | null
|
||||
Datasource *any `json:"datasource,omitempty"`
|
||||
GrafanaTemplateVariableFn *any `json:"grafanaTemplateVariableFn,omitempty"`
|
||||
|
||||
// Hide true if query is disabled (ie should not be returned to the dashboard)
|
||||
// Note this does not always imply that the query should not be executed since
|
||||
// the results from a hidden query may be used as the input to other queries (SSE etc)
|
||||
Hide *bool `json:"hide,omitempty"`
|
||||
Namespace *string `json:"namespace,omitempty"`
|
||||
|
||||
// Specify the query flavor
|
||||
// TODO make this required and give it a default
|
||||
QueryType *string `json:"queryType,omitempty"`
|
||||
|
||||
// A unique identifier for the query within the list of targets.
|
||||
// In server side expressions, the refId is used as a variable name to identify results.
|
||||
// By default, the UI will assign A->Z; however setting meaningful names may be useful.
|
||||
RefId *string `json:"refId,omitempty"`
|
||||
|
||||
// Azure Monitor query type.
|
||||
// queryType: #AzureQueryType
|
||||
@ -336,15 +349,14 @@ type DataQuery struct {
|
||||
// GrafanaTemplateVariableQueryType defines model for GrafanaTemplateVariableQueryType.
|
||||
type GrafanaTemplateVariableQueryType string
|
||||
|
||||
// MetricDefinitionsQuery defines model for MetricDefinitionsQuery.
|
||||
// @deprecated Use MetricNamespaceQuery instead
|
||||
type MetricDefinitionsQuery struct {
|
||||
BaseGrafanaTemplateVariableQuery
|
||||
Kind MetricDefinitionsQueryKind `json:"kind"`
|
||||
MetricNamespace *string `json:"metricNamespace,omitempty"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
ResourceGroup string `json:"resourceGroup"`
|
||||
ResourceName *string `json:"resourceName,omitempty"`
|
||||
Subscription string `json:"subscription"`
|
||||
Kind *MetricDefinitionsQueryKind `json:"kind,omitempty"`
|
||||
MetricNamespace *string `json:"metricNamespace,omitempty"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
ResourceGroup *string `json:"resourceGroup,omitempty"`
|
||||
ResourceName *string `json:"resourceName,omitempty"`
|
||||
Subscription *string `json:"subscription,omitempty"`
|
||||
}
|
||||
|
||||
// MetricDefinitionsQueryKind defines model for MetricDefinitionsQuery.Kind.
|
||||
@ -352,13 +364,12 @@ type MetricDefinitionsQueryKind string
|
||||
|
||||
// MetricNamesQuery defines model for MetricNamesQuery.
|
||||
type MetricNamesQuery struct {
|
||||
BaseGrafanaTemplateVariableQuery
|
||||
Kind MetricNamesQueryKind `json:"kind"`
|
||||
MetricNamespace string `json:"metricNamespace"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
ResourceGroup string `json:"resourceGroup"`
|
||||
ResourceName string `json:"resourceName"`
|
||||
Subscription string `json:"subscription"`
|
||||
Kind *MetricNamesQueryKind `json:"kind,omitempty"`
|
||||
MetricNamespace *string `json:"metricNamespace,omitempty"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
ResourceGroup *string `json:"resourceGroup,omitempty"`
|
||||
ResourceName *string `json:"resourceName,omitempty"`
|
||||
Subscription *string `json:"subscription,omitempty"`
|
||||
}
|
||||
|
||||
// MetricNamesQueryKind defines model for MetricNamesQuery.Kind.
|
||||
@ -366,13 +377,12 @@ type MetricNamesQueryKind string
|
||||
|
||||
// MetricNamespaceQuery defines model for MetricNamespaceQuery.
|
||||
type MetricNamespaceQuery struct {
|
||||
BaseGrafanaTemplateVariableQuery
|
||||
Kind MetricNamespaceQueryKind `json:"kind"`
|
||||
MetricNamespace *string `json:"metricNamespace,omitempty"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
ResourceGroup string `json:"resourceGroup"`
|
||||
ResourceName *string `json:"resourceName,omitempty"`
|
||||
Subscription string `json:"subscription"`
|
||||
Kind *MetricNamespaceQueryKind `json:"kind,omitempty"`
|
||||
MetricNamespace *string `json:"metricNamespace,omitempty"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
ResourceGroup *string `json:"resourceGroup,omitempty"`
|
||||
ResourceName *string `json:"resourceName,omitempty"`
|
||||
Subscription *string `json:"subscription,omitempty"`
|
||||
}
|
||||
|
||||
// MetricNamespaceQueryKind defines model for MetricNamespaceQuery.Kind.
|
||||
@ -380,10 +390,9 @@ type MetricNamespaceQueryKind string
|
||||
|
||||
// ResourceGroupsQuery defines model for ResourceGroupsQuery.
|
||||
type ResourceGroupsQuery struct {
|
||||
BaseGrafanaTemplateVariableQuery
|
||||
Kind ResourceGroupsQueryKind `json:"kind"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
Subscription string `json:"subscription"`
|
||||
Kind *ResourceGroupsQueryKind `json:"kind,omitempty"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
Subscription *string `json:"subscription,omitempty"`
|
||||
}
|
||||
|
||||
// ResourceGroupsQueryKind defines model for ResourceGroupsQuery.Kind.
|
||||
@ -391,12 +400,11 @@ type ResourceGroupsQueryKind string
|
||||
|
||||
// ResourceNamesQuery defines model for ResourceNamesQuery.
|
||||
type ResourceNamesQuery struct {
|
||||
BaseGrafanaTemplateVariableQuery
|
||||
Kind ResourceNamesQueryKind `json:"kind"`
|
||||
MetricNamespace string `json:"metricNamespace"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
ResourceGroup string `json:"resourceGroup"`
|
||||
Subscription string `json:"subscription"`
|
||||
Kind *ResourceNamesQueryKind `json:"kind,omitempty"`
|
||||
MetricNamespace *string `json:"metricNamespace,omitempty"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
ResourceGroup *string `json:"resourceGroup,omitempty"`
|
||||
Subscription *string `json:"subscription,omitempty"`
|
||||
}
|
||||
|
||||
// ResourceNamesQueryKind defines model for ResourceNamesQuery.Kind.
|
||||
@ -407,9 +415,8 @@ type ResultFormat string
|
||||
|
||||
// SubscriptionsQuery defines model for SubscriptionsQuery.
|
||||
type SubscriptionsQuery struct {
|
||||
BaseGrafanaTemplateVariableQuery
|
||||
Kind SubscriptionsQueryKind `json:"kind"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
Kind *SubscriptionsQueryKind `json:"kind,omitempty"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
}
|
||||
|
||||
// SubscriptionsQueryKind defines model for SubscriptionsQuery.Kind.
|
||||
@ -417,9 +424,8 @@ type SubscriptionsQueryKind string
|
||||
|
||||
// UnknownQuery defines model for UnknownQuery.
|
||||
type UnknownQuery struct {
|
||||
BaseGrafanaTemplateVariableQuery
|
||||
Kind UnknownQueryKind `json:"kind"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
Kind *UnknownQueryKind `json:"kind,omitempty"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
}
|
||||
|
||||
// UnknownQueryKind defines model for UnknownQuery.Kind.
|
||||
@ -427,10 +433,9 @@ type UnknownQueryKind string
|
||||
|
||||
// WorkspacesQuery defines model for WorkspacesQuery.
|
||||
type WorkspacesQuery struct {
|
||||
BaseGrafanaTemplateVariableQuery
|
||||
Kind WorkspacesQueryKind `json:"kind"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
Subscription string `json:"subscription"`
|
||||
Kind *WorkspacesQueryKind `json:"kind,omitempty"`
|
||||
RawQuery *string `json:"rawQuery,omitempty"`
|
||||
Subscription *string `json:"subscription,omitempty"`
|
||||
}
|
||||
|
||||
// WorkspacesQueryKind defines model for WorkspacesQuery.Kind.
|
||||
|
@ -410,9 +410,7 @@ func addTraceDataLinksToFields(query *AzureLogAnalyticsQuery, azurePortalBaseUrl
|
||||
|
||||
logsQueryType := string(dataquery.AzureQueryTypeAzureLogAnalytics)
|
||||
logsJSONModel := dataquery.AzureMonitorQuery{
|
||||
DataQuery: dataquery.DataQuery{
|
||||
QueryType: &logsQueryType,
|
||||
},
|
||||
QueryType: &logsQueryType,
|
||||
AzureLogAnalytics: &dataquery.AzureLogsQuery{
|
||||
Query: &query.TraceLogsExploreQuery,
|
||||
Resources: []string{queryJSONModel.AzureTraces.Resources[0]},
|
||||
|
@ -89,20 +89,35 @@ type AlignmentTypes string
|
||||
|
||||
// CloudMonitoringQuery defines model for CloudMonitoringQuery.
|
||||
type CloudMonitoringQuery struct {
|
||||
// DataQuery These are the common properties available to all queries in all datasources.
|
||||
// Specific implementations will *extend* this interface, adding the required
|
||||
// properties for the given context.
|
||||
DataQuery
|
||||
|
||||
// Aliases can be set to modify the legend labels. e.g. {{metric.label.xxx}}. See docs for more detail.
|
||||
AliasBy *string `json:"aliasBy,omitempty"`
|
||||
|
||||
// For mixed data sources the selected datasource is on the query level.
|
||||
// For non mixed scenarios this is undefined.
|
||||
// TODO find a better way to do this ^ that's friendly to schema
|
||||
// TODO this shouldn't be unknown but DataSourceRef | null
|
||||
Datasource *any `json:"datasource,omitempty"`
|
||||
|
||||
// Hide true if query is disabled (ie should not be returned to the dashboard)
|
||||
// Note this does not always imply that the query should not be executed since
|
||||
// the results from a hidden query may be used as the input to other queries (SSE etc)
|
||||
Hide *bool `json:"hide,omitempty"`
|
||||
|
||||
// Time interval in milliseconds.
|
||||
IntervalMs *float32 `json:"intervalMs,omitempty"`
|
||||
|
||||
// PromQL sub-query properties.
|
||||
PromQLQuery *PromQLQuery `json:"promQLQuery,omitempty"`
|
||||
|
||||
// Specify the query flavor
|
||||
// TODO make this required and give it a default
|
||||
QueryType *string `json:"queryType,omitempty"`
|
||||
|
||||
// A unique identifier for the query within the list of targets.
|
||||
// In server side expressions, the refId is used as a variable name to identify results.
|
||||
// By default, the UI will assign A->Z; however setting meaningful names may be useful.
|
||||
RefId *string `json:"refId,omitempty"`
|
||||
|
||||
// SLO sub-query properties.
|
||||
SloQuery *SLOQuery `json:"sloQuery,omitempty"`
|
||||
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/kinds/dataquery"
|
||||
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/utils"
|
||||
)
|
||||
|
||||
type annotationEvent struct {
|
||||
@ -50,7 +51,12 @@ func (e *cloudWatchExecutor) executeAnnotationQuery(ctx context.Context, pluginC
|
||||
actionPrefix := model.ActionPrefix
|
||||
alarmNamePrefix := model.AlarmNamePrefix
|
||||
|
||||
cli, err := e.getCWClient(ctx, pluginCtx, model.Region)
|
||||
region := ""
|
||||
if model.Region != nil {
|
||||
region = *model.Region
|
||||
}
|
||||
|
||||
cli, err := e.getCWClient(ctx, pluginCtx, region)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -76,9 +82,9 @@ func (e *cloudWatchExecutor) executeAnnotationQuery(ctx context.Context, pluginC
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v: %w", "failed to call cloudwatch:DescribeAlarms", err)
|
||||
}
|
||||
alarmNames = filterAlarms(resp, model.Namespace, metricName, dimensions, statistic, period)
|
||||
alarmNames = filterAlarms(resp, utils.Depointerizer(model.Namespace), metricName, dimensions, statistic, period)
|
||||
} else {
|
||||
if model.Region == "" || model.Namespace == "" || metricName == "" || statistic == "" {
|
||||
if model.Region == nil || model.Namespace == nil || metricName == "" || statistic == "" {
|
||||
return result, errors.New("invalid annotations query")
|
||||
}
|
||||
|
||||
@ -96,7 +102,7 @@ func (e *cloudWatchExecutor) executeAnnotationQuery(ctx context.Context, pluginC
|
||||
}
|
||||
}
|
||||
params := &cloudwatch.DescribeAlarmsForMetricInput{
|
||||
Namespace: aws.String(model.Namespace),
|
||||
Namespace: aws.String(utils.Depointerizer(model.Namespace)),
|
||||
MetricName: aws.String(metricName),
|
||||
Dimensions: qd,
|
||||
Statistic: aws.String(statistic),
|
||||
|
@ -210,8 +210,12 @@ func (e *cloudWatchExecutor) QueryData(ctx context.Context, req *backend.QueryDa
|
||||
// Public dashboard queries execute like alert queries, i.e. they execute on the backend, therefore, we need to handle them synchronously.
|
||||
// Since `model.Type` is set during execution on the frontend by the query runner and isn't saved with the query, we are checking here is
|
||||
// missing the `model.Type` property and if it is a log query in order to determine if it is a public dashboard query.
|
||||
fromPublicDashboard := (model.Type == "" && model.QueryMode == logsQueryMode)
|
||||
isSyncLogQuery := ((fromAlert || fromExpression) && model.QueryMode == logsQueryMode) || fromPublicDashboard
|
||||
queryMode := ""
|
||||
if model.QueryMode != nil {
|
||||
queryMode = string(*model.QueryMode)
|
||||
}
|
||||
fromPublicDashboard := model.Type == "" && queryMode == logsQueryMode
|
||||
isSyncLogQuery := ((fromAlert || fromExpression) && queryMode == logsQueryMode) || fromPublicDashboard
|
||||
if isSyncLogQuery {
|
||||
return executeSyncLogQuery(ctx, e, req)
|
||||
}
|
||||
|
@ -105,14 +105,11 @@ const (
|
||||
QueryEditorPropertyTypeString QueryEditorPropertyType = "string"
|
||||
)
|
||||
|
||||
// CloudWatchAnnotationQuery defines model for CloudWatchAnnotationQuery.
|
||||
// Shape of a CloudWatch Annotation query
|
||||
//
|
||||
// TS type is CloudWatchDefaultQuery = Omit<CloudWatchLogsQuery, 'queryMode'> & CloudWatchMetricsQuery, declared in veneer
|
||||
// #CloudWatchDefaultQuery: #CloudWatchLogsQuery & #CloudWatchMetricsQuery @cuetsy(kind="type")
|
||||
type CloudWatchAnnotationQuery struct {
|
||||
// DataQuery These are the common properties available to all queries in all datasources.
|
||||
// Specific implementations will *extend* this interface, adding the required
|
||||
// properties for the given context.
|
||||
DataQuery
|
||||
MetricStat
|
||||
|
||||
// The ID of the AWS account to query for the metric, specifying `all` will query all accounts that the monitoring account is permitted to query.
|
||||
AccountId *string `json:"accountId,omitempty"`
|
||||
|
||||
@ -149,14 +146,14 @@ type CloudWatchAnnotationQuery struct {
|
||||
MetricName *string `json:"metricName,omitempty"`
|
||||
|
||||
// A namespace is a container for CloudWatch metrics. Metrics in different namespaces are isolated from each other, so that metrics from different applications are not mistakenly aggregated into the same statistics. For example, Amazon EC2 uses the AWS/EC2 namespace.
|
||||
Namespace string `json:"namespace"`
|
||||
Namespace *string `json:"namespace,omitempty"`
|
||||
|
||||
// The length of time associated with a specific Amazon CloudWatch statistic. Can be specified by a number of seconds, 'auto', or as a duration string e.g. '15m' being 15 minutes
|
||||
Period *string `json:"period,omitempty"`
|
||||
|
||||
// Enable matching on the prefix of the action name or alarm name, specify the prefixes with actionPrefix and/or alarmNamePrefix
|
||||
PrefixMatching *bool `json:"prefixMatching,omitempty"`
|
||||
QueryMode CloudWatchQueryMode `json:"queryMode"`
|
||||
PrefixMatching *bool `json:"prefixMatching,omitempty"`
|
||||
QueryMode *CloudWatchQueryMode `json:"queryMode,omitempty"`
|
||||
|
||||
// Specify the query flavor
|
||||
// TODO make this required and give it a default
|
||||
@ -165,10 +162,10 @@ type CloudWatchAnnotationQuery struct {
|
||||
// A unique identifier for the query within the list of targets.
|
||||
// In server side expressions, the refId is used as a variable name to identify results.
|
||||
// By default, the UI will assign A->Z; however setting meaningful names may be useful.
|
||||
RefId string `json:"refId"`
|
||||
RefId *string `json:"refId,omitempty"`
|
||||
|
||||
// AWS region to query for the metric
|
||||
Region string `json:"region"`
|
||||
Region *string `json:"region,omitempty"`
|
||||
|
||||
// Metric data aggregations over specified periods of time. For detailed definitions of the statistics supported by CloudWatch, see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Statistics-definitions.html.
|
||||
Statistic *string `json:"statistic,omitempty"`
|
||||
@ -180,13 +177,8 @@ type CloudWatchAnnotationQuery struct {
|
||||
// CloudWatchDataQuery defines model for CloudWatchDataQuery.
|
||||
type CloudWatchDataQuery = map[string]any
|
||||
|
||||
// CloudWatchLogsQuery defines model for CloudWatchLogsQuery.
|
||||
// Shape of a CloudWatch Logs query
|
||||
type CloudWatchLogsQuery struct {
|
||||
// DataQuery These are the common properties available to all queries in all datasources.
|
||||
// Specific implementations will *extend* this interface, adding the required
|
||||
// properties for the given context.
|
||||
DataQuery
|
||||
|
||||
// For mixed data sources the selected datasource is on the query level.
|
||||
// For non mixed scenarios this is undefined.
|
||||
// TODO find a better way to do this ^ that's friendly to schema
|
||||
@ -199,15 +191,15 @@ type CloudWatchLogsQuery struct {
|
||||
// Hide true if query is disabled (ie should not be returned to the dashboard)
|
||||
// Note this does not always imply that the query should not be executed since
|
||||
// the results from a hidden query may be used as the input to other queries (SSE etc)
|
||||
Hide *bool `json:"hide,omitempty"`
|
||||
Id string `json:"id"`
|
||||
Hide *bool `json:"hide,omitempty"`
|
||||
Id *string `json:"id,omitempty"`
|
||||
|
||||
// @deprecated use logGroups
|
||||
LogGroupNames []string `json:"logGroupNames,omitempty"`
|
||||
|
||||
// Log groups to query
|
||||
LogGroups []LogGroup `json:"logGroups,omitempty"`
|
||||
QueryMode CloudWatchQueryMode `json:"queryMode"`
|
||||
LogGroups []LogGroup `json:"logGroups,omitempty"`
|
||||
QueryMode *CloudWatchQueryMode `json:"queryMode,omitempty"`
|
||||
|
||||
// Specify the query flavor
|
||||
// TODO make this required and give it a default
|
||||
@ -216,23 +208,17 @@ type CloudWatchLogsQuery struct {
|
||||
// A unique identifier for the query within the list of targets.
|
||||
// In server side expressions, the refId is used as a variable name to identify results.
|
||||
// By default, the UI will assign A->Z; however setting meaningful names may be useful.
|
||||
RefId string `json:"refId"`
|
||||
RefId *string `json:"refId,omitempty"`
|
||||
|
||||
// AWS region to query for the logs
|
||||
Region string `json:"region"`
|
||||
Region *string `json:"region,omitempty"`
|
||||
|
||||
// Fields to group the results by, this field is automatically populated whenever the query is updated
|
||||
StatsGroups []string `json:"statsGroups,omitempty"`
|
||||
}
|
||||
|
||||
// CloudWatchMetricsQuery defines model for CloudWatchMetricsQuery.
|
||||
// Shape of a CloudWatch Metrics query
|
||||
type CloudWatchMetricsQuery struct {
|
||||
// DataQuery These are the common properties available to all queries in all datasources.
|
||||
// Specific implementations will *extend* this interface, adding the required
|
||||
// properties for the given context.
|
||||
DataQuery
|
||||
MetricStat
|
||||
|
||||
// The ID of the AWS account to query for the metric, specifying `all` will query all accounts that the monitoring account is permitted to query.
|
||||
AccountId *string `json:"accountId,omitempty"`
|
||||
|
||||
@ -258,7 +244,7 @@ type CloudWatchMetricsQuery struct {
|
||||
Hide *bool `json:"hide,omitempty"`
|
||||
|
||||
// ID can be used to reference other queries in math expressions. The ID can include numbers, letters, and underscore, and must start with a lowercase letter.
|
||||
Id string `json:"id"`
|
||||
Id *string `json:"id,omitempty"`
|
||||
|
||||
// Change the time series legend names using dynamic labels. See https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/graph-dynamic-labels.html for more details.
|
||||
Label *string `json:"label,omitempty"`
|
||||
@ -272,7 +258,7 @@ type CloudWatchMetricsQuery struct {
|
||||
MetricQueryType *MetricQueryType `json:"metricQueryType,omitempty"`
|
||||
|
||||
// A namespace is a container for CloudWatch metrics. Metrics in different namespaces are isolated from each other, so that metrics from different applications are not mistakenly aggregated into the same statistics. For example, Amazon EC2 uses the AWS/EC2 namespace.
|
||||
Namespace string `json:"namespace"`
|
||||
Namespace *string `json:"namespace,omitempty"`
|
||||
|
||||
// The length of time associated with a specific Amazon CloudWatch statistic. Can be specified by a number of seconds, 'auto', or as a duration string e.g. '15m' being 15 minutes
|
||||
Period *string `json:"period,omitempty"`
|
||||
@ -285,10 +271,10 @@ type CloudWatchMetricsQuery struct {
|
||||
// A unique identifier for the query within the list of targets.
|
||||
// In server side expressions, the refId is used as a variable name to identify results.
|
||||
// By default, the UI will assign A->Z; however setting meaningful names may be useful.
|
||||
RefId string `json:"refId"`
|
||||
RefId *string `json:"refId,omitempty"`
|
||||
|
||||
// AWS region to query for the metric
|
||||
Region string `json:"region"`
|
||||
Region *string `json:"region,omitempty"`
|
||||
Sql *SQLExpression `json:"sql,omitempty"`
|
||||
|
||||
// When the metric query type is `metricQueryType` is set to `Query`, this field is used to specify the query string.
|
||||
|
@ -102,8 +102,8 @@ func (e *cloudWatchExecutor) executeLogAction(ctx context.Context, logsQuery mod
|
||||
}
|
||||
|
||||
region := instance.Settings.Region
|
||||
if logsQuery.Region != "" {
|
||||
region = logsQuery.Region
|
||||
if logsQuery.Region != nil {
|
||||
region = *logsQuery.Region
|
||||
}
|
||||
|
||||
logsClient, err := e.getCWLogsClient(ctx, pluginCtx, region)
|
||||
@ -248,8 +248,8 @@ func (e *cloudWatchExecutor) handleStartQuery(ctx context.Context, logsClient cl
|
||||
dataFrame.RefID = refID
|
||||
|
||||
region := "default"
|
||||
if logsQuery.Region != "" {
|
||||
region = logsQuery.Region
|
||||
if logsQuery.Region != nil {
|
||||
region = *logsQuery.Region
|
||||
}
|
||||
|
||||
dataFrame.Meta = &data.FrameMeta{
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/kinds/dataquery"
|
||||
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
|
||||
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/utils"
|
||||
)
|
||||
|
||||
const initialAlertPollPeriod = time.Second
|
||||
@ -36,9 +37,9 @@ var executeSyncLogQuery = func(ctx context.Context, e *cloudWatchExecutor, req *
|
||||
logsQuery.QueryString = *logsQuery.Expression
|
||||
}
|
||||
|
||||
region := logsQuery.Region
|
||||
if logsQuery.Region == "" || region == defaultRegion {
|
||||
logsQuery.Region = instance.Settings.Region
|
||||
region := utils.Depointerizer(logsQuery.Region)
|
||||
if region == "" || region == defaultRegion {
|
||||
logsQuery.Region = utils.Pointer(instance.Settings.Region)
|
||||
}
|
||||
|
||||
logsClient, err := e.getCWLogsClient(ctx, req.PluginContext, region)
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
|
||||
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/kinds/dataquery"
|
||||
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/utils"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -239,9 +240,9 @@ func ParseMetricDataQueries(dataQueries []backend.DataQuery, startTime time.Time
|
||||
cwQuery := &CloudWatchQuery{
|
||||
logger: logger,
|
||||
RefId: refId,
|
||||
Id: mdq.Id,
|
||||
Region: mdq.Region,
|
||||
Namespace: mdq.Namespace,
|
||||
Id: utils.Depointerizer(mdq.Id),
|
||||
Region: utils.Depointerizer(mdq.Region),
|
||||
Namespace: utils.Depointerizer(mdq.Namespace),
|
||||
TimezoneUTCOffset: mdq.TimezoneUTCOffset,
|
||||
}
|
||||
|
||||
@ -314,7 +315,7 @@ func (q *CloudWatchQuery) validateAndSetDefaults(refId string, metricsDataQuery
|
||||
q.AccountId = metricsDataQuery.AccountId
|
||||
}
|
||||
|
||||
if metricsDataQuery.Id == "" {
|
||||
if utils.Depointerizer(metricsDataQuery.Id) == "" {
|
||||
// Why not just use refId if id is not specified in the frontend? When specifying an id in the editor,
|
||||
// and alphabetical must be used. The id must be unique, so if an id like for example a, b or c would be used,
|
||||
// it would likely collide with some ref id. That's why the `query` prefix is used.
|
||||
|
@ -7,8 +7,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/kindsys"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
|
||||
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/kinds/dataquery"
|
||||
@ -898,15 +896,15 @@ func Test_migrateAliasToDynamicLabel_single_query_preserves_old_alias_and_create
|
||||
|
||||
queryToMigrate := metricsDataQuery{
|
||||
CloudWatchMetricsQuery: dataquery.CloudWatchMetricsQuery{
|
||||
Region: "us-east-1",
|
||||
Namespace: "ec2",
|
||||
MetricName: kindsys.Ptr("CPUUtilization"),
|
||||
Alias: kindsys.Ptr(tc.inputAlias),
|
||||
Region: utils.Pointer("us-east-1"),
|
||||
Namespace: utils.Pointer("ec2"),
|
||||
MetricName: utils.Pointer("CPUUtilization"),
|
||||
Alias: utils.Pointer(tc.inputAlias),
|
||||
Dimensions: &dataquery.Dimensions{
|
||||
"InstanceId": []any{"test"},
|
||||
},
|
||||
Statistic: &average,
|
||||
Period: kindsys.Ptr("600"),
|
||||
Period: utils.Pointer("600"),
|
||||
Hide: &false,
|
||||
},
|
||||
}
|
||||
|
@ -4,6 +4,15 @@ import "github.com/go-stack/stack"
|
||||
|
||||
func Pointer[T any](arg T) *T { return &arg }
|
||||
|
||||
func Depointerizer[T any](v *T) T {
|
||||
var emptyValue T
|
||||
if v != nil {
|
||||
emptyValue = *v
|
||||
}
|
||||
|
||||
return emptyValue
|
||||
}
|
||||
|
||||
// Stack is copied from grafana/pkg/infra/log
|
||||
// TODO: maybe this should live in grafana-plugin-sdk-go?
|
||||
func Stack(skip int) string {
|
||||
|
@ -43,11 +43,6 @@ type DataQuery struct {
|
||||
|
||||
// GrafanaPyroscopeDataQuery defines model for GrafanaPyroscopeDataQuery.
|
||||
type GrafanaPyroscopeDataQuery struct {
|
||||
// DataQuery These are the common properties available to all queries in all datasources.
|
||||
// Specific implementations will *extend* this interface, adding the required
|
||||
// properties for the given context.
|
||||
DataQuery
|
||||
|
||||
// For mixed data sources the selected datasource is on the query level.
|
||||
// For non mixed scenarios this is undefined.
|
||||
// TODO find a better way to do this ^ that's friendly to schema
|
||||
@ -55,7 +50,7 @@ type GrafanaPyroscopeDataQuery struct {
|
||||
Datasource *any `json:"datasource,omitempty"`
|
||||
|
||||
// Allows to group the results.
|
||||
GroupBy []string `json:"groupBy"`
|
||||
GroupBy []string `json:"groupBy,omitempty"`
|
||||
|
||||
// Hide true if query is disabled (ie should not be returned to the dashboard)
|
||||
// Note this does not always imply that the query should not be executed since
|
||||
@ -63,13 +58,13 @@ type GrafanaPyroscopeDataQuery struct {
|
||||
Hide *bool `json:"hide,omitempty"`
|
||||
|
||||
// Specifies the query label selectors.
|
||||
LabelSelector string `json:"labelSelector"`
|
||||
LabelSelector *string `json:"labelSelector,omitempty"`
|
||||
|
||||
// Sets the maximum number of nodes in the flamegraph.
|
||||
MaxNodes *int64 `json:"maxNodes,omitempty"`
|
||||
|
||||
// Specifies the type of profile to query.
|
||||
ProfileTypeId string `json:"profileTypeId"`
|
||||
ProfileTypeId *string `json:"profileTypeId,omitempty"`
|
||||
|
||||
// Specify the query flavor
|
||||
// TODO make this required and give it a default
|
||||
@ -78,7 +73,7 @@ type GrafanaPyroscopeDataQuery struct {
|
||||
// A unique identifier for the query within the list of targets.
|
||||
// In server side expressions, the refId is used as a variable name to identify results.
|
||||
// By default, the UI will assign A->Z; however setting meaningful names may be useful.
|
||||
RefId string `json:"refId"`
|
||||
RefId *string `json:"refId,omitempty"`
|
||||
|
||||
// Specifies the query span selectors.
|
||||
SpanSelector []string `json:"spanSelector,omitempty"`
|
||||
|
@ -52,6 +52,9 @@ func (d *PyroscopeDatasource) query(ctx context.Context, pCtx backend.PluginCont
|
||||
return response
|
||||
}
|
||||
|
||||
profileTypeId := depointerizer(qm.ProfileTypeId)
|
||||
labelSelector := depointerizer(qm.LabelSelector)
|
||||
|
||||
responseMutex := sync.Mutex{}
|
||||
g, gCtx := errgroup.WithContext(ctx)
|
||||
if query.QueryType == queryTypeMetrics || query.QueryType == queryTypeBoth {
|
||||
@ -75,8 +78,8 @@ func (d *PyroscopeDatasource) query(ctx context.Context, pCtx backend.PluginCont
|
||||
logger.Debug("Sending SelectSeriesRequest", "queryModel", qm, "function", logEntrypoint())
|
||||
seriesResp, err := d.client.GetSeries(
|
||||
gCtx,
|
||||
qm.ProfileTypeId,
|
||||
qm.LabelSelector,
|
||||
profileTypeId,
|
||||
labelSelector,
|
||||
query.TimeRange.From.UnixMilli(),
|
||||
query.TimeRange.To.UnixMilli(),
|
||||
qm.GroupBy,
|
||||
@ -101,7 +104,7 @@ func (d *PyroscopeDatasource) query(ctx context.Context, pCtx backend.PluginCont
|
||||
var profileResp *ProfileResponse
|
||||
if len(qm.SpanSelector) > 0 {
|
||||
logger.Debug("Calling GetSpanProfile", "queryModel", qm, "function", logEntrypoint())
|
||||
prof, err := d.client.GetSpanProfile(gCtx, qm.ProfileTypeId, qm.LabelSelector, qm.SpanSelector, query.TimeRange.From.UnixMilli(), query.TimeRange.To.UnixMilli(), qm.MaxNodes)
|
||||
prof, err := d.client.GetSpanProfile(gCtx, profileTypeId, labelSelector, qm.SpanSelector, query.TimeRange.From.UnixMilli(), query.TimeRange.To.UnixMilli(), qm.MaxNodes)
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
@ -111,7 +114,7 @@ func (d *PyroscopeDatasource) query(ctx context.Context, pCtx backend.PluginCont
|
||||
profileResp = prof
|
||||
} else {
|
||||
logger.Debug("Calling GetProfile", "queryModel", qm, "function", logEntrypoint())
|
||||
prof, err := d.client.GetProfile(gCtx, qm.ProfileTypeId, qm.LabelSelector, query.TimeRange.From.UnixMilli(), query.TimeRange.To.UnixMilli(), qm.MaxNodes)
|
||||
prof, err := d.client.GetProfile(gCtx, profileTypeId, labelSelector, query.TimeRange.From.UnixMilli(), query.TimeRange.To.UnixMilli(), qm.MaxNodes)
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
@ -450,3 +453,12 @@ func seriesToDataFrames(resp *SeriesResponse) []*data.Frame {
|
||||
}
|
||||
return frames
|
||||
}
|
||||
|
||||
func depointerizer[T any](v *T) T {
|
||||
var emptyValue T
|
||||
if v != nil {
|
||||
emptyValue = *v
|
||||
}
|
||||
|
||||
return emptyValue
|
||||
}
|
||||
|
@ -26,11 +26,11 @@ const (
|
||||
StreamingQueryTypeTraces StreamingQueryType = "traces"
|
||||
)
|
||||
|
||||
// Defines values for ErrorType.
|
||||
// Defines values for TestDataDataQueryErrorType.
|
||||
const (
|
||||
ErrorTypeFrontendException ErrorType = "frontend_exception"
|
||||
ErrorTypeFrontendObservable ErrorType = "frontend_observable"
|
||||
ErrorTypeServerPanic ErrorType = "server_panic"
|
||||
TestDataDataQueryErrorTypeFrontendException TestDataDataQueryErrorType = "frontend_exception"
|
||||
TestDataDataQueryErrorTypeFrontendObservable TestDataDataQueryErrorType = "frontend_observable"
|
||||
TestDataDataQueryErrorTypeServerPanic TestDataDataQueryErrorType = "server_panic"
|
||||
)
|
||||
|
||||
// Defines values for TestDataQueryType.
|
||||
@ -154,38 +154,54 @@ type StreamingQueryType string
|
||||
|
||||
// TestDataDataQuery defines model for TestDataDataQuery.
|
||||
type TestDataDataQuery struct {
|
||||
// DataQuery These are the common properties available to all queries in all datasources.
|
||||
// Specific implementations will *extend* this interface, adding the required
|
||||
// properties for the given context.
|
||||
DataQuery
|
||||
Alias *string `json:"alias,omitempty"`
|
||||
Channel *string `json:"channel,omitempty"`
|
||||
CsvContent *string `json:"csvContent,omitempty"`
|
||||
CsvFileName *string `json:"csvFileName,omitempty"`
|
||||
CsvWave []CSVWave `json:"csvWave,omitempty"`
|
||||
|
||||
// For mixed data sources the selected datasource is on the query level.
|
||||
// For non mixed scenarios this is undefined.
|
||||
// TODO find a better way to do this ^ that's friendly to schema
|
||||
// TODO this shouldn't be unknown but DataSourceRef | null
|
||||
Datasource *any `json:"datasource,omitempty"`
|
||||
|
||||
// Drop percentage (the chance we will lose a point 0-100)
|
||||
DropPercent *float64 `json:"dropPercent,omitempty"`
|
||||
ErrorType *ErrorType `json:"errorType,omitempty"`
|
||||
FlamegraphDiff *bool `json:"flamegraphDiff,omitempty"`
|
||||
Labels *string `json:"labels,omitempty"`
|
||||
LevelColumn *bool `json:"levelColumn,omitempty"`
|
||||
Lines *int64 `json:"lines,omitempty"`
|
||||
Nodes *NodesQuery `json:"nodes,omitempty"`
|
||||
Points [][]any `json:"points,omitempty"`
|
||||
PulseWave *PulseWaveQuery `json:"pulseWave,omitempty"`
|
||||
RawFrameContent *string `json:"rawFrameContent,omitempty"`
|
||||
ScenarioId *TestDataQueryType `json:"scenarioId,omitempty"`
|
||||
SeriesCount *int32 `json:"seriesCount,omitempty"`
|
||||
Sim *SimulationQuery `json:"sim,omitempty"`
|
||||
SpanCount *int32 `json:"spanCount,omitempty"`
|
||||
Stream *StreamingQuery `json:"stream,omitempty"`
|
||||
StringInput *string `json:"stringInput,omitempty"`
|
||||
Usa *USAQuery `json:"usa,omitempty"`
|
||||
DropPercent *float64 `json:"dropPercent,omitempty"`
|
||||
ErrorType *TestDataDataQueryErrorType `json:"errorType,omitempty"`
|
||||
FlamegraphDiff *bool `json:"flamegraphDiff,omitempty"`
|
||||
|
||||
// Hide true if query is disabled (ie should not be returned to the dashboard)
|
||||
// Note this does not always imply that the query should not be executed since
|
||||
// the results from a hidden query may be used as the input to other queries (SSE etc)
|
||||
Hide *bool `json:"hide,omitempty"`
|
||||
Labels *string `json:"labels,omitempty"`
|
||||
LevelColumn *bool `json:"levelColumn,omitempty"`
|
||||
Lines *int64 `json:"lines,omitempty"`
|
||||
Nodes *NodesQuery `json:"nodes,omitempty"`
|
||||
Points [][]any `json:"points,omitempty"`
|
||||
PulseWave *PulseWaveQuery `json:"pulseWave,omitempty"`
|
||||
|
||||
// Specify the query flavor
|
||||
// TODO make this required and give it a default
|
||||
QueryType *string `json:"queryType,omitempty"`
|
||||
RawFrameContent *string `json:"rawFrameContent,omitempty"`
|
||||
|
||||
// A unique identifier for the query within the list of targets.
|
||||
// In server side expressions, the refId is used as a variable name to identify results.
|
||||
// By default, the UI will assign A->Z; however setting meaningful names may be useful.
|
||||
RefId *string `json:"refId,omitempty"`
|
||||
ScenarioId *TestDataQueryType `json:"scenarioId,omitempty"`
|
||||
SeriesCount *int32 `json:"seriesCount,omitempty"`
|
||||
Sim *SimulationQuery `json:"sim,omitempty"`
|
||||
SpanCount *int32 `json:"spanCount,omitempty"`
|
||||
Stream *StreamingQuery `json:"stream,omitempty"`
|
||||
StringInput *string `json:"stringInput,omitempty"`
|
||||
Usa *USAQuery `json:"usa,omitempty"`
|
||||
}
|
||||
|
||||
// ErrorType defines model for TestDataDataQuery.ErrorType.
|
||||
type ErrorType string
|
||||
// TestDataDataQueryErrorType defines model for TestDataDataQuery.ErrorType.
|
||||
type TestDataDataQueryErrorType string
|
||||
|
||||
// TestDataQueryType defines model for TestDataQueryType.
|
||||
type TestDataQueryType string
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
|
||||
|
||||
"github.com/grafana/grafana/pkg/tsdb/loki/kinds/dataquery"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -39,7 +40,7 @@ func healthcheck(ctx context.Context, req *backend.CheckHealthRequest, s *Servic
|
||||
step := "1s"
|
||||
qt := "instant"
|
||||
qm := dataquery.LokiDataQuery{
|
||||
Expr: "vector(1)+vector(1)",
|
||||
Expr: util.Pointer("vector(1)+vector(1)"),
|
||||
Step: &step,
|
||||
QueryType: &qt,
|
||||
}
|
||||
|
@ -63,11 +63,6 @@ type DataQuery struct {
|
||||
|
||||
// LokiDataQuery defines model for LokiDataQuery.
|
||||
type LokiDataQuery struct {
|
||||
// DataQuery These are the common properties available to all queries in all datasources.
|
||||
// Specific implementations will *extend* this interface, adding the required
|
||||
// properties for the given context.
|
||||
DataQuery
|
||||
|
||||
// For mixed data sources the selected datasource is on the query level.
|
||||
// For non mixed scenarios this is undefined.
|
||||
// TODO find a better way to do this ^ that's friendly to schema
|
||||
@ -76,7 +71,7 @@ type LokiDataQuery struct {
|
||||
EditorMode *QueryEditorMode `json:"editorMode,omitempty"`
|
||||
|
||||
// The LogQL query.
|
||||
Expr string `json:"expr"`
|
||||
Expr *string `json:"expr,omitempty"`
|
||||
|
||||
// Hide true if query is disabled (ie should not be returned to the dashboard)
|
||||
// Note this does not always imply that the query should not be executed since
|
||||
@ -102,7 +97,7 @@ type LokiDataQuery struct {
|
||||
// A unique identifier for the query within the list of targets.
|
||||
// In server side expressions, the refId is used as a variable name to identify results.
|
||||
// By default, the UI will assign A->Z; however setting meaningful names may be useful.
|
||||
RefId string `json:"refId"`
|
||||
RefId *string `json:"refId,omitempty"`
|
||||
|
||||
// @deprecated, now use step.
|
||||
Resolution *int64 `json:"resolution,omitempty"`
|
||||
|
@ -149,7 +149,7 @@ func parseQuery(queryContext *backend.QueryDataRequest) ([]*lokiQuery, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
expr := interpolateVariables(model.Expr, interval, timeRange, queryType, step)
|
||||
expr := interpolateVariables(depointerizer(model.Expr), interval, timeRange, queryType, step)
|
||||
|
||||
direction, err := parseDirection(model.Direction)
|
||||
if err != nil {
|
||||
@ -187,3 +187,12 @@ func parseQuery(queryContext *backend.QueryDataRequest) ([]*lokiQuery, error) {
|
||||
|
||||
return qs, nil
|
||||
}
|
||||
|
||||
func depointerizer[T any](v *T) T {
|
||||
var emptyValue T
|
||||
if v != nil {
|
||||
emptyValue = *v
|
||||
}
|
||||
|
||||
return emptyValue
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ func (s *Service) SubscribeStream(ctx context.Context, req *backend.SubscribeStr
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if query.Expr == "" {
|
||||
if query.Expr != nil {
|
||||
return &backend.SubscribeStreamResponse{
|
||||
Status: backend.SubscribeStreamStatusNotFound,
|
||||
}, fmt.Errorf("missing expr in channel (subscribe)")
|
||||
@ -69,7 +69,7 @@ func (s *Service) RunStream(ctx context.Context, req *backend.RunStreamRequest,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if query.Expr == "" {
|
||||
if query.Expr != nil {
|
||||
return fmt.Errorf("missing expr in cuannel")
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ func (s *Service) RunStream(ctx context.Context, req *backend.RunStreamRequest,
|
||||
signal.Notify(interrupt, os.Interrupt)
|
||||
|
||||
params := url.Values{}
|
||||
params.Add("query", query.Expr)
|
||||
params.Add("query", *query.Expr)
|
||||
|
||||
wsurl, _ := url.Parse(dsInfo.URL)
|
||||
|
||||
@ -149,7 +149,7 @@ func (s *Service) RunStream(ctx context.Context, req *backend.RunStreamRequest,
|
||||
}
|
||||
}()
|
||||
|
||||
ticker := time.NewTicker(time.Second * 60) //.Step)
|
||||
ticker := time.NewTicker(time.Second * 60) // .Step)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
|
@ -43,11 +43,6 @@ type DataQuery struct {
|
||||
|
||||
// ParcaDataQuery defines model for ParcaDataQuery.
|
||||
type ParcaDataQuery struct {
|
||||
// DataQuery These are the common properties available to all queries in all datasources.
|
||||
// Specific implementations will *extend* this interface, adding the required
|
||||
// properties for the given context.
|
||||
DataQuery
|
||||
|
||||
// For mixed data sources the selected datasource is on the query level.
|
||||
// For non mixed scenarios this is undefined.
|
||||
// TODO find a better way to do this ^ that's friendly to schema
|
||||
@ -60,10 +55,10 @@ type ParcaDataQuery struct {
|
||||
Hide *bool `json:"hide,omitempty"`
|
||||
|
||||
// Specifies the query label selectors.
|
||||
LabelSelector string `json:"labelSelector"`
|
||||
LabelSelector *string `json:"labelSelector,omitempty"`
|
||||
|
||||
// Specifies the type of profile to query.
|
||||
ProfileTypeId string `json:"profileTypeId"`
|
||||
ProfileTypeId *string `json:"profileTypeId,omitempty"`
|
||||
|
||||
// Specify the query flavor
|
||||
// TODO make this required and give it a default
|
||||
@ -72,7 +67,7 @@ type ParcaDataQuery struct {
|
||||
// A unique identifier for the query within the list of targets.
|
||||
// In server side expressions, the refId is used as a variable name to identify results.
|
||||
// By default, the UI will assign A->Z; however setting meaningful names may be useful.
|
||||
RefId string `json:"refId"`
|
||||
RefId *string `json:"refId,omitempty"`
|
||||
}
|
||||
|
||||
// ParcaQueryType defines model for ParcaQueryType.
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/tracing"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/utils"
|
||||
"github.com/grafana/grafana/pkg/tsdb/parca/kinds/dataquery"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
@ -56,7 +57,8 @@ func (d *ParcaDatasource) query(ctx context.Context, pCtx backend.PluginContext,
|
||||
span.SetStatus(codes.Error, response.Error.Error())
|
||||
return response
|
||||
}
|
||||
response.Frames = append(response.Frames, seriesToDataFrame(seriesResp, qm.ProfileTypeId)...)
|
||||
|
||||
response.Frames = append(response.Frames, seriesToDataFrame(seriesResp, utils.Depointerizer(qm.ProfileTypeId))...)
|
||||
}
|
||||
|
||||
if query.QueryType == queryTypeProfile || query.QueryType == queryTypeBoth {
|
||||
@ -82,7 +84,7 @@ func makeProfileRequest(qm queryModel, query backend.DataQuery) *connect.Request
|
||||
Mode: v1alpha1.QueryRequest_MODE_MERGE,
|
||||
Options: &v1alpha1.QueryRequest_Merge{
|
||||
Merge: &v1alpha1.MergeProfile{
|
||||
Query: fmt.Sprintf("%s%s", qm.ProfileTypeId, qm.LabelSelector),
|
||||
Query: fmt.Sprintf("%s%s", utils.Depointerizer(qm.ProfileTypeId), utils.Depointerizer(qm.LabelSelector)),
|
||||
Start: ×tamppb.Timestamp{
|
||||
Seconds: query.TimeRange.From.Unix(),
|
||||
},
|
||||
@ -101,7 +103,7 @@ func makeProfileRequest(qm queryModel, query backend.DataQuery) *connect.Request
|
||||
func makeMetricRequest(qm queryModel, query backend.DataQuery) *connect.Request[v1alpha1.QueryRangeRequest] {
|
||||
return &connect.Request[v1alpha1.QueryRangeRequest]{
|
||||
Msg: &v1alpha1.QueryRangeRequest{
|
||||
Query: fmt.Sprintf("%s%s", qm.ProfileTypeId, qm.LabelSelector),
|
||||
Query: fmt.Sprintf("%s%s", utils.Depointerizer(qm.ProfileTypeId), utils.Depointerizer(qm.LabelSelector)),
|
||||
Start: ×tamppb.Timestamp{
|
||||
Seconds: query.TimeRange.From.Unix(),
|
||||
},
|
||||
|
@ -78,17 +78,12 @@ type TempoDataQuery = map[string]any
|
||||
|
||||
// TempoQuery defines model for TempoQuery.
|
||||
type TempoQuery struct {
|
||||
// DataQuery These are the common properties available to all queries in all datasources.
|
||||
// Specific implementations will *extend* this interface, adding the required
|
||||
// properties for the given context.
|
||||
DataQuery
|
||||
|
||||
// For mixed data sources the selected datasource is on the query level.
|
||||
// For non mixed scenarios this is undefined.
|
||||
// TODO find a better way to do this ^ that's friendly to schema
|
||||
// TODO this shouldn't be unknown but DataSourceRef | null
|
||||
Datasource *any `json:"datasource,omitempty"`
|
||||
Filters []TraceqlFilter `json:"filters"`
|
||||
Filters []TraceqlFilter `json:"filters,omitempty"`
|
||||
|
||||
// Filters that are used to query the metrics summary
|
||||
GroupBy []TraceqlFilter `json:"groupBy,omitempty"`
|
||||
@ -117,7 +112,7 @@ type TempoQuery struct {
|
||||
// A unique identifier for the query within the list of targets.
|
||||
// In server side expressions, the refId is used as a variable name to identify results.
|
||||
// By default, the UI will assign A->Z; however setting meaningful names may be useful.
|
||||
RefId string `json:"refId"`
|
||||
RefId *string `json:"refId,omitempty"`
|
||||
|
||||
// @deprecated Logfmt query to filter traces by their tags. Example: http.status_code=200 error=true
|
||||
Search *string `json:"search,omitempty"`
|
||||
|
@ -8,18 +8,15 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/grafana/codejen"
|
||||
corecodegen "github.com/grafana/grafana/pkg/codegen"
|
||||
"github.com/grafana/grafana/pkg/cuectx"
|
||||
"github.com/grafana/grafana/pkg/plugins/codegen"
|
||||
"github.com/grafana/grafana/pkg/plugins/pfs"
|
||||
"github.com/grafana/kindsys"
|
||||
"github.com/grafana/thema"
|
||||
"io/fs"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/codejen"
|
||||
corecodegen "github.com/grafana/grafana/pkg/codegen"
|
||||
"github.com/grafana/grafana/pkg/plugins/codegen"
|
||||
"github.com/grafana/grafana/pkg/plugins/pfs"
|
||||
)
|
||||
|
||||
var skipPlugins = map[string]bool{
|
||||
@ -40,25 +37,20 @@ func main() {
|
||||
log.Fatal(fmt.Errorf("could not get working directory: %s", err))
|
||||
}
|
||||
groot := filepath.Clean(filepath.Join(cwd, "../../.."))
|
||||
rt := cuectx.GrafanaThemaRuntime()
|
||||
|
||||
pluginKindGen := codejen.JennyListWithNamer(func(d *pfs.PluginDecl) string {
|
||||
return d.PluginMeta.Id
|
||||
})
|
||||
|
||||
pluginKindGen.Append(
|
||||
&codegen.PluginRegistryJenny{},
|
||||
codegen.PluginGoTypesJenny("pkg/tsdb"),
|
||||
codegen.PluginTSTypesJenny("public/app/plugins"),
|
||||
)
|
||||
|
||||
schifs := kindsys.SchemaInterfaces(rt.Context())
|
||||
schifnames := make([]string, 0, len(schifs))
|
||||
for _, schif := range schifs {
|
||||
schifnames = append(schifnames, strings.ToLower(schif.Name()))
|
||||
}
|
||||
pluginKindGen.AddPostprocessors(corecodegen.SlashHeaderMapper("public/app/plugins/gen.go"), splitSchiffer(schifnames))
|
||||
pluginKindGen.AddPostprocessors(corecodegen.SlashHeaderMapper("public/app/plugins/gen.go"), splitSchiffer())
|
||||
|
||||
declParser := pfs.NewDeclParser(rt, skipPlugins)
|
||||
declParser := pfs.NewDeclParser(skipPlugins)
|
||||
decls, err := declParser.Parse(os.DirFS(cwd))
|
||||
if err != nil {
|
||||
log.Fatalln(fmt.Errorf("parsing plugins in dir failed %s: %s", cwd, err))
|
||||
@ -69,15 +61,6 @@ func main() {
|
||||
log.Fatalln(fmt.Errorf("error writing files to disk: %s", err))
|
||||
}
|
||||
|
||||
rawResources, err := genRawResources()
|
||||
if err != nil {
|
||||
log.Fatalln(fmt.Errorf("error generating raw plugin resources: %s", err))
|
||||
}
|
||||
|
||||
if err := jfs.Merge(rawResources); err != nil {
|
||||
log.Fatalln(fmt.Errorf("Unable to merge raw resources: %s", err))
|
||||
}
|
||||
|
||||
if _, set := os.LookupEnv("CODEGEN_VERIFY"); set {
|
||||
if err = jfs.Verify(context.Background(), groot); err != nil {
|
||||
log.Fatal(fmt.Errorf("generated code is out of sync with inputs:\n%s\nrun `make gen-cue` to regenerate", err))
|
||||
@ -87,20 +70,8 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func kind2pd(rt *thema.Runtime, j codejen.OneToOne[kindsys.Kind]) codejen.OneToOne[*pfs.PluginDecl] {
|
||||
return codejen.AdaptOneToOne(j, func(pd *pfs.PluginDecl) kindsys.Kind {
|
||||
kd, err := kindsys.BindComposable(rt, pd.KindDecl)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return kd
|
||||
})
|
||||
}
|
||||
|
||||
func splitSchiffer(names []string) codejen.FileMapper {
|
||||
for i := range names {
|
||||
names[i] = names[i] + "/"
|
||||
}
|
||||
func splitSchiffer() codejen.FileMapper {
|
||||
names := []string{"panelcfg", "dataquery"}
|
||||
return func(f codejen.File) (codejen.File, error) {
|
||||
// TODO it's terrible that this has to exist, CODEJEN NEEDS TO BE BETTER
|
||||
path := filepath.ToSlash(f.RelativePath)
|
||||
@ -113,28 +84,3 @@ func splitSchiffer(names []string) codejen.FileMapper {
|
||||
return f, nil
|
||||
}
|
||||
}
|
||||
|
||||
func genRawResources() (*codejen.FS, error) {
|
||||
jennies := codejen.JennyListWithNamer(func(d []string) string {
|
||||
return "PluginsRawResources"
|
||||
})
|
||||
jennies.Append(&codegen.PluginRegistryJenny{})
|
||||
|
||||
schemas := make([]string, 0)
|
||||
filepath.WalkDir(".", func(path string, d fs.DirEntry, err error) error {
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(d.Name(), ".cue") {
|
||||
return nil
|
||||
}
|
||||
|
||||
schemas = append(schemas, "./"+filepath.Join("public", "app", "plugins", path))
|
||||
return nil
|
||||
})
|
||||
|
||||
jennies.AddPostprocessors(corecodegen.SlashHeaderMapper("public/app/plugins/gen.go"))
|
||||
|
||||
return jennies.GenerateFS(schemas)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user