diff --git a/.bra.toml b/.bra.toml index 6572f9a6afb..5af8e05ebcc 100644 --- a/.bra.toml +++ b/.bra.toml @@ -17,7 +17,7 @@ watch_exts = [".go", ".ini", ".toml", ".template.html"] ignore_files = [".*_gen.go"] build_delay = 1500 cmds = [ - ["make", "GO_BUILD_DEV=1", "build-go-fast"], + ["make", "GO_BUILD_DEV=1", "build-go"], ["make", "gen-jsonnet"], ["./bin/grafana", "server", "-profile", "-profile-addr=127.0.0.1", "-profile-port=6000", "-profile-block-rate=1", "-profile-mutex-rate=5", "-packaging=dev", "cfg:app_mode=development"] ] diff --git a/.citools/src/air/go.mod b/.citools/src/air/go.mod index 6fd4736b93d..8619eb0641e 100644 --- a/.citools/src/air/go.mod +++ b/.citools/src/air/go.mod @@ -1,6 +1,6 @@ module air -go 1.24.4 +go 1.25.3 tool github.com/air-verse/air @@ -21,7 +21,8 @@ require ( github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.8.0 // indirect github.com/tdewolff/parse/v2 v2.8.1 // indirect - golang.org/x/sys v0.33.0 // indirect - golang.org/x/text v0.25.0 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/text v0.29.0 // indirect google.golang.org/protobuf v1.36.6 // indirect ) diff --git a/.citools/src/air/go.sum b/.citools/src/air/go.sum index d733e3519f3..fbefab6f556 100644 --- a/.citools/src/air/go.sum +++ b/.citools/src/air/go.sum @@ -1,45 +1,190 @@ dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= +github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69 h1:+tu3HOoMXB7RXEINRVIpxJCT+KdYiI7LAEAUrOw3dIU= +github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69/go.mod h1:L1AbZdiDllfyYH5l5OkAaZtk7VkWe89bPJFmnDBNHxg= github.com/air-verse/air v1.62.0 h1:6CoXL4MAX9dc4xAzLfjMcDfbBoGmW5VjuuTV/1+bI+M= github.com/air-verse/air v1.62.0/go.mod h1:EO+jWuetL10tS9raffwg8WEV0t0KUeucRRaf9ii86dA= +github.com/alecthomas/chroma/v2 v2.17.2 h1:Rm81SCZ2mPoH+Q8ZCc/9YvzPUN/E7HgPiPJD8SLV6GI= +github.com/alecthomas/chroma/v2 v2.17.2/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= +github.com/armon/go-radix v1.0.1-0.20221118154546-54df44f2176c h1:651/eoCRnQ7YtSjAnSzRucrJz+3iGEFt+ysraELS81M= +github.com/armon/go-radix v1.0.1-0.20221118154546-54df44f2176c/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/bep/clocks v0.5.0 h1:hhvKVGLPQWRVsBP/UB7ErrHYIO42gINVbvqxvYTPVps= +github.com/bep/clocks v0.5.0/go.mod h1:SUq3q+OOq41y2lRQqH5fsOoxN8GbxSiT6jvoVVLCVhU= +github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= +github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= +github.com/bep/gitmap v1.6.0 h1:sDuQMm9HoTL0LtlrfxjbjgAg2wHQd4nkMup2FInYzhA= +github.com/bep/gitmap v1.6.0/go.mod h1:n+3W1f/rot2hynsqEGxGMErPRgT41n9CkGuzPvz9cIw= +github.com/bep/goat v0.5.0 h1:S8jLXHCVy/EHIoCY+btKkmcxcXFd34a0Q63/0D4TKeA= +github.com/bep/goat v0.5.0/go.mod h1:Md9x7gRxiWKs85yHlVTvHQw9rg86Bm+Y4SuYE8CTH7c= github.com/bep/godartsass/v2 v2.5.0 h1:tKRvwVdyjCIr48qgtLa4gHEdtRkPF8H1OeEhJAEv7xg= github.com/bep/godartsass/v2 v2.5.0/go.mod h1:rjsi1YSXAl/UbsGL85RLDEjRKdIKUlMQHr6ChUNYOFU= github.com/bep/golibsass v1.2.0 h1:nyZUkKP/0psr8nT6GR2cnmt99xS93Ji82ZD9AgOK6VI= github.com/bep/golibsass v1.2.0/go.mod h1:DL87K8Un/+pWUS75ggYv41bliGiolxzDKWJAq3eJ1MA= +github.com/bep/goportabletext v0.1.0 h1:8dqym2So1cEqVZiBa4ZnMM1R9l/DnC1h4ONg4J5kujw= +github.com/bep/goportabletext v0.1.0/go.mod h1:6lzSTsSue75bbcyvVc0zqd1CdApuT+xkZQ6Re5DzZFg= +github.com/bep/gowebp v0.4.0 h1:QihuVnvIKbRoeBNQkN0JPMM8ClLmD6V2jMftTFwSK3Q= +github.com/bep/gowebp v0.4.0/go.mod h1:95gtYkAA8iIn1t3HkAPurRCVGV/6NhgaHJ1urz0iIwc= +github.com/bep/imagemeta v0.12.0 h1:ARf+igs5B7pf079LrqRnwzQ/wEB8Q9v4NSDRZO1/F5k= +github.com/bep/imagemeta v0.12.0/go.mod h1:23AF6O+4fUi9avjiydpKLStUNtJr5hJB4rarG18JpN8= +github.com/bep/lazycache v0.8.0 h1:lE5frnRjxaOFbkPZ1YL6nijzOPPz6zeXasJq8WpG4L8= +github.com/bep/lazycache v0.8.0/go.mod h1:BQ5WZepss7Ko91CGdWz8GQZi/fFnCcyWupv8gyTeKwk= +github.com/bep/logg v0.4.0 h1:luAo5mO4ZkhA5M1iDVDqDqnBBnlHjmtZF6VAyTp+nCQ= +github.com/bep/logg v0.4.0/go.mod h1:Ccp9yP3wbR1mm++Kpxet91hAZBEQgmWgFgnXX3GkIV0= +github.com/bep/overlayfs v0.10.0 h1:wS3eQ6bRsLX+4AAmwGjvoFSAQoeheamxofFiJ2SthSE= +github.com/bep/overlayfs v0.10.0/go.mod h1:ouu4nu6fFJaL0sPzNICzxYsBeWwrjiTdFZdK4lI3tro= +github.com/bep/tmc v0.5.1 h1:CsQnSC6MsomH64gw0cT5f+EwQDcvZz4AazKunFwTpuI= +github.com/bep/tmc v0.5.1/go.mod h1:tGYHN8fS85aJPhDLgXETVKp+PR382OvFi2+q2GkGsq0= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= +github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/disintegration/gift v1.2.1 h1:Y005a1X4Z7Uc+0gLpSAsKhWi4qLtsdEcMIbbdvdZ6pc= +github.com/disintegration/gift v1.2.1/go.mod h1:Jh2i7f7Q2BM7Ezno3PhfezbR1xpUg9dUg3/RlKGr4HI= +github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= +github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/evanw/esbuild v0.25.3 h1:4JKyUsm/nHDhpxis4IyWXAi8GiyTwG1WdEp6OhGVE8U= +github.com/evanw/esbuild v0.25.3/go.mod h1:D2vIQZqV/vIf/VRHtViaUtViZmG7o+kKmlBfVQuRi48= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk= +github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4= +github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gohugoio/go-i18n/v2 v2.1.3-0.20230805085216-e63c13218d0e h1:QArsSubW7eDh8APMXkByjQWvuljwPGAGQpJEFn0F0wY= +github.com/gohugoio/go-i18n/v2 v2.1.3-0.20230805085216-e63c13218d0e/go.mod h1:3Ltoo9Banwq0gOtcOwxuHG6omk+AwsQPADyw2vQYOJQ= +github.com/gohugoio/hashstructure v0.5.0 h1:G2fjSBU36RdwEJBWJ+919ERvOVqAg9tfcYp47K9swqg= +github.com/gohugoio/hashstructure v0.5.0/go.mod h1:Ser0TniXuu/eauYmrwM4o64EBvySxNzITEOLlm4igec= +github.com/gohugoio/httpcache v0.7.0 h1:ukPnn04Rgvx48JIinZvZetBfHaWE7I01JR2Q2RrQ3Vs= +github.com/gohugoio/httpcache v0.7.0/go.mod h1:fMlPrdY/vVJhAriLZnrF5QpN3BNAcoBClgAyQd+lGFI= github.com/gohugoio/hugo v0.147.6 h1:rL4rnus/5qzj4+FoA+JMzsVvFJ2YZdVIH6pbuCB2P84= github.com/gohugoio/hugo v0.147.6/go.mod h1:Sb2COQPDPYG+tRSpePtzKytiuVDqkBivEhgIew1QbNo= +github.com/gohugoio/hugo-goldmark-extensions/extras v0.3.0 h1:gj49kTR5Z4Hnm0ZaQrgPVazL3DUkppw+x6XhHCmh+Wk= +github.com/gohugoio/hugo-goldmark-extensions/extras v0.3.0/go.mod h1:IMMj7xiUbLt1YNJ6m7AM4cnsX4cFnnfkleO/lBHGzUg= +github.com/gohugoio/hugo-goldmark-extensions/passthrough v0.3.1 h1:nUzXfRTszLliZuN0JTKeunXTRaiFX6ksaWP0puLLYAY= +github.com/gohugoio/hugo-goldmark-extensions/passthrough v0.3.1/go.mod h1:Wy8ThAA8p2/w1DY05vEzq6EIeI2mzDjvHsu7ULBVwog= +github.com/gohugoio/locales v0.14.0 h1:Q0gpsZwfv7ATHMbcTNepFd59H7GoykzWJIxi113XGDc= +github.com/gohugoio/locales v0.14.0/go.mod h1:ip8cCAv/cnmVLzzXtiTpPwgJ4xhKZranqNqtoIu0b/4= +github.com/gohugoio/localescompressed v1.0.1 h1:KTYMi8fCWYLswFyJAeOtuk/EkXR/KPTHHNN9OS+RTxo= +github.com/gohugoio/localescompressed v1.0.1/go.mod h1:jBF6q8D7a0vaEmcWPNcAjUZLJaIVNiwvM3WlmTvooB0= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/hairyhenderson/go-codeowners v0.7.0 h1:s0W4wF8bdsBEjTWzwzSlsatSthWtTAF2xLgo4a4RwAo= +github.com/hairyhenderson/go-codeowners v0.7.0/go.mod h1:wUlNgQ3QjqC4z8DnM5nnCYVq/icpqXJyJOukKx5U8/Q= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/jdkato/prose v1.2.1 h1:Fp3UnJmLVISmlc57BgKUzdjr0lOtjqTZicL3PaYy6cU= +github.com/jdkato/prose v1.2.1/go.mod h1:AiRHgVagnEx2JbQRQowVBKjG0bcs/vtkGCH1dYAL1rA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kyokomi/emoji/v2 v2.2.13 h1:GhTfQa67venUUvmleTNFnb+bi7S3aocF7ZCXU9fSO7U= +github.com/kyokomi/emoji/v2 v2.2.13/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/makeworld-the-better-one/dither/v2 v2.4.0 h1:Az/dYXiTcwcRSe59Hzw4RI1rSnAZns+1msaCXetrMFE= +github.com/makeworld-the-better-one/dither/v2 v2.4.0/go.mod h1:VBtN8DXO7SNtyGmLiGA7IsFeKrBkQPze1/iAeM95arc= +github.com/marekm4/color-extractor v1.2.1 h1:3Zb2tQsn6bITZ8MBVhc33Qn1k5/SEuZ18mrXGUqIwn0= +github.com/marekm4/color-extractor v1.2.1/go.mod h1:90VjmiHI6M8ez9eYUaXLdcKnS+BAOp7w+NpwBdkJmpA= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c h1:cqn374mizHuIWj+OSJCajGr/phAmuMug9qIX3l9CflE= +github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/muesli/smartcrop v0.3.0 h1:JTlSkmxWg/oQ1TcLDoypuirdE8Y/jzNirQeLkxpA6Oc= +github.com/muesli/smartcrop v0.3.0/go.mod h1:i2fCI/UorTfgEpPPLWiFBv4pye+YAG78RwcQLUkocpI= +github.com/niklasfasching/go-org v1.7.0 h1:vyMdcMWWTe/XmANk19F4k8XGBYg0GQ/gJGMimOjGMek= +github.com/niklasfasching/go-org v1.7.0/go.mod h1:WuVm4d45oePiE0eX25GqTDQIt/qPW1T9DGkRscqLW5o= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= +github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= github.com/spf13/cast v1.8.0 h1:gEN9K4b8Xws4EX0+a0reLmhq8moKn7ntRlQYgjPeCDk= github.com/spf13/cast v1.8.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.23.5 h1:/P548KcpTkIOUvNg22zN83/GiaYSOIrbqtoue4I7kYM= +github.com/tdewolff/minify/v2 v2.23.5/go.mod h1:2RI9tiIrzJU1Z5EasXEPaI1MqobRyxKHOOgrRkq5oEw= github.com/tdewolff/parse/v2 v2.8.1 h1:J5GSHru6o3jF1uLlEKVXkDxxcVx6yzOlIVIotK4w2po= github.com/tdewolff/parse/v2 v2.8.1/go.mod h1:Hwlni2tiVNKyzR1o6nUs4FOF07URA+JLBLd6dlIXYqo= +github.com/tdewolff/test v1.0.11 h1:FdLbwQVHxqG16SlkGveC0JVyrJN62COWTRyUFzfbtBE= github.com/tdewolff/test v1.0.11/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I= +github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM= +github.com/yuin/goldmark v1.7.11 h1:ZCxLyDMtz0nT2HFfsYG8WZ47Trip2+JyLysKcMYE5bo= +github.com/yuin/goldmark v1.7.11/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= +github.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9HTHs= +github.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA= +golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b h1:QoALfVG9rhQ/M7vYDScfPdWjGL9dlsVVM5VGh7aKoAA= +golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ= +golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w= +golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +gopkg.in/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY= +rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs= diff --git a/.citools/src/bra/go.mod b/.citools/src/bra/go.mod index fec1ff55bbb..43a1908f9c4 100644 --- a/.citools/src/bra/go.mod +++ b/.citools/src/bra/go.mod @@ -1,6 +1,6 @@ module bra -go 1.24.5 +go 1.25.3 tool github.com/unknwon/bra @@ -17,6 +17,6 @@ require ( github.com/unknwon/com v1.0.1 // indirect github.com/unknwon/log v0.0.0-20200308114134-929b1006e34a // indirect github.com/urfave/cli v1.22.16 // indirect - golang.org/x/sys v0.33.0 // indirect + golang.org/x/sys v0.36.0 // indirect gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect ) diff --git a/.citools/src/bra/go.sum b/.citools/src/bra/go.sum index 601cd7a8f3f..723e36ed099 100644 --- a/.citools/src/bra/go.sum +++ b/.citools/src/bra/go.sum @@ -56,8 +56,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191020152052-9984515f0562/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/.citools/src/cog/go.mod b/.citools/src/cog/go.mod index 1b0f1246663..0ee1004f974 100644 --- a/.citools/src/cog/go.mod +++ b/.citools/src/cog/go.mod @@ -1,6 +1,6 @@ module cog -go 1.24.5 +go 1.25.3 tool github.com/grafana/cog/cmd/cli @@ -40,11 +40,11 @@ require ( github.com/spf13/pflag v1.0.6 // indirect github.com/ugorji/go/codec v1.2.11 // indirect github.com/yalue/merged_fs v1.3.0 // indirect - golang.org/x/mod v0.24.0 // indirect - golang.org/x/net v0.40.0 // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/net v0.45.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.14.0 // indirect - golang.org/x/text v0.25.0 // indirect - golang.org/x/tools v0.33.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/text v0.29.0 // indirect + golang.org/x/tools v0.36.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/.citools/src/cog/go.sum b/.citools/src/cog/go.sum index 513236e89f4..fc55dd4132c 100644 --- a/.citools/src/cog/go.sum +++ b/.citools/src/cog/go.sum @@ -85,20 +85,20 @@ github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4d github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/yalue/merged_fs v1.3.0 h1:qCeh9tMPNy/i8cwDsQTJ5bLr6IRxbs6meakNE5O+wyY= github.com/yalue/merged_fs v1.3.0/go.mod h1:WqqchfVYQyclV2tnR7wtRhBddzBvLVR83Cjw9BKQw0M= -golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= -golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= -golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= -golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= -golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= -golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/.citools/src/cue/go.mod b/.citools/src/cue/go.mod index d2b53be05ce..d9a143c75c2 100644 --- a/.citools/src/cue/go.mod +++ b/.citools/src/cue/go.mod @@ -1,6 +1,6 @@ module cue -go 1.24.5 +go 1.25.3 tool cuelang.org/go/cmd/cue @@ -25,13 +25,13 @@ require ( github.com/spf13/pflag v1.0.6 // indirect github.com/stretchr/testify v1.10.0 // indirect github.com/tetratelabs/wazero v1.6.0 // indirect - golang.org/x/mod v0.24.0 // indirect - golang.org/x/net v0.40.0 // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/net v0.45.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.14.0 // indirect - golang.org/x/sys v0.33.0 // indirect - golang.org/x/text v0.25.0 // indirect - golang.org/x/tools v0.33.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/text v0.29.0 // indirect + golang.org/x/tools v0.36.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/.citools/src/cue/go.sum b/.citools/src/cue/go.sum index ff7385db2e7..86c2675545b 100644 --- a/.citools/src/cue/go.sum +++ b/.citools/src/cue/go.sum @@ -53,20 +53,20 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tetratelabs/wazero v1.6.0 h1:z0H1iikCdP8t+q341xqepY4EWvHEw8Es7tlqiVzlP3g= github.com/tetratelabs/wazero v1.6.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A= -golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= -golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= -golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= -golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/.citools/src/golangci-lint/go.mod b/.citools/src/golangci-lint/go.mod index b5152308c30..d3ac9b697aa 100644 --- a/.citools/src/golangci-lint/go.mod +++ b/.citools/src/golangci-lint/go.mod @@ -1,41 +1,48 @@ module golangci-lint -go 1.24.5 +go 1.25.3 tool github.com/golangci/golangci-lint/v2/cmd/golangci-lint require ( 4d63.com/gocheckcompilerdirectives v1.3.0 // indirect 4d63.com/gochecknoglobals v0.2.2 // indirect - github.com/4meepo/tagalign v1.4.2 // indirect - github.com/Abirdcfly/dupword v0.1.3 // indirect - github.com/Antonboom/errname v1.1.0 // indirect - github.com/Antonboom/nilnil v1.1.0 // indirect - github.com/Antonboom/testifylint v1.6.0 // indirect + codeberg.org/chavacava/garif v0.2.0 // indirect + dev.gaijin.team/go/exhaustruct/v4 v4.0.0 // indirect + dev.gaijin.team/go/golib v0.6.0 // indirect + github.com/4meepo/tagalign v1.4.3 // indirect + github.com/Abirdcfly/dupword v0.1.6 // indirect + github.com/AdminBenni/iota-mixing v1.0.0 // indirect + github.com/AlwxSin/noinlineerr v1.0.5 // indirect + github.com/Antonboom/errname v1.1.1 // indirect + github.com/Antonboom/nilnil v1.1.1 // indirect + github.com/Antonboom/testifylint v1.6.4 // indirect github.com/BurntSushi/toml v1.5.0 // indirect - github.com/Crocmagnon/fatcontext v0.7.1 // indirect - github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect - github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 // indirect + github.com/Djarvur/go-err113 v0.1.1 // indirect github.com/Masterminds/semver/v3 v3.3.1 // indirect + github.com/MirrexOne/unqueryvet v1.2.1 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect + github.com/alecthomas/chroma/v2 v2.20.0 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect - github.com/alexkohler/nakedret/v2 v2.0.5 // indirect + github.com/alexkohler/nakedret/v2 v2.0.6 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect + github.com/alfatraining/structtag v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect - github.com/alingse/nilnesserr v0.1.2 // indirect - github.com/ashanbrown/forbidigo v1.6.0 // indirect - github.com/ashanbrown/makezero v1.2.0 // indirect + github.com/alingse/nilnesserr v0.2.0 // indirect + github.com/ashanbrown/forbidigo/v2 v2.1.0 // indirect + github.com/ashanbrown/makezero/v2 v2.0.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bkielbasa/cyclop v1.2.3 // indirect github.com/blizzy78/varnamelen v0.8.0 // indirect - github.com/bombsimon/wsl/v4 v4.6.0 // indirect + github.com/bombsimon/wsl/v4 v4.7.0 // indirect + github.com/bombsimon/wsl/v5 v5.2.0 // indirect github.com/breml/bidichk v0.3.3 // indirect github.com/breml/errchkjson v0.4.1 // indirect - github.com/butuzov/ireturn v0.3.1 // indirect + github.com/butuzov/ireturn v0.4.0 // indirect github.com/butuzov/mirror v1.3.0 // indirect github.com/catenacyber/perfsprint v0.9.1 // indirect - github.com/ccojocar/zxcvbn-go v1.0.2 // indirect + github.com/ccojocar/zxcvbn-go v1.0.4 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charithe/durationcheck v0.0.10 // indirect github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect @@ -43,20 +50,20 @@ require ( github.com/charmbracelet/x/ansi v0.8.0 // indirect github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect github.com/charmbracelet/x/term v0.2.1 // indirect - github.com/chavacava/garif v0.1.0 // indirect github.com/ckaznocha/intrange v0.3.1 // indirect github.com/curioswitch/go-reassign v0.3.0 // indirect - github.com/daixiang0/gci v0.13.6 // indirect + github.com/daixiang0/gci v0.13.7 // indirect github.com/dave/dst v0.27.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/denis-tingaikin/go-header v0.5.0 // indirect + github.com/dlclark/regexp2 v1.11.5 // indirect github.com/ettle/strcase v0.2.0 // indirect github.com/fatih/color v1.18.0 // indirect github.com/fatih/structtag v1.2.0 // indirect - github.com/firefart/nonamedreturns v1.0.5 // indirect + github.com/firefart/nonamedreturns v1.0.6 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/ghostiam/protogetter v0.3.12 // indirect + github.com/ghostiam/protogetter v0.3.16 // indirect github.com/go-critic/go-critic v0.13.0 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect @@ -68,46 +75,50 @@ require ( github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobwas/glob v0.2.3 // indirect + github.com/godoc-lint/godoc-lint v0.10.0 // indirect github.com/gofrs/flock v0.12.1 // indirect + github.com/golangci/asciicheck v0.5.0 // indirect github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect - github.com/golangci/go-printf-func-name v0.1.0 // indirect + github.com/golangci/go-printf-func-name v0.1.1 // indirect github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect - github.com/golangci/golangci-lint/v2 v2.0.2 // indirect + github.com/golangci/golangci-lint/v2 v2.5.0 // indirect github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 // indirect - github.com/golangci/misspell v0.6.0 // indirect - github.com/golangci/plugin-module-register v0.1.1 // indirect + github.com/golangci/misspell v0.7.0 // indirect + github.com/golangci/nilerr v0.0.0-20250918000102-015671e622fe // indirect + github.com/golangci/plugin-module-register v0.1.2 // indirect github.com/golangci/revgrep v0.8.0 // indirect - github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed // indirect + github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e // indirect + github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e // indirect github.com/google/go-cmp v0.7.0 // indirect - github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect - github.com/gordonklaus/ineffassign v0.1.0 // indirect + github.com/gordonklaus/ineffassign v0.2.0 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/comment v1.5.0 // indirect github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect - github.com/gostaticanalysis/nilerr v0.1.1 // indirect github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/jgautheron/goconst v1.7.1 // indirect + github.com/jgautheron/goconst v1.8.2 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect - github.com/jjti/go-spancheck v0.6.4 // indirect + github.com/jjti/go-spancheck v0.6.5 // indirect github.com/julz/importas v0.2.0 // indirect github.com/karamaru-alpha/copyloopvar v1.2.1 // indirect github.com/kisielk/errcheck v1.9.0 // indirect github.com/kkHAIKE/contextcheck v1.1.6 // indirect - github.com/kulti/thelper v0.6.3 // indirect - github.com/kunwardeep/paralleltest v1.0.10 // indirect + github.com/kulti/thelper v0.7.1 // indirect + github.com/kunwardeep/paralleltest v1.0.14 // indirect github.com/lasiar/canonicalheader v1.1.2 // indirect - github.com/ldez/exptostd v0.4.2 // indirect - github.com/ldez/gomoddirectives v0.6.1 // indirect - github.com/ldez/grignotin v0.9.0 // indirect - github.com/ldez/tagliatelle v0.7.1 // indirect - github.com/ldez/usetesting v0.4.2 // indirect + github.com/ldez/exptostd v0.4.4 // indirect + github.com/ldez/gomoddirectives v0.7.0 // indirect + github.com/ldez/grignotin v0.10.1 // indirect + github.com/ldez/tagliatelle v0.7.2 // indirect + github.com/ldez/usetesting v0.5.0 // indirect github.com/leonklingele/grouper v1.1.2 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/macabu/inamedparam v0.2.0 // indirect + github.com/manuelarte/embeddedstructfieldcheck v0.4.0 // indirect + github.com/manuelarte/funcorder v0.5.0 // indirect github.com/maratori/testableexamples v1.0.0 // indirect github.com/maratori/testpackage v1.1.1 // indirect github.com/matoous/godox v1.1.0 // indirect @@ -115,7 +126,7 @@ require ( github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/mgechev/revive v1.7.0 // indirect + github.com/mgechev/revive v1.12.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moricho/tparallel v0.3.2 // indirect github.com/muesli/termenv v0.16.0 // indirect @@ -123,11 +134,10 @@ require ( github.com/nakabonne/nestif v0.3.1 // indirect github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.19.1 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/nunnatsa/ginkgolinter v0.21.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/polyfloyd/go-errorlint v1.7.1 // indirect + github.com/polyfloyd/go-errorlint v1.8.0 // indirect github.com/prometheus/client_golang v1.22.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.63.0 // indirect @@ -144,58 +154,59 @@ require ( github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect - github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect + github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.28.0 // indirect - github.com/securego/gosec/v2 v2.22.2 // indirect + github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect + github.com/securego/gosec/v2 v2.22.8 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect - github.com/sonatard/noctx v0.1.0 // indirect + github.com/sonatard/noctx v0.4.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect - github.com/spf13/afero v1.12.0 // indirect + github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/spf13/cobra v1.9.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/cobra v1.10.1 // indirect + github.com/spf13/pflag v1.0.10 // indirect github.com/spf13/viper v1.20.1 // indirect github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect github.com/stretchr/objx v0.5.2 // indirect - github.com/stretchr/testify v1.10.0 // indirect + github.com/stretchr/testify v1.11.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/tdakkota/asciicheck v0.4.1 // indirect - github.com/tetafro/godot v1.5.0 // indirect + github.com/tetafro/godot v1.5.4 // indirect github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 // indirect - github.com/timonwong/loggercheck v0.10.1 // indirect - github.com/tomarrell/wrapcheck/v2 v2.10.0 // indirect + github.com/timonwong/loggercheck v0.11.0 // indirect + github.com/tomarrell/wrapcheck/v2 v2.11.0 // indirect github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect github.com/ultraware/funlen v0.2.0 // indirect github.com/ultraware/whitespace v0.2.0 // indirect github.com/uudashr/gocognit v1.2.0 // indirect - github.com/uudashr/iface v1.3.1 // indirect + github.com/uudashr/iface v1.4.1 // indirect github.com/xen0n/gosmopolitan v1.3.0 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.3.0 // indirect github.com/ykadowak/zerologlint v0.1.5 // indirect gitlab.com/bosi/decorder v0.4.2 // indirect - go-simpler.org/musttag v0.13.0 // indirect - go-simpler.org/sloglint v0.9.0 // indirect + go-simpler.org/musttag v0.14.0 // indirect + go-simpler.org/sloglint v0.11.1 // indirect + go.augendre.info/arangolint v0.2.0 // indirect + go.augendre.info/fatcontext v0.8.1 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect - golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/mod v0.24.0 // indirect - golang.org/x/sync v0.14.0 // indirect - golang.org/x/sys v0.33.0 // indirect - golang.org/x/text v0.25.0 // indirect - golang.org/x/tools v0.33.0 // indirect + golang.org/x/exp/typeparams v0.0.0-20250911091902-df9299821621 // indirect + golang.org/x/mod v0.28.0 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/text v0.29.0 // indirect + golang.org/x/tools v0.37.0 // indirect google.golang.org/protobuf v1.36.6 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect honnef.co/go/tools v0.6.1 // indirect - mvdan.cc/gofumpt v0.7.0 // indirect + mvdan.cc/gofumpt v0.9.1 // indirect mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 // indirect ) diff --git a/.citools/src/golangci-lint/go.sum b/.citools/src/golangci-lint/go.sum index 37d9819bfeb..4748f406fb8 100644 --- a/.citools/src/golangci-lint/go.sum +++ b/.citools/src/golangci-lint/go.sum @@ -2,46 +2,58 @@ 4d63.com/gocheckcompilerdirectives v1.3.0/go.mod h1:ofsJ4zx2QAuIP/NO/NAh1ig6R1Fb18/GI7RVMwz7kAY= 4d63.com/gochecknoglobals v0.2.2 h1:H1vdnwnMaZdQW/N+NrkT1SZMTBmcwHe9Vq8lJcYYTtU= 4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0= -github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E= -github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI= -github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgBeE= -github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw= -github.com/Antonboom/errname v1.1.0 h1:A+ucvdpMwlo/myWrkHEUEBWc/xuXdud23S8tmTb/oAE= -github.com/Antonboom/errname v1.1.0/go.mod h1:O1NMrzgUcVBGIfi3xlVuvX8Q/VP/73sseCaAppfjqZw= -github.com/Antonboom/nilnil v1.1.0 h1:jGxJxjgYS3VUUtOTNk8Z1icwT5ESpLH/426fjmQG+ng= -github.com/Antonboom/nilnil v1.1.0/go.mod h1:b7sAlogQjFa1wV8jUW3o4PMzDVFLbTux+xnQdvzdcIE= -github.com/Antonboom/testifylint v1.6.0 h1:6rdILVPt4+rqcvhid8w9wJNynKLUgqHNpFyM67UeXyc= -github.com/Antonboom/testifylint v1.6.0/go.mod h1:k+nEkathI2NFjKO6HvwmSrbzUcQ6FAnbZV+ZRrnXPLI= +codeberg.org/chavacava/garif v0.2.0 h1:F0tVjhYbuOCnvNcU3YSpO6b3Waw6Bimy4K0mM8y6MfY= +codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0GiPTJmEqBQ= +dev.gaijin.team/go/exhaustruct/v4 v4.0.0 h1:873r7aNneqoBB3IaFIzhvt2RFYTuHgmMjoKfwODoI1Y= +dev.gaijin.team/go/exhaustruct/v4 v4.0.0/go.mod h1:aZ/k2o4Y05aMJtiux15x8iXaumE88YdiB0Ai4fXOzPI= +dev.gaijin.team/go/golib v0.6.0 h1:v6nnznFTs4bppib/NyU1PQxobwDHwCXXl15P7DV5Zgo= +dev.gaijin.team/go/golib v0.6.0/go.mod h1:uY1mShx8Z/aNHWDyAkZTkX+uCi5PdX7KsG1eDQa2AVE= +github.com/4meepo/tagalign v1.4.3 h1:Bnu7jGWwbfpAie2vyl63Zup5KuRv21olsPIha53BJr8= +github.com/4meepo/tagalign v1.4.3/go.mod h1:00WwRjiuSbrRJnSVeGWPLp2epS5Q/l4UEy0apLLS37c= +github.com/Abirdcfly/dupword v0.1.6 h1:qeL6u0442RPRe3mcaLcbaCi2/Y/hOcdtw6DE9odjz9c= +github.com/Abirdcfly/dupword v0.1.6/go.mod h1:s+BFMuL/I4YSiFv29snqyjwzDp4b65W2Kvy+PKzZ6cw= +github.com/AdminBenni/iota-mixing v1.0.0 h1:Os6lpjG2dp/AE5fYBPAA1zfa2qMdCAWwPMCgpwKq7wo= +github.com/AdminBenni/iota-mixing v1.0.0/go.mod h1:i4+tpAaB+qMVIV9OK3m4/DAynOd5bQFaOu+2AhtBCNY= +github.com/AlwxSin/noinlineerr v1.0.5 h1:RUjt63wk1AYWTXtVXbSqemlbVTb23JOSRiNsshj7TbY= +github.com/AlwxSin/noinlineerr v1.0.5/go.mod h1:+QgkkoYrMH7RHvcdxdlI7vYYEdgeoFOVjU9sUhw/rQc= +github.com/Antonboom/errname v1.1.1 h1:bllB7mlIbTVzO9jmSWVWLjxTEbGBVQ1Ff/ClQgtPw9Q= +github.com/Antonboom/errname v1.1.1/go.mod h1:gjhe24xoxXp0ScLtHzjiXp0Exi1RFLKJb0bVBtWKCWQ= +github.com/Antonboom/nilnil v1.1.1 h1:9Mdr6BYd8WHCDngQnNVV0b554xyisFioEKi30sksufQ= +github.com/Antonboom/nilnil v1.1.1/go.mod h1:yCyAmSw3doopbOWhJlVci+HuyNRuHJKIv6V2oYQa8II= +github.com/Antonboom/testifylint v1.6.4 h1:gs9fUEy+egzxkEbq9P4cpcMB6/G0DYdMeiFS87UiqmQ= +github.com/Antonboom/testifylint v1.6.4/go.mod h1:YO33FROXX2OoUfwjz8g+gUxQXio5i9qpVy7nXGbxDD4= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/Crocmagnon/fatcontext v0.7.1 h1:SC/VIbRRZQeQWj/TcQBS6JmrXcfA+BU4OGSVUt54PjM= -github.com/Crocmagnon/fatcontext v0.7.1/go.mod h1:1wMvv3NXEBJucFGfwOJBxSVWcoIO6emV215SMkW9MFU= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 h1:Sz1JIXEcSfhz7fUi7xHnhpIE0thVASYjvosApmHuD2k= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1/go.mod h1:n/LSCXNuIYqVfBlVXyHfMQkZDdp1/mmxfSjADd3z1Zg= +github.com/Djarvur/go-err113 v0.1.1 h1:eHfopDqXRwAi+YmCUas75ZE0+hoBHJ2GQNLYRSxao4g= +github.com/Djarvur/go-err113 v0.1.1/go.mod h1:IaWJdYFLg76t2ihfflPZnM1LIQszWOsFDh2hhhAVF6k= github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/MirrexOne/unqueryvet v1.2.1 h1:M+zdXMq84g+E1YOLa7g7ExN3dWfZQrdDSTCM7gC+m/A= +github.com/MirrexOne/unqueryvet v1.2.1/go.mod h1:IWwCwMQlSWjAIteW0t+28Q5vouyktfujzYznSIWiuOg= github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw= +github.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= -github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= -github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= -github.com/alexkohler/nakedret/v2 v2.0.5 h1:fP5qLgtwbx9EJE8dGEERT02YwS8En4r9nnZ71RK+EVU= -github.com/alexkohler/nakedret/v2 v2.0.5/go.mod h1:bF5i0zF2Wo2o4X4USt9ntUWve6JbFv02Ff4vlkmS/VU= +github.com/alecthomas/repr v0.5.1 h1:E3G4t2QbHTSNpPKBgMTln5KLkZHLOcU7r37J4pXBuIg= +github.com/alecthomas/repr v0.5.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/alexkohler/nakedret/v2 v2.0.6 h1:ME3Qef1/KIKr3kWX3nti3hhgNxw6aqN5pZmQiFSsuzQ= +github.com/alexkohler/nakedret/v2 v2.0.6/go.mod h1:l3RKju/IzOMQHmsEvXwkqMDzHHvurNQfAgE1eVmT40Q= github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/alfatraining/structtag v1.0.0 h1:2qmcUqNcCoyVJ0up879K614L9PazjBSFruTB0GOFjCc= +github.com/alfatraining/structtag v1.0.0/go.mod h1:p3Xi5SwzTi+Ryj64DqjLWz7XurHxbGsq6y3ubePJPus= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= -github.com/alingse/nilnesserr v0.1.2 h1:Yf8Iwm3z2hUUrP4muWfW83DF4nE3r1xZ26fGWUKCZlo= -github.com/alingse/nilnesserr v0.1.2/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= -github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= -github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= -github.com/ashanbrown/makezero v1.2.0 h1:/2Lp1bypdmK9wDIq7uWBlDF1iMUpIIS4A+pF6C9IEUU= -github.com/ashanbrown/makezero v1.2.0/go.mod h1:dxlPhHbDMC6N6xICzFBSK+4njQDdK8euNO0qjQMtGY4= +github.com/alingse/nilnesserr v0.2.0 h1:raLem5KG7EFVb4UIDAXgrv3N2JIaffeKNtcEXkEWd/w= +github.com/alingse/nilnesserr v0.2.0/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= +github.com/ashanbrown/forbidigo/v2 v2.1.0 h1:NAxZrWqNUQiDz19FKScQ/xvwzmij6BiOw3S0+QUQ+Hs= +github.com/ashanbrown/forbidigo/v2 v2.1.0/go.mod h1:0zZfdNAuZIL7rSComLGthgc/9/n2FqspBOH90xlCHdA= +github.com/ashanbrown/makezero/v2 v2.0.1 h1:r8GtKetWOgoJ4sLyUx97UTwyt2dO7WkGFHizn/Lo8TY= +github.com/ashanbrown/makezero/v2 v2.0.1/go.mod h1:kKU4IMxmYW1M4fiEHMb2vc5SFoPzXvgbMR9gIp5pjSw= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -50,20 +62,22 @@ github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5 github.com/bkielbasa/cyclop v1.2.3/go.mod h1:kHTwA9Q0uZqOADdupvcFJQtp/ksSnytRMe8ztxG8Fuo= github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= -github.com/bombsimon/wsl/v4 v4.6.0 h1:ew2R/N42su553DKTYqt3HSxaQN+uHQPv4xZ2MBmwaW4= -github.com/bombsimon/wsl/v4 v4.6.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg= +github.com/bombsimon/wsl/v4 v4.7.0 h1:1Ilm9JBPRczjyUs6hvOPKvd7VL1Q++PL8M0SXBDf+jQ= +github.com/bombsimon/wsl/v4 v4.7.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg= +github.com/bombsimon/wsl/v5 v5.2.0 h1:PyCCwd3Q7abGs3e34IW4jLYlBS+FbsU6iK+Tb3NnDp4= +github.com/bombsimon/wsl/v5 v5.2.0/go.mod h1:Gp8lD04z27wm3FANIUPZycXp+8huVsn0oxc+n4qfV9I= github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE= github.com/breml/bidichk v0.3.3/go.mod h1:ISbsut8OnjB367j5NseXEGGgO/th206dVa427kR8YTE= github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg= github.com/breml/errchkjson v0.4.1/go.mod h1:a23OvR6Qvcl7DG/Z4o0el6BRAjKnaReoPQFciAl9U3s= -github.com/butuzov/ireturn v0.3.1 h1:mFgbEI6m+9W8oP/oDdfA34dLisRFCj2G6o/yiI1yZrY= -github.com/butuzov/ireturn v0.3.1/go.mod h1:ZfRp+E7eJLC0NQmk1Nrm1LOrn/gQlOykv+cVPdiXH5M= +github.com/butuzov/ireturn v0.4.0 h1:+s76bF/PfeKEdbG8b54aCocxXmi0wvYdOVsWxVO7n8E= +github.com/butuzov/ireturn v0.4.0/go.mod h1:ghI0FrCmap8pDWZwfPisFD1vEc56VKH4NpQUxDHta70= github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI= github.com/catenacyber/perfsprint v0.9.1 h1:5LlTp4RwTooQjJCvGEFV6XksZvWE7wCOUvjD2z0vls0= github.com/catenacyber/perfsprint v0.9.1/go.mod h1:q//VWC2fWbcdSLEY1R3l8n0zQCDPdE4IjZwyY1HMunM= -github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= -github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= +github.com/ccojocar/zxcvbn-go v1.0.4 h1:FWnCIRMXPj43ukfX000kvBZvV6raSxakYr1nzyNrUcc= +github.com/ccojocar/zxcvbn-go v1.0.4/go.mod h1:3GxGX+rHmueTUMvm5ium7irpyjmm7ikxYFOSJB21Das= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= @@ -78,15 +92,13 @@ github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0G github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= -github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= -github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= github.com/ckaznocha/intrange v0.3.1 h1:j1onQyXvHUsPWujDH6WIjhyH26gkRt/txNlV7LspvJs= github.com/ckaznocha/intrange v0.3.1/go.mod h1:QVepyz1AkUoFQkpEqksSYpNpUo3c5W7nWh/s6SHIJJk= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/curioswitch/go-reassign v0.3.0 h1:dh3kpQHuADL3cobV/sSGETA8DOv457dwl+fbBAhrQPs= github.com/curioswitch/go-reassign v0.3.0/go.mod h1:nApPCCTtqLJN/s8HfItCcKV0jIPwluBOvZP+dsJGA88= -github.com/daixiang0/gci v0.13.6 h1:RKuEOSkGpSadkGbvZ6hJ4ddItT3cVZ9Vn9Rybk6xjl8= -github.com/daixiang0/gci v0.13.6/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= +github.com/daixiang0/gci v0.13.7 h1:+0bG5eK9vlI08J+J/NWGbWPTNiXPG4WhNLJOkSxWITQ= +github.com/daixiang0/gci v0.13.7/go.mod h1:812WVN6JLFY9S6Tv76twqmNqevN0pa3SX3nih0brVzQ= github.com/dave/dst v0.27.3 h1:P1HPoMza3cMEquVf9kKy8yXsFirry4zEnWOdYPOoIzY= github.com/dave/dst v0.27.3/go.mod h1:jHh6EOibnHgcUW3WjKHisiooEkYwqpHLBSX1iOBhEyc= github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo= @@ -97,28 +109,28 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8= github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= -github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= -github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= +github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q= github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= -github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA= -github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw= +github.com/firefart/nonamedreturns v1.0.6 h1:vmiBcKV/3EqKY3ZiPxCINmpS431OcE1S47AQUwhrg8E= +github.com/firefart/nonamedreturns v1.0.6/go.mod h1:R8NisJnSIpvPWheCq0mNRXJok6D8h7fagJTF8EMEwCo= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/ghostiam/protogetter v0.3.12 h1:xTPjH97iKph27vXRRKV0OCke5sAMoHPbVeVstdzmCLE= -github.com/ghostiam/protogetter v0.3.12/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= +github.com/ghostiam/protogetter v0.3.16 h1:UkrisuJBYLnZW6FcYUNBDJOqY3X22RtoYMlCsiNlFFA= +github.com/ghostiam/protogetter v0.3.16/go.mod h1:4SRRIv6PcjkIMpUkRUsP4TsUTqO/N3Fmvwivuc/sCHA= github.com/go-critic/go-critic v0.13.0 h1:kJzM7wzltQasSUXtYyTl6UaPVySO6GkaR1thFnJ6afY= github.com/go-critic/go-critic v0.13.0/go.mod h1:M/YeuJ3vOCQDnP2SU+ZhjgRzwzcBW87JqLpMJLrZDLI= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= @@ -148,47 +160,50 @@ github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUW github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/godoc-lint/godoc-lint v0.10.0 h1:OcyrziBi18sQSEpib6NesVHEJ/Xcng97NunePBA48g4= +github.com/godoc-lint/godoc-lint v0.10.0/go.mod h1:KleLcHu/CGSvkjUH2RvZyoK1MBC7pDQg4NxMYLcBBsw= github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/golangci/asciicheck v0.5.0 h1:jczN/BorERZwK8oiFBOGvlGPknhvq0bjnysTj4nUfo0= +github.com/golangci/asciicheck v0.5.0/go.mod h1:5RMNAInbNFw2krqN6ibBxN/zfRFa9S6tA1nPdM0l8qQ= github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 h1:WUvBfQL6EW/40l6OmeSBYQJNSif4O11+bmWEz+C7FYw= github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32/go.mod h1:NUw9Zr2Sy7+HxzdjIULge71wI6yEg1lWQr7Evcu8K0E= -github.com/golangci/go-printf-func-name v0.1.0 h1:dVokQP+NMTO7jwO4bwsRwLWeudOVUPPyAKJuzv8pEJU= -github.com/golangci/go-printf-func-name v0.1.0/go.mod h1:wqhWFH5mUdJQhweRnldEywnR5021wTdZSNgwYceV14s= +github.com/golangci/go-printf-func-name v0.1.1 h1:hIYTFJqAGp1iwoIfsNTpoq1xZAarogrvjO9AfiW3B4U= +github.com/golangci/go-printf-func-name v0.1.1/go.mod h1:Es64MpWEZbh0UBtTAICOZiB+miW53w/K9Or/4QogJss= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0aiOTsLKO2aZQAPT4nlQCsimGcSGE= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY= -github.com/golangci/golangci-lint/v2 v2.0.2 h1:dMCC8ikPiLDvHMFy3+XypSAuGDBOLzwWqqamer+bWsY= -github.com/golangci/golangci-lint/v2 v2.0.2/go.mod h1:ptNNMeGBQrbves0Qq38xvfdJg18PzxmT+7KRCOpm6i8= +github.com/golangci/golangci-lint/v2 v2.5.0 h1:BDRg4ASm4J1y/DSRY6zwJ5tr5Yy8ZqbZ79XrCeFxaQo= +github.com/golangci/golangci-lint/v2 v2.5.0/go.mod h1:IJtWJBZkLbx7AVrIUzLd8Oi3ADtwaNpWbR3wthVWHcc= github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 h1:AkK+w9FZBXlU/xUmBtSJN1+tAI4FIvy5WtnUnY8e4p8= github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95/go.mod h1:k9mmcyWKSTMcPPvQUCfRWWQ9VHJ1U9Dc0R7kaXAgtnQ= -github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= -github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= -github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= -github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= +github.com/golangci/misspell v0.7.0 h1:4GOHr/T1lTW0hhR4tgaaV1WS/lJ+ncvYCoFKmqJsj0c= +github.com/golangci/misspell v0.7.0/go.mod h1:WZyyI2P3hxPY2UVHs3cS8YcllAeyfquQcKfdeE9AFVg= +github.com/golangci/nilerr v0.0.0-20250918000102-015671e622fe h1:F1pK9tBy41i7eesBFkSNMldwtiAaWiU+3fT/24sTnNI= +github.com/golangci/nilerr v0.0.0-20250918000102-015671e622fe/go.mod h1:CtTxAluxD2ng9aIT9bPrVoMuISFWCD+SaxtvYtdWA2k= +github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3HIYbzSuP53UAYgOpg= +github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw= github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s= github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= -github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNFP0hTEi1YKjB/ub8zkpaOqFFMApi2EAs= -github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e h1:ai0EfmVYE2bRA5htgAG9r7s3tHsfjIhN98WshBTJ9jM= +github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e/go.mod h1:Vrn4B5oR9qRwM+f54koyeH3yzphlecwERs0el27Fr/s= +github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e h1:gD6P7NEo7Eqtt0ssnqSJNNndxe69DOQ24A5h7+i3KpM= +github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e/go.mod h1:h+wZwLjUTJnm/P2rwlbJdRPZXOzaT36/FwnPnY2inzc= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= -github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= -github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= -github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a h1://KbezygeMJZCSHH+HgUZiTeSoiuFspbMg1ge+eFj18= +github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA= +github.com/gordonklaus/ineffassign v0.2.0 h1:Uths4KnmwxNJNzq87fwQQDDnbNb7De00VOk9Nu0TySs= +github.com/gordonklaus/ineffassign v0.2.0/go.mod h1:TIpymnagPSexySzs7F9FnO1XFTy8IT3a59vmZp5Y9Lw= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= -github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= github.com/gostaticanalysis/comment v1.5.0 h1:X82FLl+TswsUMpMh17srGRuKaaXprTaytmEpgnKIDu8= github.com/gostaticanalysis/comment v1.5.0/go.mod h1:V6eb3gpCv9GNVqb6amXzEUX3jXLVK/AdA+IrAMSqvEc= github.com/gostaticanalysis/forcetypeassert v0.2.0 h1:uSnWrrUEYDr86OCxWa4/Tp2jeYDlogZiZHzGkWFefTk= github.com/gostaticanalysis/forcetypeassert v0.2.0/go.mod h1:M5iPavzE9pPqWyeiVXSFghQjljW1+l/Uke3PXHS6ILY= -github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= -github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8= github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs= @@ -205,12 +220,12 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= -github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jgautheron/goconst v1.8.2 h1:y0XF7X8CikZ93fSNT6WBTb/NElBu9IjaY7CCYQrCMX4= +github.com/jgautheron/goconst v1.8.2/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= -github.com/jjti/go-spancheck v0.6.4 h1:Tl7gQpYf4/TMU7AT84MN83/6PutY21Nb9fuQjFTpRRc= -github.com/jjti/go-spancheck v0.6.4/go.mod h1:yAEYdKJ2lRkDA8g7X+oKUHXOWVAXSBJRv04OhF+QUjk= +github.com/jjti/go-spancheck v0.6.5 h1:lmi7pKxa37oKYIMScialXUK6hP3iY5F1gu+mLBPgYB8= +github.com/jjti/go-spancheck v0.6.5/go.mod h1:aEogkeatBrbYsyW6y5TgDfihCulDYciL1B7rG2vSsrU= github.com/julz/importas v0.2.0 h1:y+MJN/UdL63QbFJHws9BVC5RpA2iq0kpjrFajTGivjQ= github.com/julz/importas v0.2.0/go.mod h1:pThlt589EnCYtMnmhmRYY/qn9lCf/frPOK+WMx3xiJY= github.com/karamaru-alpha/copyloopvar v1.2.1 h1:wmZaZYIjnJ0b5UoKDjUHrikcV0zuPyyxI4SVplLd2CI= @@ -226,28 +241,32 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= -github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs= -github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= +github.com/kulti/thelper v0.7.1 h1:fI8QITAoFVLx+y+vSyuLBP+rcVIB8jKooNSCT2EiI98= +github.com/kulti/thelper v0.7.1/go.mod h1:NsMjfQEy6sd+9Kfw8kCP61W1I0nerGSYSFnGaxQkcbs= +github.com/kunwardeep/paralleltest v1.0.14 h1:wAkMoMeGX/kGfhQBPODT/BL8XhK23ol/nuQ3SwFaUw8= +github.com/kunwardeep/paralleltest v1.0.14/go.mod h1:di4moFqtfz3ToSKxhNjhOZL+696QtJGCFe132CbBLGk= github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= -github.com/ldez/exptostd v0.4.2 h1:l5pOzHBz8mFOlbcifTxzfyYbgEmoUqjxLFHZkjlbHXs= -github.com/ldez/exptostd v0.4.2/go.mod h1:iZBRYaUmcW5jwCR3KROEZ1KivQQp6PHXbDPk9hqJKCQ= -github.com/ldez/gomoddirectives v0.6.1 h1:Z+PxGAY+217f/bSGjNZr/b2KTXcyYLgiWI6geMBN2Qc= -github.com/ldez/gomoddirectives v0.6.1/go.mod h1:cVBiu3AHR9V31em9u2kwfMKD43ayN5/XDgr+cdaFaKs= -github.com/ldez/grignotin v0.9.0 h1:MgOEmjZIVNn6p5wPaGp/0OKWyvq42KnzAt/DAb8O4Ow= -github.com/ldez/grignotin v0.9.0/go.mod h1:uaVTr0SoZ1KBii33c47O1M8Jp3OP3YDwhZCmzT9GHEk= -github.com/ldez/tagliatelle v0.7.1 h1:bTgKjjc2sQcsgPiT902+aadvMjCeMHrY7ly2XKFORIk= -github.com/ldez/tagliatelle v0.7.1/go.mod h1:3zjxUpsNB2aEZScWiZTHrAXOl1x25t3cRmzfK1mlo2I= -github.com/ldez/usetesting v0.4.2 h1:J2WwbrFGk3wx4cZwSMiCQQ00kjGR0+tuuyW0Lqm4lwA= -github.com/ldez/usetesting v0.4.2/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= +github.com/ldez/exptostd v0.4.4 h1:58AtQjnLcT/tI5W/1KU7xE/O7zW9RAWB6c/ScQAnfus= +github.com/ldez/exptostd v0.4.4/go.mod h1:QfdzPw6oHjFVdNV7ILoPu5sw3OZ3OG1JS0I5JN3J4Js= +github.com/ldez/gomoddirectives v0.7.0 h1:EOx8Dd56BZYSez11LVgdj025lKwlP0/E5OLSl9HDwsY= +github.com/ldez/gomoddirectives v0.7.0/go.mod h1:wR4v8MN9J8kcwvrkzrx6sC9xe9Cp68gWYCsda5xvyGc= +github.com/ldez/grignotin v0.10.1 h1:keYi9rYsgbvqAZGI1liek5c+jv9UUjbvdj3Tbn5fn4o= +github.com/ldez/grignotin v0.10.1/go.mod h1:UlDbXFCARrXbWGNGP3S5vsysNXAPhnSuBufpTEbwOas= +github.com/ldez/tagliatelle v0.7.2 h1:KuOlL70/fu9paxuxbeqlicJnCspCRjH0x8FW+NfgYUk= +github.com/ldez/tagliatelle v0.7.2/go.mod h1:PtGgm163ZplJfZMZ2sf5nhUT170rSuPgBimoyYtdaSI= +github.com/ldez/usetesting v0.5.0 h1:3/QtzZObBKLy1F4F8jLuKJiKBjjVFi1IavpoWbmqLwc= +github.com/ldez/usetesting v0.5.0/go.mod h1:Spnb4Qppf8JTuRgblLrEWb7IE6rDmUpGvxY3iRrzvDQ= github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddBCpE= github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= +github.com/manuelarte/embeddedstructfieldcheck v0.4.0 h1:3mAIyaGRtjK6EO9E73JlXLtiy7ha80b2ZVGyacxgfww= +github.com/manuelarte/embeddedstructfieldcheck v0.4.0/go.mod h1:z8dFSyXqp+fC6NLDSljRJeNQJJDWnY7RoWFzV3PC6UM= +github.com/manuelarte/funcorder v0.5.0 h1:llMuHXXbg7tD0i/LNw8vGnkDTHFpTnWqKPI85Rknc+8= +github.com/manuelarte/funcorder v0.5.0/go.mod h1:Yt3CiUQthSBMBxjShjdXMexmzpP8YGvGLjrxJNkO2hA= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= @@ -261,11 +280,10 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mgechev/revive v1.7.0 h1:JyeQ4yO5K8aZhIKf5rec56u0376h8AlKNQEmjfkjKlY= -github.com/mgechev/revive v1.7.0/go.mod h1:qZnwcNhoguE58dfi96IJeSTPeZQejNeoMQLUZGi4SW4= +github.com/mgechev/revive v1.12.0 h1:Q+/kkbbwerrVYPv9d9efaPGmAO/NsxwW/nE6ahpQaCU= +github.com/mgechev/revive v1.12.0/go.mod h1:VXsY2LsTigk8XU9BpZauVLjVrhICMOV3k1lpB3CXrp8= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= @@ -280,14 +298,12 @@ github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhK github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.19.1 h1:mjwbOlDQxZi9Cal+KfbEJTCz327OLNfwNvoZ70NJ+c4= -github.com/nunnatsa/ginkgolinter v0.19.1/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= -github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= -github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= -github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/nunnatsa/ginkgolinter v0.21.0 h1:IYwuX+ajy3G1MezlMLB1BENRtFj16+Evyi4uki1NOOQ= +github.com/nunnatsa/ginkgolinter v0.21.0/go.mod h1:QlzY9UP9zaqu58FjYxhp9bnjuwXwG1bfW5rid9ChNMw= +github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus= +github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= +github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY= +github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= @@ -295,13 +311,13 @@ github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJ github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= -github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= -github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polyfloyd/go-errorlint v1.7.1 h1:RyLVXIbosq1gBdk/pChWA8zWYLsq9UEw7a1L5TVMCnA= -github.com/polyfloyd/go-errorlint v1.7.1/go.mod h1:aXjNb1x2TNhoLsk26iv1yl7a+zTnXPhwEMtEXukiLR8= +github.com/polyfloyd/go-errorlint v1.8.0 h1:DL4RestQqRLr8U4LygLw8g2DX6RN1eBJOpa2mzsrl1Q= +github.com/polyfloyd/go-errorlint v1.8.0/go.mod h1:G2W0Q5roxbLCt0ZQbdoxQxXktTjwNyDbEaj3n7jvl4s= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= @@ -338,14 +354,14 @@ github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsF github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ= -github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= -github.com/securego/gosec/v2 v2.22.2 h1:IXbuI7cJninj0nRpZSLCUlotsj8jGusohfONMrHoF6g= -github.com/securego/gosec/v2 v2.22.2/go.mod h1:UEBGA+dSKb+VqM6TdehR7lnQtIIMorYJ4/9CW1KVQBE= +github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ= +github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8= +github.com/securego/gosec/v2 v2.22.8 h1:3NMpmfXO8wAVFZPNsd3EscOTa32Jyo6FLLlW53bexMI= +github.com/securego/gosec/v2 v2.22.8/go.mod h1:ZAw8K2ikuH9qDlfdV87JmNghnVfKB1XC7+TVzk6Utto= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -354,21 +370,22 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= -github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= -github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= +github.com/sonatard/noctx v0.4.0 h1:7MC/5Gg4SQ4lhLYR6mvOP6mQVSxCrdyiExo7atBs27o= +github.com/sonatard/noctx v0.4.0/go.mod h1:64XdbzFb18XL4LporKXp8poqZtPKbCrqQ402CV+kJas= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= -github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= -github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= +github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= -github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= +github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= @@ -376,35 +393,27 @@ github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRk github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/tdakkota/asciicheck v0.4.1 h1:bm0tbcmi0jezRA2b5kg4ozmMuGAFotKI3RZfrhfovg8= -github.com/tdakkota/asciicheck v0.4.1/go.mod h1:0k7M3rCfRXb0Z6bwgvkEIMleKH3kXNz9UqJ9Xuqopr8= github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -github.com/tetafro/godot v1.5.0 h1:aNwfVI4I3+gdxjMgYPus9eHmoBeJIbnajOyqZYStzuw= -github.com/tetafro/godot v1.5.0/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= +github.com/tetafro/godot v1.5.4 h1:u1ww+gqpRLiIA16yF2PV1CV1n/X3zhyezbNXC3E14Sg= +github.com/tetafro/godot v1.5.4/go.mod h1:eOkMrVQurDui411nBY2FA05EYH01r14LuWY/NrVDVcU= github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 h1:9LPGD+jzxMlnk5r6+hJnar67cgpDIz/iyD+rfl5r2Vk= github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460= -github.com/timonwong/loggercheck v0.10.1 h1:uVZYClxQFpw55eh+PIoqM7uAOHMrhVcDoWDery9R8Lg= -github.com/timonwong/loggercheck v0.10.1/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= -github.com/tomarrell/wrapcheck/v2 v2.10.0 h1:SzRCryzy4IrAH7bVGG4cK40tNUhmVmMDuJujy4XwYDg= -github.com/tomarrell/wrapcheck/v2 v2.10.0/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo= +github.com/timonwong/loggercheck v0.11.0 h1:jdaMpYBl+Uq9mWPXv1r8jc5fC3gyXx4/WGwTnnNKn4M= +github.com/timonwong/loggercheck v0.11.0/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= +github.com/tomarrell/wrapcheck/v2 v2.11.0 h1:BJSt36snX9+4WTIXeJ7nvHBQBcm1h2SjQMSlmQ6aFSU= +github.com/tomarrell/wrapcheck/v2 v2.11.0/go.mod h1:wFL9pDWDAbXhhPZZt+nG8Fu+h29TtnZ2MW6Lx4BRXIU= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ultraware/funlen v0.2.0 h1:gCHmCn+d2/1SemTdYMiKLAHFYxTYz7z9VIDRaTGyLkI= @@ -413,8 +422,8 @@ github.com/ultraware/whitespace v0.2.0 h1:TYowo2m9Nfj1baEQBjuHzvMRbp19i+RCcRYrSW github.com/ultraware/whitespace v0.2.0/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= github.com/uudashr/gocognit v1.2.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA= github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU= -github.com/uudashr/iface v1.3.1 h1:bA51vmVx1UIhiIsQFSNq6GZ6VPTk3WNMZgRiCe9R29U= -github.com/uudashr/iface v1.3.1/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg= +github.com/uudashr/iface v1.4.1 h1:J16Xl1wyNX9ofhpHmQ9h9gk5rnv2A6lX/2+APLTo0zU= +github.com/uudashr/iface v1.4.1/go.mod h1:pbeBPlbuU2qkNDn0mmfrxP2X+wjPMIQAy+r1MBXSXtg= github.com/xen0n/gosmopolitan v1.3.0 h1:zAZI1zefvo7gcpbCOrPSHJZJYA9ZgLfJqtKzZ5pHqQM= github.com/xen0n/gosmopolitan v1.3.0/go.mod h1:rckfr5T6o4lBtM1ga7mLGKZmLxswUoH1zxHgNXOsEt4= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= @@ -435,10 +444,14 @@ gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= -go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= -go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= -go-simpler.org/sloglint v0.9.0 h1:/40NQtjRx9txvsB/RN022KsUJU+zaaSb/9q9BSefSrE= -go-simpler.org/sloglint v0.9.0/go.mod h1:G/OrAF6uxj48sHahCzrbarVMptL2kjWTaUeC8+fOGww= +go-simpler.org/musttag v0.14.0 h1:XGySZATqQYSEV3/YTy+iX+aofbZZllJaqwFWs+RTtSo= +go-simpler.org/musttag v0.14.0/go.mod h1:uP8EymctQjJ4Z1kUnjX0u2l60WfUdQxCwSNKzE1JEOE= +go-simpler.org/sloglint v0.11.1 h1:xRbPepLT/MHPTCA6TS/wNfZrDzkGvCCqUv4Bdwc3H7s= +go-simpler.org/sloglint v0.11.1/go.mod h1:2PowwiCOK8mjiF+0KGifVOT8ZsCNiFzvfyJeJOIt8MQ= +go.augendre.info/arangolint v0.2.0 h1:2NP/XudpPmfBhQKX4rMk+zDYIj//qbt4hfZmSSTcpj8= +go.augendre.info/arangolint v0.2.0/go.mod h1:Vx4KSJwu48tkE+8uxuf0cbBnAPgnt8O1KWiT7bljq7w= +go.augendre.info/fatcontext v0.8.1 h1:/T4+cCjpL9g71gJpcFAgVo/K5VFpqlN+NPU7QXxD5+A= +go.augendre.info/fatcontext v0.8.1/go.mod h1:r3Qz4ZOzex66wfyyj5VZ1xUcl81vzvHQ6/GWzzlMEwA= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -457,21 +470,19 @@ golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac h1:TSSpLIG4v+p0rPv1pNOQtl1I8knsO4S9trOxNMOLVP4= -golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20250911091902-df9299821621 h1:Yl4H5w2RV7L/dvSHp2GerziT5K2CORgFINPaMFxWGWw= +golang.org/x/exp/typeparams v0.0.0-20250911091902-df9299821621/go.mod h1:4Mzdyp/6jzw9auFDJ3OMF5qksa7UvPnzKqTVGcb04ms= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= -golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= +golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -481,14 +492,12 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -498,8 +507,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -515,19 +524,16 @@ golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= @@ -536,33 +542,29 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= -golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= +golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= +golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= +golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -574,14 +576,13 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.2.2/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-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI= honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= -mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= -mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo= +mvdan.cc/gofumpt v0.9.1 h1:p5YT2NfFWsYyTieYgwcQ8aKV3xRvFH4uuN/zB2gBbMQ= +mvdan.cc/gofumpt v0.9.1/go.mod h1:3xYtNemnKiXaTh6R4VtlqDATFwBbdXI8lJvH/4qk7mw= mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 h1:WjUu4yQoT5BHT1w8Zu56SP8367OuBV5jvo+4Ulppyf8= mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4/go.mod h1:rthT7OuvRbaGcd5ginj6dA2oLE7YNlta9qhBNNdCaLE= diff --git a/.citools/src/jb/go.mod b/.citools/src/jb/go.mod index 05208bc103e..96fe587d14f 100644 --- a/.citools/src/jb/go.mod +++ b/.citools/src/jb/go.mod @@ -1,6 +1,6 @@ module jb -go 1.24.5 +go 1.25.3 tool github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb @@ -15,6 +15,6 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/stretchr/testify v1.10.0 // indirect - golang.org/x/sys v0.33.0 // indirect + golang.org/x/sys v0.36.0 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect ) diff --git a/.citools/src/jb/go.sum b/.citools/src/jb/go.sum index 90354357864..82c114a77ad 100644 --- a/.citools/src/jb/go.sum +++ b/.citools/src/jb/go.sum @@ -54,8 +54,8 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/.citools/src/lefthook/go.mod b/.citools/src/lefthook/go.mod index e45942a7dc1..e37e46a5ea6 100644 --- a/.citools/src/lefthook/go.mod +++ b/.citools/src/lefthook/go.mod @@ -1,6 +1,6 @@ module lefthook -go 1.24.5 +go 1.25.3 tool github.com/evilmartians/lefthook @@ -43,10 +43,9 @@ require ( github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect - golang.org/x/sys v0.33.0 // indirect - golang.org/x/term v0.32.0 // indirect - golang.org/x/text v0.25.0 // indirect - golang.org/x/tools v0.33.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/term v0.35.0 // indirect + golang.org/x/text v0.29.0 // indirect gopkg.in/alessio/shellescape.v1 v1.0.0-20170105083845-52074bc9df61 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/.citools/src/lefthook/go.sum b/.citools/src/lefthook/go.sum index b6b9533af75..c0e796f4ae9 100644 --- a/.citools/src/lefthook/go.sum +++ b/.citools/src/lefthook/go.sum @@ -91,14 +91,14 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= -golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= -golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= -golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= gopkg.in/alessio/shellescape.v1 v1.0.0-20170105083845-52074bc9df61 h1:8ajkpB4hXVftY5ko905id+dOnmorcS2CHNxxHLLDcFM= gopkg.in/alessio/shellescape.v1 v1.0.0-20170105083845-52074bc9df61/go.mod h1:IfMagxm39Ys4ybJrDb7W3Ob8RwxftP0Yy+or/NVz1O8= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/.citools/src/swagger/go.mod b/.citools/src/swagger/go.mod index 4d169e867f2..d0ed2ce2bcf 100644 --- a/.citools/src/swagger/go.mod +++ b/.citools/src/swagger/go.mod @@ -1,6 +1,6 @@ module swagger -go 1.24.5 +go 1.25.3 tool github.com/go-swagger/go-swagger/cmd/swagger @@ -51,12 +51,12 @@ require ( github.com/toqueteos/webbrowser v1.2.0 // indirect go.mongodb.org/mongo-driver v1.16.1 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.38.0 // indirect - golang.org/x/mod v0.24.0 // indirect - golang.org/x/sync v0.14.0 // indirect - golang.org/x/sys v0.33.0 // indirect - golang.org/x/text v0.25.0 // indirect - golang.org/x/tools v0.33.0 // indirect + golang.org/x/crypto v0.42.0 // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/text v0.29.0 // indirect + golang.org/x/tools v0.36.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/.citools/src/swagger/go.sum b/.citools/src/swagger/go.sum index f5342e8f329..dff45a5ee81 100644 --- a/.citools/src/swagger/go.sum +++ b/.citools/src/swagger/go.sum @@ -101,19 +101,19 @@ go.mongodb.org/mongo-driver v1.16.1 h1:rIVLL3q0IHM39dvE+z2ulZLp9ENZKThVfuvN/IiN4 go.mongodb.org/mongo-driver v1.16.1/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= -golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= -golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= -golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= -golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= -golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bbdbb9040df..781a205fa14 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -41,18 +41,20 @@ /docs/sources/ @irenerl24 /docs/sources/alerting/ @JohnnyK-Grafana -/docs/sources/dashboards/ @imatwawana /docs/sources/datasources/ @lwandz13 -/docs/sources/panels-visualizations/ @imatwawana /docs/sources/upgrade-guide/ @jtvdez /docs/sources/whatsnew/ @jtvdez -/docs/sources/developers/plugins/ @grafana/plugins-platform-frontend @grafana/plugins-platform-backend -/docs/sources/dashboards/share-dashboards-panels/_index.md @imatwawana @jtvdez -/docs/sources/dashboards/share-dashboards-panels/shared-dashboards/index.md @jtvdez -/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md @imatwawana @baldm0mma -/docs/sources/panels-visualizations/query-transform-data/sql-expressions/index.md @lwandz13 @irenerl24 +/docs/sources/developers/plugins/ @grafana/plugins-platform-frontend @grafana/plugins-platform-backend +/docs/sources/visualizations/dashboards/ @imatwawana +/docs/sources/visualizations/panels-visualizations/ @imatwawana + + +/docs/sources/visualizations/dashboards/share-dashboards-panels/_index.md @imatwawana @jtvdez +/docs/sources/visualizations/dashboards/share-dashboards-panels/shared-dashboards/index.md @jtvdez +/docs/sources/visualizations/panels-visualizations/query-transform-data/transform-data/index.md @imatwawana @baldm0mma +/docs/sources/visualizations/panels-visualizations/query-transform-data/sql-expressions/index.md @lwandz13 @irenerl24 # END Technical documentation # Backend code @@ -94,6 +96,7 @@ /apps/iam/ @grafana/access-squad /apps/sdk.mk @grafana/grafana-app-platform-squad /apps/correlations @grafana/datapro +/apps/logsdrilldown/ @grafana/observability-logs /pkg/api/ @grafana/grafana-backend-group /pkg/apis/ @grafana/grafana-app-platform-squad /pkg/apis/query @grafana/grafana-datasources-core-services @@ -302,7 +305,7 @@ /devenv/docker/blocks/prometheus_random_data/ @grafana/oss-big-tent /devenv/docker/blocks/prometheus_high_card/ @grafana/oss-big-tent /devenv/docker/blocks/prometheus_utf8/ @grafana/oss-big-tent -/devenv/docker/blocks/pyroscope/ @grafana/observability-traces-and-profiling +/devenv/docker/blocks/pyroscope/ @grafana/oss-big-tent /devenv/docker/blocks/redis/ @bergquist /devenv/docker/blocks/sensugo/ @grafana/grafana-backend-group /devenv/docker/blocks/slow_proxy/ @bergquist @@ -352,8 +355,8 @@ /pkg/tsdb/prometheus/ @grafana/oss-big-tent /pkg/tsdb/elasticsearch/ @grafana/partner-datasources /pkg/tsdb/loki/ @grafana/oss-big-tent -/pkg/tsdb/tempo/ @grafana/oss-big-tent @grafana/observability-traces-and-profiling -/pkg/tsdb/grafana-pyroscope-datasource/ @grafana/observability-traces-and-profiling +/pkg/tsdb/tempo/ @grafana/oss-big-tent +/pkg/tsdb/grafana-pyroscope-datasource/ @grafana/oss-big-tent /pkg/tsdb/parca/ @grafana/oss-big-tent # OSS Big Tent backend code @@ -429,6 +432,7 @@ /e2e-playwright/dashboards/TestDashboard.json @grafana/dashboards-squad @grafana/grafana-search-navigate-organise /e2e-playwright/dashboards/TestV2Dashboard.json @grafana/dashboards-squad /e2e-playwright/dashboards/V2DashWithRepeats.json @grafana/dashboards-squad +/e2e-playwright/dashboards/V2DashWithTabRepeats.json @grafana/dashboards-squad /e2e-playwright/dashboards-suite/adhoc-filter-from-panel.spec.ts @grafana/datapro /e2e-playwright/dashboards-suite/dashboard-browse-nested.spec.ts @grafana/grafana-search-navigate-organise /e2e-playwright/dashboards-suite/dashboard-browse.spec.ts @grafana/grafana-search-navigate-organise @@ -609,7 +613,7 @@ /packages/grafana-o11y-ds-frontend/ @grafana/observability-logs /packages/grafana-o11y-ds-frontend/src/IntervalInput/ @grafana/observability-traces-and-profiling /packages/grafana-o11y-ds-frontend/src/NodeGraph/ @grafana/observability-traces-and-profiling -/packages/grafana-o11y-ds-frontend/src/pyroscope/ @grafana/observability-traces-and-profiling +/packages/grafana-o11y-ds-frontend/src/pyroscope/ @grafana/oss-big-tent @grafana/observability-traces-and-profiling /packages/grafana-o11y-ds-frontend/src/SpanBar/ @grafana/oss-big-tent @grafana/observability-traces-and-profiling /packages/grafana-o11y-ds-frontend/src/TraceToLogs/ @grafana/oss-big-tent @grafana/observability-traces-and-profiling /packages/grafana-o11y-ds-frontend/src/TraceToMetrics/ @grafana/oss-big-tent @grafana/observability-traces-and-profiling @@ -685,10 +689,9 @@ /packages/grafana-schema/src/**/gauge @grafana/dataviz-squad /packages/grafana-schema/src/**/geomap @grafana/dataviz-squad /packages/grafana-schema/src/**/googlecloudmonitoring @grafana/partner-datasources -/packages/grafana-schema/src/**/grafanapyroscope @grafana/observability-traces-and-profiling +/packages/grafana-schema/src/**/grafanapyroscope @grafana/oss-big-tent /packages/grafana-schema/src/**/heatmap @grafana/dataviz-squad /packages/grafana-schema/src/**/histogram @grafana/dataviz-squad -/packages/grafana-schema/src/**/librarypanel @grafana/sharing-squad /packages/grafana-schema/src/**/logs @grafana/observability-logs /packages/grafana-schema/src/**/logsnew @grafana/observability-logs /packages/grafana-schema/src/**/loki @grafana/oss-big-tent @grafana/observability-logs @@ -949,6 +952,7 @@ playwright.storybook.config.ts @grafana/grafana-frontend-platform /public/app/features/serviceaccounts/ @grafana/identity-squad /public/app/features/teams/ @grafana/access-squad /public/app/features/templating/ @grafana/dashboards-squad +/public/app/features/theme-playground/ @grafana/grafana-frontend-platform /public/app/features/trails/ @grafana/observability-metrics /public/app/features/transformers/ @grafana/datapro /public/app/features/transformers/timeSeriesTable/ @grafana/dataviz-squad @grafana/app-o11y-visualizations @@ -1058,6 +1062,10 @@ playwright.storybook.config.ts @grafana/grafana-frontend-platform /scripts/codemods/explicit-barrel-imports.cjs @grafana/frontend-ops /scripts/rtk-client-generator/ @grafana/grafana-search-navigate-organise +/scripts/codeowners-manifest/ @grafana/dataviz-squad +/scripts/test-coverage-by-codeowner.js @grafana/dataviz-squad +/jest.config.codeowner.js @grafana/dataviz-squad + /scripts/**/generate-transformations* @grafana/datapro /scripts/webpack/ @grafana/frontend-ops /scripts/generate-a11y-report.sh @grafana/grafana-frontend-platform @@ -1085,8 +1093,8 @@ eslint-suppressions.json @grafanabot /public/app/plugins/datasource/prometheus/ @grafana/oss-big-tent /public/app/plugins/datasource/cloud-monitoring/ @grafana/partner-datasources /public/app/plugins/datasource/zipkin/ @grafana/oss-big-tent -/public/app/plugins/datasource/tempo/ @grafana/oss-big-tent @grafana/observability-traces-and-profiling -/public/app/plugins/datasource/grafana-pyroscope-datasource/ @grafana/observability-traces-and-profiling +/public/app/plugins/datasource/tempo/ @grafana/oss-big-tent +/public/app/plugins/datasource/grafana-pyroscope-datasource/ @grafana/oss-big-tent /public/app/plugins/datasource/parca/ @grafana/oss-big-tent /public/app/plugins/datasource/alertmanager/ @grafana/alerting-squad diff --git a/.github/commands.json b/.github/commands.json index 7b9c64b18e6..29106576726 100644 --- a/.github/commands.json +++ b/.github/commands.json @@ -144,7 +144,7 @@ "name": "datasource/grafana-pyroscope", "action": "addToProject", "addToProject": { - "url": "https://github.com/orgs/grafana/projects/221" + "url": "https://github.com/orgs/grafana/projects/457" } }, { diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1c62ef810eb..79987600b9a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,32 +1,65 @@ version: 2 updates: - package-ecosystem: "github-actions" + commit-message: + prefix: deps(actions) directory: "/" schedule: interval: "daily" - package-ecosystem: "gomod" + commit-message: + prefix: deps(go) directories: - "/" - - "/apps/playlist" - - "/apps/secret" + - "/apps/advisor" + - "/apps/alerting/alertenrichment" + - "/apps/alerting/notifications" + - "/apps/alerting/rules" + - "/apps/correlations" + - "/apps/dashboard" + - "/apps/folder" + - "/apps/iam" - "/apps/investigations" + - "/apps/playlist" + - "/apps/plugins" + - "/apps/preferences" + - "/apps/provisioning" + - "/apps/scope" + - "/apps/secret" + - "/apps/shorturl" + - "/hack" - "/pkg/aggregator" - "/pkg/apimachinery" - - "/pkg/apis/folder" - "/pkg/apiserver" - "/pkg/build" - "/pkg/build/wire" + - "/pkg/codegen" + - "/pkg/plugins/codegen" - "/pkg/promlib" - "/pkg/semconv" - - "/pkg/storage/unified/apistore" - - "/pkg/storage/unified/resource" - "/pkg/util/xorm" + - "/scripts/go-workspace" + - "/scripts/modowners" schedule: interval: "daily" time: "02:00" timezone: Etc/UTC - open-pull-requests-limit: 10 + open-pull-requests-limit: 20 + # group some updates together for easier review + groups: + go.opentelemetry.io: + patterns: + - "go.opentelemetry.io/*" + k8s.io: + patterns: + - "k8s.io/*" + aws-sdk-go: + patterns: + - "github.com/aws/aws-sdk-go*" + - "github.com/aws/smithy-go" - package-ecosystem: "docker" + commit-message: + prefix: deps(docker) directories: - "/" - "/packaging/docker/custom" @@ -35,4 +68,4 @@ updates: interval: "daily" time: "02:00" timezone: Etc/UTC - open-pull-requests-limit: 10 + open-pull-requests-limit: 20 diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 37d44d74483..aa33961bf95 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -1,6 +1,9 @@ { extends: ["config:recommended"], enabledManagers: ["npm"], + ignorePresets: [ + "github>grafana/grafana-renovate-config//presets/labels", + ], ignoreDeps: [ // ignoring these until we can upgrade to react 19 // see epic here: https://github.com/grafana/grafana/issues/98813 diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index 4591e4a1e0a..51e72e10c32 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -54,7 +54,7 @@ jobs: - name: Upload to GitHub security events if: success() || failure() # If there are security problems, GitHub will automatically comment on the PR for us. - uses: github/codeql-action/upload-sarif@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 + uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8 with: sarif_file: results.sarif category: actionlint diff --git a/.github/workflows/alerting-swagger-gen.yml b/.github/workflows/alerting-swagger-gen.yml index b431dbfbc3c..6e88f67acd8 100644 --- a/.github/workflows/alerting-swagger-gen.yml +++ b/.github/workflows/alerting-swagger-gen.yml @@ -15,7 +15,7 @@ jobs: fetch-depth: 2 persist-credentials: false - name: Set go version - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 with: go-version-file: go.mod - name: Build swagger diff --git a/.github/workflows/alerting-update-module.yml b/.github/workflows/alerting-update-module.yml index dc623c8b333..c801783d2ff 100644 --- a/.github/workflows/alerting-update-module.yml +++ b/.github/workflows/alerting-update-module.yml @@ -29,7 +29,7 @@ jobs: fi - name: Setup Go - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # 5.5.0 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # 6.0.0 with: "go-version-file": "go.mod" @@ -148,7 +148,7 @@ jobs: echo "๐Ÿ”— [View Pull Request]($PR_URL)" } >> "$GITHUB_STEP_SUMMARY" - name: Send Slack Message - uses: grafana/shared-workflows/actions/send-slack-message@send-slack-message/v2.0.3 + uses: grafana/shared-workflows/actions/send-slack-message@send-slack-message/v2.0.4 with: method: 'chat.postMessage' # send to alerting-reviews channel diff --git a/.github/workflows/analytics-events-report.yml b/.github/workflows/analytics-events-report.yml index 33d3f95d60e..51bd0e7b1ae 100644 --- a/.github/workflows/analytics-events-report.yml +++ b/.github/workflows/analytics-events-report.yml @@ -17,7 +17,7 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' cache: 'yarn' diff --git a/.github/workflows/backend-code-checks.yml b/.github/workflows/backend-code-checks.yml index 0b4fece91ab..0294a121551 100644 --- a/.github/workflows/backend-code-checks.yml +++ b/.github/workflows/backend-code-checks.yml @@ -46,12 +46,9 @@ jobs: with: persist-credentials: false - name: Setup Go - uses: actions/setup-go@v5.5.0 + uses: actions/setup-go@v6.0.0 with: - # Explicitly set Go version to 1.24.1 to ensure consistent OpenAPI spec generation - # The crypto/x509 package has additional fields in Go 1.24.1 that affect the generated specs - # This ensures the GHAs environment matches what we use in the Drone pipeline - go-version: 1.24.1 + go-version-file: go.mod cache: true - name: Verify code generation diff --git a/.github/workflows/backend-unit-tests.yml b/.github/workflows/backend-unit-tests.yml index 611d3c13931..3dd179c5c87 100644 --- a/.github/workflows/backend-unit-tests.yml +++ b/.github/workflows/backend-unit-tests.yml @@ -59,7 +59,7 @@ jobs: with: persist-credentials: false - name: Setup Go - uses: actions/setup-go@v5.5.0 + uses: actions/setup-go@v6.0.0 with: go-version-file: go.mod - name: Run unit tests @@ -94,7 +94,7 @@ jobs: with: persist-credentials: false - name: Setup Go - uses: actions/setup-go@v5.5.0 + uses: actions/setup-go@v6.0.0 with: go-version-file: go.mod - name: Setup Enterprise diff --git a/.github/workflows/backport-workflow.yml b/.github/workflows/backport-workflow.yml index 245e79cc6f7..f3d6761440c 100644 --- a/.github/workflows/backport-workflow.yml +++ b/.github/workflows/backport-workflow.yml @@ -36,7 +36,7 @@ jobs: private_key: ${{ fromJSON(steps.secrets.outputs.secrets).APP_PEM }} - name: Download PR info artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 id: download-pr-info with: github-token: ${{ github.token }} diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 86e079a43a6..761e43488ed 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -97,7 +97,7 @@ jobs: fetch-depth: 0 fetch-tags: true - name: Setup nodejs environment - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version-file: .nvmrc - name: "Configure git user" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index cfef13f22e0..b06c637112d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -72,14 +72,14 @@ jobs: - if: matrix.language == 'go' && needs.detect-changes.outputs.go == 'true' name: Set go version - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 with: go-version-file: go.mod # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL if: needs.detect-changes.outputs[matrix.language] == 'true' - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -94,4 +94,4 @@ jobs: make build-go - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 diff --git a/.github/workflows/core-plugins-build-and-release.yml b/.github/workflows/core-plugins-build-and-release.yml index 22836db5089..de8835420a3 100644 --- a/.github/workflows/core-plugins-build-and-release.yml +++ b/.github/workflows/core-plugins-build-and-release.yml @@ -58,13 +58,13 @@ jobs: PLUGINS_GRAFANA_API_KEY=core-plugins-build-and-release:PLUGINS_GRAFANA_API_KEY PLUGINS_GCOM_TOKEN=core-plugins-build-and-release:PLUGINS_GCOM_TOKEN - name: 'Authenticate to Google Cloud' - uses: 'google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f' + uses: 'google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093' with: credentials_json: '${{ env.PLUGINS_GOOGLE_CREDENTIALS }}' - name: 'Set up Cloud SDK' uses: 'google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db' - name: Setup nodejs environment - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version-file: .nvmrc cache: yarn @@ -101,7 +101,7 @@ jobs: echo "has_backend=false" >> "$GITHUB_OUTPUT" fi - name: Setup golang environment - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 if: steps.check_backend.outputs.has_backend == 'true' with: go-version-file: go.mod diff --git a/.github/workflows/create-security-patch-from-security-mirror.yml b/.github/workflows/create-security-patch-from-security-mirror.yml index 7499d925236..54dfcc668e8 100644 --- a/.github/workflows/create-security-patch-from-security-mirror.yml +++ b/.github/workflows/create-security-patch-from-security-mirror.yml @@ -25,4 +25,5 @@ jobs: patch_ref: "${{ github.base_ref }}" # this is the target branch name, Ex: "main" patch_repo: "grafana/grafana-security-patches" patch_prefix: "${{ github.event.pull_request.number }}" + sender: "${{ github.event.pull_request.user.login }}" secrets: inherit # zizmor: ignore[secrets-inherit] diff --git a/.github/workflows/detect-breaking-changes-levitate.yml b/.github/workflows/detect-breaking-changes-levitate.yml index 82351d45785..2e9b370d4e0 100644 --- a/.github/workflows/detect-breaking-changes-levitate.yml +++ b/.github/workflows/detect-breaking-changes-levitate.yml @@ -34,7 +34,7 @@ jobs: path: './pr' persist-credentials: false - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version-file: './pr/.nvmrc' @@ -86,7 +86,7 @@ jobs: ref: ${{ github.event.pull_request.base.ref }} persist-credentials: false - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version-file: './base/.nvmrc' @@ -136,17 +136,17 @@ jobs: with: persist-credentials: false - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' - name: Get built packages from pr - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: buildPr - name: Get built packages from base - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: buildBase @@ -157,7 +157,7 @@ jobs: run: unzip -j base_built_packages.zip -d ./base && rm base_built_packages.zip - id: 'auth' - uses: 'google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f' + uses: 'google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093' if: github.event.pull_request.head.repo.full_name == github.repository with: workload_identity_provider: projects/304398677251/locations/global/workloadIdentityPools/github/providers/github-provider @@ -225,12 +225,12 @@ jobs: persist-credentials: false - name: 'Download artifact' - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: levitate - name: Parsing levitate result - uses: actions/github-script@v7 + uses: actions/github-script@v8 id: levitate-run with: script: | @@ -241,7 +241,7 @@ jobs: # Check if label exists - name: Check if "levitate breaking change" label exists id: does-label-exist - uses: actions/github-script@v7 + uses: actions/github-script@v8 env: PR_NUMBER: ${{ github.event.pull_request.number }} with: @@ -334,7 +334,7 @@ jobs: # Add the label - name: Add "levitate breaking change" label if: steps.levitate-run.outputs.exit_code == 1 && steps.does-label-exist.outputs.result == 0 - uses: actions/github-script@v7 + uses: actions/github-script@v8 env: PR_NUMBER: ${{ steps.levitate-run.outputs.pr_number }} with: @@ -350,7 +350,7 @@ jobs: # Remove label (no more breaking changes) - name: Remove "levitate breaking change" label if: steps.levitate-run.outputs.exit_code == 0 && steps.does-label-exist.outputs.result == 1 - uses: actions/github-script@v7 + uses: actions/github-script@v8 env: PR_NUMBER: ${{ steps.levitate-run.outputs.pr_number }} with: @@ -368,7 +368,7 @@ jobs: # Related issue: https://github.com/renovatebot/renovate/issues/1908 - name: Add "grafana/plugins-platform-frontend" as a reviewer if: steps.levitate-run.outputs.exit_code == 1 - uses: actions/github-script@v7 + uses: actions/github-script@v8 env: PR_NUMBER: ${{ steps.levitate-run.outputs.pr_number }} with: @@ -385,7 +385,7 @@ jobs: # Remove reviewers (no more breaking changes) - name: Remove "grafana/plugins-platform-frontend" from the list of reviewers if: steps.levitate-run.outputs.exit_code == 0 - uses: actions/github-script@v7 + uses: actions/github-script@v8 env: PR_NUMBER: ${{ steps.levitate-run.outputs.pr_number }} with: diff --git a/.github/workflows/detect-plugin-extension-changes.yml b/.github/workflows/detect-plugin-extension-changes.yml index 12e21b159f1..e59a7c01a7c 100644 --- a/.github/workflows/detect-plugin-extension-changes.yml +++ b/.github/workflows/detect-plugin-extension-changes.yml @@ -36,7 +36,7 @@ jobs: - name: Check for plugin extension changes id: check-changes - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: script: | const { execSync } = require('child_process'); diff --git a/.github/workflows/feature-toggles-ci.yml b/.github/workflows/feature-toggles-ci.yml index d8808d86d67..21f5909e074 100644 --- a/.github/workflows/feature-toggles-ci.yml +++ b/.github/workflows/feature-toggles-ci.yml @@ -24,7 +24,7 @@ jobs: persist-credentials: false - name: Set up Go - uses: actions/setup-go@v5.5.0 + uses: actions/setup-go@v6.0.0 with: go-version-file: 'go.mod' cache: true diff --git a/.github/workflows/frontend-lint.yml b/.github/workflows/frontend-lint.yml index 269582b4a26..02833d61149 100644 --- a/.github/workflows/frontend-lint.yml +++ b/.github/workflows/frontend-lint.yml @@ -42,7 +42,7 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' cache: 'yarn' @@ -63,7 +63,7 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' cache: 'yarn' @@ -89,7 +89,7 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' cache: 'yarn' @@ -109,7 +109,7 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' cache: 'yarn' @@ -133,7 +133,7 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' cache: 'yarn' @@ -164,7 +164,7 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' cache: 'yarn' diff --git a/.github/workflows/go-lint.yml b/.github/workflows/go-lint.yml index 28cddc1e87a..9a85f521a09 100644 --- a/.github/workflows/go-lint.yml +++ b/.github/workflows/go-lint.yml @@ -41,7 +41,7 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: actions/setup-go@v5.5.0 + - uses: actions/setup-go@v6.0.0 with: go-version-file: ./go.mod - name: Run gofmt @@ -62,13 +62,13 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: actions/setup-go@v5.5.0 + - uses: actions/setup-go@v6.0.0 with: go-version-file: ./go.mod - name: golangci-lint - uses: golangci/golangci-lint-action@1481404843c368bc19ca9406f87d6e0fc97bdcfd + uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 with: - version: v2.0.2 + version: v2.5.0 args: | --verbose $(go list -m -f '{{.Dir}}' | xargs -I{} sh -c 'test ! -f {}/.nolint && echo {}/...') install-mode: binary diff --git a/.github/workflows/issue-opened.yml b/.github/workflows/issue-opened.yml index 9e801178c2a..2cf4fd9620a 100644 --- a/.github/workflows/issue-opened.yml +++ b/.github/workflows/issue-opened.yml @@ -39,7 +39,7 @@ jobs: - name: "Get vault secrets" id: vault-secrets - uses: grafana/shared-workflows/actions/get-vault-secrets@get-vault-secrets/v1.2.1 # zizmor: ignore[unpinned-uses] + uses: grafana/shared-workflows/actions/get-vault-secrets@get-vault-secrets/v1.3.0 # zizmor: ignore[unpinned-uses] with: # Secrets placed in the ci/repo/grafana/grafana/plugins_platform_issue_commands_github_bot path in Vault repo_secrets: | @@ -71,7 +71,7 @@ jobs: - name: "Get vault secrets" id: vault-secrets - uses: grafana/shared-workflows/actions/get-vault-secrets@get-vault-secrets/v1.2.1 # zizmor: ignore[unpinned-uses] + uses: grafana/shared-workflows/actions/get-vault-secrets@get-vault-secrets/v1.3.0 # zizmor: ignore[unpinned-uses] with: # Secrets placed in the ci/repo/grafana/grafana/plugins_platform_issue_triager path in Vault repo_secrets: | @@ -139,7 +139,7 @@ jobs: steps: - name: "Get vault secrets" id: vault-secrets - uses: grafana/shared-workflows/actions/get-vault-secrets@get-vault-secrets/v1.2.1 # zizmor: ignore[unpinned-uses] + uses: grafana/shared-workflows/actions/get-vault-secrets@get-vault-secrets/v1.3.0 # zizmor: ignore[unpinned-uses] with: # Secrets placed in the ci/repo/grafana/grafana/plugins_platform_issue_triager path in Vault repo_secrets: | diff --git a/.github/workflows/lint-build-docs.yml b/.github/workflows/lint-build-docs.yml index 90e0004edae..c9e0ab69239 100644 --- a/.github/workflows/lint-build-docs.yml +++ b/.github/workflows/lint-build-docs.yml @@ -35,7 +35,7 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' cache: 'yarn' diff --git a/.github/workflows/pr-codeql-analysis-javascript.yml b/.github/workflows/pr-codeql-analysis-javascript.yml index 6bcf4795972..ef25b9e0514 100644 --- a/.github/workflows/pr-codeql-analysis-javascript.yml +++ b/.github/workflows/pr-codeql-analysis-javascript.yml @@ -29,9 +29,9 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: "javascript" - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 diff --git a/.github/workflows/pr-codeql-analysis-python.yml b/.github/workflows/pr-codeql-analysis-python.yml index b1ed41accbe..72457f84449 100644 --- a/.github/workflows/pr-codeql-analysis-python.yml +++ b/.github/workflows/pr-codeql-analysis-python.yml @@ -39,10 +39,10 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL if: steps.check-python.outputs.skip != 'true' - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: "python" - name: Perform CodeQL Analysis if: steps.check-python.outputs.skip != 'true' - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 diff --git a/.github/workflows/pr-dependabot-update-go-workspace.yml b/.github/workflows/pr-dependabot-update-go-workspace.yml index ee4e4b5cb82..28fd61e44a2 100644 --- a/.github/workflows/pr-dependabot-update-go-workspace.yml +++ b/.github/workflows/pr-dependabot-update-go-workspace.yml @@ -45,7 +45,7 @@ jobs: persist-credentials: false - name: Set go version - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 with: go-version-file: go.mod diff --git a/.github/workflows/pr-e2e-tests.yml b/.github/workflows/pr-e2e-tests.yml index 6ade5a9c787..08b5ad7aba9 100644 --- a/.github/workflows/pr-e2e-tests.yml +++ b/.github/workflows/pr-e2e-tests.yml @@ -65,7 +65,7 @@ jobs: # If no cache hit, build Grafana - name: Build Grafana if: steps.cache.outputs.cache-hit != 'true' - uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e + uses: dagger/dagger-for-github@d913e70051faf3b907d4dd96ef1161083c88c644 with: version: 0.18.8 verb: run @@ -122,7 +122,7 @@ jobs: with: persist-credentials: false - name: Setup Go - uses: actions/setup-go@v5.5.0 + uses: actions/setup-go@v6.0.0 with: go-version-file: go.mod cache: ${{ !github.event.pull_request.head.repo.fork }} @@ -159,7 +159,7 @@ jobs: with: registry: 'us-docker.pkg.dev' environment: 'dev' - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 + - uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c with: name: grafana-docker-tar-gz path: . @@ -221,16 +221,16 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v5 with: name: grafana-tar-gz - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v5 with: name: ${{ needs.build-e2e-runner.outputs.artifact }} - name: chmod +x run: chmod +x ./e2e-runner - name: Run E2E tests - uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e + uses: dagger/dagger-for-github@d913e70051faf3b907d4dd96ef1161083c88c644 with: version: 0.18.8 verb: run @@ -267,7 +267,7 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' @@ -298,11 +298,11 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v5 with: name: grafana-tar-gz - name: Run E2E tests - uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e + uses: dagger/dagger-for-github@d913e70051faf3b907d4dd96ef1161083c88c644 with: version: 0.18.8 verb: run @@ -360,12 +360,12 @@ jobs: run: | docker cp cpp-e2e-deploy:/outputs.json /tmp/outputs.json - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v5 with: name: grafana-tar-gz - name: Run E2E tests - uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e + uses: dagger/dagger-for-github@d913e70051faf3b907d4dd96ef1161083c88c644 with: version: 0.18.8 verb: run @@ -395,12 +395,12 @@ jobs: with: persist-credentials: false - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' - name: Download blob reports from GitHub Actions Artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: path: blobs pattern: playwright-blob-* @@ -479,19 +479,19 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v5 with: name: grafana-tar-gz - name: Run PR a11y test if: github.event_name == 'pull_request' - uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e + uses: dagger/dagger-for-github@d913e70051faf3b907d4dd96ef1161083c88c644 with: version: 0.18.8 verb: run args: go run ./pkg/build/a11y --package=grafana.tar.gz - name: Run non-PR a11y test if: github.event_name != 'pull_request' - uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e + uses: dagger/dagger-for-github@d913e70051faf3b907d4dd96ef1161083c88c644 with: version: 0.18.8 verb: run @@ -525,13 +525,13 @@ jobs: with: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' - name: Install dependencies run: yarn install --immutable - name: Get pa11y results - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: pa11y-ci-results - name: Extract and publish metrics diff --git a/.github/workflows/pr-go-workspace-check.yml b/.github/workflows/pr-go-workspace-check.yml index 78a2e761ebc..c90573d6f4e 100644 --- a/.github/workflows/pr-go-workspace-check.yml +++ b/.github/workflows/pr-go-workspace-check.yml @@ -39,7 +39,7 @@ jobs: persist-credentials: false - name: Set go version - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 with: cache: false go-version-file: go.mod @@ -76,7 +76,7 @@ jobs: persist-credentials: false - name: Set go version - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 with: cache: false go-version-file: go.mod diff --git a/.github/workflows/pr-k8s-codegen-check.yml b/.github/workflows/pr-k8s-codegen-check.yml index e3512e7aeb9..4640131cc47 100644 --- a/.github/workflows/pr-k8s-codegen-check.yml +++ b/.github/workflows/pr-k8s-codegen-check.yml @@ -24,7 +24,7 @@ jobs: persist-credentials: false - name: Set go version - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 with: go-version-file: go.mod diff --git a/.github/workflows/pr-patch-check.yml b/.github/workflows/pr-patch-check.yml index 5de7fcf89ed..52f75a05ff2 100644 --- a/.github/workflows/pr-patch-check.yml +++ b/.github/workflows/pr-patch-check.yml @@ -55,7 +55,7 @@ jobs: permissions: "{\"actions\": \"write\", \"workflows\": \"write\"}" repositories: "[\"security-patch-actions\"]" - name: "Dispatch job" - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: github-token: ${{ steps.generate_token.outputs.token }} script: | diff --git a/.github/workflows/pr-test-docker.yml b/.github/workflows/pr-test-docker.yml index e1e3b466f49..3e8b7540268 100644 --- a/.github/workflows/pr-test-docker.yml +++ b/.github/workflows/pr-test-docker.yml @@ -34,6 +34,6 @@ jobs: uses: actions/checkout@v5 with: persist-credentials: false - - uses: docker/setup-docker-action@b60f85385d03ac8acfca6d9996982511d8620a19 # v4 + - uses: docker/setup-docker-action@3fb92d6d9c634363128c8cce4bc3b2826526370a # v4 - name: Build Dockerfile run: make build-docker-full diff --git a/.github/workflows/pr-test-integration.yml b/.github/workflows/pr-test-integration.yml index 936627f87a0..8e66f838a79 100644 --- a/.github/workflows/pr-test-integration.yml +++ b/.github/workflows/pr-test-integration.yml @@ -58,7 +58,7 @@ jobs: with: persist-credentials: false - name: Setup Go - uses: actions/setup-go@v5.5.0 + uses: actions/setup-go@v6.0.0 with: go-version-file: go.mod cache: true @@ -91,7 +91,7 @@ jobs: with: persist-credentials: false - name: Setup Go - uses: actions/setup-go@v5.5.0 + uses: actions/setup-go@v6.0.0 with: go-version-file: go.mod cache: true @@ -139,7 +139,7 @@ jobs: with: persist-credentials: false - name: Setup Go - uses: actions/setup-go@v5.5.0 + uses: actions/setup-go@v6.0.0 with: go-version-file: go.mod cache: true @@ -188,7 +188,7 @@ jobs: with: persist-credentials: false - name: Setup Go - uses: actions/setup-go@v5.5.0 + uses: actions/setup-go@v6.0.0 with: go-version-file: go.mod cache: true diff --git a/.github/workflows/publish-artifact.yml b/.github/workflows/publish-artifact.yml index 87a6e58f5dd..8ea0b9b90a0 100644 --- a/.github/workflows/publish-artifact.yml +++ b/.github/workflows/publish-artifact.yml @@ -44,7 +44,7 @@ jobs: permissions: id-token: write steps: - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 + - uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c with: name: ${{ inputs.name }} pattern: ${{ inputs.pattern }} diff --git a/.github/workflows/publish-kinds-next.yml b/.github/workflows/publish-kinds-next.yml index 59514bcaf75..dc52f9d25e4 100644 --- a/.github/workflows/publish-kinds-next.yml +++ b/.github/workflows/publish-kinds-next.yml @@ -27,7 +27,7 @@ jobs: persist-credentials: false - name: "Setup Go" - uses: "actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5" + uses: "actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00" with: go-version-file: go.mod diff --git a/.github/workflows/publish-kinds-release.yml b/.github/workflows/publish-kinds-release.yml index 8254879f3be..e0e4a89aa13 100644 --- a/.github/workflows/publish-kinds-release.yml +++ b/.github/workflows/publish-kinds-release.yml @@ -30,7 +30,7 @@ jobs: persist-credentials: false - name: "Setup Go" - uses: "actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5" + uses: "actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00" with: go-version-file: go.mod diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 650ba6a67c1..be9bd4b492b 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -96,7 +96,7 @@ jobs: private_key: ${{ env.GRAFANA_DELIVERY_BOT_APP_PEM }} repositories: '["grafana-enterprise"]' permissions: '{"actions": "write"}' - - uses: actions/github-script@v7 + - uses: actions/github-script@v8 env: REF: ${{ github.ref_name }} VERSION: ${{ needs.setup.outputs.version }} @@ -224,27 +224,27 @@ jobs: - build steps: - uses: grafana/shared-workflows/actions/dockerhub-login@dockerhub-login/v1.0.2 - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 + - uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c with: name: artifacts-list-linux-amd64 path: . - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 + - uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c with: name: artifacts-list-linux-arm64 path: . - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 + - uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c with: name: artifacts-list-linux-armv7 path: . - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 + - uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c with: name: artifacts-linux-amd64 path: dist - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 + - uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c with: name: artifacts-linux-arm64 path: dist - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 + - uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c with: name: artifacts-linux-armv7 path: dist @@ -333,7 +333,7 @@ jobs: body-includes: GitHub Actions Build token: ${{ steps.generate_token.outputs.token }} - name: Create or update comment - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v4 with: token: ${{ steps.generate_token.outputs.token }} comment-id: ${{ steps.fc.outputs.comment-id }} diff --git a/.github/workflows/release-npm.yml b/.github/workflows/release-npm.yml index 4dd92e9d0a1..999ccbc5e4a 100644 --- a/.github/workflows/release-npm.yml +++ b/.github/workflows/release-npm.yml @@ -60,7 +60,7 @@ jobs: echo "github.ref: $GITHUB_REF" - name: Checkout workflow ref - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: persist-credentials: false fetch-depth: 100 @@ -86,7 +86,7 @@ jobs: shell: bash - name: Checkout build commit - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: persist-credentials: false ref: ${{ inputs.grafana_commit }} @@ -123,11 +123,6 @@ jobs: - name: Validate packages run: ./scripts/validate-npm-packages.sh - - name: Debug OIDC Claims - uses: github/actions-oidc-debugger@2e9ba5d3f4bebaad1f91a2cede055115738b7ae8 - with: - audience: '${{ github.server_url }}/${{ github.repository_owner }}' - - name: Publish packages env: NPM_TAG: ${{ steps.npm-tag.outputs.NPM_TAG }} diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml index 2190e2640b4..d23d069f469 100644 --- a/.github/workflows/release-pr.yml +++ b/.github/workflows/release-pr.yml @@ -133,10 +133,10 @@ jobs: path: .grafana-main - name: Setup nodejs environment - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version-file: .nvmrc - - uses: actions/setup-go@v5.5.0 + - uses: actions/setup-go@v6.0.0 with: go-version-file: go.mod - name: Configure git user @@ -196,7 +196,7 @@ jobs: run: git add CHANGELOG.md && git commit --allow-empty -m "Update changelog" CHANGELOG.md - name: Bump versions if: ${{ inputs.bump == true || inputs.bump == 'true' }} - uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e + uses: dagger/dagger-for-github@d913e70051faf3b907d4dd96ef1161083c88c644 with: version: 0.18.8 verb: run diff --git a/.github/workflows/run-dashboard-search-e2e.yml b/.github/workflows/run-dashboard-search-e2e.yml index 24d594cb22b..32d32480aec 100644 --- a/.github/workflows/run-dashboard-search-e2e.yml +++ b/.github/workflows/run-dashboard-search-e2e.yml @@ -29,12 +29,12 @@ jobs: with: persist-credentials: false - name: Pin Go version to mod file - uses: actions/setup-go@v5.5.0 + uses: actions/setup-go@v6.0.0 with: go-version-file: 'go.mod' cache: true - run: go version - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' cache: 'yarn' diff --git a/.github/workflows/run-schema-v2-e2e.yml b/.github/workflows/run-schema-v2-e2e.yml index 09a1a1085a4..b59b1715213 100644 --- a/.github/workflows/run-schema-v2-e2e.yml +++ b/.github/workflows/run-schema-v2-e2e.yml @@ -22,11 +22,11 @@ jobs: with: persist-credentials: false - name: Pin Go version to mod file - uses: actions/setup-go@v5.5.0 + uses: actions/setup-go@v6.0.0 with: go-version-file: 'go.mod' - run: go version - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' cache: 'yarn' diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 778a49b16d0..e2fb876541b 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -11,7 +11,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v9 + - uses: actions/stale@v10 with: repo-token: ${{ secrets.GITHUB_TOKEN }} operations-per-run: 750 diff --git a/.github/workflows/storybook-a11y.yml b/.github/workflows/storybook-a11y.yml index 68ff4e75e37..5736c86d8bf 100644 --- a/.github/workflows/storybook-a11y.yml +++ b/.github/workflows/storybook-a11y.yml @@ -39,7 +39,7 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: actions/setup-node@v5 + - uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' package-manager-cache: false # too large for GH's cache limits :-( @@ -69,7 +69,7 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: actions/setup-node@v5 + - uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' package-manager-cache: false # too large for GH's cache limits :-( diff --git a/.github/workflows/swagger-gen.yml b/.github/workflows/swagger-gen.yml index 8ce3c19b396..fff7d571b0f 100644 --- a/.github/workflows/swagger-gen.yml +++ b/.github/workflows/swagger-gen.yml @@ -49,7 +49,7 @@ jobs: with: persist-credentials: false - name: Setup Go - uses: actions/setup-go@v5.5.0 + uses: actions/setup-go@v6.0.0 with: go-version-file: go.mod - name: Setup Enterprise diff --git a/.github/workflows/sync-mirror-event.yml b/.github/workflows/sync-mirror-event.yml index 4a073c9b2b3..64d5c49a96d 100644 --- a/.github/workflows/sync-mirror-event.yml +++ b/.github/workflows/sync-mirror-event.yml @@ -41,7 +41,7 @@ jobs: app_id: ${{ vars.DELIVERY_BOT_APP_ID }} private_key: ${{ env.GRAFANA_DELIVERY_BOT_APP_PEM }} - - uses: actions/github-script@v7 + - uses: actions/github-script@v8 if: github.repository == 'grafana/grafana' with: github-token: ${{ steps.generate_token.outputs.token }} diff --git a/.github/workflows/trivy-scan.yml b/.github/workflows/trivy-scan.yml index c9fe0b8cdab..1a4a9a6ed11 100644 --- a/.github/workflows/trivy-scan.yml +++ b/.github/workflows/trivy-scan.yml @@ -20,7 +20,7 @@ jobs: with: persist-credentials: false - name: Install Trivy - uses: aquasecurity/setup-trivy@9ea583eb67910444b1f64abf338bd2e105a0a93d + uses: aquasecurity/setup-trivy@e6c2c5e321ed9123bda567646e2f96565e34abe1 with: version: v0.56.2 cache: true @@ -64,7 +64,7 @@ jobs: . if: always() && github.repository == 'grafana/grafana' - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v3 + uses: github/codeql-action/upload-sarif@v4 with: sarif_file: 'trivy-results.sarif' if: always() && github.repository == 'grafana/grafana' diff --git a/.github/workflows/trufflehog.yml b/.github/workflows/trufflehog.yml index d11186c5343..7278c8ad3ed 100644 --- a/.github/workflows/trufflehog.yml +++ b/.github/workflows/trufflehog.yml @@ -31,6 +31,6 @@ jobs: persist-credentials: false fetch-depth: ${{ steps.fetch_depth.outputs.fetch_depth }} - name: Trufflehog - uses: trufflesecurity/trufflehog@eafb8c5f6a06175141c27f17bcc17941853d0047 # v3.90.0 + uses: trufflesecurity/trufflehog@ad6fc8fb446b8fafbf7ea8193d2d6bfd42f45690 # v3.90.11 with: extra_args: --results=verified diff --git a/.github/workflows/update-schema-types.yml b/.github/workflows/update-schema-types.yml index a079f1d313e..303625472ae 100644 --- a/.github/workflows/update-schema-types.yml +++ b/.github/workflows/update-schema-types.yml @@ -17,6 +17,6 @@ jobs: bundle-schema-types: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: grafana/plugin-actions/bundle-schema-types@main diff --git a/.github/workflows/verify-kinds.yml b/.github/workflows/verify-kinds.yml index 0fe82c5e67e..8940c79afeb 100644 --- a/.github/workflows/verify-kinds.yml +++ b/.github/workflows/verify-kinds.yml @@ -21,7 +21,7 @@ jobs: persist-credentials: false - name: "Setup Go" - uses: "actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5" + uses: "actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00" with: go-version-file: go.mod diff --git a/.gitignore b/.gitignore index fb7d5d30a9a..036bb5dd2b1 100644 --- a/.gitignore +++ b/.gitignore @@ -253,3 +253,7 @@ public/mockServiceWorker.js # Ignore unified storage kv store files /grafana-kv-data +/codeowners-manifest/ + +# Ignore grafana/hippocampus local cache folder +.hippo diff --git a/.prettierignore b/.prettierignore index 1f1b9e75e9b..7d9575558d9 100644 --- a/.prettierignore +++ b/.prettierignore @@ -14,6 +14,9 @@ public/sass/*.generated.scss scripts/grafana-server/tmp vendor +/coverage +/codeowners-manifest + # TS generate from cue by cuetsy **/*.gen.ts @@ -23,6 +26,7 @@ vendor # Auto-generated theme files theme.light.generated.json theme.dark.generated.json +public/app/features/theme-playground/schema.generated.json # Generated Swagger API specs public/api-merged.json diff --git a/CHANGELOG.md b/CHANGELOG.md index b4f6e525596..b1e53f42f32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,92 @@ + + +# 12.2.1 (2025-10-21) + +### Features and enhancements + +- **Go:** Update to 1.25.2 + golangci-lint v2.5.0 + golang.org/x/net v0.45.0 [#112156](https://github.com/grafana/grafana/pull/112156), [@macabu](https://github.com/macabu) +- **Go:** Update to 1.25.3 [#112361](https://github.com/grafana/grafana/pull/112361), [@macabu](https://github.com/macabu) + +### Bug fixes + +- **Auth:** Fix render user OAuth passthrough [#112092](https://github.com/grafana/grafana/pull/112092), [@mgyongyosi](https://github.com/mgyongyosi) +- **Dashboards:** Fix missing Ctrl+O keyboard shortcut for crosshair toggle [#111402](https://github.com/grafana/grafana/pull/111402), [@ivanortegaalba](https://github.com/ivanortegaalba) +- **Fix:** Fix redirection after login when Grafana is served from subpath [#111069](https://github.com/grafana/grafana/pull/111069), [@mgyongyosi](https://github.com/mgyongyosi) +- **FlameGraph:** Ensure total is only counted once for recursive function calls [#111606](https://github.com/grafana/grafana/pull/111606), [@simonswine](https://github.com/simonswine) +- **LDAP Authentication:** Fix URL to propagate username context as parameter [#111849](https://github.com/grafana/grafana/pull/111849), [@bradleypettit](https://github.com/bradleypettit) +- **Plugins:** Dependencies do not inherit parent URL for preinstall [#111769](https://github.com/grafana/grafana/pull/111769), [@wbrowne](https://github.com/wbrowne) +- **Table:** Backport the Safari 26 fixes to 12.2.1 [#111906](https://github.com/grafana/grafana/pull/111906), [@fastfrwrd](https://github.com/fastfrwrd) + + + + +# 12.1.3 (2025-10-21) + +### Features and enhancements + +- **Go:** Update to 1.25.2 + golangci-lint v2.5.0 + golang.org/x/net v0.45.0 [#112159](https://github.com/grafana/grafana/pull/112159), [@macabu](https://github.com/macabu) +- **Go:** Update to 1.25.3 [#112362](https://github.com/grafana/grafana/pull/112362), [@macabu](https://github.com/macabu) +- **Table:** Avoid thrown error due to internal React issue [#111945](https://github.com/grafana/grafana/pull/111945), [@fastfrwrd](https://github.com/fastfrwrd) + +### Bug fixes + +- **Auth:** Fix render user OAuth passthrough [#112097](https://github.com/grafana/grafana/pull/112097), [@mgyongyosi](https://github.com/mgyongyosi) +- **FlameGraph:** Ensure total is only counted once for recursive function calls [#111605](https://github.com/grafana/grafana/pull/111605), [@simonswine](https://github.com/simonswine) +- **LDAP Authentication:** Fix URL to propagate username context as parameter [#111848](https://github.com/grafana/grafana/pull/111848), [@bradleypettit](https://github.com/bradleypettit) +- **Plugins:** Dependencies do not inherit parent URL for preinstall [#111767](https://github.com/grafana/grafana/pull/111767), [@wbrowne](https://github.com/wbrowne) + + + + +# 12.0.6 (2025-10-21) + +### Features and enhancements + +- **Go:** Update to 1.25.2 + golangci-lint v2.5.0 + golang.org/x/net v0.45.0 [#112161](https://github.com/grafana/grafana/pull/112161), [@macabu](https://github.com/macabu) +- **Go:** Update to 1.25.3 [#112364](https://github.com/grafana/grafana/pull/112364), [@macabu](https://github.com/macabu) + +### Bug fixes + +- **Auth:** Fix render user OAuth passthrough [#112096](https://github.com/grafana/grafana/pull/112096), [@mgyongyosi](https://github.com/mgyongyosi) +- **FlameGraph:** Ensure total is only counted once for recursive function calls [#111604](https://github.com/grafana/grafana/pull/111604), [@simonswine](https://github.com/simonswine) +- **LDAP Authentication:** Fix URL to propagate username context as parameter [#111847](https://github.com/grafana/grafana/pull/111847), [@bradleypettit](https://github.com/bradleypettit) +- **Plugins:** Dependencies do not inherit parent URL for preinstall [#111766](https://github.com/grafana/grafana/pull/111766), [@wbrowne](https://github.com/wbrowne) + + + + +# 11.6.7 (2025-10-21) + +### Features and enhancements + +- **Analytics:** Apply proper batching to Loki exports and add configurable settings (Enterprise) +- **Go:** Update to 1.25.2 + golangci-lint v2.5.0 + golang.org/x/net v0.45.0 [#112162](https://github.com/grafana/grafana/pull/112162), [@grambbledook](https://github.com/grambbledook) +- **Go:** Update to 1.25.3 [#112365](https://github.com/grafana/grafana/pull/112365), [@macabu](https://github.com/macabu) + +### Bug fixes + +- **Auth:** Fix render user OAuth passthrough [#112094](https://github.com/grafana/grafana/pull/112094), [@mgyongyosi](https://github.com/mgyongyosi) +- **LDAP Authentication:** Fix URL to propagate username context as parameter [#111846](https://github.com/grafana/grafana/pull/111846), [@bradleypettit](https://github.com/bradleypettit) +- **Plugins:** Dependencies do not inherit parent URL for preinstall [#111801](https://github.com/grafana/grafana/pull/111801), [@wbrowne](https://github.com/wbrowne) +- **URLParams:** Stringify true values as key=true always (fixes issues with variables with true value) [#112045](https://github.com/grafana/grafana/pull/112045), [@torkelo](https://github.com/torkelo) + + + + +# 11.5.10 (2025-10-21) + +### Features and enhancements + +- **Go:** Update to 1.25.2 + golangci-lint v2.5.0 + golang.org/x/net v0.45.0 [#112163](https://github.com/grafana/grafana/pull/112163), [@macabu](https://github.com/macabu) +- **Go:** Update to 1.25.3 [#112366](https://github.com/grafana/grafana/pull/112366), [@macabu](https://github.com/macabu) + +### Bug fixes + +- **Auth:** Fix render user OAuth passthrough [#112093](https://github.com/grafana/grafana/pull/112093), [@mgyongyosi](https://github.com/mgyongyosi) +- **LDAP Authentication:** Fix URL to propagate username context as parameter [#111845](https://github.com/grafana/grafana/pull/111845), [@bradleypettit](https://github.com/bradleypettit) +- **Plugins:** Dependencies do not inherit parent URL for preinstall [#111802](https://github.com/grafana/grafana/pull/111802), [@wbrowne](https://github.com/wbrowne) + + # 12.2.0 (2025-09-23) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 818c5b57c7f..c1f5d9ddace 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,51 +2,82 @@ Thank you for your interest in contributing to Grafana! We welcome all people who want to contribute in a healthy and constructive manner within our community. To help us create a safe and positive community experience for all, we require all participants to adhere to the [Code of Conduct](CODE_OF_CONDUCT.md). -This document is a guide to help you through the process of contributing to Grafana. Be sure to check out the [Grafana Champions program](https://grafana.com/community/champions/?src=github&camp=community-cross-platform-engagement) as you start to contribute- itโ€™s designed to recognize and empower individuals who are actively contributing to the growth and success of the Grafana ecosystem. +This document is a guide to help you through the process of contributing to Grafana. Be sure to check out the [Grafana Champions program](https://grafana.com/community/champions/?src=github&camp=community-cross-platform-engagement) as you start to contribute. Itโ€™s designed to recognize and empower individuals who are actively contributing to the growth and success of the Grafana ecosystem. -Whether you're a new contributer or a seasoned veteran we hope these resources help you connect with the community: +Whether you're a new contributor or a seasoned veteran, we hope these resources help you connect with the community. -Interact and be heard: +#### Interact and be heard -- Forums: Do you have a problem, question, or curiosity? Visit our [forums](https://gra.fan/fromgithubtoforums) for a reservoir of knowledge- submit your own questions and answers! -- Meetups: Craving in-person connections without the long journeys? [Join your local Grafana & Friends meetup group](https://gra.fan/githubtomeetup)! -- Community Slack: Eager for real-time connections with fellow users? Begin a conversation on [Slack](https://gra.fan/githubtoslack). - Learn: -- YouTube: From getting started to exploring newer projects like Pyroscope and Beyla, the [Grafana YouTube channel](https://gra.fan/githubtoyoutube) has what you need to get started! -- Meetups: Join a [group near you](https://gra.fan/githubtomeetup) to learn from local experts and ask questions in real time. - Share your story: -- Meetups and blogs: Weโ€™d love to feature your OSS Grafana Labs use case or story at an upcoming Grafana & Friends meetup or on the Grafana blog! Submit your idea [here](https://gra.fan/githubtocca) and weโ€™ll connect with you on next steps if accepted. +- **Forums:** Do you have a problem, question, or curiosity? Visit our [forums](https://gra.fan/fromgithubtoforums) for a reservoir of knowledge, submit your own questions and answers! +- **Meetups:** Craving in-person connections without the long journeys? [Join your local Grafana & Friends meetup group](https://gra.fan/githubtomeetup)! +- **Community Slack:** Eager for real-time connections with fellow users? Begin a conversation on [Slack](https://gra.fan/githubtoslack). + +#### Learn + +- **YouTube:** From getting started to exploring newer projects like Pyroscope and Beyla, the [Grafana YouTube channel](https://gra.fan/githubtoyoutube) has what you need to get started! +- **Meetups:** Join a [group near you](https://gra.fan/githubtomeetup) to learn from local experts and ask questions in real time. + +#### Make technical contributions + +- You can make technical contributions with or without code. Scroll down to see how! + +#### Share your story + +- **Meetups and blogs:** Weโ€™d love to feature your OSS Grafana Labs use case or story at an upcoming Grafana & Friends meetup or on the Grafana blog! Submit your idea [here](https://gra.fan/githubtocca), and weโ€™ll connect with you on next steps if accepted. + +## Choose the right channel + +Use the right place to ask questions, report problems, and propose changes. + +- **[GitHub issues](https://github.com/grafana/grafana/issues) and [pull requests](https://github.com/grafana/grafana/pulls)**: Use for reproducible bugs in core Grafana and maintained plugins, small and actionable feature requests, and code or docs changes via pull requests. Avoid general โ€œhow do Iโ€ questions. For security issues, follow the [security policy](https://github.com/grafana/grafana/security/policy). +- **Grafana community forums**: Use for questions, troubleshooting, best practices, plugin development Q&A, and early idea discussion. Forums create a searchable public knowledge base that helps others with the same problems and questions. Start here if you are unsure: [Grafana community forums](https://community.grafana.com/). +- **Grafana Community Slack**: Use for quick, time-sensitive chats and networking. Do not rely on Slack for complex troubleshooting or decisions. Share outcomes back to a forum topic or GitHub issue/PR to keep a public record: [Grafana Community Slack](https://slack.grafana.com). +- **Not sure where to start?** Start with a forum topic. Maintainers and community members will redirect you if a GitHub issue or pull request is more appropriate. ## Make technical contributions -We welcome your technical contributions! Here are some examples: +We welcome your technical contributions! You can contribute in several ways: -- Contribute to the Grafana codebase- check out these [help-wanted issues](<(https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)>) -- Develop community [plugins](https://grafana.com/developers/plugin-tools) -- Report [bugs](https://github.com/grafana/grafana/issues/new?template=0-bug-report.yaml) -- [Triage issues](https://github.com/grafana/grafana/blob/4414b92e93440cc9ed0f281989ee71dc16216a15/contribute/triage-issues.md) -- Report [security vulnerabilities](https://github.com/grafana/grafana/security/policy) -- Submit a [feature request](https://github.com/grafana/grafana/issues/new?template=1-feature_requests.md) -- Write [technical documentation](https://github.com/grafana/grafana/blob/4414b92e93440cc9ed0f281989ee71dc16216a15/contribute/documentation/README.md) +### Contribute Code to Grafana -**Please note:** We do not currently accept contributions for translations. Please do not submit pull requests translating grafana.json files - they will be rejected. We do accept contributions to mark up phrases for translation. See [Internationalization](contribute/internationalization.md). +**What you will need:** -### Your first contribution +- Follow our [developer guide](contribute/developer-guide.md) to set up your environment. +- Adhere to our [frontend](contribute/style-guides/frontend.md) and [backend](contribute/backend/style-guide.md) style guides. +- Write or update tests ([testing guide](contribute/style-guides/testing.md)). -Unsure where to begin contributing to Grafana? Start by browsing issues labeled `beginner friendly` or `help wanted`. +**Step-by-step:** -- [Beginner-friendly](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22beginner+friendly%22) issues are generally straightforward to complete. -- [Help wanted](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) issues are problems we would like the community to help us with regardless of complexity. +1. Browse all [issues](https://github.com/grafana/grafana/issues) to find something to work on. You can also filter by [help wanted](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22). +1. Prepare a clear, descriptive pull request ([how-to guide](contribute/create-pull-request.md)). +1. Ensure you include and run the appropriate tests as part of your pull request. +1. Commit and push your changes. If you encounter merge conflicts, you may rebase your branch onto the main branch. -If you're looking to make a code change, see how to set up your environment for [local development](contribute/developer-guide.md). +### Develop a Plugin -When you're ready to contribute, it's time to [create a pull request](/contribute/create-pull-request.md). +Grafana plugins let you extend the platform with new data sources, panels, and more. This is a great way to share your ideas and make a real impact on the Grafana ecosystem. -### Develop a plugin +**Step-by-step:** -Developing a Grafana plugin is a fantastic way to share your unique ideas with the community, extend the platformโ€™s capabilities, and make a real impact on how people visualize and understand their data. Check out our guide to creating [plugins](https://grafana.com/developers/plugin-tools) +1. Read the [plugin development guide](https://grafana.com/developers/plugin-tools) to choose your plugin type and set up your environment. +2. Scaffold your plugin using the recommended tools. +3. Develop and test your plugin locally. +4. Follow best practices for code style, testing, and documentation. +5. Publish your plugin or submit it for review as described in the guide. -### Report bugs +### Contribute without code + +You can help even if you don't write code: + +- Report a bug with the [bug report template](https://github.com/grafana/grafana/issues/new?template=0-bug-report.yaml) and include steps to reproduce. +- Submit a [feature request](https://github.com/grafana/grafana/issues/new?template=1-feature_requests.md) to propose improvements. +- Improve our docs with the [documentation contribution guide](https://github.com/grafana/grafana/blob/main/contribute/documentation). +- Help with [issue triage](https://github.com/grafana/grafana/blob/main/contribute/triage-issues.md) by reviewing, labeling, and clarifying open issues. +- Report security vulnerabilities following our [security policy](https://github.com/grafana/grafana/security/policy). + +**Please note:** We do not currently accept contributions for translations. Please do not submit pull requests translating `grafana.json` files - they will be rejected. We do accept contributions to mark up phrases for translation. See [Internationalization](contribute/internationalization.md). + +#### Reporting issues Before submitting a new issue, try to make sure someone hasn't already reported the problem. Look through the [existing issues](https://github.com/grafana/grafana/issues) for similar issues. @@ -59,11 +90,11 @@ For data visualization issues: - Query results from the inspect drawer (data tab & query inspector) - Panel settings can be extracted in the panel inspect drawer JSON tab -For a dashboard related issues: +For dashboard related issues: -- Dashboard JSON can be found in the dashboard settings JSON model view +- Dashboard JSON can be found in the dashboard settings JSON model view. You can [send the panel JSON model](https://grafana.com/docs/grafana/latest/troubleshooting/send-panel-to-grafana-support/) to Grafana Labs Technical Support and request help with troubleshooting your issue. -For authentication and alerting Grafana server logs are useful. +For authentication and alerting, Grafana server logs are useful. ### Triage issues @@ -75,7 +106,7 @@ Read more about the ways you can [Triage issues](/contribute/triage-issues.md). If you believe you've found a security vulnerability, please read our [security policy](https://github.com/grafana/grafana/security/policy) for more details on reporting. -### Suggest enhancements +### Suggest features If you have an idea of how to improve Grafana, submit a [feature request](https://github.com/grafana/grafana/issues/new?template=1-feature_requests.md). diff --git a/Dockerfile b/Dockerfile index a5121873b10..16efe807bfc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,9 +14,9 @@ ARG JS_SRC=js-builder # Dependabot cannot update dependencies listed in ARGs # By using FROM instructions we can delegate dependency updates to dependabot -FROM alpine:3.21.3 AS alpine-base +FROM alpine:3.22.2 AS alpine-base FROM ubuntu:22.04 AS ubuntu-base -FROM golang:1.24.6-alpine AS go-builder-base +FROM golang:1.25.3-alpine AS go-builder-base FROM --platform=${JS_PLATFORM} node:22-alpine AS js-builder-base # Javascript build stage FROM --platform=${JS_PLATFORM} ${JS_IMAGE} AS js-builder @@ -101,6 +101,7 @@ COPY apps/provisioning apps/provisioning COPY apps/secret apps/secret COPY apps/scope apps/scope COPY apps/investigations apps/investigations +COPY apps/logsdrilldown apps/logsdrilldown COPY apps/advisor apps/advisor COPY apps/dashboard apps/dashboard COPY apps/folder apps/folder diff --git a/Makefile b/Makefile index e76e5a18940..c2ac23809c5 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ WIRE_TAGS = "oss" include .citools/Variables.mk GO = go -GO_VERSION = 1.24.6 +GO_VERSION = 1.25.3 GO_LINT_FILES ?= $(shell ./scripts/go-workspace/golangci-lint-includes.sh) GO_TEST_FILES ?= $(shell ./scripts/go-workspace/test-includes.sh) SH_FILES ?= $(shell find ./scripts -name *.sh) @@ -233,13 +233,13 @@ update-workspace: gen-go bash scripts/go-workspace/update-workspace.sh .PHONY: build-go -build-go: gen-go update-workspace ## Build all Go binaries. +build-go: ## Build all Go binaries. @echo "build go files with updated workspace" $(GO) run build.go $(GO_BUILD_FLAGS) build -build-go-fast: gen-go ## Build all Go binaries. - @echo "build go files" - $(GO) run build.go $(GO_BUILD_FLAGS) build +.PHONY: build-go-fast +build-go-fast: ## Build all Go binaries without updating workspace. + @echo "!!! [DEPRECATED] use build-go, they do the same thing now. This command will be removed soon" .PHONY: build-backend build-backend: ## Build Grafana backend. diff --git a/apps/advisor/go.mod b/apps/advisor/go.mod index 3f21822f5a4..29fd3c33281 100644 --- a/apps/advisor/go.mod +++ b/apps/advisor/go.mod @@ -1,6 +1,6 @@ module github.com/grafana/grafana/apps/advisor -go 1.24.6 +go 1.25.3 require ( github.com/Masterminds/semver/v3 v3.4.0 diff --git a/apps/advisor/pkg/app/checks/datasourcecheck/check.go b/apps/advisor/pkg/app/checks/datasourcecheck/check.go index 38846740814..ed8aa35349b 100644 --- a/apps/advisor/pkg/app/checks/datasourcecheck/check.go +++ b/apps/advisor/pkg/app/checks/datasourcecheck/check.go @@ -3,6 +3,8 @@ package datasourcecheck import ( "context" "errors" + sysruntime "runtime" + "sync" "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana/apps/advisor/pkg/app/checks" @@ -18,15 +20,18 @@ const ( HealthCheckStepID = "health-check" UIDValidationStepID = "uid-validation" MissingPluginStepID = "missing-plugin" + PromDepAuthStepID = "prom-dep-auth" ) type check struct { - DatasourceSvc datasources.DataSourceService - PluginStore pluginstore.Store - PluginContextProvider pluginContextProvider - PluginClient plugins.Client - PluginRepo repo.Service - GrafanaVersion string + DatasourceSvc datasources.DataSourceService + PluginStore pluginstore.Store + PluginContextProvider pluginContextProvider + PluginClient plugins.Client + PluginRepo repo.Service + GrafanaVersion string + pluginCanBeInstalledCache map[string]bool + pluginExistsCacheMu sync.RWMutex } func New( @@ -38,12 +43,13 @@ func New( grafanaVersion string, ) checks.Check { return &check{ - DatasourceSvc: datasourceSvc, - PluginStore: pluginStore, - PluginContextProvider: pluginContextProvider, - PluginClient: pluginClient, - PluginRepo: pluginRepo, - GrafanaVersion: grafanaVersion, + DatasourceSvc: datasourceSvc, + PluginStore: pluginStore, + PluginContextProvider: pluginContextProvider, + PluginClient: pluginClient, + PluginRepo: pluginRepo, + GrafanaVersion: grafanaVersion, + pluginCanBeInstalledCache: make(map[string]bool), } } @@ -87,6 +93,7 @@ func (c *check) Name() string { } func (c *check) Init(ctx context.Context) error { + c.pluginCanBeInstalledCache = make(map[string]bool) return nil } @@ -102,9 +109,59 @@ func (c *check) Steps() []checks.Step { PluginRepo: c.PluginRepo, GrafanaVersion: c.GrafanaVersion, }, + &promDepAuthStep{ + canBeInstalled: c.canBeInstalled, + }, } } +// canBeInstalled checks if a plugin is already installed or if it's available in the plugin repository. +// Returns true if: +// - The plugin is NOT installed AND it IS available in the repository (can be installed) +// Returns false if: +// - The plugin is already installed, OR +// - The plugin is NOT available in the repository (nothing to install) +func (c *check) canBeInstalled(ctx context.Context, pluginType string) (bool, error) { + // Check cache first with read lock for performance + c.pluginExistsCacheMu.RLock() + if canBeInstalled, found := c.pluginCanBeInstalledCache[pluginType]; found { + c.pluginExistsCacheMu.RUnlock() + return canBeInstalled, nil + } + c.pluginExistsCacheMu.RUnlock() + + // Cache miss - acquire write lock and check again (double-checked locking pattern) + c.pluginExistsCacheMu.Lock() + defer c.pluginExistsCacheMu.Unlock() + + // Another goroutine may have populated the cache while we waited for the lock + if canBeInstalled, found := c.pluginCanBeInstalledCache[pluginType]; found { + return canBeInstalled, nil + } + + // Check if plugin is already installed + if _, isInstalled := c.PluginStore.Plugin(ctx, pluginType); isInstalled { + c.pluginCanBeInstalledCache[pluginType] = false + return false, nil + } + + // Plugin is not installed - check if it's available in the repository + availablePlugins, err := c.PluginRepo.GetPluginsInfo(ctx, repo.GetPluginsInfoOptions{ + IncludeDeprecated: true, + Plugins: []string{pluginType}, + }, repo.NewCompatOpts(c.GrafanaVersion, sysruntime.GOOS, sysruntime.GOARCH)) + if err != nil { + // On error, assume plugin is installed/unavailable to avoid showing incorrect install links + return false, err + } + + // Plugin is not installed but IS available - return false to show install link + // Plugin is not installed and NOT available in repo - return true (nothing to install) + isAvailableInRepo := len(availablePlugins) > 0 + c.pluginCanBeInstalledCache[pluginType] = !isAvailableInRepo + return isAvailableInRepo, nil +} + type pluginContextProvider interface { GetWithDataSource(ctx context.Context, pluginID string, user identity.Requester, ds *datasources.DataSource) (backend.PluginContext, error) } diff --git a/apps/advisor/pkg/app/checks/datasourcecheck/check_test.go b/apps/advisor/pkg/app/checks/datasourcecheck/check_test.go index fb02a8892ad..cd1e608af5b 100644 --- a/apps/advisor/pkg/app/checks/datasourcecheck/check_test.go +++ b/apps/advisor/pkg/app/checks/datasourcecheck/check_test.go @@ -8,6 +8,7 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/identity" + "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/repo" "github.com/grafana/grafana/pkg/services/datasources" @@ -230,6 +231,101 @@ func TestCheck_Run(t *testing.T) { assert.Equal(t, MissingPluginStepID, failures[0].StepID) assert.Len(t, failures[0].Links, 1) }) + + t.Run("should return failure when prometheus datasource uses SigV4 auth", func(t *testing.T) { + jsonData := simplejson.New() + jsonData.Set("sigV4Auth", true) + datasources := []*datasources.DataSource{ + {UID: "valid-uid-1", Type: "prometheus", Name: "Prometheus", JsonData: jsonData}, + } + mockDatasourceSvc := &MockDatasourceSvc{dss: datasources} + mockPluginContextProvider := &MockPluginContextProvider{pCtx: backend.PluginContext{}} + mockPluginClient := &MockPluginClient{res: &backend.CheckHealthResult{Status: backend.HealthStatusOk}} + mockPluginRepo := &MockPluginRepo{plugins: []repo.PluginInfo{ + {ID: 1, Slug: "prometheus", Status: "active"}, + {ID: 2, Slug: "grafana-amazonprometheus-datasource", Status: "active"}, + }} + mockPluginStore := &MockPluginStore{exists: true} + + check := &check{ + DatasourceSvc: mockDatasourceSvc, + PluginContextProvider: mockPluginContextProvider, + PluginClient: mockPluginClient, + PluginRepo: mockPluginRepo, + PluginStore: mockPluginStore, + GrafanaVersion: "11.0.0", + } + + failures, err := runChecks(check) + assert.NoError(t, err) + assert.Len(t, failures, 1) + assert.Equal(t, PromDepAuthStepID, failures[0].StepID) + assert.Contains(t, failures[0].Links, advisor.CheckErrorLink{ + Message: "View SigV4 docs", + Url: "https://grafana.com/docs/grafana-cloud/connect-externally-hosted/data-sources/prometheus/configure/aws-authentication/", + }) + }) + + t.Run("should return failure when prometheus datasource uses Azure auth", func(t *testing.T) { + jsonData := simplejson.New() + jsonData.Set("azureCredentials", map[string]interface{}{"authType": "msi"}) + datasources := []*datasources.DataSource{ + {UID: "valid-uid-1", Type: "prometheus", Name: "Prometheus", JsonData: jsonData}, + } + mockDatasourceSvc := &MockDatasourceSvc{dss: datasources} + mockPluginContextProvider := &MockPluginContextProvider{pCtx: backend.PluginContext{}} + mockPluginClient := &MockPluginClient{res: &backend.CheckHealthResult{Status: backend.HealthStatusOk}} + mockPluginRepo := &MockPluginRepo{plugins: []repo.PluginInfo{ + {ID: 1, Slug: "prometheus", Status: "active"}, + {ID: 2, Slug: "grafana-azureprometheus-datasource", Status: "active"}, + }} + mockPluginStore := &MockPluginStore{exists: true} + + check := &check{ + DatasourceSvc: mockDatasourceSvc, + PluginContextProvider: mockPluginContextProvider, + PluginClient: mockPluginClient, + PluginRepo: mockPluginRepo, + PluginStore: mockPluginStore, + GrafanaVersion: "11.0.0", + } + + failures, err := runChecks(check) + assert.NoError(t, err) + assert.Len(t, failures, 1) + assert.Equal(t, PromDepAuthStepID, failures[0].StepID) + assert.Contains(t, failures[0].Links, advisor.CheckErrorLink{ + Message: "View Azure auth docs", + Url: "https://grafana.com/docs/grafana-cloud/connect-externally-hosted/data-sources/prometheus/configure/azure-authentication/", + }) + }) + + t.Run("should not return failure when prometheus datasource does not use deprecated auth", func(t *testing.T) { + jsonData := simplejson.New() + datasources := []*datasources.DataSource{ + {UID: "valid-uid-1", Type: "prometheus", Name: "Prometheus", JsonData: jsonData}, + } + mockDatasourceSvc := &MockDatasourceSvc{dss: datasources} + mockPluginContextProvider := &MockPluginContextProvider{pCtx: backend.PluginContext{}} + mockPluginClient := &MockPluginClient{res: &backend.CheckHealthResult{Status: backend.HealthStatusOk}} + mockPluginRepo := &MockPluginRepo{plugins: []repo.PluginInfo{ + {ID: 1, Slug: "prometheus", Status: "active"}, + }} + mockPluginStore := &MockPluginStore{exists: true} + + check := &check{ + DatasourceSvc: mockDatasourceSvc, + PluginContextProvider: mockPluginContextProvider, + PluginClient: mockPluginClient, + PluginRepo: mockPluginRepo, + PluginStore: mockPluginStore, + GrafanaVersion: "11.0.0", + } + + failures, err := runChecks(check) + assert.NoError(t, err) + assert.Empty(t, failures) + }) } func TestCheck_Item(t *testing.T) { diff --git a/apps/advisor/pkg/app/checks/datasourcecheck/prom_dep_auth_check_step.go b/apps/advisor/pkg/app/checks/datasourcecheck/prom_dep_auth_check_step.go new file mode 100644 index 00000000000..bc9dd1d0db1 --- /dev/null +++ b/apps/advisor/pkg/app/checks/datasourcecheck/prom_dep_auth_check_step.go @@ -0,0 +1,147 @@ +package datasourcecheck + +import ( + "context" + "fmt" + + "github.com/grafana/grafana-app-sdk/logging" + advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1" + "github.com/grafana/grafana/apps/advisor/pkg/app/checks" + "github.com/grafana/grafana/pkg/services/datasources" +) + +type promDepAuthStep struct { + canBeInstalled func(ctx context.Context, pluginType string) (bool, error) +} + +func (s *promDepAuthStep) Title() string { + return "Prometheus deprecated authentication check" +} + +func (s *promDepAuthStep) Description() string { + return "Check if Prometheus data sources are using deprecated authentication methods (Azure auth and SigV4)" +} + +func (s *promDepAuthStep) Resolution() string { + return fmt.Sprintf("Enable the feature toggle for 'prometheusTypeMigration'. If this feature toggle is already enabled, make sure that 'Azure Monitor Managed Service for Prometheus' and/or 'Amazon Managed Service for Prometheus' plugins are installed. If the data source is provisioned, edit data source type in the provisioning file to use '%s' or '%s'.", datasources.DS_AMAZON_PROMETHEUS, datasources.DS_AZURE_PROMETHEUS) +} + +func (s *promDepAuthStep) ID() string { + return PromDepAuthStepID +} + +func (s *promDepAuthStep) Run(ctx context.Context, log logging.Logger, obj *advisor.CheckSpec, item any) ([]advisor.CheckReportFailure, error) { + dataSource, ok := item.(*datasources.DataSource) + if !ok { + return nil, fmt.Errorf("invalid item type %T", item) + } + if dataSource.Type != datasources.DS_PROMETHEUS { + return nil, nil + } + if dataSource.JsonData == nil { + return nil, nil + } + + awsAuthLinks, err := s.checkUsingAWSAuth(ctx, dataSource) + if err != nil { + return nil, err + } + azureAuthLinks, err := s.checkUsingAzureAuth(ctx, dataSource) + if err != nil { + return nil, err + } + + errorLinks := append(awsAuthLinks, azureAuthLinks...) + + if len(errorLinks) == 0 { + return nil, nil + } + + return []advisor.CheckReportFailure{checks.NewCheckReportFailureWithMoreInfo( + advisor.CheckReportFailureSeverityHigh, + s.ID(), + dataSource.Name, + dataSource.UID, + errorLinks, + fmt.Sprintf("Datasource %s (UID: %s) is of type %s but it's using a deprecated authentication method so it should be migrated", dataSource.Name, dataSource.UID, dataSource.Type), + )}, nil +} + +func (s *promDepAuthStep) checkUsingAWSAuth(ctx context.Context, dataSource *datasources.DataSource) ([]advisor.CheckErrorLink, error) { + var errorLinks []advisor.CheckErrorLink + if sigV4Auth, found := dataSource.JsonData.CheckGet("sigV4Auth"); found { + if enabled, err := sigV4Auth.Bool(); err != nil || !enabled { + // Disabled or not a valid boolean + return nil, nil + } + readOnlyLink := checkReadOnly(dataSource) + + if readOnlyLink != nil { + errorLinks = append(errorLinks, *readOnlyLink) + } + + errorLinks = append(errorLinks, + advisor.CheckErrorLink{ + Message: "View SigV4 docs", + Url: "https://grafana.com/docs/grafana-cloud/connect-externally-hosted/data-sources/prometheus/configure/aws-authentication/", + }) + pluginLink := s.linkDataSource(ctx, datasources.DS_AMAZON_PROMETHEUS, "Amazon Managed Service for Prometheus") + if pluginLink != nil { + errorLinks = append(errorLinks, *pluginLink) + } + } + return errorLinks, nil +} + +func (s *promDepAuthStep) checkUsingAzureAuth(ctx context.Context, dataSource *datasources.DataSource) ([]advisor.CheckErrorLink, error) { + var errorLinks []advisor.CheckErrorLink + if azureAuth, found := dataSource.JsonData.CheckGet("azureCredentials"); found { + if _, err := azureAuth.Value(); err != nil { + // azureAuth does not have a value + return nil, nil + } + readOnlyLink := checkReadOnly(dataSource) + if readOnlyLink != nil { + errorLinks = append(errorLinks, *readOnlyLink) + } + errorLinks = append(errorLinks, + advisor.CheckErrorLink{ + Message: "View Azure auth docs", + Url: "https://grafana.com/docs/grafana-cloud/connect-externally-hosted/data-sources/prometheus/configure/azure-authentication/", + }) + pluginLink := s.linkDataSource(ctx, datasources.DS_AZURE_PROMETHEUS, "Azure Monitor Managed Service for Prometheus") + if pluginLink != nil { + errorLinks = append(errorLinks, *pluginLink) + } + } + return errorLinks, nil +} + +func checkReadOnly(dataSource *datasources.DataSource) *advisor.CheckErrorLink { + if readOnly, found := dataSource.JsonData.CheckGet("readonly"); found { + if enabled, err := readOnly.Bool(); err != nil || !enabled { + // Disabled or not a valid boolean + return nil + } + return &advisor.CheckErrorLink{ + Message: "Change provisioning file", + Url: "https://grafana.com/docs/grafana/latest/administration/provisioning/#data-sources", + } + } + return nil +} + +func (s *promDepAuthStep) linkDataSource(ctx context.Context, pluginType string, pluginName string) *advisor.CheckErrorLink { + canBeInstalled, err := s.canBeInstalled(ctx, pluginType) + if err != nil { + return nil + } + if canBeInstalled { + // Plugin is available in the repo + return &advisor.CheckErrorLink{ + Message: fmt.Sprintf("Install %s", pluginName), + Url: fmt.Sprintf("/plugins/%s", pluginType), + } + } + return nil +} diff --git a/apps/advisor/pkg/app/checkscheduler/checkscheduler.go b/apps/advisor/pkg/app/checkscheduler/checkscheduler.go index 2b337239cb6..6860d79ece5 100644 --- a/apps/advisor/pkg/app/checkscheduler/checkscheduler.go +++ b/apps/advisor/pkg/app/checkscheduler/checkscheduler.go @@ -23,21 +23,22 @@ const defaultEvaluationInterval = 7 * 24 * time.Hour // 7 days const defaultMaxHistory = 10 var ( - waitInterval = 5 * time.Second - waitMaxRetries = 3 + waitInterval = 5 * time.Second + waitMaxRetries = 3 + evalIntervalRandomVariation = 1 * time.Hour ) // Runner is a "runnable" app used to be able to expose and API endpoint // with the existing checks types. This does not need to be a CRUD resource, but it is // the only way existing at the moment to expose the check types. type Runner struct { - checkRegistry checkregistry.CheckService - client resource.Client - typesClient resource.Client - evaluationInterval time.Duration - maxHistory int - namespace string - log logging.Logger + checkRegistry checkregistry.CheckService + checksClient resource.Client + typesClient resource.Client + defaultEvalInterval time.Duration + maxHistory int + namespace string + log logging.Logger } // NewRunner creates a new Runner. @@ -73,13 +74,13 @@ func New(cfg app.Config, log logging.Logger) (app.Runnable, error) { } return &Runner{ - checkRegistry: checkRegistry, - client: client, - typesClient: typesClient, - evaluationInterval: evalInterval, - maxHistory: maxHistory, - namespace: namespace, - log: log.With("runner", "advisor.checkscheduler"), + checkRegistry: checkRegistry, + checksClient: client, + typesClient: typesClient, + defaultEvalInterval: evalInterval, + maxHistory: maxHistory, + namespace: namespace, + log: log.With("runner", "advisor.checkscheduler"), }, nil } @@ -91,47 +92,47 @@ func (r *Runner) Run(ctx context.Context) error { lastCreated, err := r.checkLastCreated(ctxWithoutCancel, logger) if err != nil { logger.Error("Error getting last check creation time", "error", err) - // Wait for interval to create the next scheduled check - lastCreated = time.Now() - } else { - // do an initial creation if necessary - if lastCreated.IsZero() { - err = r.createChecks(ctxWithoutCancel, logger) - if err != nil { - logger.Error("Error creating new check reports", "error", err) - } else { - lastCreated = time.Now() - } - } else { - // Run an initial cleanup to remove old checks - err = r.cleanupChecks(ctxWithoutCancel, logger) - if err != nil { - logger.Error("Error cleaning up old check reports", "error", err) - } + return err + } + // If there are checks already created, run an initial cleanup to remove old checks + if !lastCreated.IsZero() { + err = r.cleanupChecks(ctxWithoutCancel, logger) + if err != nil { + logger.Error("Error cleaning up old check reports", "error", err) + return err } } - nextSendInterval := getNextSendInterval(lastCreated, r.evaluationInterval) - ticker := time.NewTicker(nextSendInterval) + nextEvalTime := r.getNextEvalTime(r.defaultEvalInterval, lastCreated) + ticker := time.NewTicker(nextEvalTime) defer ticker.Stop() for { select { case <-ticker.C: - err = r.createChecks(ctxWithoutCancel, logger) + lastCreated, err := r.checkLastCreated(ctxWithoutCancel, logger) if err != nil { - logger.Error("Error creating new check reports", "error", err) + logger.Error("Error getting last check creation time", "error", err) + return err } - err = r.cleanupChecks(ctxWithoutCancel, logger) - if err != nil { - logger.Error("Error cleaning up old check reports", "error", err) + // If there are checks already created, then we can automatically create more + if !lastCreated.IsZero() { + err = r.createChecks(ctxWithoutCancel, logger) + if err != nil { + logger.Error("Error creating new check reports", "error", err) + } + + // Clean up old checks to avoid going over the limit + err = r.cleanupChecks(ctxWithoutCancel, logger) + if err != nil { + logger.Error("Error cleaning up old check reports", "error", err) + } } - if nextSendInterval != r.evaluationInterval { - nextSendInterval = r.evaluationInterval - } - ticker.Reset(nextSendInterval) + // Reset the ticker to the next send interval + nextEvalTime = r.getNextEvalTime(r.defaultEvalInterval, lastCreated) + ticker.Reset(nextEvalTime) case <-ctx.Done(): return ctx.Err() } @@ -139,7 +140,7 @@ func (r *Runner) Run(ctx context.Context) error { } func (r *Runner) listChecks(ctx context.Context, logger logging.Logger) ([]resource.Object, error) { - list, err := r.client.List(ctx, r.namespace, resource.ListOptions{ + list, err := r.checksClient.List(ctx, r.namespace, resource.ListOptions{ Limit: 1000, // Avoid pagination for normal uses cases, which is a costly operation }) if err != nil { @@ -149,7 +150,7 @@ func (r *Runner) listChecks(ctx context.Context, logger logging.Logger) ([]resou checks := list.GetItems() for list.GetContinue() != "" { logger.Debug("List has continue token, listing next page", "continue", list.GetContinue()) - list, err = r.client.List(ctx, r.namespace, resource.ListOptions{Continue: list.GetContinue(), Limit: 1000}) + list, err = r.checksClient.List(ctx, r.namespace, resource.ListOptions{Continue: list.GetContinue(), Limit: 1000}) if err != nil { return nil, err } @@ -177,7 +178,7 @@ func (r *Runner) checkLastCreated(ctx context.Context, log logging.Logger) (time // If the check is unprocessed, set it to error if checks.GetStatusAnnotation(item) == "" { log.Info("Check is unprocessed, marking as error", "check", item.GetStaticMetadata().Identifier()) - err := checks.SetStatusAnnotation(ctx, r.client, item, checks.StatusAnnotationError) + err := checks.SetStatusAnnotation(ctx, r.checksClient, item, checks.StatusAnnotationError) if err != nil { log.Error("Error setting check status to error", "error", err) } @@ -225,7 +226,7 @@ func (r *Runner) createChecks(ctx context.Context, logger logging.Logger) error Spec: advisorv0alpha1.CheckSpec{}, } id := obj.GetStaticMetadata().Identifier() - _, err := r.client.Create(ctx, id, obj, resource.CreateOptions{}) + _, err := r.checksClient.Create(ctx, id, obj, resource.CreateOptions{}) if err != nil { return fmt.Errorf("error creating check: %w", err) } @@ -268,7 +269,7 @@ func (r *Runner) cleanupChecks(ctx context.Context, logger logging.Logger) error for i := 0; i < len(checks)-r.maxHistory; i++ { check := checks[i] id := check.GetStaticMetadata().Identifier() - err := r.client.Delete(ctx, id, resource.DeleteOptions{}) + err := r.checksClient.Delete(ctx, id, resource.DeleteOptions{}) if err != nil { return fmt.Errorf("error deleting check: %w", err) } @@ -293,15 +294,25 @@ func getEvaluationInterval(pluginConfig map[string]string) (time.Duration, error return evaluationInterval, nil } -func getNextSendInterval(lastCreated time.Time, evaluationInterval time.Duration) time.Duration { - nextSendInterval := time.Until(lastCreated.Add(evaluationInterval)) - // Add random variation of one hour - randomVariation := time.Duration(rand.Int63n(time.Hour.Nanoseconds())) - nextSendInterval += randomVariation - if nextSendInterval < time.Minute { - nextSendInterval = 1 * time.Minute +func (r *Runner) getNextEvalTime(defaultEvaluationInterval time.Duration, lastCreated time.Time) time.Duration { + nextEvalTime := defaultEvaluationInterval + + baseTime := lastCreated + if lastCreated.IsZero() { + baseTime = time.Now() } - return nextSendInterval + + // Calculate the next evaluation time and add random variation + nextEvalTime = time.Until(baseTime.Add(nextEvalTime)) + randomVariation := time.Duration(rand.Int63n(evalIntervalRandomVariation.Nanoseconds())) + nextEvalTime += randomVariation + + // Ensure we always return a positive duration to avoid ticker panics + if nextEvalTime <= 0 { + nextEvalTime = 1 * time.Millisecond + } + + return nextEvalTime } func getMaxHistory(pluginConfig map[string]string) (int, error) { diff --git a/apps/advisor/pkg/app/checkscheduler/checkscheduler_test.go b/apps/advisor/pkg/app/checkscheduler/checkscheduler_test.go index de522be7adc..ce44dc07c29 100644 --- a/apps/advisor/pkg/app/checkscheduler/checkscheduler_test.go +++ b/apps/advisor/pkg/app/checkscheduler/checkscheduler_test.go @@ -4,26 +4,49 @@ import ( "context" "errors" "fmt" - "math/rand/v2" "testing" "time" "github.com/grafana/grafana-app-sdk/logging" "github.com/grafana/grafana-app-sdk/resource" advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1" + "github.com/grafana/grafana/apps/advisor/pkg/app/checkregistry" "github.com/grafana/grafana/apps/advisor/pkg/app/checks" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func init() { + waitInterval = 1 * time.Millisecond + evalIntervalRandomVariation = 1 * time.Millisecond +} + +// TestRunner_Run tests the main Run function with various scenarios func TestRunner_Run(t *testing.T) { - t.Run("does not crash when error on list", func(t *testing.T) { + t.Run("handles context cancellation gracefully", func(t *testing.T) { + runner := createTestRunner(&MockClient{}, &MockClient{}) + + ctx, cancel := context.WithCancel(context.Background()) + cancel() // Cancel immediately + + err := runner.Run(ctx) + assert.ErrorAs(t, err, &context.Canceled) + }) + + t.Run("handles timeout gracefully", func(t *testing.T) { + runner := createTestRunner(&MockClient{}, &MockClient{}) + + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond) + defer cancel() + + err := runner.Run(ctx) + assert.ErrorAs(t, err, &context.DeadlineExceeded) + }) + + t.Run("handles check list error gracefully", func(t *testing.T) { mockClient := &MockClient{ listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { - return nil, errors.New("list error") - }, - createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) { - return &advisorv0alpha1.Check{}, nil + return nil, errors.New("list checks error") }, } @@ -33,352 +56,287 @@ func TestRunner_Run(t *testing.T) { }, } - runner := &Runner{ - client: mockClient, - typesClient: mockTypesClient, - log: &logging.NoOpLogger{}, - evaluationInterval: 1 * time.Hour, - } - - ctx, cancel := context.WithCancel(context.Background()) - cancel() - err := runner.Run(ctx) - assert.ErrorAs(t, err, &context.Canceled) + runner := createTestRunner(mockClient, mockTypesClient) + err := runner.Run(context.Background()) + assert.ErrorContains(t, err, "list checks error") }) } -func TestRunner_checkLastCreated_ErrorOnList(t *testing.T) { - mockClient := &MockClient{ - listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { - return nil, errors.New("list error") - }, - } +// TestRunner_Run_CheckCreation tests check creation scenarios +func TestRunner_Run_CheckCreation(t *testing.T) { + t.Run("does not create checks on first run when no previous checks exist", func(t *testing.T) { + checksCreated := []string{} - runner := &Runner{ - client: mockClient, - log: &logging.NoOpLogger{}, - } + mockClient := &MockClient{ + listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { + // Return empty list - no previous checks + return &advisorv0alpha1.CheckList{Items: []advisorv0alpha1.Check{}}, nil + }, + createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) { + checksCreated = append(checksCreated, id.Name) + return obj, nil + }, + } - lastCreated, err := runner.checkLastCreated(context.Background(), &logging.NoOpLogger{}) - assert.Error(t, err) - assert.True(t, lastCreated.IsZero()) -} - -func TestRunner_checkLastCreated_UnprocessedCheck(t *testing.T) { - patchOperation := resource.PatchOperation{} - identifier := resource.Identifier{} - - mockClient := &MockClient{ - listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { - return &advisorv0alpha1.CheckList{ - Items: []advisorv0alpha1.Check{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "check-1", + mockTypesClient := &MockClient{ + listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { + return &advisorv0alpha1.CheckTypeList{ + Items: []advisorv0alpha1.CheckType{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-check", + }, + Spec: advisorv0alpha1.CheckTypeSpec{ + Name: "test-check", + }, }, }, - }, - }, nil - }, - patchFunc: func(ctx context.Context, id resource.Identifier, patch resource.PatchRequest, options resource.PatchOptions, into resource.Object) error { - patchOperation = patch.Operations[0] - identifier = id - return nil - }, - } + }, nil + }, + } - runner := &Runner{ - client: mockClient, - log: &logging.NoOpLogger{}, - } + // Create a mock check service with one check to match the check type + mockCheckService := &MockCheckService{checks: []checks.Check{&mockCheck{id: "test-check"}}} + runner := createTestRunnerWithRegistry(mockClient, mockTypesClient, mockCheckService) - lastCreated, err := runner.checkLastCreated(context.Background(), &logging.NoOpLogger{}) - assert.NoError(t, err) - assert.True(t, lastCreated.IsZero()) - assert.Equal(t, "check-1", identifier.Name) - assert.Equal(t, "/metadata/annotations", patchOperation.Path) - expectedAnnotations := map[string]string{ - checks.StatusAnnotation: "error", - } - assert.Equal(t, expectedAnnotations, patchOperation.Value) -} + err := runAndTimeout(runner) + assert.ErrorAs(t, err, &context.DeadlineExceeded) + // Should not create checks on first run when no previous checks exist + assert.Empty(t, checksCreated, "Should not create checks on first run when no previous checks exist") + }) -func TestRunner_checkLastCreated_PaginatedResponse(t *testing.T) { - // Create checks with different creation times - past := time.Now().Add(-1 * time.Hour) - now := time.Now() + t.Run("creates checks when evaluation interval has passed", func(t *testing.T) { + checksCreated := []string{} - mockClient := &MockClient{ - listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { - if options.Continue == "" { - // First page - return oldest and middle checks with continue token + mockClient := &MockClient{ + listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { + // Return a check that was created long ago (past the evaluation interval) return &advisorv0alpha1.CheckList{ - ListMeta: metav1.ListMeta{ - Continue: "continue-token-123", - }, Items: []advisorv0alpha1.Check{ { ObjectMeta: metav1.ObjectMeta{ - Name: "check-1", - CreationTimestamp: metav1.NewTime(past), + Name: "old-check", + CreationTimestamp: metav1.NewTime(time.Now().Add(-15 * 24 * time.Hour)), // 15 days ago Annotations: map[string]string{ - checks.StatusAnnotation: "completed", - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "check-2", - CreationTimestamp: metav1.NewTime(past), - Annotations: map[string]string{ - checks.StatusAnnotation: "completed", + checks.StatusAnnotation: checks.StatusAnnotationProcessed, }, }, }, }, }, nil - } - // Second page - verify continue token is passed and return newest check - assert.Equal(t, "continue-token-123", options.Continue) - return &advisorv0alpha1.CheckList{ - Items: []advisorv0alpha1.Check{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "check-3", - CreationTimestamp: metav1.NewTime(now), - Annotations: map[string]string{ - checks.StatusAnnotation: "completed", + }, + createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) { + checksCreated = append(checksCreated, id.Name) + return obj, nil + }, + } + + mockTypesClient := &MockClient{ + listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { + return &advisorv0alpha1.CheckTypeList{ + Items: []advisorv0alpha1.CheckType{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-check", + }, + Spec: advisorv0alpha1.CheckTypeSpec{ + Name: "test-check", }, }, }, - }, - }, nil - }, - } + }, nil + }, + } - runner := &Runner{ - client: mockClient, - log: &logging.NoOpLogger{}, - } + // Create a mock check service with one check to match the check type + mockCheckService := &MockCheckService{checks: []checks.Check{&mockCheck{id: "test-check"}}} + runner := createTestRunnerWithRegistry(mockClient, mockTypesClient, mockCheckService) - lastCreated, err := runner.checkLastCreated(context.Background(), &logging.NoOpLogger{}) - assert.NoError(t, err) - assert.Equal(t, now.Truncate(time.Second), lastCreated.Truncate(time.Second)) + err := runAndTimeout(runner) + assert.ErrorAs(t, err, &context.DeadlineExceeded) + // Should create checks when the evaluation interval has passed + assert.Greater(t, len(checksCreated), 0, "Should create checks when evaluation interval has passed") + }) } -func TestRunner_createChecks_ErrorOnCreate(t *testing.T) { - mockCheckService := &MockCheckService{checks: []checks.Check{&mockCheck{id: "check-1"}}} +// TestRunner_Run_CheckCleanup tests check cleanup scenarios +func TestRunner_Run_CheckCleanup(t *testing.T) { + t.Run("cleans up old checks when limit exceeded", func(t *testing.T) { + checksDeleted := []string{} - mockClient := &MockClient{ - createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) { - return nil, errors.New("create error") - }, - } + // Create checks that exceed the max history limit + items := make([]advisorv0alpha1.Check, 0, defaultMaxHistory+2) + for i := 0; i < defaultMaxHistory+2; i++ { + item := advisorv0alpha1.Check{} + item.SetName(fmt.Sprintf("check-%d", i)) + item.SetLabels(map[string]string{ + checks.TypeLabel: "test-type", + }) + item.SetCreationTimestamp(metav1.NewTime(time.Now().Add(-time.Duration(i) * time.Hour))) + items = append(items, item) + } - mockTypesClient := &MockClient{ - listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { - checkType := &advisorv0alpha1.CheckType{} - checkType.Spec.Name = "check-1" - return &advisorv0alpha1.CheckTypeList{ - Items: []advisorv0alpha1.CheckType{*checkType}, - }, nil - }, - } + mockClient := &MockClient{ + listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { + return &advisorv0alpha1.CheckList{Items: items}, nil + }, + deleteFunc: func(ctx context.Context, id resource.Identifier, opts resource.DeleteOptions) error { + checksDeleted = append(checksDeleted, id.Name) + return nil + }, + } - runner := &Runner{ - checkRegistry: mockCheckService, - client: mockClient, - typesClient: mockTypesClient, - log: &logging.NoOpLogger{}, - } + mockTypesClient := &MockClient{ + listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { + return &advisorv0alpha1.CheckTypeList{Items: []advisorv0alpha1.CheckType{}}, nil + }, + } - err := runner.createChecks(context.Background(), &logging.NoOpLogger{}) - assert.Error(t, err) + runner := createTestRunner(mockClient, mockTypesClient) + + err := runAndTimeout(runner) + assert.ErrorAs(t, err, &context.DeadlineExceeded) + // Should delete some checks due to cleanup + assert.Greater(t, len(checksDeleted), 0) + }) } -func TestRunner_createChecks_Success(t *testing.T) { - mockCheckService := &MockCheckService{checks: []checks.Check{&mockCheck{id: "check-1"}}} +// TestRunner_Run_UnprocessedChecks tests handling of unprocessed checks +func TestRunner_Run_UnprocessedChecks(t *testing.T) { + t.Run("marks unprocessed checks as error", func(t *testing.T) { + patchOperations := []resource.PatchOperation{} - mockClient := &MockClient{ - createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) { - return &advisorv0alpha1.Check{}, nil - }, - } + mockClient := &MockClient{ + listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { + return &advisorv0alpha1.CheckList{ + Items: []advisorv0alpha1.Check{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "unprocessed-check", + // No status annotation - unprocessed + }, + }, + }, + }, nil + }, + patchFunc: func(ctx context.Context, id resource.Identifier, patch resource.PatchRequest, options resource.PatchOptions, into resource.Object) error { + patchOperations = append(patchOperations, patch.Operations...) + return nil + }, + } - mockTypesClient := &MockClient{ - listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { - checkType := &advisorv0alpha1.CheckType{} - checkType.Spec.Name = "check-1" - return &advisorv0alpha1.CheckTypeList{ - Items: []advisorv0alpha1.CheckType{*checkType}, - }, nil - }, - } + mockTypesClient := &MockClient{ + listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { + return &advisorv0alpha1.CheckTypeList{Items: []advisorv0alpha1.CheckType{}}, nil + }, + } - runner := &Runner{ - checkRegistry: mockCheckService, - client: mockClient, - typesClient: mockTypesClient, - log: &logging.NoOpLogger{}, - } + runner := createTestRunner(mockClient, mockTypesClient) - err := runner.createChecks(context.Background(), &logging.NoOpLogger{}) - assert.NoError(t, err) + err := runAndTimeout(runner) + assert.ErrorAs(t, err, &context.DeadlineExceeded) + // Should patch unprocessed check with error status + assert.Greater(t, len(patchOperations), 0) + }) } -func TestRunner_cleanupChecks_ErrorOnList(t *testing.T) { - mockClient := &MockClient{ - listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { - return nil, errors.New("list error") - }, - } +// TestRunner_Run_Pagination tests pagination handling +func TestRunner_Run_Pagination(t *testing.T) { + t.Run("handles paginated check lists", func(t *testing.T) { + callCount := 0 - runner := &Runner{ - client: mockClient, - log: &logging.NoOpLogger{}, - } + mockClient := &MockClient{ + listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { + callCount++ + if callCount == 1 { + return &advisorv0alpha1.CheckList{ + ListMeta: metav1.ListMeta{Continue: "continue-token"}, + Items: []advisorv0alpha1.Check{ + {ObjectMeta: metav1.ObjectMeta{Name: "check-1"}}, + }, + }, nil + } + return &advisorv0alpha1.CheckList{ + Items: []advisorv0alpha1.Check{ + {ObjectMeta: metav1.ObjectMeta{Name: "check-2"}}, + }, + }, nil + }, + } - err := runner.cleanupChecks(context.Background(), &logging.NoOpLogger{}) - assert.Error(t, err) + mockTypesClient := &MockClient{ + listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { + return &advisorv0alpha1.CheckTypeList{Items: []advisorv0alpha1.CheckType{}}, nil + }, + } + + runner := createTestRunner(mockClient, mockTypesClient) + + err := runAndTimeout(runner) + assert.ErrorAs(t, err, &context.DeadlineExceeded) + // Should handle pagination correctly + assert.GreaterOrEqual(t, callCount, 2) + }) } -func TestRunner_cleanupChecks_WithinMax(t *testing.T) { - mockClient := &MockClient{ - listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { - return &advisorv0alpha1.CheckList{ - Items: []advisorv0alpha1.Check{{}, {}}, - }, nil - }, - deleteFunc: func(ctx context.Context, identifier resource.Identifier, options resource.DeleteOptions) error { - return fmt.Errorf("shouldn't be called") - }, - } +// Helper functions - runner := &Runner{ - client: mockClient, - log: &logging.NoOpLogger{}, - } - - err := runner.cleanupChecks(context.Background(), &logging.NoOpLogger{}) - assert.NoError(t, err) +// runAndTimeout runs a runner with a short timeout for testing purposes. +// This is used to terminate the runner's infinite loop in tests that don't specifically test timeout behavior. +func runAndTimeout(runner *Runner) error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond) + defer cancel() + return runner.Run(ctx) } -func TestRunner_cleanupChecks_ErrorOnDelete(t *testing.T) { - mockClient := &MockClient{ - listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { - items := make([]advisorv0alpha1.Check, 0, defaultMaxHistory+1) - for i := 0; i < defaultMaxHistory+1; i++ { - item := advisorv0alpha1.Check{} - item.SetLabels(map[string]string{ - checks.TypeLabel: "mock", - }) - items = append(items, item) - } - return &advisorv0alpha1.CheckList{ - Items: items, - }, nil - }, - deleteFunc: func(ctx context.Context, identifier resource.Identifier, options resource.DeleteOptions) error { - return errors.New("delete error") - }, - } - - runner := &Runner{ - client: mockClient, - maxHistory: defaultMaxHistory, - log: &logging.NoOpLogger{}, - } - err := runner.cleanupChecks(context.Background(), &logging.NoOpLogger{}) - assert.ErrorContains(t, err, "delete error") +// createTestRunner creates a test runner with mock clients +func createTestRunner(checkClient, typesClient *MockClient) *Runner { + return createTestRunnerWithRegistry(checkClient, typesClient, &MockCheckService{checks: []checks.Check{}}) } -func TestRunner_cleanupChecks_Success(t *testing.T) { - itemsDeleted := []string{} - items := make([]advisorv0alpha1.Check, 0, defaultMaxHistory+1) - for i := 0; i < defaultMaxHistory+1; i++ { - item := advisorv0alpha1.Check{} - item.SetName(fmt.Sprintf("check-%d", i)) - item.SetLabels(map[string]string{ - checks.TypeLabel: "mock", - }) - item.SetCreationTimestamp(metav1.NewTime(time.Time{}.Add(time.Duration(i) * time.Hour))) - items = append(items, item) +// createTestRunnerWithRegistry creates a test runner with mock clients and custom registry +func createTestRunnerWithRegistry(checkClient, typesClient *MockClient, checkRegistry checkregistry.CheckService) *Runner { + // Ensure mock clients have default implementations + if checkClient.listFunc == nil { + checkClient.listFunc = func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { + return &advisorv0alpha1.CheckList{Items: []advisorv0alpha1.Check{}}, nil + } } - // shuffle the items to ensure the oldest are deleted - rand.Shuffle(len(items), func(i, j int) { items[i], items[j] = items[j], items[i] }) - - mockClient := &MockClient{ - listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { - return &advisorv0alpha1.CheckList{ - Items: items, - }, nil - }, - deleteFunc: func(ctx context.Context, identifier resource.Identifier, options resource.DeleteOptions) error { - itemsDeleted = append(itemsDeleted, identifier.Name) + if checkClient.createFunc == nil { + checkClient.createFunc = func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) { + return obj, nil + } + } + if checkClient.deleteFunc == nil { + checkClient.deleteFunc = func(ctx context.Context, id resource.Identifier, opts resource.DeleteOptions) error { return nil - }, + } + } + if checkClient.patchFunc == nil { + checkClient.patchFunc = func(ctx context.Context, id resource.Identifier, patch resource.PatchRequest, opts resource.PatchOptions, into resource.Object) error { + return nil + } } - runner := &Runner{ - client: mockClient, - maxHistory: defaultMaxHistory, - log: &logging.NoOpLogger{}, + if typesClient.listFunc == nil { + typesClient.listFunc = func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) { + // Return empty list to match the empty MockCheckService + return &advisorv0alpha1.CheckTypeList{Items: []advisorv0alpha1.CheckType{}}, nil + } + } + + return &Runner{ + checkRegistry: checkRegistry, + checksClient: checkClient, + typesClient: typesClient, + defaultEvalInterval: 5 * time.Millisecond, + maxHistory: defaultMaxHistory, + namespace: "test-namespace", + log: &logging.NoOpLogger{}, } - err := runner.cleanupChecks(context.Background(), &logging.NoOpLogger{}) - assert.NoError(t, err) - assert.Equal(t, []string{"check-0"}, itemsDeleted) } -func Test_getEvaluationInterval(t *testing.T) { - t.Run("default", func(t *testing.T) { - interval, err := getEvaluationInterval(map[string]string{}) - assert.NoError(t, err) - assert.Equal(t, 7*24*time.Hour, interval) - }) - - t.Run("invalid", func(t *testing.T) { - interval, err := getEvaluationInterval(map[string]string{"evaluation_interval": "invalid"}) - assert.Error(t, err) - assert.Zero(t, interval) - }) - - t.Run("custom", func(t *testing.T) { - interval, err := getEvaluationInterval(map[string]string{"evaluation_interval": "1h"}) - assert.NoError(t, err) - assert.Equal(t, time.Hour, interval) - }) -} - -func Test_getMaxHistory(t *testing.T) { - t.Run("default", func(t *testing.T) { - history, err := getMaxHistory(map[string]string{}) - assert.NoError(t, err) - assert.Equal(t, 10, history) - }) - - t.Run("invalid", func(t *testing.T) { - history, err := getMaxHistory(map[string]string{"max_history": "invalid"}) - assert.Error(t, err) - assert.Zero(t, history) - }) - - t.Run("custom", func(t *testing.T) { - history, err := getMaxHistory(map[string]string{"max_history": "5"}) - assert.NoError(t, err) - assert.Equal(t, 5, history) - }) -} - -func Test_getNextSendInterval(t *testing.T) { - lastCreated := time.Now().Add(-7 * 24 * time.Hour) - evaluationInterval := 7 * 24 * time.Hour - nextSendInterval := getNextSendInterval(lastCreated, evaluationInterval) - // The next send interval should be in < 1 hour - assert.True(t, nextSendInterval < time.Hour) - // Calculate the next send interval again and it should be different - nextSendInterval2 := getNextSendInterval(lastCreated, evaluationInterval) - assert.NotEqual(t, nextSendInterval, nextSendInterval2) -} +// Mock implementations type MockClient struct { resource.Client @@ -414,7 +372,6 @@ func (m *MockCheckService) Checks() []checks.Check { type mockCheck struct { checks.Check - id string steps []checks.Step } diff --git a/apps/alerting/alertenrichment/go.mod b/apps/alerting/alertenrichment/go.mod index 48c93f1aa1e..d3b81c48e8e 100644 --- a/apps/alerting/alertenrichment/go.mod +++ b/apps/alerting/alertenrichment/go.mod @@ -1,9 +1,9 @@ module github.com/grafana/grafana/apps/alerting/alertenrichment -go 1.24.6 +go 1.25.3 require ( - github.com/grafana/grafana-app-sdk v0.46.0 + github.com/grafana/grafana-app-sdk v0.47.0 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250901080157-a0280d701b28 k8s.io/apimachinery v0.34.1 k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b @@ -26,9 +26,9 @@ require ( github.com/x448/float16 v0.8.4 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/text v0.29.0 // indirect - google.golang.org/protobuf v1.36.9 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/text v0.30.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/apps/alerting/alertenrichment/go.sum b/apps/alerting/alertenrichment/go.sum index ead26b4a7b0..019274e24b7 100644 --- a/apps/alerting/alertenrichment/go.sum +++ b/apps/alerting/alertenrichment/go.sum @@ -21,8 +21,8 @@ github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7O github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/grafana/grafana-app-sdk v0.46.0 h1:gvzQvCQgZJ/73BfAcbDt/6TAMhnVikVPxZt/UwDl+oc= -github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250901080157-a0280d701b28 h1:PgMfX4OPENz/iXmtDDIW9+poZY4UD0hhmXm7flVclDo= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250901080157-a0280d701b28/go.mod h1:av5N0Naq+8VV9MLF7zAkihy/mVq5UbS2EvRSJukDHlY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -71,8 +71,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -81,8 +81,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -91,8 +91,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/apps/alerting/notifications/go.mod b/apps/alerting/notifications/go.mod index f811c12d2f8..c888277737d 100644 --- a/apps/alerting/notifications/go.mod +++ b/apps/alerting/notifications/go.mod @@ -1,10 +1,10 @@ module github.com/grafana/grafana/apps/alerting/notifications -go 1.24.6 +go 1.25.3 require ( - github.com/grafana/grafana-app-sdk v0.46.0 - github.com/grafana/grafana-app-sdk/logging v0.45.0 + github.com/grafana/grafana-app-sdk v0.47.0 + github.com/grafana/grafana-app-sdk/logging v0.46.0 k8s.io/apimachinery v0.34.1 k8s.io/apiserver v0.34.1 k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b @@ -83,18 +83,18 @@ require ( go.uber.org/zap v1.27.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.13.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect - google.golang.org/grpc v1.75.1 // indirect - google.golang.org/protobuf v1.36.9 // indirect + google.golang.org/grpc v1.76.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/apps/alerting/notifications/go.sum b/apps/alerting/notifications/go.sum index 9166be2eae7..ea68beb1e85 100644 --- a/apps/alerting/notifications/go.sum +++ b/apps/alerting/notifications/go.sum @@ -69,10 +69,10 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= -github.com/grafana/grafana-app-sdk v0.46.0 h1:gvzQvCQgZJ/73BfAcbDt/6TAMhnVikVPxZt/UwDl+oc= -github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= -github.com/grafana/grafana-app-sdk/logging v0.45.0 h1:0SH6nYZpiLBZRwUq4J6+1vo8xuHKJjnO95/2pGOoA8w= -github.com/grafana/grafana-app-sdk/logging v0.45.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= +github.com/grafana/grafana-app-sdk/logging v0.46.0 h1:JhQ+ZK5orcmM+dZ3YZdT9uCizJEFU2I6JBNUSFWvCC8= +github.com/grafana/grafana-app-sdk/logging v0.46.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0= @@ -234,11 +234,11 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -256,8 +256,8 @@ golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -282,10 +282,10 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/apps/alerting/notifications/pkg/apis/alertingnotifications_manifest.go b/apps/alerting/notifications/pkg/apis/alertingnotifications_manifest.go index 84850cb31a1..97b11485dd1 100644 --- a/apps/alerting/notifications/pkg/apis/alertingnotifications_manifest.go +++ b/apps/alerting/notifications/pkg/apis/alertingnotifications_manifest.go @@ -14,6 +14,7 @@ import ( "github.com/grafana/grafana-app-sdk/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kube-openapi/pkg/spec3" + "k8s.io/kube-openapi/pkg/validation/spec" v0alpha1 "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1" ) @@ -77,6 +78,7 @@ var appManifestData = app.ManifestData{ Routes: app.ManifestVersionRoutes{ Namespaced: map[string]spec3.PathProps{}, Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{}, }, }, }, diff --git a/apps/alerting/rules/go.mod b/apps/alerting/rules/go.mod index 7678f821f3a..c8bbbeed938 100644 --- a/apps/alerting/rules/go.mod +++ b/apps/alerting/rules/go.mod @@ -1,10 +1,10 @@ module github.com/grafana/grafana/apps/alerting/rules -go 1.24.4 +go 1.25.3 require ( - github.com/grafana/grafana-app-sdk v0.46.0 - github.com/grafana/grafana-app-sdk/logging v0.45.0 + github.com/grafana/grafana-app-sdk v0.47.0 + github.com/grafana/grafana-app-sdk/logging v0.46.0 k8s.io/apimachinery v0.34.1 k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b ) @@ -66,18 +66,18 @@ require ( go.opentelemetry.io/proto/otlp v1.7.1 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.13.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect - google.golang.org/grpc v1.75.1 // indirect - google.golang.org/protobuf v1.36.9 // indirect + google.golang.org/grpc v1.76.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.34.1 // indirect diff --git a/apps/alerting/rules/go.sum b/apps/alerting/rules/go.sum index dadd72070fd..eb6cf0ee83d 100644 --- a/apps/alerting/rules/go.sum +++ b/apps/alerting/rules/go.sum @@ -46,10 +46,10 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grafana/grafana-app-sdk v0.46.0 h1:gvzQvCQgZJ/73BfAcbDt/6TAMhnVikVPxZt/UwDl+oc= -github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= -github.com/grafana/grafana-app-sdk/logging v0.45.0 h1:0SH6nYZpiLBZRwUq4J6+1vo8xuHKJjnO95/2pGOoA8w= -github.com/grafana/grafana-app-sdk/logging v0.45.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= +github.com/grafana/grafana-app-sdk/logging v0.46.0 h1:JhQ+ZK5orcmM+dZ3YZdT9uCizJEFU2I6JBNUSFWvCC8= +github.com/grafana/grafana-app-sdk/logging v0.46.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -161,10 +161,10 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -179,8 +179,8 @@ golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -201,10 +201,10 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 h1: google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090/go.mod h1:U8EXRNSd8sUYyDfs/It7KVWodQr+Hf9xtxyxWudSwEw= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/apps/alerting/rules/pkg/apis/alerting_manifest.go b/apps/alerting/rules/pkg/apis/alerting_manifest.go index ea4f2530948..5057a58c6e6 100644 --- a/apps/alerting/rules/pkg/apis/alerting_manifest.go +++ b/apps/alerting/rules/pkg/apis/alerting_manifest.go @@ -14,6 +14,7 @@ import ( "github.com/grafana/grafana-app-sdk/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kube-openapi/pkg/spec3" + "k8s.io/kube-openapi/pkg/validation/spec" v0alpha1 "github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1" ) @@ -66,6 +67,7 @@ var appManifestData = app.ManifestData{ Routes: app.ManifestVersionRoutes{ Namespaced: map[string]spec3.PathProps{}, Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{}, }, }, }, diff --git a/apps/correlations/go.mod b/apps/correlations/go.mod index 2f6538b879d..1856670c3cd 100644 --- a/apps/correlations/go.mod +++ b/apps/correlations/go.mod @@ -1,12 +1,10 @@ module github.com/grafana/grafana/apps/correlations -go 1.24.0 - -toolchain go1.24.6 +go 1.25.3 require ( - github.com/grafana/grafana-app-sdk v0.46.0 - github.com/grafana/grafana-app-sdk/logging v0.45.0 + github.com/grafana/grafana-app-sdk v0.47.0 + github.com/grafana/grafana-app-sdk/logging v0.46.0 k8s.io/apimachinery v0.34.1 k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b ) @@ -68,18 +66,18 @@ require ( go.opentelemetry.io/proto/otlp v1.7.1 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.13.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect - google.golang.org/grpc v1.75.1 // indirect - google.golang.org/protobuf v1.36.9 // indirect + google.golang.org/grpc v1.76.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.34.1 // indirect diff --git a/apps/correlations/go.sum b/apps/correlations/go.sum index dadd72070fd..eb6cf0ee83d 100644 --- a/apps/correlations/go.sum +++ b/apps/correlations/go.sum @@ -46,10 +46,10 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grafana/grafana-app-sdk v0.46.0 h1:gvzQvCQgZJ/73BfAcbDt/6TAMhnVikVPxZt/UwDl+oc= -github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= -github.com/grafana/grafana-app-sdk/logging v0.45.0 h1:0SH6nYZpiLBZRwUq4J6+1vo8xuHKJjnO95/2pGOoA8w= -github.com/grafana/grafana-app-sdk/logging v0.45.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= +github.com/grafana/grafana-app-sdk/logging v0.46.0 h1:JhQ+ZK5orcmM+dZ3YZdT9uCizJEFU2I6JBNUSFWvCC8= +github.com/grafana/grafana-app-sdk/logging v0.46.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -161,10 +161,10 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -179,8 +179,8 @@ golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -201,10 +201,10 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 h1: google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090/go.mod h1:U8EXRNSd8sUYyDfs/It7KVWodQr+Hf9xtxyxWudSwEw= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/apps/correlations/kinds/correlations.cue b/apps/correlations/kinds/correlations.cue index a0ffd13250a..4089057859f 100644 --- a/apps/correlations/kinds/correlations.cue +++ b/apps/correlations/kinds/correlations.cue @@ -5,15 +5,17 @@ correlationsv0alpha1: { pluralName: "Correlations" schema: { spec: { - source_ds_ref: DataSourceRef - target_ds_ref?: DataSourceRef - label: string + type: CorrelationType + source: DataSourceRef + target?: DataSourceRef description?: string - config: ConfigSpec - provisioned: bool - type: CorrelationType + label: string + config: ConfigSpec } } + selectableFields: [ + "spec.datasource.name" + ] } DataSourceRef: { @@ -32,7 +34,7 @@ ConfigSpec: { TargetSpec: [string]: _ TransformationSpec: { - type: string + type: "regex" | "logfmt" expression: string field: string mapValue: string diff --git a/apps/correlations/pkg/apis/correlation/v0alpha1/correlation_spec_gen.go b/apps/correlations/pkg/apis/correlation/v0alpha1/correlation_spec_gen.go index 8156317f1cb..e5ff4460c11 100644 --- a/apps/correlations/pkg/apis/correlation/v0alpha1/correlation_spec_gen.go +++ b/apps/correlations/pkg/apis/correlation/v0alpha1/correlation_spec_gen.go @@ -2,6 +2,14 @@ package v0alpha1 +// +k8s:openapi-gen=true +type CorrelationCorrelationType string + +const ( + CorrelationCorrelationTypeQuery CorrelationCorrelationType = "query" + CorrelationCorrelationTypeExternal CorrelationCorrelationType = "external" +) + // +k8s:openapi-gen=true type CorrelationDataSourceRef struct { // same as pluginId @@ -33,10 +41,10 @@ type CorrelationTargetSpec map[string]interface{} // +k8s:openapi-gen=true type CorrelationTransformationSpec struct { - Type string `json:"type"` - Expression string `json:"expression"` - Field string `json:"field"` - MapValue string `json:"mapValue"` + Type CorrelationTransformationSpecType `json:"type"` + Expression string `json:"expression"` + Field string `json:"field"` + MapValue string `json:"mapValue"` } // NewCorrelationTransformationSpec creates a new CorrelationTransformationSpec object. @@ -44,29 +52,28 @@ func NewCorrelationTransformationSpec() *CorrelationTransformationSpec { return &CorrelationTransformationSpec{} } -// +k8s:openapi-gen=true -type CorrelationCorrelationType string - -const ( - CorrelationCorrelationTypeQuery CorrelationCorrelationType = "query" - CorrelationCorrelationTypeExternal CorrelationCorrelationType = "external" -) - // +k8s:openapi-gen=true type CorrelationSpec struct { - SourceDsRef CorrelationDataSourceRef `json:"source_ds_ref"` - TargetDsRef *CorrelationDataSourceRef `json:"target_ds_ref,omitempty"` - Label string `json:"label"` - Description *string `json:"description,omitempty"` - Config CorrelationConfigSpec `json:"config"` - Provisioned bool `json:"provisioned"` Type CorrelationCorrelationType `json:"type"` + Source CorrelationDataSourceRef `json:"source"` + Target *CorrelationDataSourceRef `json:"target,omitempty"` + Description *string `json:"description,omitempty"` + Label string `json:"label"` + Config CorrelationConfigSpec `json:"config"` } // NewCorrelationSpec creates a new CorrelationSpec object. func NewCorrelationSpec() *CorrelationSpec { return &CorrelationSpec{ - SourceDsRef: *NewCorrelationDataSourceRef(), - Config: *NewCorrelationConfigSpec(), + Source: *NewCorrelationDataSourceRef(), + Config: *NewCorrelationConfigSpec(), } } + +// +k8s:openapi-gen=true +type CorrelationTransformationSpecType string + +const ( + CorrelationTransformationSpecTypeRegex CorrelationTransformationSpecType = "regex" + CorrelationTransformationSpecTypeLogfmt CorrelationTransformationSpecType = "logfmt" +) diff --git a/apps/correlations/pkg/apis/correlation_manifest.go b/apps/correlations/pkg/apis/correlation_manifest.go index 3a784903323..b1ba6356786 100644 --- a/apps/correlations/pkg/apis/correlation_manifest.go +++ b/apps/correlations/pkg/apis/correlation_manifest.go @@ -14,12 +14,13 @@ import ( "github.com/grafana/grafana-app-sdk/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kube-openapi/pkg/spec3" + "k8s.io/kube-openapi/pkg/validation/spec" v0alpha1 "github.com/grafana/grafana/apps/correlations/pkg/apis/correlation/v0alpha1" ) var ( - rawSchemaCorrelationv0alpha1 = []byte(`{"ConfigSpec":{"additionalProperties":false,"description":"there was a deprecated field here called type, we will need to move that for conversion and provisioning","properties":{"field":{"type":"string"},"target":{"$ref":"#/components/schemas/TargetSpec"},"transformations":{"items":{"$ref":"#/components/schemas/TransformationSpec"},"type":"array"}},"required":["field","target"],"type":"object"},"Correlation":{"properties":{"spec":{"$ref":"#/components/schemas/spec"}},"required":["spec"]},"CorrelationType":{"enum":["query","external"],"type":"string"},"DataSourceRef":{"additionalProperties":false,"properties":{"group":{"description":"same as pluginId","type":"string"},"name":{"description":"same as grafana uid","type":"string"}},"required":["group","name"],"type":"object"},"TargetSpec":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"},"TransformationSpec":{"additionalProperties":false,"properties":{"expression":{"type":"string"},"field":{"type":"string"},"mapValue":{"type":"string"},"type":{"type":"string"}},"required":["type","expression","field","mapValue"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"config":{"$ref":"#/components/schemas/ConfigSpec"},"description":{"type":"string"},"label":{"type":"string"},"provisioned":{"type":"boolean"},"source_ds_ref":{"$ref":"#/components/schemas/DataSourceRef"},"target_ds_ref":{"$ref":"#/components/schemas/DataSourceRef"},"type":{"$ref":"#/components/schemas/CorrelationType"}},"required":["source_ds_ref","label","config","provisioned","type"],"type":"object"}}`) + rawSchemaCorrelationv0alpha1 = []byte(`{"ConfigSpec":{"additionalProperties":false,"description":"there was a deprecated field here called type, we will need to move that for conversion and provisioning","properties":{"field":{"type":"string"},"target":{"$ref":"#/components/schemas/TargetSpec"},"transformations":{"items":{"$ref":"#/components/schemas/TransformationSpec"},"type":"array"}},"required":["field","target"],"type":"object"},"Correlation":{"properties":{"spec":{"$ref":"#/components/schemas/spec"}},"required":["spec"]},"CorrelationType":{"enum":["query","external"],"type":"string"},"DataSourceRef":{"additionalProperties":false,"properties":{"group":{"description":"same as pluginId","type":"string"},"name":{"description":"same as grafana uid","type":"string"}},"required":["group","name"],"type":"object"},"TargetSpec":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"},"TransformationSpec":{"additionalProperties":false,"properties":{"expression":{"type":"string"},"field":{"type":"string"},"mapValue":{"type":"string"},"type":{"enum":["regex","logfmt"],"type":"string"}},"required":["type","expression","field","mapValue"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"config":{"$ref":"#/components/schemas/ConfigSpec"},"description":{"type":"string"},"label":{"type":"string"},"source":{"$ref":"#/components/schemas/DataSourceRef"},"target":{"$ref":"#/components/schemas/DataSourceRef"},"type":{"$ref":"#/components/schemas/CorrelationType"}},"required":["type","source","label","config"],"type":"object"}}`) versionSchemaCorrelationv0alpha1 app.VersionSchema _ = json.Unmarshal(rawSchemaCorrelationv0alpha1, &versionSchemaCorrelationv0alpha1) ) @@ -39,11 +40,15 @@ var appManifestData = app.ManifestData{ Scope: "Namespaced", Conversion: false, Schema: &versionSchemaCorrelationv0alpha1, + SelectableFields: []string{ + "spec.datasource.name", + }, }, }, Routes: app.ManifestVersionRoutes{ Namespaced: map[string]spec3.PathProps{}, Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{}, }, }, }, diff --git a/apps/correlations/plugin/src/generated/correlation/v0alpha1/types.spec.gen.ts b/apps/correlations/plugin/src/generated/correlation/v0alpha1/types.spec.gen.ts index 0fa0d2a8e2e..720937480e9 100644 --- a/apps/correlations/plugin/src/generated/correlation/v0alpha1/types.spec.gen.ts +++ b/apps/correlations/plugin/src/generated/correlation/v0alpha1/types.spec.gen.ts @@ -1,5 +1,12 @@ // Code generated - EDITING IS FUTILE. DO NOT EDIT. +export enum CorrelationType { + Query = "query", + External = "external", +} + +export const defaultCorrelationType = (): CorrelationType => (CorrelationType.Query); + export interface DataSourceRef { // same as pluginId group: string; @@ -29,41 +36,32 @@ export type TargetSpec = Record; export const defaultTargetSpec = (): TargetSpec => ({}); export interface TransformationSpec { - type: string; + type: "regex" | "logfmt"; expression: string; field: string; mapValue: string; } export const defaultTransformationSpec = (): TransformationSpec => ({ - type: "", + type: "regex", expression: "", field: "", mapValue: "", }); -export enum CorrelationType { - Query = "query", - External = "external", -} - -export const defaultCorrelationType = (): CorrelationType => (CorrelationType.Query); - export interface Spec { - source_ds_ref: DataSourceRef; - target_ds_ref?: DataSourceRef; - label: string; - description?: string; - config: ConfigSpec; - provisioned: boolean; type: CorrelationType; + source: DataSourceRef; + target?: DataSourceRef; + description?: string; + label: string; + config: ConfigSpec; } export const defaultSpec = (): Spec => ({ - source_ds_ref: defaultDataSourceRef(), + type: CorrelationType.Query, + source: defaultDataSourceRef(), label: "", config: defaultConfigSpec(), - provisioned: false, - type: CorrelationType.Query, }); diff --git a/apps/dashboard/go.mod b/apps/dashboard/go.mod index adfae61e8d1..b4173d312c7 100644 --- a/apps/dashboard/go.mod +++ b/apps/dashboard/go.mod @@ -1,17 +1,17 @@ module github.com/grafana/grafana/apps/dashboard -go 1.24.6 +go 1.25.3 require ( cuelang.org/go v0.11.1 github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 - github.com/grafana/grafana-app-sdk v0.46.0 - github.com/grafana/grafana-app-sdk/logging v0.45.0 + github.com/grafana/grafana-app-sdk v0.47.0 + github.com/grafana/grafana-app-sdk/logging v0.46.0 github.com/grafana/grafana-plugin-sdk-go v0.279.0 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e github.com/prometheus/client_golang v1.23.2 github.com/stretchr/testify v1.11.1 - golang.org/x/net v0.44.0 + golang.org/x/net v0.45.0 k8s.io/apimachinery v0.34.1 k8s.io/apiserver v0.34.1 k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b @@ -54,7 +54,7 @@ require ( github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f // indirect github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 // indirect github.com/grafana/otel-profiling-go v0.5.1 // indirect - github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect @@ -106,10 +106,9 @@ require ( github.com/zeebo/xxh3 v1.0.2 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.62.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect - go.opentelemetry.io/contrib/propagators/jaeger v1.37.0 // indirect - go.opentelemetry.io/contrib/samplers/jaegerremote v0.31.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.63.0 // indirect + go.opentelemetry.io/contrib/propagators/jaeger v1.38.0 // indirect + go.opentelemetry.io/contrib/samplers/jaegerremote v0.32.0 // indirect go.opentelemetry.io/otel v1.38.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect @@ -122,19 +121,19 @@ require ( golang.org/x/crypto v0.42.0 // indirect golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect golang.org/x/mod v0.28.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 // indirect golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.13.0 // indirect golang.org/x/tools v0.37.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect - google.golang.org/grpc v1.75.1 // indirect - google.golang.org/protobuf v1.36.9 // indirect + google.golang.org/grpc v1.76.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/apps/dashboard/go.sum b/apps/dashboard/go.sum index 4358d7d815a..c8217a3939e 100644 --- a/apps/dashboard/go.sum +++ b/apps/dashboard/go.sum @@ -101,18 +101,18 @@ github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 h1:qEwZ+7MbP github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37/go.mod h1:qeWYbnWzaYGl88JlL9+DsP1GT2Cudm58rLtx13fKZdw= github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 h1:jSojuc7njleS3UOz223WDlXOinmuLAIPI0z2vtq8EgI= github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4/go.mod h1:VahT+GtfQIM+o8ht2StR6J9g+Ef+C2Vokh5uuSmOD/4= -github.com/grafana/grafana-app-sdk v0.46.0 h1:gvzQvCQgZJ/73BfAcbDt/6TAMhnVikVPxZt/UwDl+oc= -github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= -github.com/grafana/grafana-app-sdk/logging v0.45.0 h1:0SH6nYZpiLBZRwUq4J6+1vo8xuHKJjnO95/2pGOoA8w= -github.com/grafana/grafana-app-sdk/logging v0.45.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= +github.com/grafana/grafana-app-sdk/logging v0.46.0 h1:JhQ+ZK5orcmM+dZ3YZdT9uCizJEFU2I6JBNUSFWvCC8= +github.com/grafana/grafana-app-sdk/logging v0.46.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= github.com/grafana/grafana-plugin-sdk-go v0.279.0 h1:/KCrsZkj9pEGwIGovqAz1A8rjI2A2YT+ZpvgfZN0LAA= github.com/grafana/grafana-plugin-sdk-go v0.279.0/go.mod h1:/7oGN6Z7DGTGaLHhgIYrRr6Wvmdsb3BLw5hL4Kbjy88= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e h1:BTKk7LHuG1kmAkucwTA7DuMbKpKvJTKrGdBmUNO4dfQ= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e/go.mod h1:IA4SOwun8QyST9c5UNs/fN37XL6boXXDvRYFcFwbipg= github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8= github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls= -github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= -github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= +github.com/grafana/pyroscope-go/godeltaprof v0.1.9 h1:c1Us8i6eSmkW+Ez05d3co8kasnuOY813tbMN8i/a3Og= +github.com/grafana/pyroscope-go/godeltaprof v0.1.9/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0= @@ -285,14 +285,14 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.62.0 h1:wCeciVlAfb5DC8MQl/DlmAv/FVPNpQgFvI/71+hatuc= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.62.0/go.mod h1:WfEApdZDMlLUAev/0QQpr8EJ/z0VWDKYZ5tF5RH5T1U= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.63.0 h1:2pn7OzMewmYRiNtv1doZnLo3gONcnMHlFnmOR8Vgt+8= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.63.0/go.mod h1:rjbQTDEPQymPE0YnRQp9/NuPwwtL0sesz/fnqRW/v84= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= -go.opentelemetry.io/contrib/propagators/jaeger v1.37.0 h1:pW+qDVo0jB0rLsNeaP85xLuz20cvsECUcN7TE+D8YTM= -go.opentelemetry.io/contrib/propagators/jaeger v1.37.0/go.mod h1:x7bd+t034hxLTve1hF9Yn9qQJlO/pP8H5pWIt7+gsFM= -go.opentelemetry.io/contrib/samplers/jaegerremote v0.31.0 h1:l8XCsDh7L6Z7PB+vlw1s4ufNab+ayT2RMNdvDE/UyPc= -go.opentelemetry.io/contrib/samplers/jaegerremote v0.31.0/go.mod h1:XAOSk4bqj5vtoiY08bexeiafzxdXeLlxKFnwscvn8Fc= +go.opentelemetry.io/contrib/propagators/jaeger v1.38.0 h1:nXGeLvT1QtCAhkASkP/ksjkTKZALIaQBIW+JSIw1KIc= +go.opentelemetry.io/contrib/propagators/jaeger v1.38.0/go.mod h1:oMvOXk78ZR3KEuPMBgp/ThAMDy9ku/eyUVztr+3G6Wo= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.32.0 h1:oPW/SRFyHgIgxrvNhSBzqvZER2N5kRlci3/rGTOuyWo= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.32.0/go.mod h1:B9Oka5QVD0bnmZNO6gBbBta6nohD/1Z+f9waH2oXyBs= go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= @@ -334,10 +334,10 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -362,8 +362,8 @@ golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -384,10 +384,10 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 h1: google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090/go.mod h1:U8EXRNSd8sUYyDfs/It7KVWodQr+Hf9xtxyxWudSwEw= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/apps/dashboard/kinds/dashboard.cue b/apps/dashboard/kinds/dashboard.cue index 905b9606336..e8dfea3bf98 100644 --- a/apps/dashboard/kinds/dashboard.cue +++ b/apps/dashboard/kinds/dashboard.cue @@ -27,6 +27,9 @@ ConversionStatus: { // The version which was stored when the dashboard was created / updated. // Fetching this version should always succeed. storedVersion?: string + + // The original value map[string]any + source?: _ } dashboard: { diff --git a/apps/dashboard/kinds/v2beta1/dashboard_spec.cue b/apps/dashboard/kinds/v2beta1/dashboard_spec.cue index fe9d13de67f..f0278fc431c 100644 --- a/apps/dashboard/kinds/v2beta1/dashboard_spec.cue +++ b/apps/dashboard/kinds/v2beta1/dashboard_spec.cue @@ -710,9 +710,9 @@ VariableCustomFormatterFn: { // `custom`: Define the variable options manually using a comma-separated list. // `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables VariableType: "query" | "adhoc" | "groupby" | "constant" | "datasource" | "interval" | "textbox" | "custom" | - "system" | "snapshot" + "system" | "snapshot" | "switch" -VariableKind: QueryVariableKind | TextVariableKind | ConstantVariableKind | DatasourceVariableKind | IntervalVariableKind | CustomVariableKind | GroupByVariableKind | AdhocVariableKind +VariableKind: QueryVariableKind | TextVariableKind | ConstantVariableKind | DatasourceVariableKind | IntervalVariableKind | CustomVariableKind | GroupByVariableKind | AdhocVariableKind | SwitchVariableKind // Sort variable options // Accepted values are: @@ -904,6 +904,22 @@ CustomVariableKind: { spec: CustomVariableSpec } +SwitchVariableSpec: { + name: string | *"" + current: string | *"false" + enabledValue: string | *"true" + disabledValue: string | *"false" + label?: string + hide: VariableHide + skipUrlSync: bool | *false + description?: string +} + +SwitchVariableKind: { + kind: "SwitchVariable" + spec: SwitchVariableSpec +} + // GroupBy variable specification GroupByVariableSpec: { name: string | *"" diff --git a/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_kind.cue b/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_kind.cue index fb971b2cc3f..526ddba3bfc 100644 --- a/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_kind.cue +++ b/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_kind.cue @@ -364,8 +364,9 @@ lineage: schemas: [{ // `textbox`: Display a free text input field with an optional default value. // `custom`: Define the variable options manually using a comma-separated list. // `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables + // `switch`: Boolean variables rendered as a switch #VariableType: "query" | "adhoc" | "groupby" | "constant" | "datasource" | "interval" | "textbox" | "custom" | - "system" | "snapshot" @cuetsy(kind="type") @grafanamaturity(NeedsExpertReview) + "system" | "snapshot" | "switch" @cuetsy(kind="type") @grafanamaturity(NeedsExpertReview) // Color mode for a field. You can specify a single color, or select a continuous (gradient) color schemes, based on a value. // Continuous color interpolates a color using the percentage of a value relative to min and max. diff --git a/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_status_gen.go b/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_status_gen.go index 2dec6aea951..1db6c8e3467 100644 --- a/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_status_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_status_gen.go @@ -15,6 +15,8 @@ type DashboardConversionStatus struct { // The version which was stored when the dashboard was created / updated. // Fetching this version should always succeed. StoredVersion *string `json:"storedVersion,omitempty"` + // The original value map[string]any + Source interface{} `json:"source,omitempty"` } // NewDashboardConversionStatus creates a new DashboardConversionStatus object. diff --git a/apps/dashboard/pkg/apis/dashboard/v0alpha1/zz_generated.openapi.go b/apps/dashboard/pkg/apis/dashboard/v0alpha1/zz_generated.openapi.go index 0027a8b8cc4..63af5e26b7e 100644 --- a/apps/dashboard/pkg/apis/dashboard/v0alpha1/zz_generated.openapi.go +++ b/apps/dashboard/pkg/apis/dashboard/v0alpha1/zz_generated.openapi.go @@ -272,6 +272,13 @@ func schema_pkg_apis_dashboard_v0alpha1_DashboardConversionStatus(ref common.Ref Format: "", }, }, + "source": { + SchemaProps: spec.SchemaProps{ + Description: "The original value map[string]any", + Type: []string{"object"}, + Format: "", + }, + }, }, Required: []string{"failed"}, }, diff --git a/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_kind.cue b/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_kind.cue index fb971b2cc3f..526ddba3bfc 100644 --- a/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_kind.cue +++ b/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_kind.cue @@ -364,8 +364,9 @@ lineage: schemas: [{ // `textbox`: Display a free text input field with an optional default value. // `custom`: Define the variable options manually using a comma-separated list. // `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables + // `switch`: Boolean variables rendered as a switch #VariableType: "query" | "adhoc" | "groupby" | "constant" | "datasource" | "interval" | "textbox" | "custom" | - "system" | "snapshot" @cuetsy(kind="type") @grafanamaturity(NeedsExpertReview) + "system" | "snapshot" | "switch" @cuetsy(kind="type") @grafanamaturity(NeedsExpertReview) // Color mode for a field. You can specify a single color, or select a continuous (gradient) color schemes, based on a value. // Continuous color interpolates a color using the percentage of a value relative to min and max. diff --git a/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_status_gen.go b/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_status_gen.go index a2ac9850b09..5fa18c8f821 100644 --- a/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_status_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_status_gen.go @@ -15,6 +15,8 @@ type DashboardConversionStatus struct { // The version which was stored when the dashboard was created / updated. // Fetching this version should always succeed. StoredVersion *string `json:"storedVersion,omitempty"` + // The original value map[string]any + Source interface{} `json:"source,omitempty"` } // NewDashboardConversionStatus creates a new DashboardConversionStatus object. diff --git a/apps/dashboard/pkg/apis/dashboard/v1beta1/zz_generated.openapi.go b/apps/dashboard/pkg/apis/dashboard/v1beta1/zz_generated.openapi.go index ab68539f1fe..be747be2ae3 100644 --- a/apps/dashboard/pkg/apis/dashboard/v1beta1/zz_generated.openapi.go +++ b/apps/dashboard/pkg/apis/dashboard/v1beta1/zz_generated.openapi.go @@ -264,6 +264,13 @@ func schema_pkg_apis_dashboard_v1beta1_DashboardConversionStatus(ref common.Refe Format: "", }, }, + "source": { + SchemaProps: spec.SchemaProps{ + Description: "The original value map[string]any", + Type: []string{"object"}, + Format: "", + }, + }, }, Required: []string{"failed"}, }, diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec_gen.go b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec_gen.go index 3f4c7d9f1f5..bb737fb8ac3 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec_gen.go @@ -1781,7 +1781,7 @@ type DashboardAdHocFilterWithLabels struct { KeyLabel *string `json:"keyLabel,omitempty"` ValueLabels []string `json:"valueLabels,omitempty"` ForceEdit *bool `json:"forceEdit,omitempty"` - Origin string `json:"origin,omitempty"` + Origin *string `json:"origin,omitempty"` // @deprecated Condition *string `json:"condition,omitempty"` } @@ -1789,7 +1789,7 @@ type DashboardAdHocFilterWithLabels struct { // NewDashboardAdHocFilterWithLabels creates a new DashboardAdHocFilterWithLabels object. func NewDashboardAdHocFilterWithLabels() *DashboardAdHocFilterWithLabels { return &DashboardAdHocFilterWithLabels{ - Origin: DashboardFilterOrigin, + Origin: (func(input string) *string { return &input })(DashboardFilterOrigin), } } diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_status_gen.go b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_status_gen.go index 9544b902dd8..6fad54db0b4 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_status_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_status_gen.go @@ -15,6 +15,8 @@ type DashboardConversionStatus struct { // The version which was stored when the dashboard was created / updated. // Fetching this version should always succeed. StoredVersion *string `json:"storedVersion,omitempty"` + // The original value map[string]any + Source interface{} `json:"source,omitempty"` } // NewDashboardConversionStatus creates a new DashboardConversionStatus object. diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi.go b/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi.go index 1c030f705c9..548a8c93268 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi.go +++ b/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi.go @@ -1353,6 +1353,13 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardConversionStatus(ref common.Ref Format: "", }, }, + "source": { + SchemaProps: spec.SchemaProps{ + Description: "The original value map[string]any", + Type: []string{"object"}, + Format: "", + }, + }, }, Required: []string{"failed"}, }, diff --git a/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec.cue b/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec.cue index 2c7d74674f2..fb46afb5c76 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec.cue +++ b/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec.cue @@ -714,9 +714,9 @@ VariableCustomFormatterFn: { // `custom`: Define the variable options manually using a comma-separated list. // `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables VariableType: "query" | "adhoc" | "groupby" | "constant" | "datasource" | "interval" | "textbox" | "custom" | - "system" | "snapshot" + "system" | "snapshot" | "switch" -VariableKind: QueryVariableKind | TextVariableKind | ConstantVariableKind | DatasourceVariableKind | IntervalVariableKind | CustomVariableKind | GroupByVariableKind | AdhocVariableKind +VariableKind: QueryVariableKind | TextVariableKind | ConstantVariableKind | DatasourceVariableKind | IntervalVariableKind | CustomVariableKind | GroupByVariableKind | AdhocVariableKind | SwitchVariableKind // Sort variable options // Accepted values are: @@ -908,6 +908,22 @@ CustomVariableKind: { spec: CustomVariableSpec } +SwitchVariableSpec: { + name: string | *"" + current: string | *"false" + enabledValue: string | *"true" + disabledValue: string | *"false" + label?: string + hide: VariableHide + skipUrlSync: bool | *false + description?: string +} + +SwitchVariableKind: { + kind: "SwitchVariable" + spec: SwitchVariableSpec +} + // GroupBy variable specification GroupByVariableSpec: { name: string | *"" diff --git a/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec_gen.go b/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec_gen.go index d43c7765f16..2ac53a7600c 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec_gen.go @@ -1198,7 +1198,7 @@ type DashboardDashboardLink struct { // If true, includes current time range in the link as query params KeepTime bool `json:"keepTime"` // Placement can be used to display the link somewhere else on the dashboard other than above the visualisations. - Placement string `json:"placement,omitempty"` + Placement *string `json:"placement,omitempty"` } // NewDashboardDashboardLink creates a new DashboardDashboardLink object. @@ -1209,7 +1209,7 @@ func NewDashboardDashboardLink() *DashboardDashboardLink { TargetBlank: false, IncludeVars: false, KeepTime: false, - Placement: DashboardDashboardLinkPlacement, + Placement: (func(input string) *string { return &input })(DashboardDashboardLinkPlacement), } } @@ -1290,11 +1290,11 @@ func NewDashboardTimeRangeOption() *DashboardTimeRangeOption { } // +k8s:openapi-gen=true -type DashboardVariableKind = DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind +type DashboardVariableKind = DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind // NewDashboardVariableKind creates a new DashboardVariableKind object. func NewDashboardVariableKind() *DashboardVariableKind { - return NewDashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind() + return NewDashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind() } // Query variable kind @@ -1785,7 +1785,7 @@ type DashboardAdHocFilterWithLabels struct { KeyLabel *string `json:"keyLabel,omitempty"` ValueLabels []string `json:"valueLabels,omitempty"` ForceEdit *bool `json:"forceEdit,omitempty"` - Origin string `json:"origin,omitempty"` + Origin *string `json:"origin,omitempty"` // @deprecated Condition *string `json:"condition,omitempty"` } @@ -1793,7 +1793,7 @@ type DashboardAdHocFilterWithLabels struct { // NewDashboardAdHocFilterWithLabels creates a new DashboardAdHocFilterWithLabels object. func NewDashboardAdHocFilterWithLabels() *DashboardAdHocFilterWithLabels { return &DashboardAdHocFilterWithLabels{ - Origin: DashboardFilterOrigin, + Origin: (func(input string) *string { return &input })(DashboardFilterOrigin), } } @@ -1815,6 +1815,44 @@ func NewDashboardMetricFindValue() *DashboardMetricFindValue { return &DashboardMetricFindValue{} } +// +k8s:openapi-gen=true +type DashboardSwitchVariableKind struct { + Kind string `json:"kind"` + Spec DashboardSwitchVariableSpec `json:"spec"` +} + +// NewDashboardSwitchVariableKind creates a new DashboardSwitchVariableKind object. +func NewDashboardSwitchVariableKind() *DashboardSwitchVariableKind { + return &DashboardSwitchVariableKind{ + Kind: "SwitchVariable", + Spec: *NewDashboardSwitchVariableSpec(), + } +} + +// +k8s:openapi-gen=true +type DashboardSwitchVariableSpec struct { + Name string `json:"name"` + Current string `json:"current"` + EnabledValue string `json:"enabledValue"` + DisabledValue string `json:"disabledValue"` + Label *string `json:"label,omitempty"` + Hide DashboardVariableHide `json:"hide"` + SkipUrlSync bool `json:"skipUrlSync"` + Description *string `json:"description,omitempty"` +} + +// NewDashboardSwitchVariableSpec creates a new DashboardSwitchVariableSpec object. +func NewDashboardSwitchVariableSpec() *DashboardSwitchVariableSpec { + return &DashboardSwitchVariableSpec{ + Name: "", + Current: "false", + EnabledValue: "true", + DisabledValue: "false", + Hide: DashboardVariableHideDontHide, + SkipUrlSync: false, + } +} + // +k8s:openapi-gen=true type DashboardSpec struct { Annotations []DashboardAnnotationQueryKind `json:"annotations"` @@ -2433,7 +2471,7 @@ func (resource *DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTab } // +k8s:openapi-gen=true -type DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind struct { +type DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind struct { QueryVariableKind *DashboardQueryVariableKind `json:"QueryVariableKind,omitempty"` TextVariableKind *DashboardTextVariableKind `json:"TextVariableKind,omitempty"` ConstantVariableKind *DashboardConstantVariableKind `json:"ConstantVariableKind,omitempty"` @@ -2442,15 +2480,16 @@ type DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasou CustomVariableKind *DashboardCustomVariableKind `json:"CustomVariableKind,omitempty"` GroupByVariableKind *DashboardGroupByVariableKind `json:"GroupByVariableKind,omitempty"` AdhocVariableKind *DashboardAdhocVariableKind `json:"AdhocVariableKind,omitempty"` + SwitchVariableKind *DashboardSwitchVariableKind `json:"SwitchVariableKind,omitempty"` } -// NewDashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind creates a new DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind object. -func NewDashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind() *DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind { - return &DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind{} +// NewDashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind creates a new DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind object. +func NewDashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind() *DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind { + return &DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind{} } -// MarshalJSON implements a custom JSON marshalling logic to encode `DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind` as JSON. -func (resource DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind) MarshalJSON() ([]byte, error) { +// MarshalJSON implements a custom JSON marshalling logic to encode `DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind` as JSON. +func (resource DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind) MarshalJSON() ([]byte, error) { if resource.QueryVariableKind != nil { return json.Marshal(resource.QueryVariableKind) } @@ -2475,12 +2514,15 @@ func (resource DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKin if resource.AdhocVariableKind != nil { return json.Marshal(resource.AdhocVariableKind) } + if resource.SwitchVariableKind != nil { + return json.Marshal(resource.SwitchVariableKind) + } return []byte("null"), nil } -// UnmarshalJSON implements a custom JSON unmarshalling logic to decode `DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind` from JSON. -func (resource *DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind) UnmarshalJSON(raw []byte) error { +// UnmarshalJSON implements a custom JSON unmarshalling logic to decode `DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind` from JSON. +func (resource *DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind) UnmarshalJSON(raw []byte) error { if raw == nil { return nil } @@ -2553,6 +2595,14 @@ func (resource *DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKi resource.QueryVariableKind = &dashboardQueryVariableKind return nil + case "SwitchVariable": + var dashboardSwitchVariableKind DashboardSwitchVariableKind + if err := json.Unmarshal(raw, &dashboardSwitchVariableKind); err != nil { + return err + } + + resource.SwitchVariableKind = &dashboardSwitchVariableKind + return nil case "TextVariable": var dashboardTextVariableKind DashboardTextVariableKind if err := json.Unmarshal(raw, &dashboardTextVariableKind); err != nil { diff --git a/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_status_gen.go b/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_status_gen.go index 62d39eb766d..a6bd3ee5e18 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_status_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_status_gen.go @@ -15,6 +15,8 @@ type DashboardConversionStatus struct { // The version which was stored when the dashboard was created / updated. // Fetching this version should always succeed. StoredVersion *string `json:"storedVersion,omitempty"` + // The original value map[string]any + Source interface{} `json:"source,omitempty"` } // NewDashboardConversionStatus creates a new DashboardConversionStatus object. diff --git a/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi.go b/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi.go index d1429c9ae7f..5e51134e80c 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi.go +++ b/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi.go @@ -14,127 +14,129 @@ import ( func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { return map[string]common.OpenAPIDefinition{ - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.AnnotationActions": schema_pkg_apis_dashboard_v2beta1_AnnotationActions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.AnnotationPermission": schema_pkg_apis_dashboard_v2beta1_AnnotationPermission(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.Dashboard": schema_pkg_apis_dashboard_v2beta1_Dashboard(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAccess": schema_pkg_apis_dashboard_v2beta1_DashboardAccess(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAction": schema_pkg_apis_dashboard_v2beta1_DashboardAction(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardActionVariable": schema_pkg_apis_dashboard_v2beta1_DashboardActionVariable(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdHocFilterWithLabels": schema_pkg_apis_dashboard_v2beta1_DashboardAdHocFilterWithLabels(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdhocVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardAdhocVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdhocVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardAdhocVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationPanelFilter": schema_pkg_apis_dashboard_v2beta1_DashboardAnnotationPanelFilter(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationQueryKind": schema_pkg_apis_dashboard_v2beta1_DashboardAnnotationQueryKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationQuerySpec": schema_pkg_apis_dashboard_v2beta1_DashboardAnnotationQuerySpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutItemKind": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutItemKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutItemSpec": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutItemSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridRepeatOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardClient": schema_pkg_apis_dashboard_v2beta1_DashboardClient(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingDataKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingDataKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingDataSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingDataSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingGroupKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingGroupKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingGroupSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingGroupSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingTimeRangeSizeKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingTimeRangeSizeKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingTimeRangeSizeSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingTimeRangeSizeSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConstantVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardConstantVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConstantVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConstantVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConversionStatus": schema_pkg_apis_dashboard_v2beta1_DashboardConversionStatus(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardCustomVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardCustomVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardCustomVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardCustomVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDashboardLink": schema_pkg_apis_dashboard_v2beta1_DashboardDashboardLink(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDataLink": schema_pkg_apis_dashboard_v2beta1_DashboardDataLink(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDataQueryKind": schema_pkg_apis_dashboard_v2beta1_DashboardDataQueryKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDataTransformerConfig": schema_pkg_apis_dashboard_v2beta1_DashboardDataTransformerConfig(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDatasourceVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardDatasourceVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDatasourceVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardDatasourceVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDynamicConfigValue": schema_pkg_apis_dashboard_v2beta1_DashboardDynamicConfigValue(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardElementReference": schema_pkg_apis_dashboard_v2beta1_DashboardElementReference(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFetchOptions": schema_pkg_apis_dashboard_v2beta1_DashboardFetchOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFieldColor": schema_pkg_apis_dashboard_v2beta1_DashboardFieldColor(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFieldConfig": schema_pkg_apis_dashboard_v2beta1_DashboardFieldConfig(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFieldConfigSource": schema_pkg_apis_dashboard_v2beta1_DashboardFieldConfigSource(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutItemKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutItemKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutItemSpec": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutItemSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGroupByVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardGroupByVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGroupByVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardGroupByVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardInfinityOptions": schema_pkg_apis_dashboard_v2beta1_DashboardInfinityOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardIntervalVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardIntervalVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardIntervalVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardIntervalVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardJSONCodec": schema_pkg_apis_dashboard_v2beta1_DashboardJSONCodec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardLibraryPanelKind": schema_pkg_apis_dashboard_v2beta1_DashboardLibraryPanelKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardLibraryPanelKindSpec": schema_pkg_apis_dashboard_v2beta1_DashboardLibraryPanelKindSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardLibraryPanelRef": schema_pkg_apis_dashboard_v2beta1_DashboardLibraryPanelRef(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardList": schema_pkg_apis_dashboard_v2beta1_DashboardList(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardMatcherConfig": schema_pkg_apis_dashboard_v2beta1_DashboardMatcherConfig(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardMetadata": schema_pkg_apis_dashboard_v2beta1_DashboardMetadata(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardMetricFindValue": schema_pkg_apis_dashboard_v2beta1_DashboardMetricFindValue(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelKind": schema_pkg_apis_dashboard_v2beta1_DashboardPanelKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelKindOrLibraryPanelKind": schema_pkg_apis_dashboard_v2beta1_DashboardPanelKindOrLibraryPanelKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelQueryKind": schema_pkg_apis_dashboard_v2beta1_DashboardPanelQueryKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelQuerySpec": schema_pkg_apis_dashboard_v2beta1_DashboardPanelQuerySpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelSpec": schema_pkg_apis_dashboard_v2beta1_DashboardPanelSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryGroupKind": schema_pkg_apis_dashboard_v2beta1_DashboardQueryGroupKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryGroupSpec": schema_pkg_apis_dashboard_v2beta1_DashboardQueryGroupSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryOptionsSpec": schema_pkg_apis_dashboard_v2beta1_DashboardQueryOptionsSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRangeMap": schema_pkg_apis_dashboard_v2beta1_DashboardRangeMap(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRegexMap": schema_pkg_apis_dashboard_v2beta1_DashboardRegexMap(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardRepeatOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardRowRepeatOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutRowKind": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutRowKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutRowSpec": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutRowSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSpec": schema_pkg_apis_dashboard_v2beta1_DashboardSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSpecialValueMap": schema_pkg_apis_dashboard_v2beta1_DashboardSpecialValueMap(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardStatus": schema_pkg_apis_dashboard_v2beta1_DashboardStatus(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardStringOrArrayOfString": schema_pkg_apis_dashboard_v2beta1_DashboardStringOrArrayOfString(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardStringOrFloat64": schema_pkg_apis_dashboard_v2beta1_DashboardStringOrFloat64(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardTabRepeatOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutTabKind": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutTabKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutTabSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutTabSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTextVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardTextVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTextVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTextVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardThreshold": schema_pkg_apis_dashboard_v2beta1_DashboardThreshold(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardThresholdsConfig": schema_pkg_apis_dashboard_v2beta1_DashboardThresholdsConfig(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTimeRangeOption": schema_pkg_apis_dashboard_v2beta1_DashboardTimeRangeOption(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTimeSettingsSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTimeSettingsSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTransformationKind": schema_pkg_apis_dashboard_v2beta1_DashboardTransformationKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1ActionStyle": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1ActionStyle(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1AdhocVariableKindDatasource": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1AdhocVariableKindDatasource(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1DataQueryKindDatasource": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1DataQueryKindDatasource(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1FieldConfigSourceOverrides": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1FieldConfigSourceOverrides(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1GroupByVariableKindDatasource": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1GroupByVariableKindDatasource(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1RangeMapOptions": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1RangeMapOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1RegexMapOptions": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1RegexMapOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1SpecialValueMapOptions": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1SpecialValueMapOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardValueMap": schema_pkg_apis_dashboard_v2beta1_DashboardValueMap(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap": schema_pkg_apis_dashboard_v2beta1_DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardValueMappingResult": schema_pkg_apis_dashboard_v2beta1_DashboardValueMappingResult(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVariableOption": schema_pkg_apis_dashboard_v2beta1_DashboardVariableOption(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVersionInfo": schema_pkg_apis_dashboard_v2beta1_DashboardVersionInfo(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVersionList": schema_pkg_apis_dashboard_v2beta1_DashboardVersionList(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVizConfigKind": schema_pkg_apis_dashboard_v2beta1_DashboardVizConfigKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVizConfigSpec": schema_pkg_apis_dashboard_v2beta1_DashboardVizConfigSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardWithAccessInfo": schema_pkg_apis_dashboard_v2beta1_DashboardWithAccessInfo(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanel": schema_pkg_apis_dashboard_v2beta1_LibraryPanel(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanelList": schema_pkg_apis_dashboard_v2beta1_LibraryPanelList(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanelSpec": schema_pkg_apis_dashboard_v2beta1_LibraryPanelSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanelStatus": schema_pkg_apis_dashboard_v2beta1_LibraryPanelStatus(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.VersionsQueryOptions": schema_pkg_apis_dashboard_v2beta1_VersionsQueryOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.AnnotationActions": schema_pkg_apis_dashboard_v2beta1_AnnotationActions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.AnnotationPermission": schema_pkg_apis_dashboard_v2beta1_AnnotationPermission(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.Dashboard": schema_pkg_apis_dashboard_v2beta1_Dashboard(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAccess": schema_pkg_apis_dashboard_v2beta1_DashboardAccess(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAction": schema_pkg_apis_dashboard_v2beta1_DashboardAction(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardActionVariable": schema_pkg_apis_dashboard_v2beta1_DashboardActionVariable(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdHocFilterWithLabels": schema_pkg_apis_dashboard_v2beta1_DashboardAdHocFilterWithLabels(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdhocVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardAdhocVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdhocVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardAdhocVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationPanelFilter": schema_pkg_apis_dashboard_v2beta1_DashboardAnnotationPanelFilter(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationQueryKind": schema_pkg_apis_dashboard_v2beta1_DashboardAnnotationQueryKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationQuerySpec": schema_pkg_apis_dashboard_v2beta1_DashboardAnnotationQuerySpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutItemKind": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutItemKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutItemSpec": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutItemSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridRepeatOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardClient": schema_pkg_apis_dashboard_v2beta1_DashboardClient(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingDataKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingDataKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingDataSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingDataSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingGroupKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingGroupKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingGroupSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingGroupSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingTimeRangeSizeKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingTimeRangeSizeKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingTimeRangeSizeSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingTimeRangeSizeSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConstantVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardConstantVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConstantVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConstantVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConversionStatus": schema_pkg_apis_dashboard_v2beta1_DashboardConversionStatus(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardCustomVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardCustomVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardCustomVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardCustomVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDashboardLink": schema_pkg_apis_dashboard_v2beta1_DashboardDashboardLink(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDataLink": schema_pkg_apis_dashboard_v2beta1_DashboardDataLink(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDataQueryKind": schema_pkg_apis_dashboard_v2beta1_DashboardDataQueryKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDataTransformerConfig": schema_pkg_apis_dashboard_v2beta1_DashboardDataTransformerConfig(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDatasourceVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardDatasourceVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDatasourceVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardDatasourceVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDynamicConfigValue": schema_pkg_apis_dashboard_v2beta1_DashboardDynamicConfigValue(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardElementReference": schema_pkg_apis_dashboard_v2beta1_DashboardElementReference(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFetchOptions": schema_pkg_apis_dashboard_v2beta1_DashboardFetchOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFieldColor": schema_pkg_apis_dashboard_v2beta1_DashboardFieldColor(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFieldConfig": schema_pkg_apis_dashboard_v2beta1_DashboardFieldConfig(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFieldConfigSource": schema_pkg_apis_dashboard_v2beta1_DashboardFieldConfigSource(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutItemKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutItemKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutItemSpec": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutItemSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGroupByVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardGroupByVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGroupByVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardGroupByVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardInfinityOptions": schema_pkg_apis_dashboard_v2beta1_DashboardInfinityOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardIntervalVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardIntervalVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardIntervalVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardIntervalVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardJSONCodec": schema_pkg_apis_dashboard_v2beta1_DashboardJSONCodec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardLibraryPanelKind": schema_pkg_apis_dashboard_v2beta1_DashboardLibraryPanelKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardLibraryPanelKindSpec": schema_pkg_apis_dashboard_v2beta1_DashboardLibraryPanelKindSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardLibraryPanelRef": schema_pkg_apis_dashboard_v2beta1_DashboardLibraryPanelRef(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardList": schema_pkg_apis_dashboard_v2beta1_DashboardList(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardMatcherConfig": schema_pkg_apis_dashboard_v2beta1_DashboardMatcherConfig(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardMetadata": schema_pkg_apis_dashboard_v2beta1_DashboardMetadata(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardMetricFindValue": schema_pkg_apis_dashboard_v2beta1_DashboardMetricFindValue(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelKind": schema_pkg_apis_dashboard_v2beta1_DashboardPanelKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelKindOrLibraryPanelKind": schema_pkg_apis_dashboard_v2beta1_DashboardPanelKindOrLibraryPanelKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelQueryKind": schema_pkg_apis_dashboard_v2beta1_DashboardPanelQueryKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelQuerySpec": schema_pkg_apis_dashboard_v2beta1_DashboardPanelQuerySpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelSpec": schema_pkg_apis_dashboard_v2beta1_DashboardPanelSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryGroupKind": schema_pkg_apis_dashboard_v2beta1_DashboardQueryGroupKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryGroupSpec": schema_pkg_apis_dashboard_v2beta1_DashboardQueryGroupSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryOptionsSpec": schema_pkg_apis_dashboard_v2beta1_DashboardQueryOptionsSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRangeMap": schema_pkg_apis_dashboard_v2beta1_DashboardRangeMap(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRegexMap": schema_pkg_apis_dashboard_v2beta1_DashboardRegexMap(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardRepeatOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardRowRepeatOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutRowKind": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutRowKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutRowSpec": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutRowSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSpec": schema_pkg_apis_dashboard_v2beta1_DashboardSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSpecialValueMap": schema_pkg_apis_dashboard_v2beta1_DashboardSpecialValueMap(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardStatus": schema_pkg_apis_dashboard_v2beta1_DashboardStatus(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardStringOrArrayOfString": schema_pkg_apis_dashboard_v2beta1_DashboardStringOrArrayOfString(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardStringOrFloat64": schema_pkg_apis_dashboard_v2beta1_DashboardStringOrFloat64(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSwitchVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardSwitchVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSwitchVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardSwitchVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardTabRepeatOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutTabKind": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutTabKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutTabSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutTabSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTextVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardTextVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTextVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTextVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardThreshold": schema_pkg_apis_dashboard_v2beta1_DashboardThreshold(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardThresholdsConfig": schema_pkg_apis_dashboard_v2beta1_DashboardThresholdsConfig(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTimeRangeOption": schema_pkg_apis_dashboard_v2beta1_DashboardTimeRangeOption(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTimeSettingsSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTimeSettingsSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTransformationKind": schema_pkg_apis_dashboard_v2beta1_DashboardTransformationKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1ActionStyle": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1ActionStyle(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1AdhocVariableKindDatasource": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1AdhocVariableKindDatasource(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1DataQueryKindDatasource": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1DataQueryKindDatasource(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1FieldConfigSourceOverrides": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1FieldConfigSourceOverrides(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1GroupByVariableKindDatasource": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1GroupByVariableKindDatasource(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1RangeMapOptions": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1RangeMapOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1RegexMapOptions": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1RegexMapOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1SpecialValueMapOptions": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1SpecialValueMapOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardValueMap": schema_pkg_apis_dashboard_v2beta1_DashboardValueMap(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap": schema_pkg_apis_dashboard_v2beta1_DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardValueMappingResult": schema_pkg_apis_dashboard_v2beta1_DashboardValueMappingResult(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVariableOption": schema_pkg_apis_dashboard_v2beta1_DashboardVariableOption(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVersionInfo": schema_pkg_apis_dashboard_v2beta1_DashboardVersionInfo(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVersionList": schema_pkg_apis_dashboard_v2beta1_DashboardVersionList(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVizConfigKind": schema_pkg_apis_dashboard_v2beta1_DashboardVizConfigKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVizConfigSpec": schema_pkg_apis_dashboard_v2beta1_DashboardVizConfigSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardWithAccessInfo": schema_pkg_apis_dashboard_v2beta1_DashboardWithAccessInfo(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanel": schema_pkg_apis_dashboard_v2beta1_LibraryPanel(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanelList": schema_pkg_apis_dashboard_v2beta1_LibraryPanelList(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanelSpec": schema_pkg_apis_dashboard_v2beta1_LibraryPanelSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanelStatus": schema_pkg_apis_dashboard_v2beta1_LibraryPanelStatus(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.VersionsQueryOptions": schema_pkg_apis_dashboard_v2beta1_VersionsQueryOptions(ref), } } @@ -1358,6 +1360,13 @@ func schema_pkg_apis_dashboard_v2beta1_DashboardConversionStatus(ref common.Refe Format: "", }, }, + "source": { + SchemaProps: spec.SchemaProps{ + Description: "The original value map[string]any", + Type: []string{"object"}, + Format: "", + }, + }, }, Required: []string{"failed"}, }, @@ -3452,7 +3461,7 @@ func schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKind(ref common.Ref } } -func schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -3498,11 +3507,16 @@ func schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKindOrTextVariableK Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdhocVariableKind"), }, }, + "SwitchVariableKind": { + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSwitchVariableKind"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdhocVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConstantVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardCustomVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDatasourceVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGroupByVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardIntervalVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTextVariableKind"}, + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdhocVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConstantVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardCustomVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDatasourceVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGroupByVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardIntervalVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSwitchVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTextVariableKind"}, } } @@ -4054,7 +4068,7 @@ func schema_pkg_apis_dashboard_v2beta1_DashboardSpec(ref common.ReferenceCallbac Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind"), + Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind"), }, }, }, @@ -4065,7 +4079,7 @@ func schema_pkg_apis_dashboard_v2beta1_DashboardSpec(ref common.ReferenceCallbac }, }, Dependencies: []string{ - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDashboardLink", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelKindOrLibraryPanelKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTimeSettingsSpec"}, + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDashboardLink", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelKindOrLibraryPanelKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTimeSettingsSpec"}, } } @@ -4174,6 +4188,101 @@ func schema_pkg_apis_dashboard_v2beta1_DashboardStringOrFloat64(ref common.Refer } } +func schema_pkg_apis_dashboard_v2beta1_DashboardSwitchVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSwitchVariableSpec"), + }, + }, + }, + Required: []string{"kind", "spec"}, + }, + }, + Dependencies: []string{ + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSwitchVariableSpec"}, + } +} + +func schema_pkg_apis_dashboard_v2beta1_DashboardSwitchVariableSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "current": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "enabledValue": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "disabledValue": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "label": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "hide": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "skipUrlSync": { + SchemaProps: spec.SchemaProps{ + Default: false, + Type: []string{"boolean"}, + Format: "", + }, + }, + "description": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"name", "current", "enabledValue", "disabledValue", "hide", "skipUrlSync"}, + }, + }, + } +} + func schema_pkg_apis_dashboard_v2beta1_DashboardTabRepeatOptions(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi_violation_exceptions.list b/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi_violation_exceptions.list index b6c9fc53fd2..5a0edf5747d 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi_violation_exceptions.list +++ b/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi_violation_exceptions.list @@ -55,14 +55,15 @@ API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/ap API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardIntervalVariableSpec,AutoMin API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardPanelKindOrLibraryPanelKind,LibraryPanelKind API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardPanelKindOrLibraryPanelKind,PanelKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,AdhocVariableKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,ConstantVariableKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,CustomVariableKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,DatasourceVariableKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,GroupByVariableKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,IntervalVariableKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,QueryVariableKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,TextVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,AdhocVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,ConstantVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,CustomVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,DatasourceVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,GroupByVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,IntervalVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,QueryVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,SwitchVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,TextVariableKind API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardStringOrArrayOfString,ArrayOfString API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardStringOrArrayOfString,String API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardStringOrFloat64,Float64 diff --git a/apps/dashboard/pkg/apis/dashboard_manifest.go b/apps/dashboard/pkg/apis/dashboard_manifest.go index 3ea4e0284b3..1409424fbe2 100644 --- a/apps/dashboard/pkg/apis/dashboard_manifest.go +++ b/apps/dashboard/pkg/apis/dashboard_manifest.go @@ -13,6 +13,7 @@ import ( "github.com/grafana/grafana-app-sdk/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kube-openapi/pkg/spec3" + "k8s.io/kube-openapi/pkg/validation/spec" v0alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1" v1beta1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1" @@ -39,6 +40,7 @@ var appManifestData = app.ManifestData{ Routes: app.ManifestVersionRoutes{ Namespaced: map[string]spec3.PathProps{}, Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{}, }, }, @@ -56,6 +58,7 @@ var appManifestData = app.ManifestData{ Routes: app.ManifestVersionRoutes{ Namespaced: map[string]spec3.PathProps{}, Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{}, }, }, @@ -73,6 +76,7 @@ var appManifestData = app.ManifestData{ Routes: app.ManifestVersionRoutes{ Namespaced: map[string]spec3.PathProps{}, Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{}, }, }, @@ -90,6 +94,7 @@ var appManifestData = app.ManifestData{ Routes: app.ManifestVersionRoutes{ Namespaced: map[string]spec3.PathProps{}, Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{}, }, }, }, diff --git a/apps/dashboard/pkg/migration/README.md b/apps/dashboard/pkg/migration/README.md index 489659ec23e..4dffadf42bb 100644 --- a/apps/dashboard/pkg/migration/README.md +++ b/apps/dashboard/pkg/migration/README.md @@ -1,10 +1,144 @@ # Dashboard migrations -This document describes the Grafana dashboard migration system, including metrics, logging, and testing infrastructure for dashboard schema migrations and API version conversions. +This document describes the Grafana dashboard migration system, focusing on conversion-level practices including metrics, logging, and testing infrastructure for API version conversions. For schema version migration implementation details, see the [SchemaVersion Migration Guide](./schemaversion/README.md). + +## Table of Contents + +- [Overview](#overview) + - [Conversion Flow](#conversion-flow-v0--v1--v2) + - [v0 to v1 Conversion](#v0-to-v1-conversion) + - [v1 to v2 Conversion](#v1-to-v2-conversion) +- [Conversion Matrix](#conversion-matrix) +- [API Versions](#api-versions) +- [Schema Versions](#schema-versions) +- [Testing](#testing) + - [Backend conversion tests](#backend-conversion-tests) + - [Frontend migration comparison tests](#frontend-migration-comparison-tests) +- [Monitoring Migrations](#monitoring-migrations) + - [Metrics](#metrics) + - [Dashboard conversion success metric](#1-dashboard-conversion-success-metric) + - [Dashboard conversion failure metric](#2-dashboard-conversion-failure-metric) + - [Error Types](#error-types) + - [Logging](#logging) + - [Log structure](#log-structure) + - [Log levels](#log-levels) + - [Implementation Details](#implementation-details) + - [Automatic instrumentation](#automatic-instrumentation) + - [Error handling](#error-handling) + - [Registration](#registration) + - [Metrics registration](#metrics-registration) + - [Available metrics](#available-metrics) +- [Related Documentation](#related-documentation) ## Overview -## Metrics +The Grafana dashboard migration system operates across three main conversion layers: + +### Conversion Flow: v0 โ†’ v1 โ†’ v2 + +``` +v0alpha1 (Legacy JSON) โ†’ v1beta1 (Migrated JSON) โ†’ v2alpha1/v2beta1 (Structured) +``` + +#### v0 to v1 Conversion: +- All schema migrations (v0-v42) are executed in the backend +- Ports the logic from DashboardMigrator and implements built-in plugin migrations for panel plugins since backend cannot load plugins +- Transforms legacy JSON dashboards to migrated JSON format +- Handles backward compatibility for older dashboard formats +- See [SchemaVersion Migration Guide](./schemaversion/README.md) for detailed instructions on creating new schema migrations + +#### v1 to v2 Conversion: +- API version conversions between different Kubernetes API versions +- Transforms JSON dashboards to structured dashboard format +- v2 schema is the stable, typed schema with proper type definitions +- Handles modern dashboard features and Kubernetes-native storage + +## Conversion Matrix + +The system supports conversions between all dashboard API versions: + +| From โ†“ / To โ†’ | v0alpha1 | v1beta1 | v2alpha1 | v2beta1 | +|---------------|----------|---------|----------|---------| +| **v0alpha1** | โœ“ | โœ“ | โœ“ | โœ“ | +| **v1beta1** | โœ“ | โœ“ | โœ“ | โœ“ | +| **v2alpha1** | โœ“ | โœ“ | โœ“ | โœ“ | +| **v2beta1** | โœ“ | โœ“ | โœ“ | โœ“ | + +Each conversion path is automatically instrumented with metrics and logging. + +## API Versions + +The supported dashboard API versions are: + +- `dashboard.grafana.app/v0alpha1` - Legacy JSON dashboard format +- `dashboard.grafana.app/v1beta1` - Migrated JSON dashboard format +- `dashboard.grafana.app/v2alpha1` - New structured dashboard format +- `dashboard.grafana.app/v2beta1` - Enhanced structured dashboard format + +## Schema Versions + +Schema versions (v13-v42) apply only to v0alpha1 and v1beta1 dashboards: + +- **Minimum supported version**: v13 +- **Latest version**: v42 +- **Migration path**: Sequential (v13โ†’v14โ†’v15...โ†’v42) + +For detailed information about creating schema version migrations, see the [SchemaVersion Migration Guide](./schemaversion/README.md). + +## Testing + +The implementation includes comprehensive test coverage for conversion-level operations: + +- **Backend conversion tests**: API version conversions with metrics validation +- **Frontend tests**: TypeScript conversion tests +- **Integration tests**: End-to-end conversion validation +- **Metrics tests**: Prometheus counter validation + +### Backend conversion tests + +The backend conversion tests validate API version conversions and metrics instrumentation: + +- **API conversion tests**: Test conversions between v0alpha1, v1beta1, v2alpha1, v2beta1 +- **Metrics validation**: Tests verify that conversion metrics are properly recorded +- **Error handling**: Tests validate error classification and logging +- **Performance**: Tests ensure conversion operations are efficient + +**Test execution:** +```bash +# All backend conversion tests +go test ./apps/dashboard/pkg/migration/conversion/... -v + +# Metrics validation tests +go test ./apps/dashboard/pkg/migration/... -run TestSchemaMigrationMetrics +``` + +### Frontend migration comparison tests + +The frontend migration comparison tests validate that backend and frontend conversion logic produce consistent results: + +- **Test methodology**: Compares backend vs frontend conversion outputs through DashboardModel integration +- **Dataset coverage**: Tests run against curated test files covering various conversion scenarios +- **Test location**: `public/app/features/dashboard/state/DashboardMigratorToBackend.test.ts` +- **Test data**: Located in `apps/dashboard/pkg/migration/testdata/input/` and `testdata/output/` + +**Test execution:** +```bash +# Frontend migration comparison tests +yarn test DashboardMigratorToBackend.test.ts +``` + +**Test approach:** +- **Frontend path**: `jsonInput โ†’ DashboardModel โ†’ DashboardMigrator โ†’ getSaveModelClone()` +- **Backend path**: `jsonInput โ†’ Backend Conversion โ†’ backendOutput โ†’ DashboardModel โ†’ getSaveModelClone()` +- **Comparison**: Direct comparison of final converted states from both paths + +For schema version migration testing details, see the [SchemaVersion Migration Guide](./schemaversion/README.md). + +## Monitoring Migrations + +The dashboard migration system provides comprehensive observability through metrics, logging, and error classification to monitor conversion operations. + +### Metrics The dashboard migration system now provides comprehensive observability through: - **Prometheus metrics** for tracking conversion success/failure rates and performance @@ -12,7 +146,7 @@ The dashboard migration system now provides comprehensive observability through: - **Automatic instrumentation** via wrapper functions that eliminate code duplication - **Error classification** to distinguish between different types of migration failures -### 1. Dashboard conversion success metric +#### 1. Dashboard conversion success metric **Metric Name:** `grafana_dashboard_migration_conversion_success_total` @@ -36,7 +170,7 @@ grafana_dashboard_migration_conversion_success_total{ } 1250 ``` -### 2. Dashboard conversion failure metric +#### 2. Dashboard conversion failure metric **Metric Name:** `grafana_dashboard_migration_conversion_failure_total` @@ -62,28 +196,28 @@ grafana_dashboard_migration_conversion_failure_total{ } 42 ``` -## Error types +### Error Types The `error_type` label classifies failures into three categories: -### 1. `conversion_error` +#### 1. `conversion_error` - General conversion failures not related to schema migration - API-level conversion issues - Programming errors in conversion functions -### 2. `schema_version_migration_error` +#### 2. `schema_version_migration_error` - Failures during individual schema version migrations (v14โ†’v15, v15โ†’v16, etc.) - Schema-specific transformation errors - Data format incompatibilities -### 3. `schema_minimum_version_error` +#### 3. `schema_minimum_version_error` - Dashboards with schema versions below the minimum supported version (< v13) - These are logged as warnings rather than errors - Indicates dashboards that cannot be migrated automatically -## Logging +### Logging -### Log structure +#### Log structure All migration logs use structured logging with consistent field names: @@ -102,9 +236,9 @@ All migration logs use structured logging with consistent field names: - `erroredConversionFunc` - Name of the conversion function that failed - `error` - The actual error message -### Log levels +#### Log levels -#### Success (DEBUG level) +##### Success (DEBUG level) ```json { "level": "debug", @@ -117,7 +251,7 @@ All migration logs use structured logging with consistent field names: } ``` -#### Conversion/Migration Error (ERROR level) +##### Conversion/Migration Error (ERROR level) ```json { "level": "error", @@ -134,7 +268,7 @@ All migration logs use structured logging with consistent field names: } ``` -#### Minimum Version Error (WARN level) +##### Minimum Version Error (WARN level) ```json { "level": "warn", @@ -151,9 +285,9 @@ All migration logs use structured logging with consistent field names: } ``` -## Implementation details +### Implementation Details -### Automatic instrumentation +#### Automatic instrumentation All dashboard conversions are automatically instrumented via the `withConversionMetrics` wrapper function: @@ -165,7 +299,7 @@ s.AddConversionFunc((*dashv0.Dashboard)(nil), (*dashv1.Dashboard)(nil), })) ``` -### Error handling +#### Error handling Custom error types provide structured error information: @@ -187,9 +321,9 @@ type ConversionError struct { } ``` -## Registration +### Registration -### Metrics registration +#### Metrics registration Metrics must be registered with Prometheus during service initialization: @@ -200,7 +334,7 @@ import "github.com/grafana/grafana/apps/dashboard/pkg/migration" migration.RegisterMetrics(prometheusRegistry) ``` -### Available metrics +#### Available metrics The following metrics are available after registration: @@ -212,86 +346,7 @@ migration.MDashboardConversionSuccessTotal migration.MDashboardConversionFailureTotal ``` -## Conversion matrix - -The system supports conversions between all dashboard API versions: - -| From โ†“ / To โ†’ | v0alpha1 | v1beta1 | v2alpha1 | v2beta1 | -|---------------|----------|---------|----------|---------| -| **v0alpha1** | โœ“ | โœ“ | โœ“ | โœ“ | -| **v1beta1** | โœ“ | โœ“ | โœ“ | โœ“ | -| **v2alpha1** | โœ“ | โœ“ | โœ“ | โœ“ | -| **v2beta1** | โœ“ | โœ“ | โœ“ | โœ“ | - -Each conversion path is automatically instrumented with metrics and logging. - -## API versions - -The supported dashboard API versions are: - -- `dashboard.grafana.app/v0alpha1` - Legacy JSON dashboard format -- `dashboard.grafana.app/v1beta1` - Migrated JSON dashboard format -- `dashboard.grafana.app/v2alpha1` - New structured dashboard format -- `dashboard.grafana.app/v2beta1` - Enhanced structured dashboard format - -## Schema versions - -Schema versions (v13-v41) apply only to v0alpha1 and v1beta1 dashboards: - -- **Minimum supported version**: v13 -- **Latest version**: v41 -- **Migration path**: Sequential (v13โ†’v14โ†’v15...โ†’v41) - -## Migration testing - -The implementation includes comprehensive test coverage: - -- **Backend tests**: Go migration tests with metrics validation -- **Frontend tests**: TypeScript conversion tests -- **Integration tests**: End-to-end conversion validation -- **Metrics tests**: Prometheus counter validation - -### Backend migration tests - -The backend migration tests validate schema version migrations and API conversions: - -- **Schema migration tests**: Test individual schema version upgrades (v14โ†’v15, v15โ†’v16, etc.) -- **Conversion tests**: Test API version conversions with automatic metrics instrumentation -- **Test data**: Uses curated test files from `testdata/input/` covering schema versions 14-41 -- **Metrics validation**: Tests verify that conversion metrics are properly recorded - -**Test execution:** -```bash -# All backend migration tests -go test ./apps/dashboard/pkg/migration/... -v - -# Schema migration tests only -go test ./apps/dashboard/pkg/migration/ -v - -# API conversion tests with metrics -go test ./apps/dashboard/pkg/migration/conversion/... -v -``` - -### Frontend migration comparison tests - -The frontend migration comparison tests validate that backend and frontend migration logic produce consistent results: - -- **Test methodology**: Compares backend vs frontend migration outputs through DashboardModel integration -- **Dataset coverage**: Tests run against 42 curated test files spanning schema versions 14-41 -- **Test location**: `public/app/features/dashboard/state/DashboardMigratorToBackend.test.ts` -- **Test data**: Located in `apps/dashboard/pkg/migration/testdata/input/` and `testdata/output/` - -**Test execution:** -```bash -# Frontend migration comparison tests -yarn test DashboardMigratorToBackend.test.ts -``` - -**Test approach:** -- **Frontend path**: `jsonInput โ†’ DashboardModel โ†’ DashboardMigrator โ†’ getSaveModelClone()` -- **Backend path**: `jsonInput โ†’ Backend Migration โ†’ backendOutput โ†’ DashboardModel โ†’ getSaveModelClone()` -- **Comparison**: Direct comparison of final migrated states from both paths - -## Related documentation +## Related Documentation +- [Schema Migration Guide](./schemaversion/README.md) - Complete guide for creating new dashboard schema migrations - [PR #110178 - Dashboard migration: Add missing metrics registration](https://github.com/grafana/grafana/pull/110178) diff --git a/apps/dashboard/pkg/migration/conversion/conversion_test.go b/apps/dashboard/pkg/migration/conversion/conversion_test.go index 9ee40f17ad7..2ea168e9522 100644 --- a/apps/dashboard/pkg/migration/conversion/conversion_test.go +++ b/apps/dashboard/pkg/migration/conversion/conversion_test.go @@ -305,23 +305,6 @@ func TestConversionMetrics(t *testing.T) { expectedSourceSchema: "v2alpha1", expectedTargetSchema: "v2beta1", }, - { - name: "v0 to v1 conversion with minimum version error (succeeds but marks failed)", - source: &dashv0.Dashboard{ - ObjectMeta: metav1.ObjectMeta{UID: "test-uid-4"}, - Spec: common.Unstructured{Object: map[string]any{ - "title": "old dashboard", - "schemaVersion": 5, // Below minimum version (13) - }}, - }, - target: &dashv1.Dashboard{}, - expectAPISuccess: true, // Conversion succeeds but status indicates failure - expectMetricsSuccess: false, - expectedSourceAPI: dashv0.APIVERSION, - expectedTargetAPI: dashv1.APIVERSION, - expectedSourceSchema: "5", - expectedTargetSchema: fmt.Sprintf("%d", 41), // LATEST_VERSION - }, } for _, tt := range tests { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v0alpha1.json index 1191a6aef3b..3306c334c5e 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v0alpha1.json @@ -15,7 +15,505 @@ "conversion": { "failed": true, "error": "backend conversion not yet implemented", - "storedVersion": "v2alpha1" + "storedVersion": "v2alpha1", + "source": { + "kind": "Dashboard", + "apiVersion": "dashboard.grafana.app/v2alpha1", + "metadata": { + "name": "test-v2alpha1-complete", + "labels": { + "category": "test" + }, + "annotations": { + "description": "Complete example of v2alpha1 dashboard features" + } + }, + "spec": { + "annotations": [ + { + "kind": "AnnotationQuery", + "spec": { + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "query": { + "kind": "grafana", + "spec": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + } + }, + "enable": true, + "hide": false, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "builtIn": true + } + }, + { + "kind": "AnnotationQuery", + "spec": { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "query": { + "kind": "prometheus", + "spec": { + "expr": "changes(process_start_time_seconds[1m])", + "refId": "Anno" + } + }, + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "Prometheus Annotations", + "builtIn": false + } + } + ], + "cursorSync": "Tooltip", + "description": "This dashboard demonstrates all features that need to be converted from v2alpha1 to v2beta1", + "editable": true, + "elements": { + "panel-1": { + "kind": "Panel", + "spec": { + "id": 1, + "title": "Panel with Conditional Rendering", + "description": "This panel demonstrates conditional rendering features", + "links": null, + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "prometheus", + "spec": { + "expr": "up{job=\"grafana\"}" + } + }, + "datasource": { + "uid": "gdev-prometheus" + }, + "refId": "A", + "hidden": false + } + } + ], + "transformations": [ + { + "kind": "reduce", + "spec": { + "id": "reduce", + "options": { + "includeTimeField": false, + "mode": "reduceFields", + "reducers": [ + "mean" + ] + } + } + } + ], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "stat", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "textMode": "auto" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "type": "value", + "options": { + "0": { + "text": "Down", + "color": "red" + }, + "1": { + "text": "Up", + "color": "green" + } + } + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "red" + }, + { + "value": 1, + "color": "green" + } + ] + }, + "color": { + "mode": "thresholds" + } + }, + "overrides": [] + } + } + } + } + } + }, + "layout": { + "kind": "RowsLayout", + "spec": { + "rows": [ + { + "kind": "Row", + "spec": { + "title": "Conditional Row", + "collapse": false, + "hideHeader": false, + "fillScreen": false, + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "visibility": "show", + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "variable": "group_by", + "operator": "includes", + "value": "instance" + } + }, + { + "kind": "ConditionalRenderingData", + "spec": { + "value": true + } + }, + { + "kind": "ConditionalRenderingTimeRangeSize", + "spec": { + "value": "1h" + } + } + ] + } + }, + "layout": { + "kind": "GridLayout", + "spec": { + "items": [ + { + "kind": "GridLayoutItem", + "spec": { + "x": 0, + "y": 0, + "width": 24, + "height": 8, + "element": { + "kind": "ElementReference", + "name": "panel-1" + } + } + } + ] + } + } + } + } + ] + } + }, + "links": null, + "liveNow": true, + "preload": true, + "tags": [ + "test", + "example", + "migration" + ], + "timeSettings": { + "timezone": "browser", + "from": "now-6h", + "to": "now", + "autoRefresh": "10s", + "autoRefreshIntervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "hideTimepicker": false, + "weekStart": "monday", + "fiscalYearStartMonth": 0 + }, + "title": "Test: Complete V2alpha1 Dashboard Example", + "variables": [ + { + "kind": "QueryVariable", + "spec": { + "name": "prometheus_query", + "current": { + "text": "All", + "value": [ + "$__all" + ] + }, + "label": "Prometheus Query", + "hide": "dontHide", + "refresh": "time", + "skipUrlSync": false, + "description": "Shows all up metrics", + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "query": { + "kind": "prometheus", + "spec": { + "expr": "up" + } + }, + "regex": "", + "sort": "alphabetical", + "definition": "up", + "options": null, + "multi": true, + "includeAll": true, + "allowCustomValue": false + } + }, + { + "kind": "TextVariable", + "spec": { + "name": "text_var", + "current": { + "selected": true, + "text": "server1", + "value": "server1" + }, + "query": "server1,server2,server3", + "label": "Text Variable", + "hide": "dontHide", + "skipUrlSync": false, + "description": "A simple text variable" + } + }, + { + "kind": "ConstantVariable", + "spec": { + "name": "constant_var", + "query": "production", + "current": { + "selected": true, + "text": "production", + "value": "production" + }, + "label": "Constant", + "hide": "dontHide", + "skipUrlSync": true, + "description": "A constant value" + } + }, + { + "kind": "DatasourceVariable", + "spec": { + "name": "ds_var", + "pluginId": "prometheus", + "refresh": "load", + "regex": "/^gdev-/", + "current": { + "text": "gdev-prometheus", + "value": "gdev-prometheus" + }, + "options": [ + { + "text": "gdev-prometheus", + "value": "gdev-prometheus" + } + ], + "multi": false, + "includeAll": false, + "label": "Datasource", + "hide": "dontHide", + "skipUrlSync": false, + "description": "Select a datasource", + "allowCustomValue": false + } + }, + { + "kind": "IntervalVariable", + "spec": { + "name": "interval", + "query": "1m,5m,10m,30m,1h,6h,12h,1d", + "current": { + "selected": true, + "text": "5m", + "value": "5m" + }, + "options": [ + { + "text": "1m", + "value": "1m" + }, + { + "text": "5m", + "value": "5m" + }, + { + "text": "10m", + "value": "10m" + }, + { + "text": "30m", + "value": "30m" + }, + { + "text": "1h", + "value": "1h" + }, + { + "text": "6h", + "value": "6h" + }, + { + "text": "12h", + "value": "12h" + }, + { + "text": "1d", + "value": "1d" + } + ], + "auto": true, + "auto_min": "10s", + "auto_count": 30, + "refresh": "load", + "label": "Interval", + "hide": "dontHide", + "skipUrlSync": false, + "description": "Time interval selection" + } + }, + { + "kind": "CustomVariable", + "spec": { + "name": "custom_var", + "query": "prod : Production, staging : Staging, dev : Development", + "current": { + "text": [ + "Production" + ], + "value": [ + "prod" + ] + }, + "options": [ + { + "text": "Production", + "value": "prod" + }, + { + "text": "Staging", + "value": "staging" + }, + { + "text": "Development", + "value": "dev" + } + ], + "multi": true, + "includeAll": true, + "allValue": "*", + "label": "Custom Options", + "hide": "dontHide", + "skipUrlSync": false, + "description": "Custom multi-value variable", + "allowCustomValue": true + } + }, + { + "kind": "GroupByVariable", + "spec": { + "name": "group_by", + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "current": { + "text": "instance", + "value": "instance" + }, + "options": null, + "multi": false, + "label": "Group By", + "hide": "dontHide", + "skipUrlSync": false, + "description": "Group metrics by label" + } + }, + { + "kind": "AdhocVariable", + "spec": { + "name": "filters", + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "baseFilters": [ + { + "key": "job", + "operator": "=", + "value": "grafana", + "condition": "AND" + } + ], + "filters": [], + "defaultKeys": [ + { + "text": "job", + "value": "job", + "expandable": true + }, + { + "text": "instance", + "value": "instance", + "expandable": true + } + ], + "label": "Filters", + "hide": "dontHide", + "skipUrlSync": false, + "allowCustomValue": false + } + } + ] + }, + "status": {} + } } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v1beta1.json index ed784b45834..c55f325789d 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v1beta1.json @@ -15,7 +15,505 @@ "conversion": { "failed": true, "error": "backend conversion not yet implemented", - "storedVersion": "v2alpha1" + "storedVersion": "v2alpha1", + "source": { + "kind": "Dashboard", + "apiVersion": "dashboard.grafana.app/v2alpha1", + "metadata": { + "name": "test-v2alpha1-complete", + "labels": { + "category": "test" + }, + "annotations": { + "description": "Complete example of v2alpha1 dashboard features" + } + }, + "spec": { + "annotations": [ + { + "kind": "AnnotationQuery", + "spec": { + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "query": { + "kind": "grafana", + "spec": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + } + }, + "enable": true, + "hide": false, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "builtIn": true + } + }, + { + "kind": "AnnotationQuery", + "spec": { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "query": { + "kind": "prometheus", + "spec": { + "expr": "changes(process_start_time_seconds[1m])", + "refId": "Anno" + } + }, + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "Prometheus Annotations", + "builtIn": false + } + } + ], + "cursorSync": "Tooltip", + "description": "This dashboard demonstrates all features that need to be converted from v2alpha1 to v2beta1", + "editable": true, + "elements": { + "panel-1": { + "kind": "Panel", + "spec": { + "id": 1, + "title": "Panel with Conditional Rendering", + "description": "This panel demonstrates conditional rendering features", + "links": null, + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "prometheus", + "spec": { + "expr": "up{job=\"grafana\"}" + } + }, + "datasource": { + "uid": "gdev-prometheus" + }, + "refId": "A", + "hidden": false + } + } + ], + "transformations": [ + { + "kind": "reduce", + "spec": { + "id": "reduce", + "options": { + "includeTimeField": false, + "mode": "reduceFields", + "reducers": [ + "mean" + ] + } + } + } + ], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "stat", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "textMode": "auto" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "type": "value", + "options": { + "0": { + "text": "Down", + "color": "red" + }, + "1": { + "text": "Up", + "color": "green" + } + } + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "red" + }, + { + "value": 1, + "color": "green" + } + ] + }, + "color": { + "mode": "thresholds" + } + }, + "overrides": [] + } + } + } + } + } + }, + "layout": { + "kind": "RowsLayout", + "spec": { + "rows": [ + { + "kind": "Row", + "spec": { + "title": "Conditional Row", + "collapse": false, + "hideHeader": false, + "fillScreen": false, + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "visibility": "show", + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "variable": "group_by", + "operator": "includes", + "value": "instance" + } + }, + { + "kind": "ConditionalRenderingData", + "spec": { + "value": true + } + }, + { + "kind": "ConditionalRenderingTimeRangeSize", + "spec": { + "value": "1h" + } + } + ] + } + }, + "layout": { + "kind": "GridLayout", + "spec": { + "items": [ + { + "kind": "GridLayoutItem", + "spec": { + "x": 0, + "y": 0, + "width": 24, + "height": 8, + "element": { + "kind": "ElementReference", + "name": "panel-1" + } + } + } + ] + } + } + } + } + ] + } + }, + "links": null, + "liveNow": true, + "preload": true, + "tags": [ + "test", + "example", + "migration" + ], + "timeSettings": { + "timezone": "browser", + "from": "now-6h", + "to": "now", + "autoRefresh": "10s", + "autoRefreshIntervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "hideTimepicker": false, + "weekStart": "monday", + "fiscalYearStartMonth": 0 + }, + "title": "Test: Complete V2alpha1 Dashboard Example", + "variables": [ + { + "kind": "QueryVariable", + "spec": { + "name": "prometheus_query", + "current": { + "text": "All", + "value": [ + "$__all" + ] + }, + "label": "Prometheus Query", + "hide": "dontHide", + "refresh": "time", + "skipUrlSync": false, + "description": "Shows all up metrics", + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "query": { + "kind": "prometheus", + "spec": { + "expr": "up" + } + }, + "regex": "", + "sort": "alphabetical", + "definition": "up", + "options": null, + "multi": true, + "includeAll": true, + "allowCustomValue": false + } + }, + { + "kind": "TextVariable", + "spec": { + "name": "text_var", + "current": { + "selected": true, + "text": "server1", + "value": "server1" + }, + "query": "server1,server2,server3", + "label": "Text Variable", + "hide": "dontHide", + "skipUrlSync": false, + "description": "A simple text variable" + } + }, + { + "kind": "ConstantVariable", + "spec": { + "name": "constant_var", + "query": "production", + "current": { + "selected": true, + "text": "production", + "value": "production" + }, + "label": "Constant", + "hide": "dontHide", + "skipUrlSync": true, + "description": "A constant value" + } + }, + { + "kind": "DatasourceVariable", + "spec": { + "name": "ds_var", + "pluginId": "prometheus", + "refresh": "load", + "regex": "/^gdev-/", + "current": { + "text": "gdev-prometheus", + "value": "gdev-prometheus" + }, + "options": [ + { + "text": "gdev-prometheus", + "value": "gdev-prometheus" + } + ], + "multi": false, + "includeAll": false, + "label": "Datasource", + "hide": "dontHide", + "skipUrlSync": false, + "description": "Select a datasource", + "allowCustomValue": false + } + }, + { + "kind": "IntervalVariable", + "spec": { + "name": "interval", + "query": "1m,5m,10m,30m,1h,6h,12h,1d", + "current": { + "selected": true, + "text": "5m", + "value": "5m" + }, + "options": [ + { + "text": "1m", + "value": "1m" + }, + { + "text": "5m", + "value": "5m" + }, + { + "text": "10m", + "value": "10m" + }, + { + "text": "30m", + "value": "30m" + }, + { + "text": "1h", + "value": "1h" + }, + { + "text": "6h", + "value": "6h" + }, + { + "text": "12h", + "value": "12h" + }, + { + "text": "1d", + "value": "1d" + } + ], + "auto": true, + "auto_min": "10s", + "auto_count": 30, + "refresh": "load", + "label": "Interval", + "hide": "dontHide", + "skipUrlSync": false, + "description": "Time interval selection" + } + }, + { + "kind": "CustomVariable", + "spec": { + "name": "custom_var", + "query": "prod : Production, staging : Staging, dev : Development", + "current": { + "text": [ + "Production" + ], + "value": [ + "prod" + ] + }, + "options": [ + { + "text": "Production", + "value": "prod" + }, + { + "text": "Staging", + "value": "staging" + }, + { + "text": "Development", + "value": "dev" + } + ], + "multi": true, + "includeAll": true, + "allValue": "*", + "label": "Custom Options", + "hide": "dontHide", + "skipUrlSync": false, + "description": "Custom multi-value variable", + "allowCustomValue": true + } + }, + { + "kind": "GroupByVariable", + "spec": { + "name": "group_by", + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "current": { + "text": "instance", + "value": "instance" + }, + "options": null, + "multi": false, + "label": "Group By", + "hide": "dontHide", + "skipUrlSync": false, + "description": "Group metrics by label" + } + }, + { + "kind": "AdhocVariable", + "spec": { + "name": "filters", + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "baseFilters": [ + { + "key": "job", + "operator": "=", + "value": "grafana", + "condition": "AND" + } + ], + "filters": [], + "defaultKeys": [ + { + "text": "job", + "value": "job", + "expandable": true + }, + { + "text": "instance", + "value": "instance", + "expandable": true + } + ], + "label": "Filters", + "hide": "dontHide", + "skipUrlSync": false, + "allowCustomValue": false + } + } + ] + }, + "status": {} + } } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v0alpha1.json index 46365be1c23..4497423cc53 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v0alpha1.json @@ -9,7 +9,1055 @@ "conversion": { "failed": true, "error": "backend conversion not yet implemented", - "storedVersion": "v2alpha1" + "storedVersion": "v2alpha1", + "source": { + "kind": "Dashboard", + "apiVersion": "dashboard.grafana.app/v2alpha1", + "metadata": { + "name": "test-v2alpha1-annotations" + }, + "spec": { + "annotations": [ + { + "kind": "AnnotationQuery", + "spec": { + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "query": { + "kind": "grafana", + "spec": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + } + }, + "enable": true, + "hide": false, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "builtIn": true + } + }, + { + "kind": "AnnotationQuery", + "spec": { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "query": { + "kind": "grafana-testdata-datasource", + "spec": { + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + "enable": true, + "hide": false, + "iconColor": "blue", + "name": "testdata-annos", + "builtIn": false + } + }, + { + "kind": "AnnotationQuery", + "spec": { + "query": { + "kind": "prometheus", + "spec": { + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + "enable": true, + "hide": false, + "iconColor": "blue", + "name": "no-ds-testdata-annos", + "builtIn": false + } + }, + { + "kind": "AnnotationQuery", + "spec": { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "query": { + "kind": "prometheus", + "spec": { + "expr": "{action=\"add_client\"}", + "interval": "", + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "prom-annos", + "builtIn": false + } + }, + { + "kind": "AnnotationQuery", + "spec": { + "query": { + "kind": "prometheus", + "spec": { + "expr": "{action=\"add_client\"}", + "interval": "", + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "no-ds-prom-annos", + "builtIn": false + } + }, + { + "kind": "AnnotationQuery", + "spec": { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "PBBCEC2D313BC06C3" + }, + "query": { + "kind": "grafana-postgresql-datasource", + "spec": { + "editorMode": "builder", + "format": "table", + "lines": 10, + "rawSql": "", + "refId": "Anno", + "scenarioId": "annotations", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + }, + "enable": true, + "hide": false, + "iconColor": "red", + "name": "postgress-annos", + "builtIn": false + } + }, + { + "kind": "AnnotationQuery", + "spec": { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "query": { + "kind": "elasticsearch", + "spec": { + "lines": 10, + "query": "test query", + "refId": "Anno", + "scenarioId": "annotations" + } + }, + "enable": true, + "hide": false, + "iconColor": "red", + "name": "elastic - annos", + "builtIn": false, + "legacyOptions": { + "tagsField": "asd", + "textField": "asd", + "timeEndField": "asdas", + "timeField": "asd" + } + } + } + ], + "cursorSync": "Off", + "editable": true, + "elements": { + "panel-1": { + "kind": "Panel", + "spec": { + "id": 1, + "title": "Simple timeseries (WITH DS REF)", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "grafana-testdata-datasource", + "spec": { + "scenarioId": "random_walk", + "seriesCount": 3 + } + }, + "datasource": { + "uid": "gdev-testdata" + }, + "refId": "A", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "timeseries", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + } + }, + "overrides": [] + } + } + } + } + }, + "panel-2": { + "kind": "Panel", + "spec": { + "id": 2, + "title": "Simple stat (NO DS REF)", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "grafana-testdata-datasource", + "spec": { + "scenarioId": "random_walk", + "seriesCount": 4 + } + }, + "refId": "A", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "stat", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "thresholds" + } + }, + "overrides": [] + } + } + } + } + }, + "panel-3": { + "kind": "Panel", + "spec": { + "id": 3, + "title": "Panel with NO REF to gdev-prometheus", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "prometheus", + "spec": { + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "useBackend": false + } + }, + "refId": "A", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "timeseries", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + } + }, + "overrides": [] + } + } + } + } + }, + "panel-4": { + "kind": "Panel", + "spec": { + "id": 4, + "title": "Panel with ref to gdev-prometheus", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "prometheus", + "spec": { + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "useBackend": false + } + }, + "datasource": { + "uid": "gdev-prometheus" + }, + "refId": "A", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "timeseries", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + } + }, + "overrides": [] + } + } + } + } + }, + "panel-5": { + "kind": "Panel", + "spec": { + "id": 5, + "title": "Mixed DS WITH REFS", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "prometheus", + "spec": { + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "legendFormat": "__auto", + "range": true, + "useBackend": false + } + }, + "datasource": { + "uid": "gdev-prometheus" + }, + "refId": "A", + "hidden": false + } + }, + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "grafana-testdata-datasource", + "spec": {} + }, + "datasource": { + "uid": "gdev-testdata" + }, + "refId": "B", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "timeseries", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + } + }, + "overrides": [] + } + } + } + } + }, + "panel-6": { + "kind": "Panel", + "spec": { + "id": 6, + "title": "Mixed DS WITHOUT REFS", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "prometheus", + "spec": { + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "legendFormat": "__auto", + "range": true, + "useBackend": false + } + }, + "refId": "A", + "hidden": false + } + }, + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "grafana-testdata-datasource", + "spec": {} + }, + "refId": "B", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "timeseries", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + } + }, + "overrides": [] + } + } + } + } + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "maxColumnCount": 3, + "columnWidthMode": "standard", + "rowHeightMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-3" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-4" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-2" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-1" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-5" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-6" + } + } + } + ] + } + }, + "links": [], + "liveNow": false, + "preload": false, + "tags": [], + "timeSettings": { + "timezone": "browser", + "from": "now-6h", + "to": "now", + "autoRefresh": "", + "autoRefreshIntervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "hideTimepicker": false, + "fiscalYearStartMonth": 0 + }, + "title": "Test: V2alpha1 dashboard with annotations", + "variables": [ + { + "kind": "QueryVariable", + "spec": { + "name": "variable-ds-prometheus", + "current": { + "text": null, + "value": null + }, + "hide": "dontHide", + "refresh": "", + "skipUrlSync": false, + "datasource": { + "uid": "gdev-prometheus" + }, + "query": { + "kind": "prometheus", + "spec": { + "expr": "up" + } + }, + "regex": "", + "sort": "", + "options": null, + "multi": false, + "includeAll": false, + "allowCustomValue": false + } + }, + { + "kind": "QueryVariable", + "spec": { + "name": "variable-no-ds", + "current": { + "text": null, + "value": null + }, + "hide": "dontHide", + "refresh": "", + "skipUrlSync": false, + "query": { + "kind": "grafana-testdata-datasource", + "spec": { + "csv": "1,2,3,4", + "scenarioId": "csv_metric_values" + } + }, + "regex": "", + "sort": "", + "options": null, + "multi": false, + "includeAll": false, + "allowCustomValue": false + } + }, + { + "kind": "QueryVariable", + "spec": { + "name": "variable-no-ds-empty-query", + "current": { + "text": null, + "value": null + }, + "hide": "dontHide", + "refresh": "", + "skipUrlSync": false, + "query": { + "kind": "grafana-testdata-datasource", + "spec": {} + }, + "regex": "", + "sort": "", + "options": null, + "multi": false, + "includeAll": false, + "allowCustomValue": false + } + }, + { + "kind": "QueryVariable", + "spec": { + "name": "variable-no-default-ds", + "current": { + "text": null, + "value": null + }, + "hide": "dontHide", + "refresh": "", + "skipUrlSync": false, + "query": { + "kind": "prometheus", + "spec": { + "expr": "up" + } + }, + "regex": "", + "sort": "", + "options": null, + "multi": false, + "includeAll": false, + "allowCustomValue": false + } + } + ] + }, + "status": {} + } } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v1beta1.json index a0cf65052a7..11151fc1345 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v1beta1.json @@ -9,7 +9,1055 @@ "conversion": { "failed": true, "error": "backend conversion not yet implemented", - "storedVersion": "v2alpha1" + "storedVersion": "v2alpha1", + "source": { + "kind": "Dashboard", + "apiVersion": "dashboard.grafana.app/v2alpha1", + "metadata": { + "name": "test-v2alpha1-annotations" + }, + "spec": { + "annotations": [ + { + "kind": "AnnotationQuery", + "spec": { + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "query": { + "kind": "grafana", + "spec": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + } + }, + "enable": true, + "hide": false, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "builtIn": true + } + }, + { + "kind": "AnnotationQuery", + "spec": { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "query": { + "kind": "grafana-testdata-datasource", + "spec": { + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + "enable": true, + "hide": false, + "iconColor": "blue", + "name": "testdata-annos", + "builtIn": false + } + }, + { + "kind": "AnnotationQuery", + "spec": { + "query": { + "kind": "prometheus", + "spec": { + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + "enable": true, + "hide": false, + "iconColor": "blue", + "name": "no-ds-testdata-annos", + "builtIn": false + } + }, + { + "kind": "AnnotationQuery", + "spec": { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "query": { + "kind": "prometheus", + "spec": { + "expr": "{action=\"add_client\"}", + "interval": "", + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "prom-annos", + "builtIn": false + } + }, + { + "kind": "AnnotationQuery", + "spec": { + "query": { + "kind": "prometheus", + "spec": { + "expr": "{action=\"add_client\"}", + "interval": "", + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "no-ds-prom-annos", + "builtIn": false + } + }, + { + "kind": "AnnotationQuery", + "spec": { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "PBBCEC2D313BC06C3" + }, + "query": { + "kind": "grafana-postgresql-datasource", + "spec": { + "editorMode": "builder", + "format": "table", + "lines": 10, + "rawSql": "", + "refId": "Anno", + "scenarioId": "annotations", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + }, + "enable": true, + "hide": false, + "iconColor": "red", + "name": "postgress-annos", + "builtIn": false + } + }, + { + "kind": "AnnotationQuery", + "spec": { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "query": { + "kind": "elasticsearch", + "spec": { + "lines": 10, + "query": "test query", + "refId": "Anno", + "scenarioId": "annotations" + } + }, + "enable": true, + "hide": false, + "iconColor": "red", + "name": "elastic - annos", + "builtIn": false, + "legacyOptions": { + "tagsField": "asd", + "textField": "asd", + "timeEndField": "asdas", + "timeField": "asd" + } + } + } + ], + "cursorSync": "Off", + "editable": true, + "elements": { + "panel-1": { + "kind": "Panel", + "spec": { + "id": 1, + "title": "Simple timeseries (WITH DS REF)", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "grafana-testdata-datasource", + "spec": { + "scenarioId": "random_walk", + "seriesCount": 3 + } + }, + "datasource": { + "uid": "gdev-testdata" + }, + "refId": "A", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "timeseries", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + } + }, + "overrides": [] + } + } + } + } + }, + "panel-2": { + "kind": "Panel", + "spec": { + "id": 2, + "title": "Simple stat (NO DS REF)", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "grafana-testdata-datasource", + "spec": { + "scenarioId": "random_walk", + "seriesCount": 4 + } + }, + "refId": "A", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "stat", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "thresholds" + } + }, + "overrides": [] + } + } + } + } + }, + "panel-3": { + "kind": "Panel", + "spec": { + "id": 3, + "title": "Panel with NO REF to gdev-prometheus", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "prometheus", + "spec": { + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "useBackend": false + } + }, + "refId": "A", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "timeseries", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + } + }, + "overrides": [] + } + } + } + } + }, + "panel-4": { + "kind": "Panel", + "spec": { + "id": 4, + "title": "Panel with ref to gdev-prometheus", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "prometheus", + "spec": { + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "useBackend": false + } + }, + "datasource": { + "uid": "gdev-prometheus" + }, + "refId": "A", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "timeseries", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + } + }, + "overrides": [] + } + } + } + } + }, + "panel-5": { + "kind": "Panel", + "spec": { + "id": 5, + "title": "Mixed DS WITH REFS", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "prometheus", + "spec": { + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "legendFormat": "__auto", + "range": true, + "useBackend": false + } + }, + "datasource": { + "uid": "gdev-prometheus" + }, + "refId": "A", + "hidden": false + } + }, + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "grafana-testdata-datasource", + "spec": {} + }, + "datasource": { + "uid": "gdev-testdata" + }, + "refId": "B", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "timeseries", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + } + }, + "overrides": [] + } + } + } + } + }, + "panel-6": { + "kind": "Panel", + "spec": { + "id": 6, + "title": "Mixed DS WITHOUT REFS", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "prometheus", + "spec": { + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "legendFormat": "__auto", + "range": true, + "useBackend": false + } + }, + "refId": "A", + "hidden": false + } + }, + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "grafana-testdata-datasource", + "spec": {} + }, + "refId": "B", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "timeseries", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + } + }, + "overrides": [] + } + } + } + } + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "maxColumnCount": 3, + "columnWidthMode": "standard", + "rowHeightMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-3" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-4" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-2" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-1" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-5" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-6" + } + } + } + ] + } + }, + "links": [], + "liveNow": false, + "preload": false, + "tags": [], + "timeSettings": { + "timezone": "browser", + "from": "now-6h", + "to": "now", + "autoRefresh": "", + "autoRefreshIntervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "hideTimepicker": false, + "fiscalYearStartMonth": 0 + }, + "title": "Test: V2alpha1 dashboard with annotations", + "variables": [ + { + "kind": "QueryVariable", + "spec": { + "name": "variable-ds-prometheus", + "current": { + "text": null, + "value": null + }, + "hide": "dontHide", + "refresh": "", + "skipUrlSync": false, + "datasource": { + "uid": "gdev-prometheus" + }, + "query": { + "kind": "prometheus", + "spec": { + "expr": "up" + } + }, + "regex": "", + "sort": "", + "options": null, + "multi": false, + "includeAll": false, + "allowCustomValue": false + } + }, + { + "kind": "QueryVariable", + "spec": { + "name": "variable-no-ds", + "current": { + "text": null, + "value": null + }, + "hide": "dontHide", + "refresh": "", + "skipUrlSync": false, + "query": { + "kind": "grafana-testdata-datasource", + "spec": { + "csv": "1,2,3,4", + "scenarioId": "csv_metric_values" + } + }, + "regex": "", + "sort": "", + "options": null, + "multi": false, + "includeAll": false, + "allowCustomValue": false + } + }, + { + "kind": "QueryVariable", + "spec": { + "name": "variable-no-ds-empty-query", + "current": { + "text": null, + "value": null + }, + "hide": "dontHide", + "refresh": "", + "skipUrlSync": false, + "query": { + "kind": "grafana-testdata-datasource", + "spec": {} + }, + "regex": "", + "sort": "", + "options": null, + "multi": false, + "includeAll": false, + "allowCustomValue": false + } + }, + { + "kind": "QueryVariable", + "spec": { + "name": "variable-no-default-ds", + "current": { + "text": null, + "value": null + }, + "hide": "dontHide", + "refresh": "", + "skipUrlSync": false, + "query": { + "kind": "prometheus", + "spec": { + "expr": "up" + } + }, + "regex": "", + "sort": "", + "options": null, + "multi": false, + "includeAll": false, + "allowCustomValue": false + } + } + ] + }, + "status": {} + } } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.groupby-adhoc-vars.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.groupby-adhoc-vars.v0alpha1.json index add335f4b5e..ae50ed46c5d 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.groupby-adhoc-vars.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.groupby-adhoc-vars.v0alpha1.json @@ -9,7 +9,100 @@ "conversion": { "failed": true, "error": "backend conversion not yet implemented", - "storedVersion": "v2alpha1" + "storedVersion": "v2alpha1", + "source": { + "kind": "Dashboard", + "apiVersion": "dashboard.grafana.app/v2alpha1", + "metadata": { + "name": "test-v2alpha1-groupby-adhoc-vars" + }, + "spec": { + "annotations": null, + "cursorSync": "", + "elements": null, + "layout": null, + "links": null, + "preload": false, + "tags": null, + "timeSettings": { + "from": "", + "to": "", + "autoRefresh": "", + "autoRefreshIntervals": null, + "hideTimepicker": false, + "fiscalYearStartMonth": 0 + }, + "title": "Test: V2alpha1 dashboard with group by and adhoc variables", + "variables": [ + { + "kind": "GroupByVariable", + "spec": { + "name": "", + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "current": { + "text": "text7", + "value": "value7" + }, + "options": null, + "multi": false, + "label": "Group By Variable", + "hide": "dontHide", + "skipUrlSync": false, + "description": "A group by variable" + } + }, + { + "kind": "AdhocVariable", + "spec": { + "name": "adhocVar", + "datasource": { + "type": "prometheus", + "uid": "datasource-3" + }, + "baseFilters": [ + { + "key": "key1", + "operator": "=", + "value": "value1", + "condition": "AND" + }, + { + "key": "key2", + "operator": "=", + "value": "value2", + "condition": "OR" + } + ], + "filters": [ + { + "key": "key3", + "operator": "=", + "value": "value3", + "condition": "AND" + } + ], + "defaultKeys": [ + { + "text": "defaultKey1", + "value": "defaultKey1", + "group": "defaultGroup1", + "expandable": true + } + ], + "label": "Adhoc Variable", + "hide": "dontHide", + "skipUrlSync": false, + "description": "An adhoc variable", + "allowCustomValue": true + } + } + ] + }, + "status": {} + } } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.groupby-adhoc-vars.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.groupby-adhoc-vars.v1beta1.json index 4656a14bc7b..4f7ce909299 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.groupby-adhoc-vars.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.groupby-adhoc-vars.v1beta1.json @@ -9,7 +9,100 @@ "conversion": { "failed": true, "error": "backend conversion not yet implemented", - "storedVersion": "v2alpha1" + "storedVersion": "v2alpha1", + "source": { + "kind": "Dashboard", + "apiVersion": "dashboard.grafana.app/v2alpha1", + "metadata": { + "name": "test-v2alpha1-groupby-adhoc-vars" + }, + "spec": { + "annotations": null, + "cursorSync": "", + "elements": null, + "layout": null, + "links": null, + "preload": false, + "tags": null, + "timeSettings": { + "from": "", + "to": "", + "autoRefresh": "", + "autoRefreshIntervals": null, + "hideTimepicker": false, + "fiscalYearStartMonth": 0 + }, + "title": "Test: V2alpha1 dashboard with group by and adhoc variables", + "variables": [ + { + "kind": "GroupByVariable", + "spec": { + "name": "", + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "current": { + "text": "text7", + "value": "value7" + }, + "options": null, + "multi": false, + "label": "Group By Variable", + "hide": "dontHide", + "skipUrlSync": false, + "description": "A group by variable" + } + }, + { + "kind": "AdhocVariable", + "spec": { + "name": "adhocVar", + "datasource": { + "type": "prometheus", + "uid": "datasource-3" + }, + "baseFilters": [ + { + "key": "key1", + "operator": "=", + "value": "value1", + "condition": "AND" + }, + { + "key": "key2", + "operator": "=", + "value": "value2", + "condition": "OR" + } + ], + "filters": [ + { + "key": "key3", + "operator": "=", + "value": "value3", + "condition": "AND" + } + ], + "defaultKeys": [ + { + "text": "defaultKey1", + "value": "defaultKey1", + "group": "defaultGroup1", + "expandable": true + } + ], + "label": "Adhoc Variable", + "hide": "dontHide", + "skipUrlSync": false, + "description": "An adhoc variable", + "allowCustomValue": true + } + } + ] + }, + "status": {} + } } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v0alpha1.json index 86e7f731622..acde79a0bcc 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v0alpha1.json @@ -9,7 +9,219 @@ "conversion": { "failed": true, "error": "backend conversion not yet implemented", - "storedVersion": "v2alpha1" + "storedVersion": "v2alpha1", + "source": { + "kind": "Dashboard", + "apiVersion": "dashboard.grafana.app/v2alpha1", + "metadata": { + "name": "test-v2alpha1-viz-config" + }, + "spec": { + "annotations": null, + "cursorSync": "", + "elements": { + "panel-1": { + "kind": "Panel", + "spec": { + "id": 1, + "title": "Simple timeseries (WITH DS REF)", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "grafana-testdata-datasource", + "spec": { + "scenarioId": "random_walk", + "seriesCount": 3 + } + }, + "datasource": { + "uid": "gdev-testdata" + }, + "refId": "A", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "timeseries", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + } + }, + "overrides": [] + } + } + } + } + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "maxColumnCount": 3, + "columnWidthMode": "standard", + "rowHeightMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-3" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-4" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-2" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-1" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-5" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-6" + } + } + } + ] + } + }, + "links": [], + "liveNow": false, + "preload": false, + "tags": [], + "timeSettings": { + "timezone": "browser", + "from": "now-6h", + "to": "now", + "autoRefresh": "", + "autoRefreshIntervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "hideTimepicker": false, + "fiscalYearStartMonth": 0 + }, + "title": "Test: V2alpha1 dashboard with viz config", + "variables": null + }, + "status": {} + } } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v1beta1.json index cc538fe2f92..e0812fa1a2b 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v1beta1.json @@ -9,7 +9,219 @@ "conversion": { "failed": true, "error": "backend conversion not yet implemented", - "storedVersion": "v2alpha1" + "storedVersion": "v2alpha1", + "source": { + "kind": "Dashboard", + "apiVersion": "dashboard.grafana.app/v2alpha1", + "metadata": { + "name": "test-v2alpha1-viz-config" + }, + "spec": { + "annotations": null, + "cursorSync": "", + "elements": { + "panel-1": { + "kind": "Panel", + "spec": { + "id": 1, + "title": "Simple timeseries (WITH DS REF)", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "grafana-testdata-datasource", + "spec": { + "scenarioId": "random_walk", + "seriesCount": 3 + } + }, + "datasource": { + "uid": "gdev-testdata" + }, + "refId": "A", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "timeseries", + "spec": { + "pluginVersion": "12.1.0-pre", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + } + }, + "overrides": [] + } + } + } + } + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "maxColumnCount": 3, + "columnWidthMode": "standard", + "rowHeightMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-3" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-4" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-2" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-1" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-5" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-6" + } + } + } + ] + } + }, + "links": [], + "liveNow": false, + "preload": false, + "tags": [], + "timeSettings": { + "timezone": "browser", + "from": "now-6h", + "to": "now", + "autoRefresh": "", + "autoRefreshIntervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "hideTimepicker": false, + "fiscalYearStartMonth": 0 + }, + "title": "Test: V2alpha1 dashboard with viz config", + "variables": null + }, + "status": {} + } } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/v0.go b/apps/dashboard/pkg/migration/conversion/v0.go index a1ccc0e5a6c..9eb42167072 100644 --- a/apps/dashboard/pkg/migration/conversion/v0.go +++ b/apps/dashboard/pkg/migration/conversion/v0.go @@ -78,6 +78,7 @@ func Convert_V0_to_V2alpha1(in *dashv0.Dashboard, out *dashv2alpha1.Dashboard, s StoredVersion: ptr.To(dashv0.VERSION), Failed: true, Error: ptr.To("backend conversion not yet implemented"), + Source: in, }, } @@ -94,6 +95,7 @@ func Convert_V0_to_V2beta1(in *dashv0.Dashboard, out *dashv2beta1.Dashboard, sco StoredVersion: ptr.To(dashv0.VERSION), Failed: true, Error: ptr.To("backend conversion not yet implemented"), + Source: in, }, } diff --git a/apps/dashboard/pkg/migration/conversion/v1.go b/apps/dashboard/pkg/migration/conversion/v1.go index 2dd51ffff03..86b3827af27 100644 --- a/apps/dashboard/pkg/migration/conversion/v1.go +++ b/apps/dashboard/pkg/migration/conversion/v1.go @@ -49,6 +49,7 @@ func Convert_V1_to_V2alpha1(in *dashv1.Dashboard, out *dashv2alpha1.Dashboard, s StoredVersion: ptr.To(dashv1.VERSION), Failed: true, Error: ptr.To("backend conversion not yet implemented"), + Source: in, }, } @@ -65,6 +66,7 @@ func Convert_V1_to_V2beta1(in *dashv1.Dashboard, out *dashv2beta1.Dashboard, sco StoredVersion: ptr.To(dashv1.VERSION), Failed: true, Error: ptr.To("backend conversion not yet implemented"), + Source: in, }, } diff --git a/apps/dashboard/pkg/migration/conversion/v2.go b/apps/dashboard/pkg/migration/conversion/v2.go index a7dfb9f39fd..91fcd8cf07a 100644 --- a/apps/dashboard/pkg/migration/conversion/v2.go +++ b/apps/dashboard/pkg/migration/conversion/v2.go @@ -20,6 +20,7 @@ func Convert_V2alpha1_to_V0(in *dashv2alpha1.Dashboard, out *dashv0.Dashboard, s StoredVersion: ptr.To(dashv2alpha1.VERSION), Failed: true, Error: ptr.To("backend conversion not yet implemented"), + Source: in, }, } @@ -36,6 +37,7 @@ func Convert_V2alpha1_to_V1(in *dashv2alpha1.Dashboard, out *dashv1.Dashboard, s StoredVersion: ptr.To(dashv2alpha1.VERSION), Failed: true, Error: ptr.To("backend conversion not yet implemented"), + Source: in, }, } @@ -52,6 +54,7 @@ func Convert_V2alpha1_to_V2beta1(in *dashv2alpha1.Dashboard, out *dashv2beta1.Da StoredVersion: ptr.To(dashv2alpha1.VERSION), Failed: true, Error: ptr.To(err.Error()), + Source: in, }, } @@ -79,6 +82,7 @@ func Convert_V2beta1_to_V0(in *dashv2beta1.Dashboard, out *dashv0.Dashboard, sco StoredVersion: ptr.To(dashv2beta1.VERSION), Failed: true, Error: ptr.To("backend conversion not yet implemented"), + Source: in, }, } @@ -95,6 +99,7 @@ func Convert_V2beta1_to_V1(in *dashv2beta1.Dashboard, out *dashv1.Dashboard, sco StoredVersion: ptr.To(dashv2beta1.VERSION), Failed: true, Error: ptr.To("backend conversion not yet implemented"), + Source: in, }, } @@ -111,6 +116,7 @@ func Convert_V2beta1_to_V2alpha1(in *dashv2beta1.Dashboard, out *dashv2alpha1.Da StoredVersion: ptr.To(dashv2beta1.VERSION), Failed: true, Error: ptr.To("backend conversion not yet implemented"), + Source: in, }, } diff --git a/apps/dashboard/pkg/migration/frontend_defaults.go b/apps/dashboard/pkg/migration/frontend_defaults.go index 6f4cbbf87a4..c376be6f47f 100644 --- a/apps/dashboard/pkg/migration/frontend_defaults.go +++ b/apps/dashboard/pkg/migration/frontend_defaults.go @@ -2,6 +2,8 @@ package migration import ( "sort" + + "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" ) // applyFrontendDefaults applies all DashboardModel constructor defaults @@ -64,7 +66,6 @@ func applyFrontendDefaults(dashboard map[string]interface{}) { sortPanelsByGridPos(dashboard) // Built-in components - addBuiltInAnnotationQuery(dashboard) initMeta(dashboard) // Variable cleanup @@ -549,6 +550,7 @@ func cleanupPanelForSaveWithContext(panel map[string]interface{}, isNested bool) // Clean up internal markers delete(panel, "_originallyHadTransformations") + delete(panel, "_originallyHadFieldConfigCustom") } // filterDefaultValues removes properties that match the default values (matches frontend's isEqual logic) @@ -600,8 +602,21 @@ func filterDefaultValues(panel map[string]interface{}, originalProperties map[st for prop, defaultValue := range defaults { if panelValue, exists := panel[prop]; exists { if isEqual(panelValue, defaultValue) { - // Special case: fieldConfig is always removed if it matches defaults (frontend getSaveModel behavior) + // Special case: fieldConfig - handle preservation of original custom object first if prop == "fieldConfig" { + // Check if we need to preserve the custom object before removing fieldConfig + if panel["_originallyHadFieldConfigCustom"] == true { + // Ensure fieldConfig structure exists with custom object + if fieldConfig, ok := panelValue.(map[string]interface{}); ok { + if defaults, ok := fieldConfig["defaults"].(map[string]interface{}); ok { + if _, hasCustom := defaults["custom"]; !hasCustom { + defaults["custom"] = map[string]interface{}{} + } + // Don't remove fieldConfig if we added custom back + continue + } + } + } delete(panel, prop) } else { // Only remove if it wasn't originally present in the input @@ -616,12 +631,32 @@ func filterDefaultValues(panel map[string]interface{}, originalProperties map[st // Remove empty targets arrays (frontend removes them in cleanup) removeIfDefaultValue(panel, "targets", []interface{}{}) + // Handle case where fieldConfig was removed but originally had custom object + if panel["_originallyHadFieldConfigCustom"] == true { + if _, hasFieldConfig := panel["fieldConfig"]; !hasFieldConfig { + // Recreate fieldConfig with custom object + panel["fieldConfig"] = map[string]interface{}{ + "defaults": map[string]interface{}{ + "custom": map[string]interface{}{}, + }, + "overrides": []interface{}{}, + } + } + } + // Clean up fieldConfig to match frontend behavior if fieldConfig, exists := panel["fieldConfig"].(map[string]interface{}); exists { // Clean up fieldConfig defaults to match frontend behavior if defaults, hasDefaults := fieldConfig["defaults"].(map[string]interface{}); hasDefaults { // Remove properties that frontend considers as defaults and omits cleanupFieldConfigDefaults(defaults, panel) + + // Preserve custom object if it was originally present, even if empty + if panel["_originallyHadFieldConfigCustom"] == true { + if _, hasCustom := defaults["custom"]; !hasCustom { + defaults["custom"] = map[string]interface{}{} + } + } } } } @@ -759,10 +794,12 @@ func cleanupVariable(variable map[string]interface{}) { if variableType, ok := variable["type"].(string); ok { switch variableType { case "query": - // Query variables: keep options: [] if refresh !== never - // Since refresh is not specified in the input, it defaults to not "never" - if _, hasOptions := variable["options"]; !hasOptions { - variable["options"] = []interface{}{} + // Query variables: keep options: [] if refresh !== never (matches frontend getSaveModel logic) + refresh := schemaversion.GetIntValue(variable, "refresh", 1) // Default to 1 (onDashboardLoad) if not specified + if refresh != 0 { // 0 = VariableRefreshNever + if _, hasOptions := variable["options"]; !hasOptions { + variable["options"] = []interface{}{} + } } case "constant": // Constant variables: remove options completely @@ -909,32 +946,13 @@ func applyPanelAutoMigration(panel map[string]interface{}) { var newType string // Graph needs special logic as it can be migrated to multiple panels - if panelType == "graph" { + // Including graphite which was previously migrated to graph in the schema version 2 migration in DashboardMigrator.ts + // but this was a bug because in there graphite was set to graph, but since those migrations run + // after PanelModel.restoreModel where autoMigrateFrom is set, this caused the graph migration to be skipped. + // And this resulted in a dashboard with invalid panels. + if panelType == "graph" || panelType == "graphite" { // Check xaxis mode for special cases - if xaxis, ok := panel["xaxis"].(map[string]interface{}); ok { - if mode, ok := xaxis["mode"].(string); ok { - switch mode { - case "series": - // Check legend values for bargauge - if legend, ok := panel["legend"].(map[string]interface{}); ok { - if values, ok := legend["values"].(bool); ok && values { - newType = "bargauge" - } else { - newType = "barchart" - } - } else { - newType = "barchart" - } - case "histogram": - newType = "histogram" - } - } - } - - // Default graph migration to timeseries - if newType == "" { - newType = "timeseries" - } + newType = getGraphAutoMigration(panel) } else { // Check autoMigrateAngular mapping autoMigrateAngular := map[string]string{ @@ -958,6 +976,36 @@ func applyPanelAutoMigration(panel map[string]interface{}) { } } +func getGraphAutoMigration(panel map[string]interface{}) string { + newType := "" + if xaxis, ok := panel["xaxis"].(map[string]interface{}); ok { + if mode, ok := xaxis["mode"].(string); ok { + switch mode { + case "series": + // Check legend values for bargauge + if legend, ok := panel["legend"].(map[string]interface{}); ok { + if values, ok := legend["values"].(bool); ok && values { + newType = "bargauge" + } else { + newType = "barchart" + } + } else { + newType = "barchart" + } + case "histogram": + newType = "histogram" + } + } + } + + // Default graph migration to timeseries + if newType == "" { + newType = "timeseries" + } + + return newType +} + // removeNullValuesRecursively removes null values from nested objects and arrays // This matches the frontend's JSON.stringify/parse behavior func removeNullValuesRecursively(data interface{}) { @@ -1013,8 +1061,9 @@ func cleanupDashboardDefaults(dashboard map[string]interface{}) { // Remove transient properties that frontend filters out during getSaveModelClone() // These properties are lost during frontend's property copying loop in getSaveModelCloneOld() - delete(dashboard, "preload") // Transient dashboard loading state delete(dashboard, "iteration") // Template variable iteration timestamp + delete(dashboard, "nav") // Removed after V7 migration + delete(dashboard, "pulldowns") // Removed after V6 migration - frontend doesn't have this property } // cleanupFieldConfigDefaults removes properties that frontend considers as defaults and omits @@ -1085,3 +1134,36 @@ func trackPanelOriginalTransformations(panel map[string]interface{}) { } } } + +// trackOriginalFieldConfigCustom marks panels that had fieldConfig.defaults.custom in the original input +// This is needed to match frontend hasOwnProperty behavior and preserve empty custom objects +func trackOriginalFieldConfigCustom(dashboard map[string]interface{}) { + if panels, ok := dashboard["panels"].([]interface{}); ok { + for _, panelInterface := range panels { + if panel, ok := panelInterface.(map[string]interface{}); ok { + trackPanelOriginalFieldConfigCustom(panel) + } + } + } +} + +// trackPanelOriginalFieldConfigCustom recursively tracks fieldConfig.defaults.custom in panels and nested panels +func trackPanelOriginalFieldConfigCustom(panel map[string]interface{}) { + // Mark if this panel had fieldConfig.defaults.custom in original input + if fieldConfig, ok := panel["fieldConfig"].(map[string]interface{}); ok { + if defaults, ok := fieldConfig["defaults"].(map[string]interface{}); ok { + if _, hasCustom := defaults["custom"]; hasCustom { + panel["_originallyHadFieldConfigCustom"] = true + } + } + } + + // Handle nested panels in row panels + if nestedPanels, ok := panel["panels"].([]interface{}); ok { + for _, nestedPanelInterface := range nestedPanels { + if nestedPanel, ok := nestedPanelInterface.(map[string]interface{}); ok { + trackPanelOriginalFieldConfigCustom(nestedPanel) + } + } + } +} diff --git a/apps/dashboard/pkg/migration/frontend_defaults_test.go b/apps/dashboard/pkg/migration/frontend_defaults_test.go index b17a941164a..5bc126eacec 100644 --- a/apps/dashboard/pkg/migration/frontend_defaults_test.go +++ b/apps/dashboard/pkg/migration/frontend_defaults_test.go @@ -807,6 +807,193 @@ func TestTransformationsArrayContextAwareLogic(t *testing.T) { } } +func TestTrackOriginalFieldConfigCustom(t *testing.T) { + tests := []struct { + name string + input map[string]interface{} + expected map[string]interface{} + }{ + { + name: "track_top_level_panel_with_fieldConfig_custom", + input: map[string]interface{}{ + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "timeseries", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "custom": map[string]interface{}{}, + }, + "overrides": []interface{}{}, + }, + }, + map[string]interface{}{ + "id": 2, + "type": "table", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{}, + "overrides": []interface{}{}, + }, + }, + map[string]interface{}{ + "id": 3, + "type": "stat", + "title": "Panel without fieldConfig", + }, + }, + }, + expected: map[string]interface{}{ + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "timeseries", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "custom": map[string]interface{}{}, + }, + "overrides": []interface{}{}, + }, + "_originallyHadFieldConfigCustom": true, // marker added + }, + map[string]interface{}{ + "id": 2, + "type": "table", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{}, + "overrides": []interface{}{}, + }, + // no marker added - no custom object + }, + map[string]interface{}{ + "id": 3, + "type": "stat", + "title": "Panel without fieldConfig", + // no marker added - no fieldConfig + }, + }, + }, + }, + { + name: "track_nested_panels_in_row_with_fieldConfig_custom", + input: map[string]interface{}{ + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "row", + "title": "Row Panel", + "panels": []interface{}{ + map[string]interface{}{ + "id": 10, + "type": "singlestat", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "custom": map[string]interface{}{}, + }, + "overrides": []interface{}{}, + }, + }, + map[string]interface{}{ + "id": 11, + "type": "graph", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "unit": "bytes", + }, + "overrides": []interface{}{}, + }, + }, + }, + }, + }, + }, + expected: map[string]interface{}{ + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "row", + "title": "Row Panel", + "panels": []interface{}{ + map[string]interface{}{ + "id": 10, + "type": "singlestat", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "custom": map[string]interface{}{}, + }, + "overrides": []interface{}{}, + }, + "_originallyHadFieldConfigCustom": true, // marker added to nested panel + }, + map[string]interface{}{ + "id": 11, + "type": "graph", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "unit": "bytes", + }, + "overrides": []interface{}{}, + }, + // no marker added - no custom object + }, + }, + }, + }, + }, + }, + { + name: "track_panels_with_non_empty_custom", + input: map[string]interface{}{ + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "timeseries", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "custom": map[string]interface{}{ + "axisPlacement": "left", + }, + }, + "overrides": []interface{}{}, + }, + }, + }, + }, + expected: map[string]interface{}{ + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "timeseries", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "custom": map[string]interface{}{ + "axisPlacement": "left", + }, + }, + "overrides": []interface{}{}, + }, + "_originallyHadFieldConfigCustom": true, // marker added for non-empty custom + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Create a deep copy of input for testing + dashboard := deepCopy(tt.input).(map[string]interface{}) + + // Apply the tracking logic + trackOriginalFieldConfigCustom(dashboard) + + // Verify the result + if !compareValues(dashboard, tt.expected) { + t.Errorf("Test %s failed.\nExpected: %+v\nGot: %+v", tt.name, tt.expected, dashboard) + } + }) + } +} + func TestTrackOriginalTransformations(t *testing.T) { tests := []struct { name string @@ -915,6 +1102,123 @@ func TestTrackOriginalTransformations(t *testing.T) { } } +func TestCleanupPanelForSavePreservesOriginalFieldConfigCustom(t *testing.T) { + tests := []struct { + name string + input map[string]interface{} + expected map[string]interface{} + }{ + { + name: "preserve_empty_custom_when_originally_present", + input: map[string]interface{}{ + "type": "singlestat", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "custom": map[string]interface{}{}, // Empty but originally present + }, + "overrides": []interface{}{}, + }, + "_originallyHadFieldConfigCustom": true, // Marker indicating it was originally present + }, + expected: map[string]interface{}{ + "type": "stat", // Auto-migrated from singlestat + "autoMigrateFrom": "singlestat", // Auto-migration marker + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "custom": map[string]interface{}{}, // Should be preserved + }, + "overrides": []interface{}{}, + }, + }, + }, + { + name: "remove_empty_custom_when_not_originally_present", + input: map[string]interface{}{ + "type": "timeseries", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "custom": map[string]interface{}{}, // Empty and not originally present + }, + "overrides": []interface{}{}, + }, + // No marker - custom was not originally present + }, + expected: map[string]interface{}{ + "type": "timeseries", + // fieldConfig should be removed entirely as it matches defaults + }, + }, + { + name: "preserve_non_empty_custom_regardless_of_marker", + input: map[string]interface{}{ + "type": "table", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "custom": map[string]interface{}{ + "displayMode": "list", + }, + }, + "overrides": []interface{}{}, + }, + }, + expected: map[string]interface{}{ + "type": "table", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "custom": map[string]interface{}{ + "displayMode": "list", + }, + }, + "overrides": []interface{}{}, + }, + }, + }, + { + name: "add_custom_when_originally_present_but_missing", + input: map[string]interface{}{ + "type": "stat", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{}, // custom missing + "overrides": []interface{}{}, + }, + "_originallyHadFieldConfigCustom": true, // But marker indicates it was originally present + }, + expected: map[string]interface{}{ + "type": "stat", + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "custom": map[string]interface{}{}, // Should be added back + }, + "overrides": []interface{}{}, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + panel := make(map[string]interface{}) + for k, v := range tt.input { + panel[k] = v + } + + cleanupPanelForSaveWithContext(panel, false) + + // Verify expected properties exist + for key, expectedValue := range tt.expected { + if actualValue, exists := panel[key]; !exists { + t.Errorf("Property %s should exist but is missing", key) + } else if !compareValues(actualValue, expectedValue) { + t.Errorf("Property %s has wrong value. Expected: %v, Got: %v", key, expectedValue, actualValue) + } + } + + // Verify internal markers are cleaned up + assertPropertyRemoved(t, panel, "_originallyHadFieldConfigCustom") + }) + } +} + func TestCleanupPanelForSave(t *testing.T) { tests := []struct { name string diff --git a/apps/dashboard/pkg/migration/migrate.go b/apps/dashboard/pkg/migration/migrate.go index 62a24db3f2c..08cba231fd3 100644 --- a/apps/dashboard/pkg/migration/migrate.go +++ b/apps/dashboard/pkg/migration/migrate.go @@ -66,6 +66,10 @@ func (m *migrator) migrate(ctx context.Context, dash map[string]interface{}, tar // This is needed to match frontend hasOwnProperty behavior trackOriginalTransformations(dash) + // 1.1. Track which panels had fieldConfig.defaults.custom in original input + // This is needed to preserve empty custom objects that were originally present + trackOriginalFieldConfigCustom(dash) + // 2. Apply ALL frontend defaults FIRST (DashboardModel + PanelModel defaults) // This replicates the behavior of the frontend DashboardModel and PanelModel constructors applyFrontendDefaults(dash) @@ -122,7 +126,11 @@ func (m *migrator) migrate(ctx context.Context, dash map[string]interface{}, tar } } - // 6. Clean up the dashboard to match frontend getSaveModel behavior + // 6. Add built-in annotation query after all migrations are complete + // This matches the frontend DashboardModel constructor behavior + addBuiltInAnnotationQuery(dash) + + // 7. Clean up the dashboard to match frontend getSaveModel behavior // This removes properties that shouldn't be persisted and filters out default values cleanupDashboardForSave(dash) diff --git a/apps/dashboard/pkg/migration/schemaversion/README.md b/apps/dashboard/pkg/migration/schemaversion/README.md new file mode 100644 index 00000000000..e1cfdc45a95 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/README.md @@ -0,0 +1,524 @@ +# Dashboard Schema Migration Guide + +This guide provides comprehensive instructions for creating new dashboard schema migrations in Grafana. + +## Table of Contents + +- [Overview](#overview) +- [Current Schema Versions](#current-schema-versions) +- [Creating a New Migration](#creating-a-new-migration) + - [Step 1: Create the Migration File](#step-1-create-the-migration-file) + - [Step 2: Register the Migration](#step-2-register-the-migration) + - [Step 3: Create Test Data](#step-3-create-test-data) + - [Step 4: Run Tests](#step-4-run-tests) + - [Step 5: Frontend-Backend Consistency Validation](#step-5-frontend-backend-consistency-validation) + - [Step 6: Unit Testing](#step-6-unit-testing) +- [Utility Functions](#utility-functions) + - [Type Conversion](#type-conversion) + - [Data Access](#data-access) +- [Common Pitfalls](#common-pitfalls) + - [Type Assertions](#1-type-assertions) + - [Null Handling](#2-null-handling) + - [Nested Panel Processing](#3-nested-panel-processing) +- [Migration Beyond v42](#migration-beyond-v42) + - [When to Add Schema Migrations vs Panel Migrations](#when-to-add-schema-migrations-vs-panel-migrations) +- [Testing Guidelines](#testing-guidelines) + - [Test File Naming](#test-file-naming) + - [Test Data Requirements](#test-data-requirements) + - [Running Tests](#running-tests) +- [Comprehensive Testing Strategy](#comprehensive-testing-strategy) + - [Backend Migration Tests](#backend-migration-tests) + - [Frontend Migration Comparison Tests](#frontend-migration-comparison-tests) + - [Single Version Migration Testing](#single-version-migration-testing) +- [Resources](#resources) +- [Getting Help](#getting-help) + +## Overview + +Dashboard schema migrations ensure backward compatibility as the dashboard data model evolves. Each migration transforms dashboards from one schema version to the next, allowing older dashboards to work with newer Grafana versions. + +## Current Schema Versions + +- **Minimum Version**: 13 +- **Latest Version**: 42 +- **Backend Location**: `apps/dashboard/pkg/migration/schemaversion/` +- **Frontend Location**: `public/app/features/dashboard/state/DashboardMigrator.ts` + +## Creating a New Migration + +### Step 1: Create the Migration File + +Create a new file: `v{N}.go` where `{N}` is the target schema version. + +```go +package schemaversion + +import "context" + +// V{N} migrates [describe what this migration does]. +// +// [Detailed description of the migration including:] +// - What properties are being changed +// - Why the migration is necessary +// - Any special handling or edge cases +// +// Example before migration: +// +// "panels": [ +// { +// "id": 1, +// "type": "graph", +// "oldProperty": "value" +// } +// ] +// +// Example after migration: +// +// "panels": [ +// { +// "id": 1, +// "type": "graph", +// "newProperty": "value" +// } +// ] +func V{N}(_ context.Context, dashboard map[string]interface{}) error { + dashboard["schemaVersion"] = {N} + + // Your migration logic here + // Transform dashboard properties as needed + + return nil +} +``` + +### Step 2: Register the Migration + +Add your migration to `migrations.go`: + +```go +func GetMigrations(dsInfoProvider DataSourceInfoProvider) map[int]SchemaVersionMigrationFunc { + return map[int]SchemaVersionMigrationFunc{ + // ... existing migrations + {N}: V{N}, // Add your migration here + // ... rest of migrations + } +} +``` + +### Step 3: Create Test Data + +#### Input Test File +Create `testdata/input/v{N}.{name}.json` with schema version `{N-1}` with scenarios to cover the specific migration: + +```json +{ + "title": "V{N} Migration Test Dashboard", + "schemaVersion": {N-1}, + "panels": [ + { + "id": 1, + "type": "graph", + "title": "Test Panel", + "oldProperty": "value" + } + ] +} +``` + +#### Expected Output +The test system will generate `testdata/output/latest_version/v{N}.{name}.v42.json` automatically. + +### Step 4: Run Tests + +```bash +# Run migration tests +go test ./apps/dashboard/pkg/migration/... + +# Run specific migration test +go test ./apps/dashboard/pkg/migration/... -run TestMigrate +``` + +For comprehensive testing strategies including single version tests, frontend comparison tests, and full pipeline testing, see the [Comprehensive Testing Strategy](#comprehensive-testing-strategy) section. + +### Step 5: Frontend-Backend Consistency Validation + +Implement different changes in the migration until frontend matches exactly with the backend side. Add as many scenarios as possible to ensure comprehensive coverage of all use cases. + +For detailed testing strategies including single version tests, frontend comparison tests, and full pipeline testing, see the [Comprehensive Testing Strategy](#comprehensive-testing-strategy) section. + +#### Test Scenarios to Cover + +**Panel-Level Changes:** +- Panels with different types (graph, table, stat, etc.) +- Panels with nested panels (rows) +- Panels with various property combinations +- Panels with missing or null properties +- Panels with deprecated properties + +**Dashboard-Level Changes:** +- Dashboard properties (title, tags, time, etc.) +- Templating variables (query, textbox, custom, etc.) +- Annotations and links +- Time picker settings +- Refresh settings + +**Edge Cases:** +- Empty dashboards +- Dashboards with only rows +- Dashboards with mixed panel types +- Dashboards with complex nested structures +- Dashboards with invalid or malformed data + +**Property Transformations:** +- Property renaming scenarios +- Property type conversions +- Property value transformations +- Property removal scenarios +- Property addition scenarios + +#### Validation Process + +1. **Create comprehensive test data** covering all scenarios +2. **Run backend migration** and capture output +3. **Run frontend migration** and capture output +4. **Compare outputs** using strict equality checks +5. **Iterate on migration logic** until outputs match exactly +6. **Add more test cases** for any discrepancies found + +#### Test Data Requirements + +Create multiple test files for each migration: +- `v{N}.basic.{name}.json` - Basic functionality +- `v{N}.edge_cases.{name}.json` - Edge cases and error conditions +- `v{N}.complex.{name}.json` - Complex dashboard structures +- `v{N}.property_changes.{name}.json` - Property transformation scenarios + +### Step 6: Unit Testing + +Add comprehensive unit tests for both backend and frontend migrations to ensure the correct logic is implemented. + +#### Backend Unit Tests + +Create unit tests in `v{N}_test.go`: + +```go +package schemaversion_test + +import ( + "context" + "testing" + "github.com/stretchr/testify/require" + "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" +) + +func TestV{N}(t *testing.T) { + tests := []struct { + name string + input map[string]interface{} + expected map[string]interface{} + }{ + { + name: "basic property migration", + input: map[string]interface{}{ + "schemaVersion": {N-1}, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "graph", + "oldProperty": "value", + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": {N}, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "graph", + "newProperty": "value", + }, + }, + }, + }, + { + name: "edge case - missing property", + input: map[string]interface{}{ + "schemaVersion": {N-1}, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "graph", + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": {N}, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "graph", + }, + }, + }, + }, + // Add more test cases... + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := schemaversion.V{N}(context.Background(), tt.input) + require.NoError(t, err) + require.Equal(t, tt.expected, tt.input) + }) + } +} +``` + +#### Frontend Unit Tests + +Create unit tests in `DashboardMigrator.test.ts`: + +```typescript +describe('V{N} Migration', () => { + it('should migrate basic property changes', () => { + const dashboard = { + schemaVersion: {N-1}, + panels: [ + { + id: 1, + type: 'graph', + oldProperty: 'value' + } + ] + }; + + const model = new DashboardModel(dashboard); + expect(model.schemaVersion).toBe({N}); + expect(model.panels[0].newProperty).toBe('value'); + expect(model.panels[0].oldProperty).toBeUndefined(); + }); + + it('should handle edge cases correctly', () => { + const dashboard = { + schemaVersion: {N-1}, + panels: [] + }; + + const model = new DashboardModel(dashboard); + expect(model.schemaVersion).toBe({N}); + expect(model.panels).toEqual([]); + }); + + // Add more test cases... +}); +``` + + +#### Running Unit Tests + +```bash +# Backend unit tests +go test ./apps/dashboard/pkg/migration/schemaversion/... -run TestV{N} + +# Frontend unit tests +yarn test DashboardMigrator.test.ts -t "V{N}" + +# Integration tests +go test ./apps/dashboard/pkg/migration/... -run TestMigrate +yarn test DashboardMigratorToBackend.test.ts +``` + + + +## Utility Functions + +### Type Conversion +```go +// Convert various types to float64 +func ConvertToFloat(value interface{}) (float64, bool) { + // Implementation in utils.go +} + +// Get string value with default +func GetStringValue(data map[string]interface{}, key string, defaultValue string) string { + // Implementation in utils.go +} + +// Get boolean value with default +func GetBoolValue(data map[string]interface{}, key string) bool { + // Implementation in utils.go +} +``` + +### Data Access +```go +// Safe property access +if value, ok := panel["property"].(string); ok { + // Use value +} + +// Safe array access +if panels, ok := dashboard["panels"].([]interface{}); ok { + // Process panels +} +``` + +## Common Pitfalls + +### 1. Type Assertions +```go +// โŒ Wrong - can panic +value := panel["property"].(string) + +// โœ… Correct - safe type assertion +if value, ok := panel["property"].(string); ok { + // Use value +} +``` + +### 2. Null Handling +```go +// โŒ Wrong - removes intentional nulls +if value == nil { + delete(panel, "property") +} + +// โœ… Correct - preserve intentional nulls +if value == nil && !isIntentionallyNull(panel, "property") { + delete(panel, "property") +} +``` + +### 3. Nested Panel Processing +```go +// โŒ Wrong - misses nested panels +for _, panel := range panels { + migratePanel(panel) +} + +// โœ… Correct - handles nested panels +for _, panel := range panels { + migratePanelRecursively(panel) +} +``` + +## Migration Beyond v42 + +**Important**: Schema version 42 is the final version for the v1 dashboard API. For new migrations beyond v42: + +1. **Backend**: Continue adding schema versions in Go +2. **Frontend**: Use panel-specific migration handlers instead of schema versions +3. **Justification Required**: Each new migration must be properly justified +4. **v2 Transition**: Consider the impact on the transition to schema v2 + +### When to Add Schema Migrations vs Panel Migrations + +**Add Schema Migration** when: +- Changes affect dashboard-level properties +- Cross-panel transformations are needed +- Backward compatibility requires schema version increment +- **With proper justification** about why it can't be handled as panel migration + +**Use Panel-Specific Migrations** when: +- Changes are panel-type specific +- Can be handled within individual panel plugins +- Don't require dashboard-level schema changes + +## Testing Guidelines + +### Test File Naming +- Input: `v{N}.{descriptive_name}.json` +- Output: `v{N}.{descriptive_name}.v42.json` + +### Test Data Requirements +- Input schema version should be `{N-1}` +- Include comprehensive test cases +- Test edge cases and error conditions +- Use realistic dashboard data + +### Running Tests +```bash +# Run all migration tests +go test ./apps/dashboard/pkg/migration/... + +# Run specific test +go test ./apps/dashboard/pkg/migration/... -run TestMigrate + +# Run with verbose output +go test ./apps/dashboard/pkg/migration/... -v +``` + +## Comprehensive Testing Strategy + +### Backend Migration Tests + +The backend migration tests validate schema version migrations and API conversions: + +- **Schema migration tests**: Test individual schema version upgrades (v14โ†’v15, v15โ†’v16, etc.) +- **Conversion tests**: Test API version conversions with automatic metrics instrumentation +- **Test data**: Uses curated test files from `testdata/input/` covering schema versions 14-42 +- **Metrics validation**: Tests verify that conversion metrics are properly recorded + +**Test execution:** +```bash +# All backend migration tests +go test ./apps/dashboard/pkg/migration/... -v + +# Schema migration tests only +go test ./apps/dashboard/pkg/migration/ -v + +# API conversion tests with metrics +go test ./apps/dashboard/pkg/migration/conversion/... -v +``` + +### Frontend Migration Comparison Tests + +The frontend migration comparison tests validate that backend and frontend migration logic produce consistent results: + +- **Test methodology**: Compares backend vs frontend migration outputs through DashboardModel integration +- **Dataset coverage**: Tests run against 42+ curated test files spanning schema versions 14-42 +- **Test location**: `public/app/features/dashboard/state/DashboardMigratorToBackend.test.ts` +- **Test data**: Located in `apps/dashboard/pkg/migration/testdata/input/` and `testdata/output/` + +**Test execution:** +```bash +# Frontend migration comparison tests +yarn test DashboardMigratorToBackend.test.ts +``` + +**Test approach:** +- **Frontend path**: `jsonInput โ†’ DashboardModel โ†’ DashboardMigrator โ†’ getSaveModelClone()` +- **Backend path**: `jsonInput โ†’ Backend Migration โ†’ backendOutput โ†’ DashboardModel โ†’ getSaveModelClone()` +- **Comparison**: Direct comparison of final migrated states from both paths + +### Single Version Migration Testing + +The system supports both single version and full pipeline testing: + +- **Single version tests**: Test individual migrations (v15 โ†’ v16) +- **Full pipeline tests**: Test complete migration (v15 โ†’ v42) +- **Test directories**: `single_version/` vs `latest_version/` +- **Coverage**: Comprehensive testing of all migration paths + +**Test execution:** +```bash +# Single version migration tests +go test ./apps/dashboard/pkg/migration/... -run TestMigrateSingleVersion + +# Full pipeline tests +go test ./apps/dashboard/pkg/migration/... -run TestMigrate +``` + +## Resources + +- [Migration Architecture Documentation](../../../docs/migration-architecture.md) +- [Frontend Migration Guide](../../../../public/app/features/dashboard/state/README.md) +- [Test Data Examples](../testdata/input/) +- [Existing Migration Examples](./) + +## Getting Help + +- Review existing migrations for patterns +- Check test data for examples +- Consult the team for complex migrations +- Use the migration test utilities for common operations diff --git a/apps/dashboard/pkg/migration/schemaversion/angular_migration.go b/apps/dashboard/pkg/migration/schemaversion/angular_migration.go deleted file mode 100644 index 7dee79d8c29..00000000000 --- a/apps/dashboard/pkg/migration/schemaversion/angular_migration.go +++ /dev/null @@ -1,89 +0,0 @@ -package schemaversion - -var notPersistedProperties = []string{ - "events", - "isViewing", - "isEditing", - "isInView", - "hasRefreshed", - "cachedPluginOptions", - "plugin", - "queryRunner", - "replaceVariables", - "configRev", - "hasSavedPanelEditChange", - "getDisplayTitle", - "dataSupport", - "key", - "isNew", - "refreshWhenInView", -} - -var mustKeepProperties = []string{ - "id", - "gridPos", - "type", - "title", - "scopedVars", - "repeat", - "repeatPanelId", - "repeatDirection", - "repeatedByRow", - "minSpan", - "collapsed", - "panels", - "targets", - "datasource", - "timeFrom", - "timeShift", - "hideTimeOverride", - "description", - "links", - "fullscreen", - "isEditing", - "isViewing", - "hasRefreshed", - "events", - "cacheTimeout", - "queryCachingTTL", - "cachedPluginOptions", - "transparent", - "pluginVersion", - "queryRunner", - "transformations", - "fieldConfig", - "maxDataPoints", - "interval", - "replaceVariables", - "libraryPanel", - "getDisplayTitle", - "configRev", - "key", -} - -// getOptionsToRemember returns a map of panel properties that should be remembered -// during panel type changes, excluding notPersistedProperties and mustKeepProperties -func getOptionsToRemember(panel map[string]interface{}) map[string]interface{} { - // Create sets for faster lookup - notPersistedSet := make(map[string]bool) - for _, prop := range notPersistedProperties { - notPersistedSet[prop] = true - } - - mustKeepSet := make(map[string]bool) - for _, prop := range mustKeepProperties { - mustKeepSet[prop] = true - } - - // Filter the panel properties - result := make(map[string]interface{}) - for key, value := range panel { - // Skip properties that are in notPersistedProperties or mustKeepProperties - if notPersistedSet[key] || mustKeepSet[key] { - continue - } - result[key] = value - } - - return result -} diff --git a/apps/dashboard/pkg/migration/schemaversion/migrations.go b/apps/dashboard/pkg/migration/schemaversion/migrations.go index e8d50a9aecb..a278c2e685e 100644 --- a/apps/dashboard/pkg/migration/schemaversion/migrations.go +++ b/apps/dashboard/pkg/migration/schemaversion/migrations.go @@ -7,11 +7,8 @@ import ( ) const ( - MIN_VERSION = 13 + MIN_VERSION = 0 LATEST_VERSION = 42 - - // The pluginVersion to set after simulating auto-migrate for angular panels - pluginVersionForAutoMigrate = "12.1.0" ) type SchemaVersionMigrationFunc func(context.Context, map[string]interface{}) error @@ -38,6 +35,18 @@ type PanelPluginInfo struct { func GetMigrations(dsInfoProvider DataSourceInfoProvider) map[int]SchemaVersionMigrationFunc { return map[int]SchemaVersionMigrationFunc{ + 2: V2, + 3: V3, + 4: V4, + 5: V5, + 6: V6, + 7: V7, + 8: V8, + 9: V9, + 10: V10, + 11: V11, + 12: V12, + 13: V13, 14: V14, 15: V15, 16: V16, diff --git a/apps/dashboard/pkg/migration/schemaversion/v10.go b/apps/dashboard/pkg/migration/schemaversion/v10.go new file mode 100644 index 00000000000..6b218460aac --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v10.go @@ -0,0 +1,97 @@ +package schemaversion + +import "context" + +// V10 migration removes the first threshold value from table panel styles when they have 3 or more thresholds. +// This migration aligns with the frontend schema version 10 changes that addressed aliasYAxis changes +// specifically for table panels with threshold configurations. +// +// Background: +// In earlier versions, table panels stored threshold values as arrays with the first element representing +// a baseline value that was not actually used in threshold calculations. This migration removes that +// unused first element to clean up the data structure. +// +// Example before migration: +// { +// "schemaVersion": 9, +// "panels": [ +// { +// "type": "table", +// "styles": [ +// { +// "thresholds": ["10", "20", "30"] +// }, +// { +// "thresholds": ["100", "200", "300"] +// } +// ] +// } +// ] +// } +// +// Example after migration: +// { +// "schemaVersion": 10, +// "panels": [ +// { +// "type": "table", +// "styles": [ +// { +// "thresholds": ["20", "30"] +// }, +// { +// "thresholds": ["200", "300"] +// } +// ] +// } +// ] +// } + +func V10(_ context.Context, dashboard map[string]interface{}) error { + dashboard["schemaVersion"] = 10 + + panels, ok := dashboard["panels"].([]interface{}) + if !ok { + return nil + } + + for _, p := range panels { + panel, ok := p.(map[string]interface{}) + if !ok { + continue + } + + // Only process table panels + panelType := GetStringValue(panel, "type") + if panelType != "table" { + continue + } + + styles, ok := panel["styles"].([]interface{}) + if !ok { + continue + } + + // Process each style in the table panel + for _, s := range styles { + style, ok := s.(map[string]interface{}) + if !ok { + continue + } + + thresholds, ok := style["thresholds"].([]interface{}) + if !ok { + continue + } + + // Only modify thresholds if they have 3 or more values + if len(thresholds) >= 3 { + // Remove the first threshold value + newThresholds := thresholds[1:] + style["thresholds"] = newThresholds + } + } + } + + return nil +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v10_test.go b/apps/dashboard/pkg/migration/schemaversion/v10_test.go new file mode 100644 index 00000000000..a1bb57cf94f --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v10_test.go @@ -0,0 +1,209 @@ +package schemaversion_test + +import ( + "testing" + + "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" +) + +func TestV10(t *testing.T) { + tests := []migrationTestCase{ + { + name: "table panel with thresholds having 3 or more values should have first threshold removed", + input: map[string]interface{}{ + "title": "V10 Table Thresholds Migration Test Dashboard", + "schemaVersion": 9, + "panels": []interface{}{ + map[string]interface{}{ + "type": "table", + "id": 1, + "styles": []interface{}{ + map[string]interface{}{ + "thresholds": []interface{}{"10", "20", "30"}, + }, + map[string]interface{}{ + "thresholds": []interface{}{"100", "200", "300"}, + }, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V10 Table Thresholds Migration Test Dashboard", + "schemaVersion": 10, + "panels": []interface{}{ + map[string]interface{}{ + "type": "table", + "id": 1, + "styles": []interface{}{ + map[string]interface{}{ + "thresholds": []interface{}{"20", "30"}, + }, + map[string]interface{}{ + "thresholds": []interface{}{"200", "300"}, + }, + }, + }, + }, + }, + }, + { + name: "table panel with thresholds having less than 3 values should remain unchanged", + input: map[string]interface{}{ + "title": "V10 Table Thresholds No Change Test Dashboard", + "schemaVersion": 9, + "panels": []interface{}{ + map[string]interface{}{ + "type": "table", + "id": 1, + "styles": []interface{}{ + map[string]interface{}{ + "thresholds": []interface{}{"10", "20"}, + }, + map[string]interface{}{ + "thresholds": []interface{}{"100"}, + }, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V10 Table Thresholds No Change Test Dashboard", + "schemaVersion": 10, + "panels": []interface{}{ + map[string]interface{}{ + "type": "table", + "id": 1, + "styles": []interface{}{ + map[string]interface{}{ + "thresholds": []interface{}{"10", "20"}, + }, + map[string]interface{}{ + "thresholds": []interface{}{"100"}, + }, + }, + }, + }, + }, + }, + { + name: "non-table panels should remain unchanged", + input: map[string]interface{}{ + "title": "V10 Non-Table Panel Test Dashboard", + "schemaVersion": 9, + "panels": []interface{}{ + map[string]interface{}{ + "type": "graph", + "id": 1, + "styles": []interface{}{ + map[string]interface{}{ + "thresholds": []interface{}{"10", "20", "30"}, + }, + }, + }, + map[string]interface{}{ + "type": "singlestat", + "id": 2, + "styles": []interface{}{ + map[string]interface{}{ + "thresholds": []interface{}{"100", "200", "300"}, + }, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V10 Non-Table Panel Test Dashboard", + "schemaVersion": 10, + "panels": []interface{}{ + map[string]interface{}{ + "type": "graph", + "id": 1, + "styles": []interface{}{ + map[string]interface{}{ + "thresholds": []interface{}{"10", "20", "30"}, + }, + }, + }, + map[string]interface{}{ + "type": "singlestat", + "id": 2, + "styles": []interface{}{ + map[string]interface{}{ + "thresholds": []interface{}{"100", "200", "300"}, + }, + }, + }, + }, + }, + }, + { + name: "table panel without styles should remain unchanged", + input: map[string]interface{}{ + "title": "V10 Table No Styles Test Dashboard", + "schemaVersion": 9, + "panels": []interface{}{ + map[string]interface{}{ + "type": "table", + "id": 1, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V10 Table No Styles Test Dashboard", + "schemaVersion": 10, + "panels": []interface{}{ + map[string]interface{}{ + "type": "table", + "id": 1, + }, + }, + }, + }, + { + name: "table panel with styles but no thresholds should remain unchanged", + input: map[string]interface{}{ + "title": "V10 Table No Thresholds Test Dashboard", + "schemaVersion": 9, + "panels": []interface{}{ + map[string]interface{}{ + "type": "table", + "id": 1, + "styles": []interface{}{ + map[string]interface{}{ + "colorMode": "cell", + }, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V10 Table No Thresholds Test Dashboard", + "schemaVersion": 10, + "panels": []interface{}{ + map[string]interface{}{ + "type": "table", + "id": 1, + "styles": []interface{}{ + map[string]interface{}{ + "colorMode": "cell", + }, + }, + }, + }, + }, + }, + { + name: "dashboard without panels should only update schema version", + input: map[string]interface{}{ + "title": "V10 No Panels Test Dashboard", + "schemaVersion": 9, + }, + expected: map[string]interface{}{ + "title": "V10 No Panels Test Dashboard", + "schemaVersion": 10, + }, + }, + } + runMigrationTests(t, tests, schemaversion.V10) +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v11.go b/apps/dashboard/pkg/migration/schemaversion/v11.go new file mode 100644 index 00000000000..a31e13315a0 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v11.go @@ -0,0 +1,28 @@ +package schemaversion + +import "context" + +// V11 migration is a no-op migration +// It only updates the schema version to 11 +// It's created to keep the migration history consistent +// Frontend migrator doesn't have a migration for schema version 11 +// No specific migration logic is needed between schema version 10 and 11 + +// Example before migration: +// { +// "schemaVersion": 10, +// "title": "My Dashboard", +// "panels": [...] +// } + +// Example after migration: +// { +// "schemaVersion": 11, +// "title": "My Dashboard", +// "panels": [...] +// } + +func V11(_ context.Context, dashboard map[string]interface{}) error { + dashboard["schemaVersion"] = 11 + return nil +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v11_test.go b/apps/dashboard/pkg/migration/schemaversion/v11_test.go new file mode 100644 index 00000000000..d357b141639 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v11_test.go @@ -0,0 +1,38 @@ +package schemaversion_test + +import ( + "testing" + + "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" +) + +func TestV11(t *testing.T) { + tests := []migrationTestCase{ + { + name: "v11 no-op migration, updates schema version only", + input: map[string]interface{}{ + "title": "V11 No-Op Migration Test Dashboard", + "schemaVersion": 10, + "panels": []interface{}{ + map[string]interface{}{ + "type": "graph", + "title": "Panel remains unchanged", + "id": 1, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V11 No-Op Migration Test Dashboard", + "schemaVersion": 11, + "panels": []interface{}{ + map[string]interface{}{ + "type": "graph", + "title": "Panel remains unchanged", + "id": 1, + }, + }, + }, + }, + } + runMigrationTests(t, tests, schemaversion.V11) +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v12.go b/apps/dashboard/pkg/migration/schemaversion/v12.go new file mode 100644 index 00000000000..2eb97281937 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v12.go @@ -0,0 +1,66 @@ +package schemaversion + +import "context" + +// V12 migrates template variables to update their refresh and hide properties. +// This migration ensures that: +// 1. Variables with refresh=true get refresh=1, and variables with refresh=false get refresh=0 +// 2. Variables with hideVariable=true get hide=2 (hide variable) +// 3. Variables with hideLabel=true get hide=1 (hide label) +// +// Example before migration: +// +// "templating": { +// "list": [ +// { "type": "query", "name": "var1", "refresh": true, "hideVariable": true }, +// { "type": "query", "name": "var2", "refresh": false, "hideLabel": true } +// ] +// } +// +// Example after migration: +// +// "templating": { +// "list": [ +// { "type": "query", "name": "var1", "refresh": 1, "hide": 2 }, +// { "type": "query", "name": "var2", "refresh": 0, "hide": 1 } +// ] +// } +func V12(_ context.Context, dashboard map[string]interface{}) error { + dashboard["schemaVersion"] = 12 + + templating, ok := dashboard["templating"].(map[string]interface{}) + if !ok { + return nil + } + + list, ok := templating["list"].([]interface{}) + if !ok { + return nil + } + + for _, v := range list { + variable, ok := v.(map[string]interface{}) + if !ok { + continue + } + + // Update refresh property + if _, hasRefresh := variable["refresh"]; hasRefresh { + if GetBoolValue(variable, "refresh") { + variable["refresh"] = 1 + } else { + variable["refresh"] = 0 + } + } + + // Update hide property based on hideVariable and hideLabel + // hideVariable takes priority over hideLabel + if GetBoolValue(variable, "hideVariable") { + variable["hide"] = 2 + } else if GetBoolValue(variable, "hideLabel") { + variable["hide"] = 1 + } + } + + return nil +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v12_test.go b/apps/dashboard/pkg/migration/schemaversion/v12_test.go new file mode 100644 index 00000000000..eef78ee450c --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v12_test.go @@ -0,0 +1,316 @@ +package schemaversion_test + +import ( + "testing" + + "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" +) + +func TestV12(t *testing.T) { + tests := []migrationTestCase{ + { + name: "variable with refresh=true gets refresh=1", + input: map[string]interface{}{ + "title": "V12 Refresh True Test", + "schemaVersion": 11, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "refresh_true_var", + "refresh": true, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V12 Refresh True Test", + "schemaVersion": 12, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "refresh_true_var", + "refresh": 1, + }, + }, + }, + }, + }, + { + name: "variable with refresh=false gets refresh=0", + input: map[string]interface{}{ + "title": "V12 Refresh False Test", + "schemaVersion": 11, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "refresh_false_var", + "refresh": false, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V12 Refresh False Test", + "schemaVersion": 12, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "refresh_false_var", + "refresh": 0, + }, + }, + }, + }, + }, + { + name: "variable with hideVariable=true gets hide=2", + input: map[string]interface{}{ + "title": "V12 Hide Variable Test", + "schemaVersion": 11, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "hide_variable_var", + "hideVariable": true, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V12 Hide Variable Test", + "schemaVersion": 12, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "hide_variable_var", + "hideVariable": true, + "hide": 2, + }, + }, + }, + }, + }, + { + name: "variable with hideLabel=true gets hide=1", + input: map[string]interface{}{ + "title": "V12 Hide Label Test", + "schemaVersion": 11, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "hide_label_var", + "hideLabel": true, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V12 Hide Label Test", + "schemaVersion": 12, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "hide_label_var", + "hideLabel": true, + "hide": 1, + }, + }, + }, + }, + }, + { + name: "variable with both hideVariable and hideLabel prioritizes hideVariable", + input: map[string]interface{}{ + "title": "V12 Hide Priority Test", + "schemaVersion": 11, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "priority_var", + "hideVariable": true, + "hideLabel": true, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V12 Hide Priority Test", + "schemaVersion": 12, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "priority_var", + "hideVariable": true, + "hideLabel": true, + "hide": 2, + }, + }, + }, + }, + }, + { + name: "variable with no refresh or hide properties is unchanged", + input: map[string]interface{}{ + "title": "V12 No Properties Test", + "schemaVersion": 11, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "no_properties_var", + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V12 No Properties Test", + "schemaVersion": 12, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "no_properties_var", + }, + }, + }, + }, + }, + { + name: "dashboard without templating is unchanged", + input: map[string]interface{}{ + "title": "V12 No Templating Test", + "schemaVersion": 11, + }, + expected: map[string]interface{}{ + "title": "V12 No Templating Test", + "schemaVersion": 12, + }, + }, + { + name: "dashboard with empty templating list is unchanged", + input: map[string]interface{}{ + "title": "V12 Empty Templating Test", + "schemaVersion": 11, + "templating": map[string]interface{}{ + "list": []interface{}{}, + }, + }, + expected: map[string]interface{}{ + "title": "V12 Empty Templating Test", + "schemaVersion": 12, + "templating": map[string]interface{}{ + "list": []interface{}{}, + }, + }, + }, + { + name: "variables with hideVariable=false and hideLabel=false do not get hide property", + input: map[string]interface{}{ + "title": "V12 False Hide Properties Test", + "schemaVersion": 11, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "false_hide_var", + "hideVariable": false, + "hideLabel": false, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V12 False Hide Properties Test", + "schemaVersion": 12, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "false_hide_var", + "hideVariable": false, + "hideLabel": false, + }, + }, + }, + }, + }, + { + name: "variable with hideVariable=false but hideLabel=true gets hide=1", + input: map[string]interface{}{ + "title": "V12 Mixed Hide Properties Test", + "schemaVersion": 11, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "mixed_hide_var", + "hideVariable": false, + "hideLabel": true, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V12 Mixed Hide Properties Test", + "schemaVersion": 12, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "mixed_hide_var", + "hideVariable": false, + "hideLabel": true, + "hide": 1, + }, + }, + }, + }, + }, + { + name: "variable with all properties gets all migrations applied", + input: map[string]interface{}{ + "title": "V12 All Properties Test", + "schemaVersion": 11, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "all_properties_var", + "refresh": true, + "hideVariable": true, + "hideLabel": false, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V12 All Properties Test", + "schemaVersion": 12, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "type": "query", + "name": "all_properties_var", + "refresh": 1, + "hideVariable": true, + "hideLabel": false, + "hide": 2, + }, + }, + }, + }, + }, + } + + runMigrationTests(t, tests, schemaversion.V12) +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v13.go b/apps/dashboard/pkg/migration/schemaversion/v13.go new file mode 100644 index 00000000000..791c3576022 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v13.go @@ -0,0 +1,11 @@ +package schemaversion + +import ( + "context" +) + +// V13 is a no-op migration +func V13(_ context.Context, dashboard map[string]interface{}) error { + dashboard["schemaVersion"] = 13 + return nil +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v13_test.go b/apps/dashboard/pkg/migration/schemaversion/v13_test.go new file mode 100644 index 00000000000..729bcb25120 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v13_test.go @@ -0,0 +1,38 @@ +package schemaversion_test + +import ( + "testing" + + "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" +) + +func TestV13(t *testing.T) { + tests := []migrationTestCase{ + { + name: "v13 no-op migration, updates schema version only", + input: map[string]interface{}{ + "title": "V13 No-Op Migration Test Dashboard", + "schemaVersion": 12, + "panels": []interface{}{ + map[string]interface{}{ + "type": "graph", + "title": "Panel remains unchanged", + "id": 1, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V13 No-Op Migration Test Dashboard", + "schemaVersion": 13, + "panels": []interface{}{ + map[string]interface{}{ + "type": "graph", + "title": "Panel remains unchanged", + "id": 1, + }, + }, + }, + }, + } + runMigrationTests(t, tests, schemaversion.V13) +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v16.go b/apps/dashboard/pkg/migration/schemaversion/v16.go index da6db1dcc1a..779498e864a 100644 --- a/apps/dashboard/pkg/migration/schemaversion/v16.go +++ b/apps/dashboard/pkg/migration/schemaversion/v16.go @@ -271,19 +271,30 @@ func (r *rowArea) getPanelPosition(panelHeight int, panelWidth int) map[string]i func getMaxPanelID(rows []interface{}) int { maxID := 0 + hasValidID := false + for _, rowInterface := range rows { if row, ok := rowInterface.(map[string]interface{}); ok { if panels, ok := row["panels"].([]interface{}); ok { for _, panelInterface := range panels { if panel, ok := panelInterface.(map[string]interface{}); ok { - if id := GetIntValue(panel, "id", 0); id > maxID { - maxID = id + if id := GetIntValue(panel, "id", 0); id > 0 { + hasValidID = true + if id > maxID { + maxID = id + } } } } } } } + + // If no valid IDs found, return 0 (matches frontend behavior) + if !hasValidID { + return 0 + } + return maxID } @@ -327,7 +338,9 @@ func calculatePanelDimensionsFromSpan(span float64, panel map[string]interface{} } } - panelWidth := int(math.Floor(span * widthFactor)) + // Match frontend logic: Math.floor(panel.span) * widthFactor (line 914 in DashboardMigrator.ts) + // Frontend floors the span FIRST, then multiplies by widthFactor + panelWidth := int(math.Floor(span)) * int(widthFactor) panelHeight := defaultHeight if panelHeightValue, hasHeight := panel["height"]; hasHeight { diff --git a/apps/dashboard/pkg/migration/schemaversion/v16_test.go b/apps/dashboard/pkg/migration/schemaversion/v16_test.go index 007e912fc85..57d758c81cb 100644 --- a/apps/dashboard/pkg/migration/schemaversion/v16_test.go +++ b/apps/dashboard/pkg/migration/schemaversion/v16_test.go @@ -1649,6 +1649,65 @@ func TestV16(t *testing.T) { }, }, }, + { + name: "should correctly calculate panel width from fractional spans", + input: map[string]interface{}{ + "schemaVersion": 15, + "rows": []interface{}{ + map[string]interface{}{ + "collapse": false, + "height": 55.625 * 38, // Original height from oldest-historical-1913-dashboard-nobreak.json + "panels": []interface{}{ + map[string]interface{}{ + "id": 3, + "type": "text", + "title": "Nobreak APC Modulo - X", + "span": 6.070139911634757, // Fractional span from real dashboard + }, + map[string]interface{}{ + "id": 5, + "type": "text", + "title": "Nobreak APC Modulo - Y", + "span": 5.929860088365242, // Fractional span from real dashboard + }, + }, + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 16, + "panels": []interface{}{ + map[string]interface{}{ + "id": 3, + "type": "text", + "title": "Nobreak APC Modulo - X", + "gridPos": map[string]interface{}{ + "x": 0, + "y": 0, + // Critical: Frontend logic Math.floor(6.070139911634757) * 2 = 6 * 2 = 12 + // NOT Math.floor(6.070139911634757 * 2) = Math.floor(12.140279823269514) = 12 + // Both give same result here, but test documents the correct order + "w": 12, + "h": 56, // ceil(55.625 * 38 / 38) = 56 + }, + }, + map[string]interface{}{ + "id": 5, + "type": "text", + "title": "Nobreak APC Modulo - Y", + "gridPos": map[string]interface{}{ + "x": 12, + "y": 0, + // Critical: Frontend logic Math.floor(5.929860088365242) * 2 = 5 * 2 = 10 + // NOT Math.floor(5.929860088365242 * 2) = Math.floor(11.859720176730484) = 11 + // This is the actual bug we fixed - old backend would give w: 11, new gives w: 10 + "w": 10, + "h": 56, + }, + }, + }, + }, + }, } runMigrationTests(t, tests, schemaversion.V16) diff --git a/apps/dashboard/pkg/migration/schemaversion/v2.go b/apps/dashboard/pkg/migration/schemaversion/v2.go new file mode 100644 index 00000000000..4e9636ad808 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v2.go @@ -0,0 +1,71 @@ +package schemaversion + +import "context" + +// V2 migrates dashboard from schema version 0 or 1 to 2. +// This migration handles the legacy services.filter structure. +// It matches the frontend DashboardMigrator.ts logic for oldVersion < 2 && finalTargetVersion >= 2. +// +// Key migrations: +// 1. Services filter migration: old.services.filter.time -> dashboard.time +// 2. Services filter migration: old.services.filter.list -> dashboard.templating.list +// +// Example before migration: +// +// { +// "schemaVersion": 1, +// "services": { +// "filter": { +// "time": {"from": "now-1h", "to": "now"}, +// "list": [{"name": "var1", "type": "query"}] +// } +// } +// } +// +// Example after migration: +// +// { +// "schemaVersion": 2, +// "time": {"from": "now-1h", "to": "now"}, +// "templating": { +// "list": [{"name": "var1", "type": "query"}] +// } +// } +func V2(_ context.Context, dashboard map[string]interface{}) error { + dashboard["schemaVersion"] = 2 + + // Migrate services.filter structure + migrateServicesFilter(dashboard) + + return nil +} + +// migrateServicesFilter migrates the legacy services.filter structure +func migrateServicesFilter(dashboard map[string]interface{}) { + services, ok := dashboard["services"].(map[string]interface{}) + if !ok { + return + } + + filter, ok := services["filter"].(map[string]interface{}) + if !ok { + return + } + + // Migrate time property + if time, ok := filter["time"]; ok { + dashboard["time"] = time + } + + // Migrate templating list + if list, ok := filter["list"]; ok { + if _, exists := dashboard["templating"]; !exists { + dashboard["templating"] = map[string]interface{}{} + } + templating := dashboard["templating"].(map[string]interface{}) + templating["list"] = list + } + + // Remove the services property after migration + delete(dashboard, "services") +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v24.go b/apps/dashboard/pkg/migration/schemaversion/v24.go index 4526e23d15e..d9b4dd59ed4 100644 --- a/apps/dashboard/pkg/migration/schemaversion/v24.go +++ b/apps/dashboard/pkg/migration/schemaversion/v24.go @@ -2,189 +2,59 @@ package schemaversion import ( "context" - "strconv" ) -// V24 migration migrates the angular table panel to the standard table panel -// In the frontend, this is an auto-migration meaning that this angular panel is always migrated to table panel. -// The backend replicates the complete frontend auto-migration logic since it cannot rely on frontend auto-migration. -// -// This migration performs: -// 1. Converts 'styles' array to 'fieldConfig' with 'defaults' and 'overrides' -// 2. Migrates thresholds and colors to new threshold format -// 3. Converts column-specific styles to field overrides -// 4. Migrates transformations from old format to new transformation system -// 5. Handles various style properties: unit, decimals, alignment, color modes, links, date formatting, hidden columns -// 6. Removes deprecated properties: styles, transform, columns +// V24 migration handles setting autoMigrateFrom +// This is a hacky way that matches frontend's logic +// For reason see https://github.com/grafana/grafana/pull/102146 +// The issue is that if panel is "table" and it has styles, it should be migrated to "table-old" -// Example 1: Basic table with defaults -// Before migration: +// Example before migration: // { -// "panels": [ -// { -// "id": 1, -// "type": "table", -// "title": "Basic Table", -// "styles": [ -// { -// "pattern": "/.*/", -// "thresholds": ["10", "20", "30"], -// "colors": ["green", "yellow", "red"], -// "unit": "bytes", -// "decimals": 2 -// } -// ], -// "targets": [{ "refId": "A" }] -// } -// ] +// "id": 4, +// "type": "table", +// "title": "Table with Timeseries to Rows Transform", +// "description": "Tests migration of timeseries_to_rows transform to seriesToRows transformation.", +// "styles": [ +// { +// "pattern": "/.*/", +// "unit": "short" +// } +// ], +// "transform": "timeseries_to_rows", +// "targets": [{ "refId": "A" }] // } // -// After migration: +// Example after migration: // { -// "panels": [ -// { -// "id": 1, -// "type": "table", -// "title": "Basic Table", -// "fieldConfig": { -// "defaults": { -// "unit": "bytes", -// "decimals": 2, -// "custom": {}, -// "thresholds": { -// "mode": "absolute", -// "steps": [ -// { "color": "green", "value": null }, -// { "color": "green", "value": 10 }, -// { "color": "yellow", "value": 20 }, -// { "color": "red", "value": 30 } -// ] -// } -// }, -// "overrides": [] -// }, -// "transformations": [], -// "targets": [{ "refId": "A" }], -// "pluginVersion": "{current_grafana_version}" -// } -// ] -// } - -// Example 2: Complex table with overrides and transformations -// Before migration: -// { -// "panels": [ -// { -// "id": 2, -// "type": "table", -// "title": "Complex Table", -// "styles": [ -// { -// "pattern": "/.*/", -// "unit": "percent", -// "align": "center", -// "colorMode": "cell" -// }, -// { -// "pattern": "Status", -// "alias": "Current Status", -// "colorMode": "value", -// "align": "left" -// }, -// { -// "pattern": "/Error.*/", -// "link": true, -// "linkUrl": "http://example.com/errors", -// "linkTooltip": "View errors", -// "linkTargetBlank": true -// }, -// { -// "pattern": "Time", -// "type": "date", -// "dateFormat": "YYYY-MM-DD HH:mm:ss", -// "alias": "Timestamp" -// }, -// { -// "pattern": "Hidden", -// "type": "hidden" -// } -// ], -// "transform": "timeseries_aggregations", -// "columns": [ -// { "value": "avg", "text": "Average" }, -// { "value": "max", "text": "Maximum" } -// ], -// "targets": [{ "refId": "A" }] -// } -// ] -// } -// -// After migration: -// { -// "panels": [ -// { -// "id": 2, -// "type": "table", -// "title": "Complex Table", -// "fieldConfig": { -// "defaults": { -// "unit": "percent", -// "custom": { -// "align": "center", -// "cellOptions": { "type": "color-background" } -// } -// }, -// "overrides": [ -// { -// "matcher": { "id": "byName", "options": "Status" }, -// "properties": [ -// { "id": "displayName", "value": "Current Status" }, -// { "id": "custom.cellOptions", "value": { "type": "color-text" } }, -// { "id": "custom.align", "value": "left" } -// ] -// }, -// { -// "matcher": { "id": "byRegexp", "options": "/Error.*/" }, -// "properties": [ -// { -// "id": "links", -// "value": [{ -// "title": "View errors", -// "url": "http://example.com/errors", -// "targetBlank": true -// }] -// } -// ] -// }, -// { -// "matcher": { "id": "byName", "options": "Time" }, -// "properties": [ -// { "id": "displayName", "value": "Timestamp" }, -// { "id": "unit", "value": "time: YYYY-MM-DD HH:mm:ss" } -// ] -// }, -// { -// "matcher": { "id": "byName", "options": "Hidden" }, -// "properties": [ -// { "id": "custom.hideFrom.viz", "value": true } -// ] -// } -// ] -// }, -// "transformations": [ -// { -// "id": "reduce", -// "options": { -// "reducers": ["mean", "max"], -// "includeTimeField": false -// } -// } -// ], -// "targets": [{ "refId": "A" }], -// "pluginVersion": "{current_grafana_version}" -// } -// ] -// } +// "autoMigrateFrom": "table-old", +// "datasource": { +// "apiVersion": "v1", +// "type": "prometheus", +// "uid": "default-ds-uid" +// }, +// "description": "Tests migration of timeseries_to_rows transform to seriesToRows transformation.", +// "id": 4, +// "styles": [ +// { +// "pattern": "/.*/", +// "unit": "short" +// } +// ], +// "targets": [ +// { +// "datasource": { +// "apiVersion": "v1", +// "type": "prometheus", +// "uid": "default-ds-uid" +// }, +// "refId": "A" +// } +// ], +// "title": "Table with Timeseries to Rows Transform", +// "transform": "timeseries_to_rows", +// "type": "table" +// } func V24(_ context.Context, dashboard map[string]interface{}) error { dashboard["schemaVersion"] = 24 @@ -211,406 +81,18 @@ func V24(_ context.Context, dashboard map[string]interface{}) error { continue } - // The grafana version that matches the hardcoded autoMigrate plugins - panelMap["pluginVersion"] = pluginVersionForAutoMigrate - err := tablePanelChangedHandler(panelMap) - if err != nil { - return err - } - } - - return nil -} - -func tablePanelChangedHandler(panel map[string]interface{}) error { - prevOptions := getOptionsToRemember(panel) - - transformations := migrateTransformations(panel, prevOptions) - - prevDefaults := findDefaultStyle(prevOptions) - defaults := migrateDefaults(prevDefaults) - - overrides := findNonDefaultStyles(prevOptions) - - if len(overrides) == 0 { - overrides = []interface{}{} - } - - // Only add transformations if they're not empty - frontend omits empty arrays - if len(transformations) > 0 { - panel["transformations"] = transformations - } - panel["fieldConfig"] = map[string]interface{}{ - "defaults": defaults, - "overrides": overrides, - } - - // Add minimal table panel options to match frontend behavior - // Frontend doesn't add default footer options, so we don't either - panel["options"] = map[string]interface{}{ - "cellHeight": "sm", - "showHeader": true, - } - - // Remove deprecated properties - delete(panel, "styles") - delete(panel, "transform") - delete(panel, "columns") - - // Remove legend property - frontend table panel migration doesn't preserve it - delete(panel, "legend") - - return nil -} - -// findDefaultStyle finds the style with pattern '/.*/' (default style) -func findDefaultStyle(prevOptions map[string]interface{}) map[string]interface{} { - if styles, ok := prevOptions["styles"].([]interface{}); ok { - for _, style := range styles { - if styleMap, ok := style.(map[string]interface{}); ok { - if pattern, ok := styleMap["pattern"].(string); ok && pattern == "/.*/" { - return styleMap - } - } - } - } - return nil -} - -// findNonDefaultStyles finds all styles that don't have pattern '/.*/' -func findNonDefaultStyles(prevOptions map[string]interface{}) []interface{} { - var overrides []interface{} - - if styles, ok := prevOptions["styles"].([]interface{}); ok { - for _, style := range styles { - if styleMap, ok := style.(map[string]interface{}); ok { - if pattern, ok := styleMap["pattern"].(string); ok && pattern != "/.*/" { - override := migrateTableStyleToOverride(styleMap) - overrides = append(overrides, override) - } - } - } - } - return overrides -} - -// migrateTransformations converts old table transformations to new format -func migrateTransformations(panel map[string]interface{}, oldOpts map[string]interface{}) []interface{} { - transformations := []interface{}{} - if existing, ok := panel["transformations"].([]interface{}); ok { - transformations = existing - } - - // Check if oldOpts has a transform that we can map - if transform, ok := oldOpts["transform"].(string); ok { - if newTransformID, exists := transformsMap[transform]; exists { - opts := map[string]interface{}{ - "reducers": []interface{}{}, - } - - // Handle timeseries_aggregations specifically - if transform == "timeseries_aggregations" { - opts["includeTimeField"] = false - - // Map columns to reducers - if columns, ok := oldOpts["columns"].([]interface{}); ok { - var reducers []interface{} - for _, column := range columns { - if columnMap, ok := column.(map[string]interface{}); ok { - if value, ok := columnMap["value"].(string); ok { - if reducer, exists := columnsMap[value]; exists { - reducers = append(reducers, reducer) - } - } - } - } - opts["reducers"] = reducers - } - } - - // Add the transformation - transformation := map[string]interface{}{ - "id": newTransformID, - "options": opts, - } - transformations = append(transformations, transformation) - } - } - - return transformations -} - -// transformsMap maps old transform names to new transformation IDs -var transformsMap = map[string]string{ - "timeseries_to_rows": "seriesToRows", - "timeseries_to_columns": "seriesToColumns", - "timeseries_aggregations": "reduce", - "table": "merge", -} - -// columnsMap maps old column values to new reducer names -var columnsMap = map[string]string{ - "avg": "mean", - "min": "min", - "max": "max", - "total": "sum", - "current": "lastNotNull", - "count": "count", -} - -// migrateTableStyleToOverride converts a table style to a field config override -func migrateTableStyleToOverride(style map[string]interface{}) map[string]interface{} { - pattern, _ := style["pattern"].(string) - - // Determine field matcher ID based on pattern - fieldMatcherID := "byName" - if pattern != "" && len(pattern) >= 2 && pattern[0] == '/' && pattern[len(pattern)-1] == '/' { - fieldMatcherID = "byRegexp" - } - - override := map[string]interface{}{ - "matcher": map[string]interface{}{ - "id": fieldMatcherID, - "options": pattern, - }, - "properties": []interface{}{}, - } - - properties := override["properties"].([]interface{}) - - // Add display name - if alias, ok := style["alias"].(string); ok && alias != "" { - properties = append(properties, map[string]interface{}{ - "id": "displayName", - "value": alias, - }) - } - - // Add unit - if unit, ok := style["unit"].(string); ok && unit != "" { - properties = append(properties, map[string]interface{}{ - "id": "unit", - "value": unit, - }) - } - - // Add decimals - if decimals := GetIntValue(style, "decimals", -1); decimals != -1 { - properties = append(properties, map[string]interface{}{ - "id": "decimals", - "value": decimals, - }) - } - - // Handle date type - if styleType, ok := style["type"].(string); ok && styleType == "date" { - if dateFormat, ok := style["dateFormat"].(string); ok { - properties = append(properties, map[string]interface{}{ - "id": "unit", - "value": "time: " + dateFormat, - }) - } - } - - // Handle hidden type - if styleType, ok := style["type"].(string); ok && styleType == "hidden" { - properties = append(properties, map[string]interface{}{ - "id": "custom.hideFrom.viz", - "value": true, - }) - } - - // Handle links - if link, ok := style["link"].(bool); ok && link { - linkTooltip, _ := style["linkTooltip"].(string) - linkUrl, _ := style["linkUrl"].(string) - linkTargetBlank, _ := style["linkTargetBlank"].(bool) - - properties = append(properties, map[string]interface{}{ - "id": "links", - "value": []interface{}{ - map[string]interface{}{ - "title": linkTooltip, - "url": linkUrl, - "targetBlank": linkTargetBlank, - }, - }, - }) - } - - // Handle color mode - if colorMode, ok := style["colorMode"].(string); ok && colorMode != "" { - if newColorMode, exists := colorModeMap[colorMode]; exists { - properties = append(properties, map[string]interface{}{ - "id": "custom.cellOptions", - "value": map[string]interface{}{ - "type": newColorMode, - }, - }) - } - } - - // Handle alignment - if align, ok := style["align"].(string); ok && align != "" { - var alignValue interface{} - if align == "auto" { - alignValue = nil // Frontend sets to null and filters it out + var currentType string + if wasAngularTable { + currentType = "table-old" } else { - alignValue = align + currentType = "table" } - properties = append(properties, map[string]interface{}{ - "id": "custom.align", - "value": alignValue, - }) - } - // Handle thresholds - if thresholds, ok := style["thresholds"].([]interface{}); ok && len(thresholds) > 0 { - if colors, ok := style["colors"].([]interface{}); ok && len(colors) > 0 { - steps := generateThresholds(thresholds, colors) - properties = append(properties, map[string]interface{}{ - "id": "thresholds", - "value": map[string]interface{}{ - "mode": "absolute", - "steps": steps, - }, - }) + if currentType == "table-old" { + panelMap["autoMigrateFrom"] = "table-old" + panelMap["type"] = "table" } } - override["properties"] = properties - return override -} - -// migrateDefaults converts default table styles to field config defaults -func migrateDefaults(prevDefaults map[string]interface{}) map[string]interface{} { - defaults := map[string]interface{}{ - "custom": map[string]interface{}{ - "align": "auto", - "cellOptions": map[string]interface{}{ - "type": "auto", - }, - "inspect": false, - "footer": map[string]interface{}{ - "reducers": []interface{}{}, - }, - }, - "mappings": []interface{}{}, - } - - // Add default thresholds for all table panels to match frontend behavior - // The frontend applies the table panel's default field config which includes thresholds - hasThresholds := false - if prevDefaults != nil { - if thresholds, ok := prevDefaults["thresholds"].([]interface{}); ok && len(thresholds) > 0 { - hasThresholds = true - } - } - - // Add default thresholds for all table panels (when prevDefaults exists) without existing thresholds - if !hasThresholds { - defaults["thresholds"] = map[string]interface{}{ - "mode": "absolute", - "steps": []interface{}{ - map[string]interface{}{"color": "green", "value": (*float64)(nil)}, - map[string]interface{}{"color": "red", "value": 80}, - }, - } - } - - if prevDefaults == nil { - return defaults - } - - if unit := GetStringValue(prevDefaults, "unit"); unit != "" { - defaults["unit"] = unit - } - - if decimals := GetIntValue(prevDefaults, "decimals", -1); decimals != -1 { - defaults["decimals"] = decimals - } - - if alias, ok := prevDefaults["alias"].(string); ok { - defaults["displayName"] = alias - } - - if align, ok := prevDefaults["align"].(string); ok && align != "" { - var alignValue interface{} - if align == "auto" { - alignValue = nil // Frontend sets to null and filters it out - } else { - alignValue = align - } - defaults["custom"].(map[string]interface{})["align"] = alignValue - } - - if thresholds, ok := prevDefaults["thresholds"].([]interface{}); ok && len(thresholds) > 0 { - if colors, ok := prevDefaults["colors"].([]interface{}); ok && len(colors) > 0 { - steps := generateThresholds(thresholds, colors) - defaults["thresholds"] = map[string]interface{}{ - "mode": "absolute", - "steps": steps, - } - } - } - - if colorMode, ok := prevDefaults["colorMode"].(string); ok && colorMode != "" { - if newColorMode, exists := colorModeMap[colorMode]; exists { - defaults["custom"].(map[string]interface{})["cellOptions"] = map[string]interface{}{ - "type": newColorMode, - } - } - } - - return defaults -} - -func generateThresholds(thresholds []interface{}, colors []interface{}) []interface{} { - steps := []interface{}{} - - // Add the base step (equivalent to -Infinity) - var baseColor interface{} = "red" // default fallback - if len(colors) > 0 && colors[0] != nil { - baseColor = colors[0] - } - - steps = append(steps, map[string]interface{}{ - "color": baseColor, - "value": (*float64)(nil), - }) - - // Add threshold steps - for i, threshold := range thresholds { - var value float64 - switch v := threshold.(type) { - case string: - if parsed, err := strconv.ParseFloat(v, 64); err == nil { - value = parsed - } - case float64: - value = v - case int: - value = float64(v) - } - - step := map[string]interface{}{ - "value": value, - } - - // Only add color if there's a corresponding color in the colors array - // This matches the frontend behavior where colors[idx] might be undefined - if i+1 < len(colors) && colors[i+1] != nil { - step["color"] = colors[i+1] - } - - steps = append(steps, step) - } - - return steps -} - -var colorModeMap = map[string]string{ - "cell": "color-background", - "row": "color-background", - "value": "color-text", + return nil } diff --git a/apps/dashboard/pkg/migration/schemaversion/v24_test.go b/apps/dashboard/pkg/migration/schemaversion/v24_test.go index 45bbf0b1df2..9abec040221 100644 --- a/apps/dashboard/pkg/migration/schemaversion/v24_test.go +++ b/apps/dashboard/pkg/migration/schemaversion/v24_test.go @@ -44,6 +44,16 @@ func TestV24TablePanelMigration(t *testing.T) { }, description: "V24 migration should not add empty transformations arrays to table panels", }, + { + name: "migrate_table_old_to_table", + input: map[string]interface{}{ + "type": "table-old", + }, + expected: map[string]interface{}{ + "type": "table", + }, + description: "V24 migration should migrate table-old to table", + }, } for _, tt := range tests { diff --git a/apps/dashboard/pkg/migration/schemaversion/v28.go b/apps/dashboard/pkg/migration/schemaversion/v28.go index 2144ae65959..d1f3bab6e37 100644 --- a/apps/dashboard/pkg/migration/schemaversion/v28.go +++ b/apps/dashboard/pkg/migration/schemaversion/v28.go @@ -2,61 +2,32 @@ package schemaversion import ( "context" - "fmt" - "strconv" - "strings" ) -// V28 migrates singlestat panels to stat/gauge panels and removes deprecated variable properties. -// -// The migration performs two main tasks: -// 1. Migrates singlestat panels to either stat or gauge panels based on their configuration -// 2. Removes deprecated variable properties (tags, tagsQuery, tagValuesQuery, useTags) -// -// The migration includes comprehensive logic from the frontend: -// - Panel type migration (singlestat -> stat/gauge) -// - Field config migration with thresholds, mappings, and display options -// - Options migration including reduceOptions, orientation, and other panel-specific settings -// - Support for both angular singlestat and grafana-singlestat-panel migrations +// V28 removes deprecated variable properties (tags, tagsQuery, tagValuesQuery, useTags) // // Example before migration: // -// "panels": [ -// { -// "type": "singlestat", -// "gauge": { "show": true }, -// "targets": [{ "refId": "A" }] -// } -// ], -// "templating": { -// "list": [ -// { "name": "var1", "tags": ["tag1"], "tagsQuery": "query", "tagValuesQuery": "values", "useTags": true } -// ] +// { +// "templating": { +// "list": [ +// { "name": "var1", "tags": ["tag1"], "tagsQuery": "query", "tagValuesQuery": "values", "useTags": true } +// ] +// } // } // // Example after migration: // -// "panels": [ -// { -// "type": "gauge", -// "targets": [{ "refId": "A" }] -// } -// ], -// "templating": { -// "list": [ -// { "name": "var1" } -// ] +// { +// "templating": { +// "list": [ +// { "name": "var1" } +// ] +// } // } func V28(_ context.Context, dashboard map[string]interface{}) error { dashboard["schemaVersion"] = 28 - // Migrate singlestat panels - if panels, ok := dashboard["panels"].([]interface{}); ok { - if err := processPanels(panels); err != nil { - return err - } - } - // Remove deprecated variable properties if templating, ok := dashboard["templating"].(map[string]interface{}); ok { if list, ok := templating["list"].([]interface{}); ok { @@ -71,751 +42,6 @@ func V28(_ context.Context, dashboard map[string]interface{}) error { return nil } -func processPanels(panels []interface{}) error { - for _, panel := range panels { - p, ok := panel.(map[string]interface{}) - if !ok { - continue - } - - // Process nested panels if this is a row panel - if p["type"] == "row" { - if nestedPanels, ok := p["panels"].([]interface{}); ok { - if err := processPanels(nestedPanels); err != nil { - return err - } - } - continue - } - - // Migrate singlestat panels (including those already auto-migrated to stat) - if p["type"] == "singlestat" || p["type"] == "grafana-singlestat-panel" || - p["autoMigrateFrom"] == "singlestat" || p["autoMigrateFrom"] == "grafana-singlestat-panel" { - if err := migrateSinglestatPanel(p); err != nil { - return err - } - } - - // Note: Panel defaults (including options object) are already applied - // by applyPanelDefaults() in the main migration flow for ALL panels - // No need for stat-specific normalization - } - - return nil -} - -func migrateSinglestatPanel(panel map[string]interface{}) error { - targetType := "stat" - - // NOTE: The legacy types "singlestat" and "gauge" are both angular only - // This are not supported by any version that could run this migration, so there is - // no need to maintain a distinction or fallback to the non-stat version - - // NOTE: DashboardMigrator's migrateSinglestat function has some logic that never gets called - // migrateSinglestat will only run if (panel.type === 'singlestat') - // but this will not be the case because PanelModel runs restoreModel in the constructor - // and since singlestat is in the autoMigrateAngular map, it will be migrated to stat, - // and therefore migrateSinglestat will never run so this logic inside of it will never apply - // if ((panel as any).gauge?.show) { - // gaugePanelPlugin.meta = config.panels['gauge'] - // panel.changePlugin(gaugePanelPlugin) - - // Store original type for migration context (only for stat/gauge migration) - // Set autoMigrateFrom to track the original type for proper migration logic - originalType := panel["type"].(string) - // Only set autoMigrateFrom if it doesn't already exist (preserve frontend defaults) - if _, exists := panel["autoMigrateFrom"]; !exists { - panel["autoMigrateFrom"] = originalType - } - panel["type"] = targetType - panel["pluginVersion"] = pluginVersionForAutoMigrate - - // Migrate panel options and field config - migrateSinglestatOptions(panel, originalType) - - return nil -} - -// migrateSinglestatOptions handles the complete migration of singlestat panel options and field config -func migrateSinglestatOptions(panel map[string]interface{}, originalType string) { - // Preserve important panel-level properties that should not be removed - // These properties are preserved by the frontend's getSaveModel() method - var maxDataPoints interface{} - if mdp, exists := panel["maxDataPoints"]; exists { - maxDataPoints = mdp - } - - // Initialize field config if not present - if panel["fieldConfig"] == nil { - panel["fieldConfig"] = map[string]interface{}{ - "defaults": map[string]interface{}{}, - "overrides": []interface{}{}, - } - } - - fieldConfig := panel["fieldConfig"].(map[string]interface{}) - defaults := fieldConfig["defaults"].(map[string]interface{}) - - // Migrate from angular singlestat configuration using appropriate strategy - // Use autoMigrateFrom if available, otherwise use originalType - migrationType := originalType - if autoMigrateFrom, exists := panel["autoMigrateFrom"].(string); exists { - migrationType = autoMigrateFrom - } - - if migrationType == "grafana-singlestat-panel" { - migrateGrafanaSinglestatPanel(panel, defaults) - } else { - migratetSinglestat(panel, defaults) - } - - // Apply shared migration logic - applySharedSinglestatMigration(defaults) - - // Apply complete stat panel defaults (matches frontend getPanelOptionsWithDefaults) - // The frontend applies these defaults after migration via applyPluginOptionDefaults - applyCompleteStatPanelDefaults(panel) - - // Create proper fieldConfig structure from defaults - createFieldConfigFromDefaults(panel, defaults) - - // Restore preserved panel-level properties - if maxDataPoints != nil { - panel["maxDataPoints"] = maxDataPoints - } - - // Clean up old angular properties after migration - cleanupAngularProperties(panel) -} - -// getDefaultStatOptions returns the default options structure for stat panels -// This matches the frontend's stat panel defaultOptions exactly -func getDefaultStatOptions() map[string]interface{} { - // For now, return the explicit defaults until we integrate the centralized system - return map[string]interface{}{ - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "percentChangeColorMode": "standard", - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true, - "reduceOptions": map[string]interface{}{ - "calcs": []string{"lastNotNull"}, // Matches frontend: ReducerID.lastNotNull - "fields": "", - "values": false, - }, - "orientation": "auto", - } -} - -// migratetSinglestat handles explicit migration from 'singlestat' panels -// Based on frontend migrateFromAngularSinglestat function -func migratetSinglestat(panel map[string]interface{}, defaults map[string]interface{}) { - angularOpts := extractAngularOptions(panel) - - // Extract valueName for reducer mapping (matches frontend migrateFromAngularSinglestat) - var valueName string - if vn, ok := angularOpts["valueName"].(string); ok { - valueName = vn - } - - // Set calcs based on valueName (matches frontend: calcs: [reducer ? reducer.id : ReducerID.mean]) - var calcs []string - if reducer := getReducerForValueName(valueName); reducer != "" { - calcs = []string{reducer} - } else { - // Use mean as fallback (matches frontend migrateFromAngularSinglestat: ReducerID.mean) - calcs = []string{"mean"} - } - - // Create options exactly like frontend migrateFromAngularSinglestat - options := map[string]interface{}{ - "reduceOptions": map[string]interface{}{ - "calcs": calcs, - "fields": "", - "values": false, - }, - "orientation": "horizontal", // Matches frontend migrateFromAngularSinglestat: VizOrientation.Horizontal - } - - // Migrate thresholds FIRST (consolidated: both panel types create DEFAULT_THRESHOLDS for empty strings) - migrateThresholds(angularOpts, defaults) - - // If no thresholds were set from angular migration, add default stat panel thresholds - // This matches the behavior of frontend pluginLoaded which adds default thresholds - if _, hasThresholds := defaults["thresholds"]; !hasThresholds { - defaults["thresholds"] = map[string]interface{}{ - "mode": "absolute", - "steps": []interface{}{ - map[string]interface{}{ - "color": "green", - "value": (*float64)(nil), - }, - map[string]interface{}{ - "color": "red", - "value": 80, - }, - }, - } - } - - // Apply common angular option migrations (value mappings can now use threshold colors) - applyCommonAngularMigration(panel, defaults, options, angularOpts) - - // Merge new options with existing panel options to preserve properties like maxDataPoints - if existingOptions, exists := panel["options"].(map[string]interface{}); exists { - for key, value := range options { - existingOptions[key] = value - } - } else { - panel["options"] = options - } -} - -// migrateGrafanaSinglestatPanel handles auto-migration from 'grafana-singlestat-panel' -// Uses the same migration logic as singlestat panels since the frontend applies -// migrateFromAngularSinglestat to both panel types. -func migrateGrafanaSinglestatPanel(panel map[string]interface{}, defaults map[string]interface{}) { - migratetSinglestat(panel, defaults) -} - -// migrateThresholds handles threshold migration for both singlestat panel types -// Both panel types now create DEFAULT_THRESHOLDS when threshold string is empty (consolidated behavior) -func migrateThresholds(angularOpts map[string]interface{}, defaults map[string]interface{}) { - if thresholds, ok := angularOpts["thresholds"].(string); ok { - if colors, ok := angularOpts["colors"].([]interface{}); ok { - if thresholds != "" { - // Non-empty thresholds: use normal migration - migrateThresholdsAndColors(defaults, thresholds, colors) - } else { - // Empty thresholds: use frontend DEFAULT_THRESHOLDS fallback (both panel types) - defaults["thresholds"] = map[string]interface{}{ - "mode": "absolute", - "steps": []interface{}{ - map[string]interface{}{ - "color": "green", - "value": (*float64)(nil), // Use pointer to ensure field is present in JSON - }, - map[string]interface{}{ - "color": "red", - "value": 80, - }, - }, - } - } - } - } -} - -// applyCommonAngularMigration applies migrations common to both singlestat types -func applyCommonAngularMigration(panel map[string]interface{}, defaults map[string]interface{}, options map[string]interface{}, angularOpts map[string]interface{}) { - // Migrate table column - // Based on sharedSingleStatPanelChangedHandler line ~125: options.reduceOptions.fields = `/^${prevPanel.tableColumn}$/` - if tableColumn, ok := angularOpts["tableColumn"].(string); ok && tableColumn != "" { - options["reduceOptions"].(map[string]interface{})["fields"] = "/^" + tableColumn + "$/" - } - - // Migrate unit from format property (matches frontend sharedSingleStatPanelChangedHandler) - if format, ok := angularOpts["format"].(string); ok { - defaults["unit"] = format - } - - // Migrate decimals - if decimals, ok := angularOpts["decimals"]; ok { - defaults["decimals"] = decimals - } - - // Note: Frontend migrateFromAngularSinglestat does migrate nullPointMode to nullValueMode - // but the frontend's getSaveModel() method removes it, so we don't add it here - // if nullPointMode, ok := angularOpts["nullPointMode"]; ok { - // defaults["nullValueMode"] = nullPointMode - // } - - // Migrate null text - if nullText, ok := angularOpts["nullText"].(string); ok { - defaults["noValue"] = nullText - } - - // Migrate value mappings (thresholds should already be migrated) - valueMaps, _ := angularOpts["valueMaps"].([]interface{}) - migrateValueMappings(angularOpts, defaults, valueMaps) - - // Migrate sparkline configuration - // Based on statPanelChangedHandler lines ~20-23: sparkline migration logic - if sparkline, ok := angularOpts["sparkline"].(map[string]interface{}); ok { - if show, ok := sparkline["show"].(bool); ok && show { - options["graphMode"] = "area" - } else { - options["graphMode"] = "none" - } - } else { - // Default to no graph mode if no sparkline configuration - options["graphMode"] = "none" - } - - // Migrate color configuration - // Based on statPanelChangedHandler lines ~25-38: colorBackground and colorValue migration - colorMode := determineColorMode(angularOpts) - options["colorMode"] = colorMode - - // Sparkline color migration only happens when colorMode is "none" - if colorMode == "none" { - migrateSparklineColor(angularOpts, defaults, options) - } - - // Migrate text mode - // Based on statPanelChangedHandler lines ~45-47: valueName === 'name' migration - if valueName, ok := angularOpts["valueName"].(string); ok && valueName == "name" { - options["textMode"] = "name" - } - - if angularOpts["gauge"] != nil && angularOpts["gauge"].(map[string]interface{})["show"] == true { - defaults["min"] = angularOpts["gauge"].(map[string]interface{})["minValue"] - defaults["max"] = angularOpts["gauge"].(map[string]interface{})["maxValue"] - } -} - -// applyCompleteStatPanelDefaults applies the complete stat panel defaults -// This matches the frontend's getPanelOptionsWithDefaults behavior after migration -func applyCompleteStatPanelDefaults(panel map[string]interface{}) { - // Get or create options object - options, exists := panel["options"].(map[string]interface{}) - if !exists { - options = map[string]interface{}{} - panel["options"] = options - } - - defaultOptions := getDefaultStatOptions() - - // Merge defaults with existing options, but don't override existing values - // This matches the frontend's getPanelOptionsWithDefaults behavior - for key, defaultValue := range defaultOptions { - if _, exists := options[key]; !exists { - options[key] = defaultValue - } - } -} - -// applySharedSinglestatMigration applies shared migration logic for all singlestat panels -// Based on sharedSingleStatMigrationHandler in packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.ts -func applySharedSinglestatMigration(defaults map[string]interface{}) { - // Ensure thresholds have proper structure - if thresholds, ok := defaults["thresholds"].(map[string]interface{}); ok { - if steps, ok := thresholds["steps"].([]interface{}); ok { - // Ensure first threshold is -Infinity (represented as null in JSON) - if len(steps) > 0 { - if firstStep, ok := steps[0].(map[string]interface{}); ok { - if firstStep["value"] == nil { - firstStep["value"] = nil // Use null instead of -math.Inf(1) - } - } - } - } - } - - // Handle percent/percentunit units - // Based on sharedSingleStatMigrationHandler lines ~280-300: percent/percentunit min/max handling - if unit, ok := defaults["unit"].(string); ok { - switch unit { - case "percent": - if defaults["min"] == nil { - defaults["min"] = 0 - } - if defaults["max"] == nil { - defaults["max"] = 100 - } - case "percentunit": - if defaults["min"] == nil { - defaults["min"] = 0 - } - if defaults["max"] == nil { - defaults["max"] = 1 - } - } - } -} - -// Helper functions - -func extractAngularOptions(panel map[string]interface{}) map[string]interface{} { - // Some panels might have angular options directly in the root - // Check for common angular properties - angularProps := []string{ - "valueName", "tableColumn", "format", "decimals", "nullPointMode", "nullText", - "thresholds", "colors", "valueMaps", "gauge", "sparkline", "colorBackground", "colorValue", - } - for _, prop := range angularProps { - if _, exists := panel[prop]; exists { - return panel - } - } - - return map[string]interface{}{} -} - -// getReducerForValueName returns the mapped reducer or empty string for invalid values -func getReducerForValueName(valueName string) string { - reducerMap := map[string]string{ - "min": "min", - "max": "max", - "mean": "mean", - "avg": "mean", // avg maps to mean - "median": "median", - "sum": "sum", - "count": "count", - "first": "firstNotNull", - "last": "lastNotNull", - "name": "lastNotNull", - "current": "lastNotNull", - "total": "sum", - } - - if reducer, ok := reducerMap[valueName]; ok { - return reducer - } - - return "" -} - -func migrateThresholdsAndColors(defaults map[string]interface{}, thresholdsStr string, colors []interface{}) { - // Parse thresholds string (e.g., "10,20,30") - // Based on sharedSingleStatPanelChangedHandler lines ~145-165: Convert thresholds and color values - thresholds := []interface{}{} - thresholdValues := strings.Split(thresholdsStr, ",") - - // Create threshold steps - for i, color := range colors { - step := map[string]interface{}{ - "color": color, - } - - if i == 0 { - // Frontend expects explicit null value for first step, not omitted field - // Use a pointer to ensure the field is present in JSON with null value - var nullValue *float64 - step["value"] = nullValue - } else if i-1 < len(thresholdValues) { - if val, err := strconv.ParseFloat(strings.TrimSpace(thresholdValues[i-1]), 64); err == nil { - step["value"] = val - } - } - - thresholds = append(thresholds, step) - } - - defaults["thresholds"] = map[string]interface{}{ - "mode": "absolute", - "steps": thresholds, - } -} - -func migrateValueMappings(panel map[string]interface{}, defaults map[string]interface{}, valueMappings []interface{}) { - mappings := []interface{}{} - mappingType := panel["mappingType"] - - // Check for inconsistent mapping configuration - // If panel has rangeMaps but mappingType is 1, or vice versa, fix it - hasValueMaps := panel["valueMaps"] != nil && IsArray(panel["valueMaps"]) && len(panel["valueMaps"].([]interface{})) > 0 - hasRangeMaps := panel["rangeMaps"] != nil && IsArray(panel["rangeMaps"]) && len(panel["rangeMaps"].([]interface{})) > 0 - - if hasRangeMaps && mappingType == float64(1) { - mappingType = 2 - } else if hasValueMaps && mappingType == float64(2) { - mappingType = 1 - } else if mappingType == nil { - if hasValueMaps { - mappingType = 1 - } else if hasRangeMaps { - mappingType = 2 - } - } - - switch mappingType { - case 1: - for _, valueMap := range valueMappings { - valueMapping := valueMap.(map[string]interface{}) - upgradedMapping := upgradeOldAngularValueMapping(valueMapping, defaults["thresholds"]) - if upgradedMapping != nil { - mappings = append(mappings, upgradedMapping) - } - } - case 2: - // Handle range mappings - if rangeMaps, ok := panel["rangeMaps"].([]interface{}); ok { - for _, rangeMap := range rangeMaps { - rangeMapping := rangeMap.(map[string]interface{}) - upgradedMapping := upgradeOldAngularValueMapping(rangeMapping, defaults["thresholds"]) - if upgradedMapping != nil { - mappings = append(mappings, upgradedMapping) - } - } - } - } - - defaults["mappings"] = mappings -} - -// upgradeOldAngularValueMapping converts old angular value mappings to new format -// Based on upgradeOldAngularValueMapping in packages/grafana-data/src/utils/valueMappings.ts -func upgradeOldAngularValueMapping(old map[string]interface{}, thresholds interface{}) map[string]interface{} { - valueMaps := map[string]interface{}{ - "type": "value", - "options": map[string]interface{}{}, - } - newMappings := []interface{}{} - - // Use the color we would have picked from thresholds - // Frontend uses old.text to determine color, not old.value - var color interface{} - if text, ok := old["text"].(string); ok { - if numeric, err := parseNumericValue(text); err == nil { - if thresholdsMap, ok := thresholds.(map[string]interface{}); ok { - if steps, ok := thresholdsMap["steps"].([]interface{}); ok { - level := getActiveThreshold(numeric, steps) - if level != nil { - if levelColor, ok := level["color"]; ok { - color = levelColor - } - } - } - } - } - } - - // Determine mapping type - mappingType := old["type"] - if mappingType == nil { - // Try to guess from available properties - if old["value"] != nil { - mappingType = 1 // ValueToText - } else if old["from"] != nil || old["to"] != nil { - mappingType = 2 // RangeToText - } - } - - switch mappingType { - case 1: // ValueToText - if value, ok := old["value"]; ok && value != nil { - if valueStr, ok := value.(string); ok && valueStr == "null" { - newMappings = append(newMappings, map[string]interface{}{ - "type": "special", - "options": map[string]interface{}{ - "match": "null", - "result": map[string]interface{}{"text": old["text"], "color": color}, - }, - }) - } else { - valueMaps["options"].(map[string]interface{})[fmt.Sprintf("%v", value)] = map[string]interface{}{ - "text": old["text"], - "color": color, - } - } - } - case 2: // RangeToText - from := old["from"] - to := old["to"] - if (from != nil && fmt.Sprintf("%v", from) == "null") || (to != nil && fmt.Sprintf("%v", to) == "null") { - newMappings = append(newMappings, map[string]interface{}{ - "type": "special", - "options": map[string]interface{}{ - "match": "null", - "result": map[string]interface{}{"text": old["text"], "color": color}, - }, - }) - } else { - var fromVal, toVal interface{} - if from != nil { - if fromStr, ok := from.(string); ok { - if fromFloat, err := strconv.ParseFloat(fromStr, 64); err == nil { - fromVal = fromFloat - } - } else { - fromVal = from - } - } - if to != nil { - if toStr, ok := to.(string); ok { - if toFloat, err := strconv.ParseFloat(toStr, 64); err == nil { - toVal = toFloat - } - } else { - toVal = to - } - } - - newMappings = append(newMappings, map[string]interface{}{ - "type": "range", - "options": map[string]interface{}{ - "from": fromVal, - "to": toVal, - "result": map[string]interface{}{"text": old["text"], "color": color}, - }, - }) - } - } - - // Add valueMaps if it has options - if len(valueMaps["options"].(map[string]interface{})) > 0 { - newMappings = append([]interface{}{valueMaps}, newMappings...) - } - - if len(newMappings) > 0 { - return newMappings[0].(map[string]interface{}) - } - - return nil -} - -// getActiveThreshold finds the active threshold for a given value -// Based on getActiveThreshold in packages/grafana-data/src/field/thresholds.ts -func getActiveThreshold(value float64, steps []interface{}) map[string]interface{} { - for i := len(steps) - 1; i >= 0; i-- { - if step, ok := steps[i].(map[string]interface{}); ok { - if stepValue, ok := step["value"]; ok { - if stepValue == nil { - // First step with null value (represents -Infinity) - return step - } - if stepFloat, ok := stepValue.(float64); ok && value >= stepFloat { - return step - } - } - } - } - return nil -} - -// parseNumericValue converts various types to float64 for threshold calculations -func parseNumericValue(value interface{}) (float64, error) { - switch v := value.(type) { - case string: - return strconv.ParseFloat(v, 64) - case float64: - return v, nil - case float32: - return float64(v), nil - case int: - return float64(v), nil - case int32: - return float64(v), nil - case int64: - return float64(v), nil - default: - return 0, fmt.Errorf("cannot convert %T to numeric value", value) - } -} - -// createFieldConfigFromDefaults creates the proper fieldConfig structure from defaults -// and removes all legacy properties from the panel -func createFieldConfigFromDefaults(panel map[string]interface{}, defaults map[string]interface{}) { - // Ensure fieldConfig exists - if panel["fieldConfig"] == nil { - panel["fieldConfig"] = map[string]interface{}{ - "defaults": map[string]interface{}{}, - "overrides": []interface{}{}, - } - } - - fieldConfig := panel["fieldConfig"].(map[string]interface{}) - fieldDefaults := fieldConfig["defaults"].(map[string]interface{}) - - // Copy all defaults to fieldConfig.defaults - for key, value := range defaults { - fieldDefaults[key] = value - } - - // Note: Frontend doesn't add these extra fieldConfig defaults - // Color is handled in sparkline migration logic - // nullValueMode and unit are not added by frontend - - // Remove all legacy properties from the panel - legacyProperties := []string{ - "colors", "thresholds", "valueMaps", "grid", "legend", "mappingTypes", "gauge", - "autoMigrateFrom", "colorBackground", "colorValue", "format", "mappingType", - "nullPointMode", "postfix", "postfixFontSize", "prefix", - "prefixFontSize", "rangeMaps", "sparkline", "tableColumn", "valueFontSize", - "valueName", "aliasYAxis", "bars", "dashLength", "dashes", "fill", "fillGradient", - "lineInterpolation", "lineWidth", "pointRadius", "points", "spaceLength", - "stack", "steppedLine", "xAxis", "yAxes", "yAxis", "zIndex", - } - - for _, prop := range legacyProperties { - delete(panel, prop) - } -} - -// cleanupAngularProperties removes old angular properties after migration -// Based on PanelModel.clearPropertiesBeforePluginChange in public/app/features/dashboard/state/PanelModel.ts -// This function removes ALL properties except those in mustKeepProps to match frontend behavior exactly -func cleanupAngularProperties(panel map[string]interface{}) { - // Properties that must be kept (matching frontend mustKeepProps) - mustKeepProps := map[string]bool{ - "id": true, "gridPos": true, "type": true, "title": true, "scopedVars": true, - "repeat": true, "repeatPanelId": true, "repeatDirection": true, "repeatedByRow": true, - "minSpan": true, "collapsed": true, "panels": true, "targets": true, "datasource": true, - "timeFrom": true, "timeShift": true, "hideTimeOverride": true, "description": true, - "links": true, "fullscreen": true, "isEditing": true, "isViewing": true, - "hasRefreshed": true, "events": true, "cacheTimeout": true, "queryCachingTTL": true, - "cachedPluginOptions": true, "transparent": true, "pluginVersion": true, - "fieldConfig": true, "options": true, // These are set by migration - "maxDataPoints": true, "interval": true, // Panel-level properties preserved by frontend - "autoMigrateFrom": true, // Preserve autoMigrateFrom for proper migration logic - } - - // Remove ALL properties except those in mustKeepProps (matching frontend behavior) - for key := range panel { - if !mustKeepProps[key] { - delete(panel, key) - } - } - - // Ensure all targets have refIds (matching frontend ensureQueryIds behavior) - ensureTargetRefIds(panel) -} - -// ensureTargetRefIds assigns refIds to targets that don't have them -// This matches the frontend PanelModel.ensureQueryIds() behavior -func ensureTargetRefIds(panel map[string]interface{}) { - targets, ok := panel["targets"].([]interface{}) - if !ok || len(targets) == 0 { - return - } - - // Find existing refIds - existingRefIds := make(map[string]bool) - for _, targetInterface := range targets { - if target, ok := targetInterface.(map[string]interface{}); ok { - if refId, ok := target["refId"].(string); ok { - existingRefIds[refId] = true - } - } - } - - // Assign refIds to targets that don't have them - letters := "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - letterIndex := 0 - - for _, targetInterface := range targets { - if target, ok := targetInterface.(map[string]interface{}); ok { - refId, hasRefId := target["refId"].(string) - if !hasRefId || refId == "" { - // Find next available refId - for letterIndex < len(letters) { - refId := string(letters[letterIndex]) - if !existingRefIds[refId] { - target["refId"] = refId - existingRefIds[refId] = true - break - } - letterIndex++ - } - letterIndex++ - } - } - } -} - // removeDeprecatedVariableProperties removes deprecated properties from variables // Based on DashboardMigrator.ts v28 migration: variable property cleanup func removeDeprecatedVariableProperties(variable map[string]interface{}) { @@ -843,45 +69,3 @@ func removeDeprecatedVariableProperties(variable map[string]interface{}) { } } } - -// determineColorMode determines the color mode based on angular options -func determineColorMode(angularOpts map[string]interface{}) string { - if colorBackground, ok := angularOpts["colorBackground"].(bool); ok && colorBackground { - return "background" - } - - if colorValue, ok := angularOpts["colorValue"].(bool); ok && colorValue { - return "value" - } - - return "none" -} - -// migrateSparklineColor migrates sparkline color configuration when colorMode is "none" -// Based on statPanelChangedHandler lines 31-38 -func migrateSparklineColor(angularOpts map[string]interface{}, defaults map[string]interface{}, options map[string]interface{}) { - sparkline, ok := angularOpts["sparkline"].(map[string]interface{}) - if !ok { - return - } - - show, ok := sparkline["show"].(bool) - if !ok || !show { - return - } - - graphMode, ok := options["graphMode"].(string) - if !ok || graphMode != "area" { - return - } - - lineColor, ok := sparkline["lineColor"].(string) - if !ok { - return - } - - defaults["color"] = map[string]interface{}{ - "mode": "fixed", - "fixedColor": lineColor, - } -} diff --git a/apps/dashboard/pkg/migration/schemaversion/v28_test.go b/apps/dashboard/pkg/migration/schemaversion/v28_test.go index 68fc1c5fedd..b597d913f98 100644 --- a/apps/dashboard/pkg/migration/schemaversion/v28_test.go +++ b/apps/dashboard/pkg/migration/schemaversion/v28_test.go @@ -5,101 +5,186 @@ import ( "testing" ) -func TestV28SinglestatMigration(t *testing.T) { - tests := []struct { - name string - input map[string]interface{} - expected map[string]interface{} - description string - }{ - { - name: "migrate_range_maps_to_field_config_mappings", - input: map[string]interface{}{ - "type": "singlestat", - "rangeMaps": []interface{}{ - map[string]interface{}{ - "from": "null", - "to": "N/A", - }, - }, - "mappingType": 1, // Inconsistent - should be 2 for rangeMaps - }, - expected: map[string]interface{}{ - "type": "stat", - "fieldConfig": map[string]interface{}{ - "defaults": map[string]interface{}{ - "mappings": []interface{}{ - map[string]interface{}{ - "options": map[string]interface{}{ - "match": "null", - "result": map[string]interface{}{ - "text": "N/A", - }, - }, - "type": "special", - }, - }, - }, - }, - }, - description: "RangeMaps should migrate to fieldConfig.mappings, and inconsistent mappingType should be fixed to 2 (RangeToText)", - }, - { - name: "migrate_sparkline_color_when_color_mode_none", - input: map[string]interface{}{ - "type": "singlestat", - "colorMode": "None", - "sparkline": map[string]interface{}{ - "lineColor": "rgb(31, 120, 193)", - }, - }, - expected: map[string]interface{}{ - "type": "stat", - "fieldConfig": map[string]interface{}{ - "defaults": map[string]interface{}{ - "color": map[string]interface{}{ - "mode": "fixed", - "fixedColor": "rgb(31, 120, 193)", - }, - }, - }, - }, - description: "Sparkline lineColor should migrate to fieldConfig.defaults.color only when colorMode is None", - }, - } +type migrationTestCase struct { + name string + input map[string]interface{} + expected map[string]interface{} +} +func runMigrationTests(t *testing.T, tests []migrationTestCase, migrationFunc func(context.Context, map[string]interface{}) error) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - dashboard := map[string]interface{}{ - "schemaVersion": 27, - "panels": []interface{}{tt.input}, + // Create a copy of the input + dashboard := make(map[string]interface{}) + for k, v := range tt.input { + dashboard[k] = v } - err := V28(context.Background(), dashboard) + err := migrationFunc(context.Background(), dashboard) if err != nil { - t.Fatalf("V28 migration failed: %v", err) + t.Fatalf("Migration failed: %v", err) } - if dashboard["schemaVersion"] != 28 { - t.Errorf("Expected schemaVersion to be 28, got %v", dashboard["schemaVersion"]) + // Verify the result matches expected + if !deepEqual(dashboard, tt.expected) { + t.Errorf("Migration result doesn't match expected.\nExpected: %+v\nGot: %+v", tt.expected, dashboard) } - - panels, ok := dashboard["panels"].([]interface{}) - if !ok || len(panels) == 0 { - t.Fatalf("Expected panels array with at least one panel") - } - - panel, ok := panels[0].(map[string]interface{}) - if !ok { - t.Fatalf("Expected panel to be a map") - } - - // Verify panel type was changed to stat - if panel["type"] != "stat" { - t.Errorf("Expected panel type to be 'stat', got %v", panel["type"]) - } - - t.Logf("โœ“ %s: %s", tt.name, tt.description) }) } } + +func deepEqual(a, b interface{}) bool { + // Simple deep comparison for test purposes + // This is a simplified version - in production you'd use reflect.DeepEqual or similar + switch aVal := a.(type) { + case map[string]interface{}: + bVal, ok := b.(map[string]interface{}) + if !ok || len(aVal) != len(bVal) { + return false + } + for k, v := range aVal { + if !deepEqual(v, bVal[k]) { + return false + } + } + return true + case []interface{}: + bVal, ok := b.([]interface{}) + if !ok || len(aVal) != len(bVal) { + return false + } + for i, v := range aVal { + if !deepEqual(v, bVal[i]) { + return false + } + } + return true + default: + return a == b + } +} + +func TestV28(t *testing.T) { + tests := []migrationTestCase{ + { + name: "v28 removes deprecated variable properties", + input: map[string]interface{}{ + "title": "V28 Variable Properties Migration Test Dashboard", + "schemaVersion": 27, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "var1", + "tags": []interface{}{"tag1", "tag2"}, + "tagsQuery": "query_string", + "tagValuesQuery": "values_query", + "useTags": true, + "type": "query", + }, + map[string]interface{}{ + "name": "var2", + "tags": []interface{}{}, + "tagsQuery": "", // Empty string should not be removed + "tagValuesQuery": "", // Empty string should not be removed + "useTags": false, // False should not be removed + "type": "custom", + }, + }, + }, + "panels": []interface{}{ + map[string]interface{}{ + "type": "singlestat", + "title": "Singlestat Panel (unchanged by v28)", + "id": 1, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V28 Variable Properties Migration Test Dashboard", + "schemaVersion": 28, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "var1", + "type": "query", + // tags, tagsQuery, tagValuesQuery, useTags should be removed + }, + map[string]interface{}{ + "name": "var2", + "tagsQuery": "", // Empty string preserved + "tagValuesQuery": "", // Empty string preserved + "useTags": false, // False preserved + "type": "custom", + // only tags should be removed + }, + }, + }, + "panels": []interface{}{ + map[string]interface{}{ + "type": "singlestat", + "title": "Singlestat Panel (unchanged by v28)", + "id": 1, + }, + }, + }, + }, + { + name: "v28 handles dashboard without templating", + input: map[string]interface{}{ + "title": "Dashboard without templating", + "schemaVersion": 27, + "panels": []interface{}{ + map[string]interface{}{ + "type": "singlestat", + "title": "Singlestat Panel", + "id": 1, + }, + }, + }, + expected: map[string]interface{}{ + "title": "Dashboard without templating", + "schemaVersion": 28, + "panels": []interface{}{ + map[string]interface{}{ + "type": "singlestat", + "title": "Singlestat Panel", + "id": 1, + }, + }, + }, + }, + { + name: "v28 handles empty templating list", + input: map[string]interface{}{ + "title": "Dashboard with empty templating", + "schemaVersion": 27, + "templating": map[string]interface{}{ + "list": []interface{}{}, + }, + "panels": []interface{}{ + map[string]interface{}{ + "type": "singlestat", + "title": "Singlestat Panel", + "id": 1, + }, + }, + }, + expected: map[string]interface{}{ + "title": "Dashboard with empty templating", + "schemaVersion": 28, + "templating": map[string]interface{}{ + "list": []interface{}{}, + }, + "panels": []interface{}{ + map[string]interface{}{ + "type": "singlestat", + "title": "Singlestat Panel", + "id": 1, + }, + }, + }, + }, + } + + runMigrationTests(t, tests, V28) +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v2_test.go b/apps/dashboard/pkg/migration/schemaversion/v2_test.go new file mode 100644 index 00000000000..69ebb5e0b22 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v2_test.go @@ -0,0 +1,216 @@ +package schemaversion_test + +import ( + "testing" + + "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" +) + +func TestV2(t *testing.T) { + tests := []migrationTestCase{ + { + name: "services filter migration moves time and templating list", + input: map[string]interface{}{ + "title": "V2 Services Filter Migration Test", + "schemaVersion": 1, + "services": map[string]interface{}{ + "filter": map[string]interface{}{ + "time": map[string]interface{}{ + "from": "now-1h", + "to": "now", + }, + "list": []interface{}{ + map[string]interface{}{ + "name": "var1", + "type": "query", + }, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V2 Services Filter Migration Test", + "schemaVersion": 2, + "time": map[string]interface{}{ + "from": "now-1h", + "to": "now", + }, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "var1", + "type": "query", + }, + }, + }, + }, + }, + { + name: "comprehensive services filter migration", + input: map[string]interface{}{ + "title": "V2 Comprehensive Services Migration Test", + "schemaVersion": 1, + "services": map[string]interface{}{ + "filter": map[string]interface{}{ + "time": map[string]interface{}{ + "from": "now-6h", + "to": "now", + }, + "list": []interface{}{ + map[string]interface{}{ + "name": "server", + "type": "query", + }, + }, + }, + }, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "graphite", + "title": "CPU Usage", + }, + }, + }, + expected: map[string]interface{}{ + "title": "V2 Comprehensive Services Migration Test", + "schemaVersion": 2, + "time": map[string]interface{}{ + "from": "now-6h", + "to": "now", + }, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "server", + "type": "query", + }, + }, + }, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "graphite", // Panel types are not migrated by V2 anymore + "title": "CPU Usage", + }, + }, + }, + }, + { + name: "dashboard with no services or panels", + input: map[string]interface{}{ + "title": "V2 Minimal Migration Test", + "schemaVersion": 1, + }, + expected: map[string]interface{}{ + "title": "V2 Minimal Migration Test", + "schemaVersion": 2, + }, + }, + { + name: "services filter with only time (no list)", + input: map[string]interface{}{ + "title": "V2 Services Time Only Test", + "schemaVersion": 1, + "services": map[string]interface{}{ + "filter": map[string]interface{}{ + "time": map[string]interface{}{ + "from": "now-2h", + "to": "now", + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V2 Services Time Only Test", + "schemaVersion": 2, + "time": map[string]interface{}{ + "from": "now-2h", + "to": "now", + }, + }, + }, + { + name: "services filter with only list (no time)", + input: map[string]interface{}{ + "title": "V2 Services List Only Test", + "schemaVersion": 1, + "services": map[string]interface{}{ + "filter": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "env", + "type": "custom", + }, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V2 Services List Only Test", + "schemaVersion": 2, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "env", + "type": "custom", + }, + }, + }, + }, + }, + { + name: "panels remain unchanged when no services filter", + input: map[string]interface{}{ + "title": "V2 Panels Unchanged Test", + "schemaVersion": 1, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "graphite", + "legend": true, + "y_format": "short", + "y2_format": "bytes", + "grid": map[string]interface{}{ + "min": 0, + "max": 100, + }, + }, + map[string]interface{}{ + "id": 2, + "type": "graph", + "legend": map[string]interface{}{ + "show": false, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V2 Panels Unchanged Test", + "schemaVersion": 2, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "graphite", // Panel migrations handled by auto-migration + "legend": true, + "y_format": "short", + "y2_format": "bytes", + "grid": map[string]interface{}{ + "min": 0, + "max": 100, + }, + }, + map[string]interface{}{ + "id": 2, + "type": "graph", + "legend": map[string]interface{}{ + "show": false, + }, + }, + }, + }, + }, + } + + runMigrationTests(t, tests, schemaversion.V2) +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v3.go b/apps/dashboard/pkg/migration/schemaversion/v3.go new file mode 100644 index 00000000000..54163d2b685 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v3.go @@ -0,0 +1,9 @@ +package schemaversion + +import "context" + +// V3 is a no-op migration +func V3(_ context.Context, dashboard map[string]interface{}) error { + dashboard["schemaVersion"] = 3 + return nil +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v36.go b/apps/dashboard/pkg/migration/schemaversion/v36.go index c45c4ad56a2..7874e80b1d9 100644 --- a/apps/dashboard/pkg/migration/schemaversion/v36.go +++ b/apps/dashboard/pkg/migration/schemaversion/v36.go @@ -139,7 +139,8 @@ func migrateTemplateVariables(dashboard map[string]interface{}, datasources []Da ds, exists := varMap["datasource"] // Handle null datasource variables by setting to default (matches frontend behavior) - if !exists || ds == nil { + // Only add datasource if it's explicitly null, not if it doesn't exist + if exists && ds == nil { varMap["datasource"] = GetDataSourceRef(defaultDS) } // Note: Frontend v36 migration only converts null datasources to default objects diff --git a/apps/dashboard/pkg/migration/schemaversion/v38.go b/apps/dashboard/pkg/migration/schemaversion/v38.go index 84171e287c9..2af4817788c 100644 --- a/apps/dashboard/pkg/migration/schemaversion/v38.go +++ b/apps/dashboard/pkg/migration/schemaversion/v38.go @@ -112,26 +112,22 @@ func processPanelsV38(panels []interface{}) { continue } - defaults, ok := fieldConfig["defaults"].(map[string]interface{}) - if !ok { - continue - } - - custom, ok := defaults["custom"].(map[string]interface{}) - if !ok { - continue - } - - // Migrate displayMode to cellOptions - if displayMode, exists := custom["displayMode"]; exists { - if displayModeStr, ok := displayMode.(string); ok { - custom["cellOptions"] = migrateTableDisplayModeToCellOptions(displayModeStr) + // Process defaults.custom if it exists + if defaults, ok := fieldConfig["defaults"].(map[string]interface{}); ok { + if custom, ok := defaults["custom"].(map[string]interface{}); ok { + // Migrate displayMode to cellOptions in defaults + if displayMode, exists := custom["displayMode"]; exists { + if displayModeStr, ok := displayMode.(string); ok { + custom["cellOptions"] = migrateTableDisplayModeToCellOptions(displayModeStr) + } + // Delete the legacy field + delete(custom, "displayMode") + } } - // Delete the legacy field - delete(custom, "displayMode") } // Update any overrides referencing the cell display mode + // This must be called regardless of whether defaults.custom exists migrateOverrides(fieldConfig) } } diff --git a/apps/dashboard/pkg/migration/schemaversion/v38_test.go b/apps/dashboard/pkg/migration/schemaversion/v38_test.go index 1032b784c83..c24d1ec734d 100644 --- a/apps/dashboard/pkg/migration/schemaversion/v38_test.go +++ b/apps/dashboard/pkg/migration/schemaversion/v38_test.go @@ -440,6 +440,164 @@ func TestV38(t *testing.T) { }, }, }, + { + name: "table with missing defaults.custom but overrides with custom.displayMode", + input: map[string]interface{}{ + "title": "V38 Missing Defaults Custom Test", + "schemaVersion": 37, + "panels": []interface{}{ + // Table with no custom in defaults but custom.displayMode in overrides + map[string]interface{}{ + "type": "table", + "title": "Table with Missing Defaults Custom", + "id": 1, + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{}, // No custom object + "overrides": []interface{}{ + map[string]interface{}{ + "matcher": map[string]interface{}{ + "id": "byName", + "options": "name", + }, + "properties": []interface{}{ + map[string]interface{}{ + "id": "color", + "value": map[string]interface{}{ + "fixedColor": "yellow", + "mode": "fixed", + }, + }, + map[string]interface{}{ + "id": "custom.displayMode", + "value": "color-background", + }, + }, + }, + }, + }, + }, + // Table with empty custom in defaults but custom.displayMode in overrides + map[string]interface{}{ + "type": "table", + "title": "Table with Empty Custom", + "id": 2, + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "custom": map[string]interface{}{}, // Empty custom object + }, + "overrides": []interface{}{ + map[string]interface{}{ + "matcher": map[string]interface{}{ + "id": "byName", + "options": "status", + }, + "properties": []interface{}{ + map[string]interface{}{ + "id": "custom.displayMode", + "value": "gradient-gauge", + }, + }, + }, + map[string]interface{}{ + "matcher": map[string]interface{}{ + "id": "byName", + "options": "value", + }, + "properties": []interface{}{ + map[string]interface{}{ + "id": "custom.displayMode", + "value": "lcd-gauge", + }, + }, + }, + }, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V38 Missing Defaults Custom Test", + "schemaVersion": 38, + "panels": []interface{}{ + // Table with no custom in defaults but custom.displayMode in overrides (migrated) + map[string]interface{}{ + "type": "table", + "title": "Table with Missing Defaults Custom", + "id": 1, + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{}, // Still no custom object + "overrides": []interface{}{ + map[string]interface{}{ + "matcher": map[string]interface{}{ + "id": "byName", + "options": "name", + }, + "properties": []interface{}{ + map[string]interface{}{ + "id": "color", + "value": map[string]interface{}{ + "fixedColor": "yellow", + "mode": "fixed", + }, + }, + map[string]interface{}{ + "id": "custom.cellOptions", + "value": map[string]interface{}{ + "type": "color-background", + "mode": "gradient", + }, + }, + }, + }, + }, + }, + }, + // Table with empty custom in defaults but custom.displayMode in overrides (migrated) + map[string]interface{}{ + "type": "table", + "title": "Table with Empty Custom", + "id": 2, + "fieldConfig": map[string]interface{}{ + "defaults": map[string]interface{}{ + "custom": map[string]interface{}{}, // Empty custom object + }, + "overrides": []interface{}{ + map[string]interface{}{ + "matcher": map[string]interface{}{ + "id": "byName", + "options": "status", + }, + "properties": []interface{}{ + map[string]interface{}{ + "id": "custom.cellOptions", + "value": map[string]interface{}{ + "type": "gauge", + "mode": "gradient", + }, + }, + }, + }, + map[string]interface{}{ + "matcher": map[string]interface{}{ + "id": "byName", + "options": "value", + }, + "properties": []interface{}{ + map[string]interface{}{ + "id": "custom.cellOptions", + "value": map[string]interface{}{ + "type": "gauge", + "mode": "lcd", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, } runMigrationTests(t, tests, schemaversion.V38) } diff --git a/apps/dashboard/pkg/migration/schemaversion/v3_test.go b/apps/dashboard/pkg/migration/schemaversion/v3_test.go new file mode 100644 index 00000000000..cbd0b4e43ce --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v3_test.go @@ -0,0 +1,38 @@ +package schemaversion_test + +import ( + "testing" + + "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" +) + +func TestV3(t *testing.T) { + tests := []migrationTestCase{ + { + name: "v3 no-op migration, updates schema version only", + input: map[string]interface{}{ + "title": "V3 No-Op Migration Test Dashboard", + "schemaVersion": 2, + "panels": []interface{}{ + map[string]interface{}{ + "type": "graph", + "title": "Panel remains unchanged", + "id": 1, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V3 No-Op Migration Test Dashboard", + "schemaVersion": 3, + "panels": []interface{}{ + map[string]interface{}{ + "type": "graph", + "title": "Panel remains unchanged", + "id": 1, + }, + }, + }, + }, + } + runMigrationTests(t, tests, schemaversion.V3) +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v4.go b/apps/dashboard/pkg/migration/schemaversion/v4.go new file mode 100644 index 00000000000..02346ed8c25 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v4.go @@ -0,0 +1,9 @@ +package schemaversion + +import "context" + +// V4 is a no-op migration +func V4(_ context.Context, dashboard map[string]interface{}) error { + dashboard["schemaVersion"] = 4 + return nil +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v4_test.go b/apps/dashboard/pkg/migration/schemaversion/v4_test.go new file mode 100644 index 00000000000..a4f9f856a72 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v4_test.go @@ -0,0 +1,38 @@ +package schemaversion_test + +import ( + "testing" + + "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" +) + +func TestV4(t *testing.T) { + tests := []migrationTestCase{ + { + name: "v4 no-op migration, updates schema version only", + input: map[string]interface{}{ + "title": "V4 No-Op Migration Test Dashboard", + "schemaVersion": 3, + "panels": []interface{}{ + map[string]interface{}{ + "type": "graph", + "title": "Panel remains unchanged", + "id": 1, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V4 No-Op Migration Test Dashboard", + "schemaVersion": 4, + "panels": []interface{}{ + map[string]interface{}{ + "type": "graph", + "title": "Panel remains unchanged", + "id": 1, + }, + }, + }, + }, + } + runMigrationTests(t, tests, schemaversion.V4) +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v5.go b/apps/dashboard/pkg/migration/schemaversion/v5.go new file mode 100644 index 00000000000..976aa5333ab --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v5.go @@ -0,0 +1,11 @@ +package schemaversion + +import ( + "context" +) + +// V5 is a no-op migration +func V5(_ context.Context, dashboard map[string]interface{}) error { + dashboard["schemaVersion"] = 5 + return nil +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v5_test.go b/apps/dashboard/pkg/migration/schemaversion/v5_test.go new file mode 100644 index 00000000000..fe0f137667a --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v5_test.go @@ -0,0 +1,38 @@ +package schemaversion_test + +import ( + "testing" + + "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" +) + +func TestV5(t *testing.T) { + tests := []migrationTestCase{ + { + name: "v5 no-op migration, updates schema version only", + input: map[string]interface{}{ + "title": "V5 No-Op Migration Test Dashboard", + "schemaVersion": 4, + "panels": []interface{}{ + map[string]interface{}{ + "type": "graph", + "title": "Panel remains unchanged", + "id": 1, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V5 No-Op Migration Test Dashboard", + "schemaVersion": 5, + "panels": []interface{}{ + map[string]interface{}{ + "type": "graph", + "title": "Panel remains unchanged", + "id": 1, + }, + }, + }, + }, + } + runMigrationTests(t, tests, schemaversion.V5) +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v6.go b/apps/dashboard/pkg/migration/schemaversion/v6.go new file mode 100644 index 00000000000..f5e8af73ba8 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v6.go @@ -0,0 +1,100 @@ +package schemaversion + +import "context" + +// V6 migration handles the pulldowns to annotations conversion and template variable updates. +// This migration moves annotations from the legacy pulldowns array to the new annotations structure +// and updates template variables to use the new schema format. +// +// Background: +// In earlier versions, dashboards used a "pulldowns" property array to store various UI elements +// including annotations. This migration extracts annotations from pulldowns and creates the new +// annotations structure. It also updates template variables to ensure proper datasource handling +// and type normalization. +// +// Example before migration: +// { +// "schemaVersion": 5, +// "pulldowns": [ +// { "type": "filtering", "enable": true }, +// { "type": "annotations", "enable": true, "annotations": [{"name": "old"}] } +// ], +// "templating": { +// "list": [ +// { "name": "server", "type": "filter" }, +// { "name": "metric", "datasource": undefined, "allFormat": undefined } +// ] +// } +// } +// +// Example after migration: +// { +// "schemaVersion": 6, +// "annotations": { +// "list": [{"name": "old"}] +// }, +// "templating": { +// "list": [ +// { "name": "server", "type": "query", "datasource": null }, +// { "name": "metric", "type": "query", "datasource": null } +// ] +// } +// } + +func V6(_ context.Context, dashboard map[string]interface{}) error { + dashboard["schemaVersion"] = 6 + + // Move drop-downs to new schema (matches frontend DashboardMigrator logic) + // Find annotations in pulldowns array: equivalent to find(old.pulldowns, { type: 'annotations' }) + if pulldowns, ok := dashboard["pulldowns"].([]interface{}); ok { + for _, pulldownInterface := range pulldowns { + if pulldown, ok := pulldownInterface.(map[string]interface{}); ok { + if pulldownType, exists := pulldown["type"]; exists && pulldownType == "annotations" { + // Found annotations pulldown, extract annotations + if annotations, hasAnnotations := pulldown["annotations"]; hasAnnotations { + dashboard["annotations"] = map[string]interface{}{ + "list": annotations, + } + } else { + // If no annotations property, create empty list + dashboard["annotations"] = map[string]interface{}{ + "list": []interface{}{}, + } + } + break // Found what we're looking for, no need to continue + } + } + } + } + + // Update template variables + if templating, ok := dashboard["templating"].(map[string]interface{}); ok { + if list, ok := templating["list"].([]interface{}); ok { + for _, variableInterface := range list { + if variable, ok := variableInterface.(map[string]interface{}); ok { + // If datasource is undefined/missing, set to null + if _, exists := variable["datasource"]; !exists { + variable["datasource"] = nil + } + + // Convert 'filter' type to 'query' + if varType, exists := variable["type"]; exists && varType == "filter" { + variable["type"] = "query" + } + + // If type is undefined/missing, set to 'query' + if _, exists := variable["type"]; !exists { + variable["type"] = "query" + } + + // Remove allFormat if it's undefined + if allFormat, exists := variable["allFormat"]; exists && allFormat == nil { + delete(variable, "allFormat") + } + } + } + } + } + + return nil +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v6_test.go b/apps/dashboard/pkg/migration/schemaversion/v6_test.go new file mode 100644 index 00000000000..6668c8392c6 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v6_test.go @@ -0,0 +1,541 @@ +package schemaversion_test + +import ( + "testing" + + "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" +) + +func TestV6Migration(t *testing.T) { + testCases := []migrationTestCase{ + { + name: "pulldowns to annotations conversion with existing annotations", + input: map[string]interface{}{ + "schemaVersion": 5, + "pulldowns": []interface{}{ + map[string]interface{}{ + "type": "filtering", + "enable": true, + }, + map[string]interface{}{ + "type": "annotations", + "enable": true, + "annotations": []interface{}{ + map[string]interface{}{ + "name": "old annotation", + "datasource": "prometheus", + "enable": true, + }, + }, + }, + }, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "server", + "type": "filter", + }, + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "pulldowns": []interface{}{ + map[string]interface{}{ + "type": "filtering", + "enable": true, + }, + map[string]interface{}{ + "type": "annotations", + "enable": true, + "annotations": []interface{}{ + map[string]interface{}{ + "name": "old annotation", + "datasource": "prometheus", + "enable": true, + }, + }, + }, + }, + "annotations": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "old annotation", + "datasource": "prometheus", + "enable": true, + }, + }, + }, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "server", + "type": "query", + "datasource": nil, + }, + }, + }, + }, + }, + { + name: "pulldowns to annotations conversion with empty annotations", + input: map[string]interface{}{ + "schemaVersion": 5, + "pulldowns": []interface{}{ + map[string]interface{}{ + "type": "annotations", + "enable": true, + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "pulldowns": []interface{}{ + map[string]interface{}{ + "type": "annotations", + "enable": true, + }, + }, + "annotations": map[string]interface{}{ + "list": []interface{}{}, + }, + }, + }, + { + name: "no annotations pulldown found", + input: map[string]interface{}{ + "schemaVersion": 5, + "pulldowns": []interface{}{ + map[string]interface{}{ + "type": "filtering", + "enable": true, + }, + map[string]interface{}{ + "type": "other", + "enable": false, + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "pulldowns": []interface{}{ + map[string]interface{}{ + "type": "filtering", + "enable": true, + }, + map[string]interface{}{ + "type": "other", + "enable": false, + }, + }, + }, + }, + { + name: "no pulldowns property", + input: map[string]interface{}{ + "schemaVersion": 5, + "title": "Test Dashboard", + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "title": "Test Dashboard", + }, + }, + { + name: "empty pulldowns array", + input: map[string]interface{}{ + "schemaVersion": 5, + "pulldowns": []interface{}{}, + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "pulldowns": []interface{}{}, + }, + }, + { + name: "template variables migration - filter to query type", + input: map[string]interface{}{ + "schemaVersion": 5, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "server", + "type": "filter", + }, + map[string]interface{}{ + "name": "metric", + "type": "query", + }, + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "server", + "type": "query", + "datasource": nil, + }, + map[string]interface{}{ + "name": "metric", + "type": "query", + "datasource": nil, + }, + }, + }, + }, + }, + { + name: "template variables migration - missing type becomes query", + input: map[string]interface{}{ + "schemaVersion": 5, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "server", + }, + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "server", + "type": "query", + "datasource": nil, + }, + }, + }, + }, + }, + { + name: "template variables migration - existing datasource preserved", + input: map[string]interface{}{ + "schemaVersion": 5, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "server", + "type": "query", + "datasource": "prometheus", + }, + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "server", + "type": "query", + "datasource": "prometheus", + }, + }, + }, + }, + }, + { + name: "template variables migration - allFormat removal", + input: map[string]interface{}{ + "schemaVersion": 5, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "server", + "type": "query", + "allFormat": nil, + }, + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "server", + "type": "query", + "datasource": nil, + }, + }, + }, + }, + }, + { + name: "template variables migration - allFormat with value preserved", + input: map[string]interface{}{ + "schemaVersion": 5, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "server", + "type": "query", + "allFormat": "glob", + }, + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "server", + "type": "query", + "datasource": nil, + "allFormat": "glob", + }, + }, + }, + }, + }, + { + name: "no templating property", + input: map[string]interface{}{ + "schemaVersion": 5, + "title": "Test Dashboard", + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "title": "Test Dashboard", + }, + }, + { + name: "empty templating list", + input: map[string]interface{}{ + "schemaVersion": 5, + "templating": map[string]interface{}{ + "list": []interface{}{}, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "templating": map[string]interface{}{ + "list": []interface{}{}, + }, + }, + }, + { + name: "complex dashboard with both pulldowns and templating", + input: map[string]interface{}{ + "schemaVersion": 5, + "title": "Complex Dashboard", + "pulldowns": []interface{}{ + map[string]interface{}{ + "type": "filtering", + "enable": true, + }, + map[string]interface{}{ + "type": "annotations", + "enable": true, + "annotations": []interface{}{ + map[string]interface{}{ + "name": "deployment", + "datasource": "prometheus", + "enable": true, + "iconColor": "red", + }, + map[string]interface{}{ + "name": "alerts", + "datasource": "loki", + "enable": false, + }, + }, + }, + }, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "environment", + "type": "filter", + "allFormat": nil, + }, + map[string]interface{}{ + "name": "service", + "datasource": "prometheus", + "allFormat": "glob", + }, + map[string]interface{}{ + "name": "region", + "type": "custom", + }, + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "title": "Complex Dashboard", + "pulldowns": []interface{}{ + map[string]interface{}{ + "type": "filtering", + "enable": true, + }, + map[string]interface{}{ + "type": "annotations", + "enable": true, + "annotations": []interface{}{ + map[string]interface{}{ + "name": "deployment", + "datasource": "prometheus", + "enable": true, + "iconColor": "red", + }, + map[string]interface{}{ + "name": "alerts", + "datasource": "loki", + "enable": false, + }, + }, + }, + }, + "annotations": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "deployment", + "datasource": "prometheus", + "enable": true, + "iconColor": "red", + }, + map[string]interface{}{ + "name": "alerts", + "datasource": "loki", + "enable": false, + }, + }, + }, + "templating": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "environment", + "type": "query", + "datasource": nil, + }, + map[string]interface{}{ + "name": "service", + "type": "query", + "datasource": "prometheus", + "allFormat": "glob", + }, + map[string]interface{}{ + "name": "region", + "type": "custom", + "datasource": nil, + }, + }, + }, + }, + }, + { + name: "invalid pulldowns structure", + input: map[string]interface{}{ + "schemaVersion": 5, + "pulldowns": "invalid_structure", + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "pulldowns": "invalid_structure", + }, + }, + { + name: "invalid templating structure", + input: map[string]interface{}{ + "schemaVersion": 5, + "templating": "invalid_structure", + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "templating": "invalid_structure", + }, + }, + { + name: "invalid templating list structure", + input: map[string]interface{}{ + "schemaVersion": 5, + "templating": map[string]interface{}{ + "list": "invalid_list", + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "templating": map[string]interface{}{ + "list": "invalid_list", + }, + }, + }, + { + name: "pulldown item with invalid structure", + input: map[string]interface{}{ + "schemaVersion": 5, + "pulldowns": []interface{}{ + "invalid_pulldown", + map[string]interface{}{ + "type": "annotations", + "enable": true, + "annotations": []interface{}{ + map[string]interface{}{ + "name": "valid annotation", + }, + }, + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "pulldowns": []interface{}{ + "invalid_pulldown", + map[string]interface{}{ + "type": "annotations", + "enable": true, + "annotations": []interface{}{ + map[string]interface{}{ + "name": "valid annotation", + }, + }, + }, + }, + "annotations": map[string]interface{}{ + "list": []interface{}{ + map[string]interface{}{ + "name": "valid annotation", + }, + }, + }, + }, + }, + { + name: "template variable with invalid structure", + input: map[string]interface{}{ + "schemaVersion": 5, + "templating": map[string]interface{}{ + "list": []interface{}{ + "invalid_variable", + map[string]interface{}{ + "name": "valid_variable", + "type": "filter", + }, + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 6, + "templating": map[string]interface{}{ + "list": []interface{}{ + "invalid_variable", + map[string]interface{}{ + "name": "valid_variable", + "type": "query", + "datasource": nil, + }, + }, + }, + }, + }, + } + + runMigrationTests(t, testCases, schemaversion.V6) +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v7.go b/apps/dashboard/pkg/migration/schemaversion/v7.go new file mode 100644 index 00000000000..15416f9b608 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v7.go @@ -0,0 +1,73 @@ +package schemaversion + +import "context" + +// V7 migration handles the nav to timepicker conversion and ensures query refIds. +// This migration transforms the legacy nav property to the newer timepicker format +// and ensures all panel targets have refId properties. +// +// Background: +// In earlier versions, dashboards used a "nav" property array to store time picker +// configuration. This migration moves the first nav item to the "timepicker" property. +// Additionally, it ensures all query targets have refId properties assigned. +// +// Example before migration: +// { +// "schemaVersion": 6, +// "nav": [ +// { +// "enable": true, +// "type": "timepicker", +// "status": "Stable", +// "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"], +// "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"], +// "now": true, +// "collapse": false, +// "notice": false +// } +// ], +// "panels": [ +// { +// "targets": [ +// {"expr": "up"}, +// {"expr": "cpu_usage", "refId": "B"} +// ] +// } +// ] +// } +// +// Example after migration: +// { +// "schemaVersion": 7, +// "timepicker": { +// "enable": true, +// "type": "timepicker", +// "status": "Stable", +// "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"], +// "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"], +// "now": true, +// "collapse": false, +// "notice": false +// }, +// "panels": [ +// { +// "targets": [ +// {"expr": "up", "refId": "A"}, +// {"expr": "cpu_usage", "refId": "B"} +// ] +// } +// ] +// } + +func V7(_ context.Context, dashboard map[string]interface{}) error { + dashboard["schemaVersion"] = 7 + + // Convert nav to timepicker (matches frontend DashboardMigrator logic) + if nav, ok := dashboard["nav"].([]interface{}); ok && len(nav) > 0 { + if firstNav, ok := nav[0].(map[string]interface{}); ok { + dashboard["timepicker"] = firstNav + } + } + + return nil +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v7_test.go b/apps/dashboard/pkg/migration/schemaversion/v7_test.go new file mode 100644 index 00000000000..5ac73cdf61a --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v7_test.go @@ -0,0 +1,208 @@ +package schemaversion_test + +import ( + "testing" + + "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" +) + +func TestV7Migration(t *testing.T) { + testCases := []migrationTestCase{ + { + name: "nav to timepicker conversion with query refId assignment", + input: map[string]interface{}{ + "schemaVersion": 6, + "nav": []interface{}{ + map[string]interface{}{ + "enable": true, + "type": "timepicker", + "status": "Stable", + "time_options": []interface{}{"5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"}, + "refresh_intervals": []interface{}{"5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"}, + "now": true, + "collapse": false, + "notice": false, + }, + }, + "panels": []interface{}{ + map[string]interface{}{ + "targets": []interface{}{ + map[string]interface{}{"expr": "up"}, + map[string]interface{}{"expr": "cpu_usage", "refId": "B"}, + }, + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 7, + "nav": []interface{}{ + map[string]interface{}{ + "enable": true, + "type": "timepicker", + "status": "Stable", + "time_options": []interface{}{"5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"}, + "refresh_intervals": []interface{}{"5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"}, + "now": true, + "collapse": false, + "notice": false, + }, + }, + "timepicker": map[string]interface{}{ + "enable": true, + "type": "timepicker", + "status": "Stable", + "time_options": []interface{}{"5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"}, + "refresh_intervals": []interface{}{"5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"}, + "now": true, + "collapse": false, + "notice": false, + }, + "panels": []interface{}{ + map[string]interface{}{ + "targets": []interface{}{ + map[string]interface{}{"expr": "up"}, + map[string]interface{}{"expr": "cpu_usage", "refId": "B"}, + }, + }, + }, + }, + }, + { + name: "nav conversion without panels", + input: map[string]interface{}{ + "schemaVersion": 6, + "nav": []interface{}{ + map[string]interface{}{ + "enable": true, + "type": "timepicker", + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 7, + "timepicker": map[string]interface{}{ + "enable": true, + "type": "timepicker", + }, + "nav": []interface{}{ + map[string]interface{}{ + "enable": true, + "type": "timepicker", + }, + }, + }, + }, + { + name: "empty nav array", + input: map[string]interface{}{ + "schemaVersion": 6, + "nav": []interface{}{}, + }, + expected: map[string]interface{}{ + "schemaVersion": 7, + "nav": []interface{}{}, + }, + }, + { + name: "no nav property", + input: map[string]interface{}{ + "schemaVersion": 6, + "title": "Test Dashboard", + }, + expected: map[string]interface{}{ + "schemaVersion": 7, + "title": "Test Dashboard", + }, + }, + { + name: "panels with nested panels", + input: map[string]interface{}{ + "schemaVersion": 6, + "panels": []interface{}{ + map[string]interface{}{ + "type": "row", + "panels": []interface{}{ + map[string]interface{}{ + "targets": []interface{}{ + map[string]interface{}{"expr": "memory_usage"}, + }, + }, + }, + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 7, + "panels": []interface{}{ + map[string]interface{}{ + "type": "row", + "panels": []interface{}{ + map[string]interface{}{ + "targets": []interface{}{ + map[string]interface{}{"expr": "memory_usage"}, + }, + }, + }, + }, + }, + }, + }, + { + name: "multiple nav items - only first is used", + input: map[string]interface{}{ + "schemaVersion": 6, + "nav": []interface{}{ + map[string]interface{}{ + "enable": true, + "type": "timepicker", + }, + map[string]interface{}{ + "enable": false, + "type": "other", + }, + }, + }, + expected: map[string]interface{}{ + "schemaVersion": 7, + "timepicker": map[string]interface{}{ + "enable": true, + "type": "timepicker", + }, + "nav": []interface{}{ + map[string]interface{}{ + "enable": true, + "type": "timepicker", + }, + map[string]interface{}{ + "enable": false, + "type": "other", + }, + }, + }, + }, + { + name: "invalid nav structure", + input: map[string]interface{}{ + "schemaVersion": 6, + "nav": "invalid", + }, + expected: map[string]interface{}{ + "schemaVersion": 7, + "nav": "invalid", + }, + }, + { + name: "panels with invalid structure", + input: map[string]interface{}{ + "schemaVersion": 6, + "panels": "invalid", + }, + expected: map[string]interface{}{ + "schemaVersion": 7, + "panels": "invalid", + }, + }, + } + + runMigrationTests(t, testCases, schemaversion.V7) +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v8.go b/apps/dashboard/pkg/migration/schemaversion/v8.go new file mode 100644 index 00000000000..ec8c3940caf --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v8.go @@ -0,0 +1,206 @@ +package schemaversion + +import "context" + +// V8 migration updates old InfluxDB query schema to the new format. +// This migration transforms the legacy InfluxDB query structure with fields, tags, and groupBy +// into the newer select-based query format. +// +// Background: +// In earlier versions, InfluxDB queries were stored using a different schema with separate +// fields, tags, and groupBy properties. This migration converts them to the newer select +// format that is more structured and easier to work with. +// +// The migration handles two cases: +// 1. Raw queries: Simply removes the fields and fill properties +// 2. Structured queries: Converts fields to select format and updates groupBy structure +// +// Example before migration (structured query): +// { +// "schemaVersion": 7, +// "panels": [ +// { +// "targets": [ +// { +// "fields": [ +// {"name": "value", "func": "mean", "mathExpr": "*2", "asExpr": "doubled"} +// ], +// "tags": [{"key": "host", "value": "server1"}], +// "groupBy": [ +// {"type": "time", "interval": "1m"}, +// {"type": "tag", "key": "host"} +// ], +// "fill": "null" +// } +// ] +// } +// ] +// } +// +// Example after migration (structured query): +// { +// "schemaVersion": 8, +// "panels": [ +// { +// "targets": [ +// { +// "select": [ +// [ +// {"type": "field", "params": ["value"]}, +// {"type": "mean", "params": []}, +// {"type": "math", "params": ["*2"]}, +// {"type": "alias", "params": ["doubled"]} +// ] +// ], +// "tags": [{"key": "host", "value": "server1"}], +// "groupBy": [ +// {"type": "time", "params": ["1m"]}, +// {"type": "tag", "params": ["host"]}, +// {"type": "fill", "params": ["null"]} +// ] +// } +// ] +// } +// ] +// } + +func V8(_ context.Context, dashboard map[string]interface{}) error { + dashboard["schemaVersion"] = 8 + + panels, ok := dashboard["panels"].([]interface{}) + if !ok { + return nil + } + + for _, p := range panels { + panel, ok := p.(map[string]interface{}) + if !ok { + continue + } + + targets, ok := panel["targets"].([]interface{}) + if !ok { + continue + } + + for _, t := range targets { + target, ok := t.(map[string]interface{}) + if !ok { + continue + } + + // Check if this target has the old InfluxDB schema + fields, hasFields := target["fields"] + _, hasTags := target["tags"] + groupBy, hasGroupBy := target["groupBy"] + + if !hasFields || !hasTags || !hasGroupBy { + continue + } + + // Check if this is a raw query + rawQuery, isRawQuery := target["rawQuery"].(bool) + if isRawQuery && rawQuery { + // For raw queries, just delete fields and fill + delete(target, "fields") + delete(target, "fill") + } else { + // For structured queries, convert fields to select format + fieldsArray, ok := fields.([]interface{}) + if ok { + selectArray := make([]interface{}, 0, len(fieldsArray)) + + for _, f := range fieldsArray { + field, ok := f.(map[string]interface{}) + if !ok { + continue + } + + parts := make([]interface{}, 0) + + // Add field part + if name, ok := field["name"].(string); ok { + parts = append(parts, map[string]interface{}{ + "type": "field", + "params": []interface{}{name}, + }) + } + + // Add function part + if funcName, ok := field["func"].(string); ok { + parts = append(parts, map[string]interface{}{ + "type": funcName, + "params": []interface{}{}, + }) + } + + // Add math expression if present + if mathExpr, ok := field["mathExpr"].(string); ok { + parts = append(parts, map[string]interface{}{ + "type": "math", + "params": []interface{}{mathExpr}, + }) + } + + // Add alias if present + if asExpr, ok := field["asExpr"].(string); ok { + parts = append(parts, map[string]interface{}{ + "type": "alias", + "params": []interface{}{asExpr}, + }) + } + + if len(parts) > 0 { + selectArray = append(selectArray, parts) + } + } + + target["select"] = selectArray + } + + // Remove the old fields property + delete(target, "fields") + + // Update groupBy format + if groupByArray, ok := groupBy.([]interface{}); ok { + for _, gb := range groupByArray { + groupByPart, ok := gb.(map[string]interface{}) + if !ok { + continue + } + + // Convert time groupBy + if partType, ok := groupByPart["type"].(string); ok && partType == "time" { + if interval, ok := groupByPart["interval"].(string); ok { + groupByPart["params"] = []interface{}{interval} + delete(groupByPart, "interval") + } + } + + // Convert tag groupBy + if partType, ok := groupByPart["type"].(string); ok && partType == "tag" { + if key, ok := groupByPart["key"].(string); ok { + groupByPart["params"] = []interface{}{key} + delete(groupByPart, "key") + } + } + } + + // Add fill to groupBy if present + if fill, hasFill := target["fill"]; hasFill { + newGroupByArray := make([]interface{}, len(groupByArray)) + copy(newGroupByArray, groupByArray) + newGroupByArray = append(newGroupByArray, map[string]interface{}{ + "type": "fill", + "params": []interface{}{fill}, + }) + target["groupBy"] = newGroupByArray + delete(target, "fill") + } + } + } + } + } + + return nil +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v8_test.go b/apps/dashboard/pkg/migration/schemaversion/v8_test.go new file mode 100644 index 00000000000..725e93c6334 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v8_test.go @@ -0,0 +1,252 @@ +package schemaversion_test + +import ( + "testing" + + "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" +) + +func TestV8(t *testing.T) { + tests := []migrationTestCase{ + { + name: "InfluxDB structured query should be converted to new select format", + input: map[string]interface{}{ + "title": "V8 InfluxDB Query Migration Test Dashboard", + "schemaVersion": 7, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "targets": []interface{}{ + map[string]interface{}{ + "fields": []interface{}{ + map[string]interface{}{ + "name": "value", + "func": "mean", + "mathExpr": "*2", + "asExpr": "doubled", + }, + map[string]interface{}{ + "name": "count", + "func": "sum", + }, + }, + "tags": []interface{}{ + map[string]interface{}{ + "key": "host", + "value": "server1", + }, + }, + "groupBy": []interface{}{ + map[string]interface{}{ + "type": "time", + "interval": "1m", + }, + map[string]interface{}{ + "type": "tag", + "key": "host", + }, + }, + "fill": "null", + }, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V8 InfluxDB Query Migration Test Dashboard", + "schemaVersion": 8, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "targets": []interface{}{ + map[string]interface{}{ + "select": []interface{}{ + []interface{}{ + map[string]interface{}{ + "type": "field", + "params": []interface{}{"value"}, + }, + map[string]interface{}{ + "type": "mean", + "params": []interface{}{}, + }, + map[string]interface{}{ + "type": "math", + "params": []interface{}{"*2"}, + }, + map[string]interface{}{ + "type": "alias", + "params": []interface{}{"doubled"}, + }, + }, + []interface{}{ + map[string]interface{}{ + "type": "field", + "params": []interface{}{"count"}, + }, + map[string]interface{}{ + "type": "sum", + "params": []interface{}{}, + }, + }, + }, + "tags": []interface{}{ + map[string]interface{}{ + "key": "host", + "value": "server1", + }, + }, + "groupBy": []interface{}{ + map[string]interface{}{ + "type": "time", + "params": []interface{}{"1m"}, + }, + map[string]interface{}{ + "type": "tag", + "params": []interface{}{"host"}, + }, + map[string]interface{}{ + "type": "fill", + "params": []interface{}{"null"}, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "InfluxDB raw query should only remove fields and fill", + input: map[string]interface{}{ + "title": "V8 InfluxDB Raw Query Migration Test Dashboard", + "schemaVersion": 7, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "targets": []interface{}{ + map[string]interface{}{ + "rawQuery": true, + "fields": []interface{}{ + map[string]interface{}{ + "name": "value", + "func": "mean", + }, + }, + "tags": []interface{}{ + map[string]interface{}{ + "key": "host", + "value": "server1", + }, + }, + "groupBy": []interface{}{ + map[string]interface{}{ + "type": "time", + "interval": "1m", + }, + }, + "fill": "null", + }, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V8 InfluxDB Raw Query Migration Test Dashboard", + "schemaVersion": 8, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "targets": []interface{}{ + map[string]interface{}{ + "rawQuery": true, + "tags": []interface{}{ + map[string]interface{}{ + "key": "host", + "value": "server1", + }, + }, + "groupBy": []interface{}{ + map[string]interface{}{ + "type": "time", + "interval": "1m", + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "targets without old InfluxDB schema should remain unchanged", + input: map[string]interface{}{ + "title": "V8 Non-InfluxDB Target Test Dashboard", + "schemaVersion": 7, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "targets": []interface{}{ + map[string]interface{}{ + "expr": "up", + "refId": "A", + "format": "time_series", + }, + }, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V8 Non-InfluxDB Target Test Dashboard", + "schemaVersion": 8, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "targets": []interface{}{ + map[string]interface{}{ + "expr": "up", + "refId": "A", + "format": "time_series", + }, + }, + }, + }, + }, + }, + { + name: "panels without targets should remain unchanged", + input: map[string]interface{}{ + "title": "V8 No Targets Test Dashboard", + "schemaVersion": 7, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "text", + }, + }, + }, + expected: map[string]interface{}{ + "title": "V8 No Targets Test Dashboard", + "schemaVersion": 8, + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "text", + }, + }, + }, + }, + { + name: "dashboard without panels should only update schema version", + input: map[string]interface{}{ + "title": "V8 No Panels Test Dashboard", + "schemaVersion": 7, + }, + expected: map[string]interface{}{ + "title": "V8 No Panels Test Dashboard", + "schemaVersion": 8, + }, + }, + } + runMigrationTests(t, tests, schemaversion.V8) +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v9.go b/apps/dashboard/pkg/migration/schemaversion/v9.go new file mode 100644 index 00000000000..dde0fcc3cea --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v9.go @@ -0,0 +1,42 @@ +package schemaversion + +import ( + "context" +) + +// V9 migration removes the first threshold value from singlestat panel thresholds when they have 3 or more values. +// This migration aligns with the frontend schema version 9 changes that addressed aliasYAxis changes +// specifically for singlestat panels with threshold configurations. +// +// Background: +// In earlier versions, singlestat panels stored threshold values as comma-separated strings with the first element +// representing a baseline value that was not actually used in threshold calculations. This migration removes that +// unused first element to clean up the data structure. +// +// Example before migration: +// { +// "schemaVersion": 8, +// "panels": [ +// { +// "type": "singlestat", +// "thresholds": "10,20,30" +// } +// ] +// } +// +// Example after migration: +// { +// "schemaVersion": 9, +// "panels": [ +// { +// "type": "singlestat", +// "thresholds": "20,30" +// } +// ] +// } + +func V9(_ context.Context, dashboard map[string]interface{}) error { + dashboard["schemaVersion"] = 9 + + return nil +} diff --git a/apps/dashboard/pkg/migration/schemaversion/v9_test.go b/apps/dashboard/pkg/migration/schemaversion/v9_test.go new file mode 100644 index 00000000000..aa6bf311711 --- /dev/null +++ b/apps/dashboard/pkg/migration/schemaversion/v9_test.go @@ -0,0 +1,38 @@ +package schemaversion_test + +import ( + "testing" + + "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" +) + +func TestV9(t *testing.T) { + tests := []migrationTestCase{ + { + name: "v11 no-op migration, updates schema version only", + input: map[string]interface{}{ + "title": "V9 No-Op Migration Test Dashboard", + "schemaVersion": 8, + "panels": []interface{}{ + map[string]interface{}{ + "type": "graph", + "title": "Panel remains unchanged", + "id": 1, + }, + }, + }, + expected: map[string]interface{}{ + "title": "V9 No-Op Migration Test Dashboard", + "schemaVersion": 9, + "panels": []interface{}{ + map[string]interface{}{ + "type": "graph", + "title": "Panel remains unchanged", + "id": 1, + }, + }, + }, + }, + } + runMigrationTests(t, tests, schemaversion.V9) +} diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mssql/mssql_fakedata.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mssql/mssql_fakedata.v42.json index 9d091b0a35d..45c41bc2847 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mssql/mssql_fakedata.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mssql/mssql_fakedata.v42.json @@ -327,60 +327,12 @@ } }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-mssql" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 10, "w": 24, @@ -388,11 +340,35 @@ "y": 18 }, "id": 4, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -405,14 +381,7 @@ } ], "title": "Values", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" } ], diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mssql/mssql_unittest.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mssql/mssql_unittest.v42.json index 9f651c9bf02..36dbc69d1cc 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mssql/mssql_unittest.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mssql/mssql_unittest.v42.json @@ -77,40 +77,12 @@ "links": [], "panels": [ { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-mssql-ds-tests" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, + "fontSize": "100%", "gridPos": { "h": 4, "w": 24, @@ -118,11 +90,28 @@ "y": 0 }, "id": 2, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "string", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -135,71 +124,16 @@ } ], "title": "Data types", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-mssql-ds-tests" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 3, "w": 6, @@ -207,11 +141,35 @@ "y": 4 }, "id": 32, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -225,71 +183,16 @@ } ], "title": "cast(null as bigint) as time", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-mssql-ds-tests" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 3, "w": 6, @@ -297,11 +200,35 @@ "y": 4 }, "id": 33, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -315,71 +242,16 @@ } ], "title": "cast(null as datetime) as time", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-mssql-ds-tests" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 3, "w": 6, @@ -387,11 +259,35 @@ "y": 4 }, "id": 34, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -405,71 +301,16 @@ } ], "title": "GETDATE() as time", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-mssql-ds-tests" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 3, "w": 6, @@ -477,11 +318,35 @@ "y": 4 }, "id": 35, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -495,14 +360,7 @@ } ], "title": "GETUTCDATE() as time", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mysql/mysql_fakedata.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mysql/mysql_fakedata.v42.json index e05dc3f21f7..e946b4f7c53 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mysql/mysql_fakedata.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mysql/mysql_fakedata.v42.json @@ -329,60 +329,12 @@ } }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-mysql" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 9, "w": 24, @@ -390,11 +342,36 @@ "y": 18 }, "id": 6, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "link": false, + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -408,14 +385,7 @@ } ], "title": "Values", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" } ], diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mysql/mysql_unittest.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mysql/mysql_unittest.v42.json index d528c6d6198..02768fa9b68 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mysql/mysql_unittest.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-mysql/mysql_unittest.v42.json @@ -77,40 +77,12 @@ "links": [], "panels": [ { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-mysql-ds-tests" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, + "fontSize": "100%", "gridPos": { "h": 4, "w": 24, @@ -118,11 +90,28 @@ "y": 0 }, "id": 2, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "string", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -135,71 +124,16 @@ } ], "title": "Data types", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-mysql-ds-tests" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "time_sec" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 3, "w": 6, @@ -207,11 +141,35 @@ "y": 4 }, "id": 32, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "time_sec", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -225,71 +183,16 @@ } ], "title": "cast(null as unsigned integer) as time", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-mysql-ds-tests" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "time_sec" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 3, "w": 6, @@ -297,11 +200,35 @@ "y": 4 }, "id": 33, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "time_sec", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -315,71 +242,16 @@ } ], "title": "cast(null as datetime) as time", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-mysql-ds-tests" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "time_sec" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 3, "w": 6, @@ -387,11 +259,35 @@ "y": 4 }, "id": 34, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "time_sec", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -405,71 +301,16 @@ } ], "title": "cast()NOW() as datetime) as time", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-mysql-ds-tests" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 3, "w": 6, @@ -477,11 +318,35 @@ "y": 4 }, "id": 35, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -495,14 +360,7 @@ } ], "title": "NOW() as time", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-postgres/postgres_fakedata.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-postgres/postgres_fakedata.v42.json index 8d8faf154cc..d30bfa70e7e 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-postgres/postgres_fakedata.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-postgres/postgres_fakedata.v42.json @@ -371,60 +371,12 @@ } }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-postgres" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 9, "w": 24, @@ -432,11 +384,36 @@ "y": 18 }, "id": 6, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "link": false, + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -450,14 +427,7 @@ } ], "title": "Values", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" } ], diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-postgres/postgres_unittest.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-postgres/postgres_unittest.v42.json index a86b8d4c1be..3bdbf26db6a 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-postgres/postgres_unittest.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-postgres/postgres_unittest.v42.json @@ -77,40 +77,12 @@ "links": [], "panels": [ { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-postgres-ds-tests" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, + "fontSize": "100%", "gridPos": { "h": 4, "w": 24, @@ -118,11 +90,28 @@ "y": 0 }, "id": 2, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 1, + "desc": false }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "string", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -135,71 +124,16 @@ } ], "title": "Data types", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-postgres-ds-tests" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 3, "w": 6, @@ -207,11 +141,35 @@ "y": 4 }, "id": 32, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -225,71 +183,16 @@ } ], "title": "cast(null as bigint) as time", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-postgres-ds-tests" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 3, "w": 6, @@ -297,11 +200,35 @@ "y": 4 }, "id": 33, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -315,71 +242,16 @@ } ], "title": "cast(null as datetime) as time", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-postgres-ds-tests" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 3, "w": 6, @@ -387,11 +259,35 @@ "y": 4 }, "id": 34, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -405,71 +301,16 @@ } ], "title": "localtimestamp as time", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "uid": "gdev-postgres-ds-tests" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 3, "w": 6, @@ -477,11 +318,35 @@ "y": 4 }, "id": 35, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "", @@ -495,14 +360,7 @@ } ], "title": "NOW() as time", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-testdata/demo1.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-testdata/demo1.v42.json index c8986249791..323bac1d906 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-testdata/demo1.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/datasource-testdata/demo1.v42.json @@ -1293,6 +1293,7 @@ "type": "timeseries" } ], + "preload": false, "refresh": false, "schemaVersion": 42, "tags": [ diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/feature-templating/testdata-nested-variables-drilldown.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/feature-templating/testdata-nested-variables-drilldown.v42.json index d86c55cc494..c1a9689ddd8 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/feature-templating/testdata-nested-variables-drilldown.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/feature-templating/testdata-nested-variables-drilldown.v42.json @@ -49,44 +49,26 @@ "type": "text" }, { + "autoMigrateFrom": "singlestat", + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], "datasource": { "apiVersion": "v1", "type": "grafana-testdata-datasource", "uid": "testdata-type-uid" }, - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "rgb(31, 120, 193)", - "mode": "fixed" - }, - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "none" - }, - "overrides": [] + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true }, "gridPos": { "h": 6, @@ -102,25 +84,37 @@ "url": "d/-Y-tnEDWk/dashboard-tests-nested-template-variables?orgId=1\u0026${__all_variables}\u0026${__url_time_range}" } ], - "maxDataPoints": 100, - "options": { - "colorMode": "none", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": true }, - "pluginVersion": "12.1.0", + "tableColumn": "", "targets": [ { "datasource": { @@ -132,8 +126,18 @@ "scenarioId": "random_walk" } ], + "thresholds": "", "title": "Panel drilldown link test", - "type": "stat" + "type": "stat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" }, { "aliasColors": {}, diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/feature-templating/testdata-nested-variables.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/feature-templating/testdata-nested-variables.v42.json index a7e8cab830f..8fce11b3b1a 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/feature-templating/testdata-nested-variables.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/feature-templating/testdata-nested-variables.v42.json @@ -55,43 +55,31 @@ "type": "text" }, { + "autoMigrateFrom": "singlestat", + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { - "color": { - "fixedColor": "rgb(31, 120, 193)", - "mode": "fixed" - }, - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "none" + "custom": {} }, "overrides": [] }, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, "gridPos": { "h": 9, "w": 4, @@ -106,25 +94,28 @@ "url": "d/O6GmNPvWk/dashboard-tests-nested-template-variables-drilldown?orgId=1\u0026${__all_variables}\u0026${__url_time_range}" } ], + "mappingType": 1, + "mappingTypes": [], "maxDataPoints": 100, - "options": { - "colorMode": "none", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true + "nullPointMode": "connected", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": true }, - "pluginVersion": "12.1.0", + "tableColumn": "", "targets": [ { "datasource": { @@ -134,8 +125,18 @@ "scenarioId": "random_walk" } ], + "thresholds": "", "title": "Panel drilldown link test", - "type": "stat" + "type": "stat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" }, { "datasource": { diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-canvas/canvas-connection-examples.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-canvas/canvas-connection-examples.v42.json index d9cf29cad55..99cb1d0b28e 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-canvas/canvas-connection-examples.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-canvas/canvas-connection-examples.v42.json @@ -3941,6 +3941,7 @@ "type": "canvas" } ], + "preload": false, "refresh": "", "schemaVersion": 42, "tags": [ diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-common/lazy_loading.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-common/lazy_loading.v42.json index da8363866ae..0079708be32 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-common/lazy_loading.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-common/lazy_loading.v42.json @@ -191,38 +191,24 @@ "type": "bargauge" }, { + "autoMigrateFrom": "singlestat", + "colorBackground": false, + "colorValue": true, + "colors": [ + "#299c46", + "#73BF69", + "#d44a3a" + ], "datasource": { "type": "grafana-testdata-datasource" }, - "fieldConfig": { - "defaults": { - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ms" - }, - "overrides": [] + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true }, "gridPos": { "h": 4, @@ -231,25 +217,38 @@ "y": 7 }, "id": 20, - "maxDataPoints": 100, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "pluginVersion": "6.2.0-pre", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "p99", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": true }, - "pluginVersion": "12.1.0", + "tableColumn": "", "targets": [ { "datasource": { @@ -259,41 +258,37 @@ "scenarioId": "random_walk" } ], - "type": "stat" + "thresholds": "", + "type": "stat", + "valueFontSize": "120%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" }, { + "autoMigrateFrom": "singlestat", + "colorBackground": false, + "colorValue": true, + "colors": [ + "#299c46", + "#73BF69", + "#d44a3a" + ], "datasource": { "type": "grafana-testdata-datasource" }, - "fieldConfig": { - "defaults": { - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ms" - }, - "overrides": [] + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true }, "gridPos": { "h": 4, @@ -302,25 +297,38 @@ "y": 7 }, "id": 23, - "maxDataPoints": 100, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "pluginVersion": "6.2.0-pre", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "p95", + "prefixFontSize": "80%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": true }, - "pluginVersion": "12.1.0", + "tableColumn": "", "targets": [ { "datasource": { @@ -330,41 +338,37 @@ "scenarioId": "random_walk" } ], - "type": "stat" + "thresholds": "", + "type": "stat", + "valueFontSize": "120%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" }, { + "autoMigrateFrom": "singlestat", + "colorBackground": false, + "colorValue": true, + "colors": [ + "#299c46", + "#73BF69", + "#d44a3a" + ], "datasource": { "type": "grafana-testdata-datasource" }, - "fieldConfig": { - "defaults": { - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ms" - }, - "overrides": [] + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true }, "gridPos": { "h": 4, @@ -373,25 +377,38 @@ "y": 7 }, "id": 24, - "maxDataPoints": 100, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "pluginVersion": "6.2.0-pre", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "p90", + "prefixFontSize": "80%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": true }, - "pluginVersion": "12.1.0", + "tableColumn": "", "targets": [ { "datasource": { @@ -401,41 +418,37 @@ "scenarioId": "random_walk" } ], - "type": "stat" + "thresholds": "", + "type": "stat", + "valueFontSize": "120%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" }, { + "autoMigrateFrom": "singlestat", + "colorBackground": false, + "colorValue": true, + "colors": [ + "#299c46", + "#73BF69", + "#d44a3a" + ], "datasource": { "type": "grafana-testdata-datasource" }, - "fieldConfig": { - "defaults": { - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ms" - }, - "overrides": [] + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true }, "gridPos": { "h": 4, @@ -444,25 +457,38 @@ "y": 7 }, "id": 45, - "maxDataPoints": 100, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "pluginVersion": "6.2.0-pre", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "p90", + "prefixFontSize": "80%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": true }, - "pluginVersion": "12.1.0", + "tableColumn": "", "targets": [ { "datasource": { @@ -472,7 +498,17 @@ "scenarioId": "random_walk" } ], - "type": "stat" + "thresholds": "", + "type": "stat", + "valueFontSize": "120%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" }, { "aliasColors": { diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-common/panels_without_title.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-common/panels_without_title.v42.json index 68e5cbefd7c..d7fa2960e45 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-common/panels_without_title.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-common/panels_without_title.v42.json @@ -20,45 +20,27 @@ "links": [], "panels": [ { + "autoMigrateFrom": "singlestat", + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "#5794F2", + "#d44a3a" + ], "datasource": { "apiVersion": "v1", "type": "grafana-testdata-datasource", "uid": "testdata-type-uid" }, "description": "asdasdas", - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "rgb(31, 120, 193)", - "mode": "fixed" - }, - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ms" - }, - "overrides": [] + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true }, "gridPos": { "h": 4, @@ -67,25 +49,37 @@ "y": 0 }, "id": 8, - "maxDataPoints": 100, - "options": { - "colorMode": "none", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "100%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": true }, - "pluginVersion": "12.1.0", + "tableColumn": "", "targets": [ { "datasource": { @@ -97,50 +91,42 @@ "scenarioId": "random_walk" } ], + "thresholds": "", "timeShift": "2h", "title": "Title", - "type": "stat" + "type": "stat", + "valueFontSize": "120%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" }, { + "autoMigrateFrom": "singlestat", + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "#5794F2", + "#d44a3a" + ], "datasource": { "apiVersion": "v1", "type": "grafana-testdata-datasource", "uid": "testdata-type-uid" }, "description": "asdasdas", - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "rgb(31, 120, 193)", - "mode": "fixed" - }, - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ms" - }, - "overrides": [] + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true }, "gridPos": { "h": 4, @@ -149,25 +135,37 @@ "y": 0 }, "id": 2, - "maxDataPoints": 100, - "options": { - "colorMode": "none", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "100%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": true }, - "pluginVersion": "12.1.0", + "tableColumn": "", "targets": [ { "datasource": { @@ -179,49 +177,41 @@ "scenarioId": "random_walk" } ], + "thresholds": "", "timeShift": "2h", - "type": "stat" + "type": "stat", + "valueFontSize": "120%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" }, { + "autoMigrateFrom": "singlestat", + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "#5794F2", + "#d44a3a" + ], "datasource": { "apiVersion": "v1", "type": "grafana-testdata-datasource", "uid": "testdata-type-uid" }, "description": "asdasdas", - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "rgb(31, 120, 193)", - "mode": "fixed" - }, - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ms" - }, - "overrides": [] + "format": "ms", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true }, "gridPos": { "h": 4, @@ -230,25 +220,37 @@ "y": 4 }, "id": 4, - "maxDataPoints": 100, - "options": { - "colorMode": "none", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "100%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": true }, - "pluginVersion": "12.1.0", + "tableColumn": "", "targets": [ { "datasource": { @@ -260,9 +262,19 @@ "scenarioId": "random_walk" } ], + "thresholds": "", "timeShift": "2h", "title": "Panel Title", - "type": "stat" + "type": "stat", + "valueFontSize": "120%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" }, { "datasource": { @@ -404,43 +416,27 @@ "type": "text" }, { + "autoMigrateFrom": "singlestat", + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], "datasource": { "apiVersion": "v1", "type": "grafana-testdata-datasource", "uid": "testdata-type-uid" }, "description": "asdasdas", - "fieldConfig": { - "defaults": { - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "max": 100, - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "none" - }, - "overrides": [] + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true }, "gridPos": { "h": 4, @@ -449,25 +445,38 @@ "y": 8 }, "id": 10, - "maxDataPoints": 100, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "pluginVersion": "6.2.0-pre", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false }, - "pluginVersion": "12.1.0", + "tableColumn": "", "targets": [ { "datasource": { @@ -479,8 +488,18 @@ "scenarioId": "random_walk" } ], + "thresholds": "", "timeShift": "2h", - "type": "stat" + "type": "stat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" }, { "datasource": { diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_new.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_new.v42.json new file mode 100644 index 00000000000..a85230fd842 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_new.v42.json @@ -0,0 +1,2200 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 525, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [], + "title": "Basic single ", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 0, + "y": 1 + }, + "id": 1, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.4, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": true, + "spotlight": false + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Plain", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 4, + "y": 1 + }, + "id": 4, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.4, + "effects": { + "barGlow": false, + "centerGlow": true, + "rounded": true, + "spotlight": false + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Center glow", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 8, + "y": 1 + }, + "id": 3, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.4, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": false + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Center and bar glow", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 12, + "y": 1 + }, + "id": 5, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.4, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Spotlight", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 16, + "y": 1 + }, + "id": 8, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.4, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": true + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Sparkline", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 0, + "y": 7 + }, + "id": 22, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.72, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": false, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Square butts", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 4, + "y": 7 + }, + "id": 23, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.72, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": false, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "gauge", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Square butts gauge", + "type": "radialbar" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 13 + }, + "id": 17, + "panels": [], + "title": "Bar width", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 0, + "y": 14 + }, + "id": 18, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.1, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Bar width 0,1", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 5, + "y": 14 + }, + "id": 19, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.32, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Bar width 0,32", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 10, + "y": 14 + }, + "id": 20, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.57, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Bar width 0,57", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 15, + "y": 14 + }, + "id": 21, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.8, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Bar width 0,8", + "type": "radialbar" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 20 + }, + "id": 24, + "panels": [], + "title": "Thresholds", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 0, + "y": 21 + }, + "id": 25, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.9, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "gauge", + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Plain thresholds", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 6, + "y": 21 + }, + "id": 26, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.72, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 37, + "segmentSpacing": 0.31, + "shape": "gauge", + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Thresholds segmented", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 12, + "y": 21 + }, + "id": 29, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.72, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 46, + "segmentSpacing": 0.3, + "shape": "gauge", + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Segmented + gradient", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 27 + }, + "id": 30, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.9, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "gauge", + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Plain thresholds", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 27 + }, + "id": 28, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.72, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 62, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Thresholds circle segmented", + "type": "radialbar" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 34 + }, + "id": 31, + "panels": [], + "title": "Threshold labels", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "semi-dark-yellow", + "value": 40 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 7, + "x": 0, + "y": 35 + }, + "id": 32, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.9, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 62, + "segmentSpacing": 0.3, + "shape": "gauge", + "showThresholdLabels": true, + "showThresholdMarkers": true, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Thresholds labels", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "semi-dark-yellow", + "value": 40 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 7, + "x": 7, + "y": 35 + }, + "id": 34, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.9, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 62, + "segmentSpacing": 0.3, + "shape": "gauge", + "showThresholdLabels": true, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Thresholds labels only", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "semi-dark-yellow", + "value": 40 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 6, + "x": 14, + "y": 35 + }, + "id": 33, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.9, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 80, + "segmentSpacing": 0.59, + "shape": "circle", + "showThresholdLabels": true, + "showThresholdMarkers": true, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Thresholds labels + circle", + "type": "radialbar" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 45 + }, + "id": 6, + "panels": [], + "title": "Gradient modes", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "palette-classic" + }, + "mappings": [], + "max": 100, + "min": 1, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 9, + "maxDataPoints": 20, + "options": { + "barWidth": 12, + "barWidthFactor": 0.4, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "glow": "both", + "gradient": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false, + "spotlight": true + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "max": 98, + "min": 5, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 5, + "spread": 12, + "startValue": 50 + } + ], + "title": "Auto gradient + classic palette", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "continuous-GrYlRd" + }, + "mappings": [], + "max": 100, + "min": 1, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 52 + }, + "id": 11, + "maxDataPoints": 20, + "options": { + "barWidth": 12, + "barWidthFactor": 0.4, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "glow": "both", + "gradient": "scheme", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "gauge", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": true, + "spotlight": true + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "max": 98, + "min": 5, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 5, + "spread": 12, + "startValue": 50 + } + ], + "title": "Continuous color scheme ", + "type": "radialbar" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 58 + }, + "id": 12, + "panels": [], + "title": "Segmented", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "continuous-GrYlRd" + }, + "decimals": 0, + "mappings": [], + "max": 8, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "suffix:/ 8 " + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 59 + }, + "id": 13, + "maxDataPoints": 20, + "options": { + "barWidth": 12, + "barWidthFactor": 0.49, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "glow": "both", + "gradient": "scheme", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 8, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false, + "spotlight": true + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "max": 8, + "min": 1, + "noise": 2, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1, + "spread": 6, + "startValue": 0 + } + ], + "title": "Active gateways", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "continuous-GrYlRd" + }, + "decimals": 0, + "mappings": [], + "max": 12, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "suffix:/ 12" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 5, + "x": 4, + "y": 59 + }, + "id": 14, + "maxDataPoints": 20, + "options": { + "barWidth": 12, + "barWidthFactor": 0.49, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "sparkline": false, + "spotlight": true + }, + "glow": "both", + "gradient": "scheme", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 12, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false, + "spotlight": true + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "max": 12, + "min": 1, + "noise": 2, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1, + "spread": 6, + "startValue": 0 + } + ], + "title": "Active pods", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "red", + "mode": "fixed" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 5, + "x": 9, + "y": 59 + }, + "id": 15, + "maxDataPoints": 20, + "options": { + "barWidth": 12, + "barWidthFactor": 0.84, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "glow": "both", + "gradient": "hue", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 39, + "segmentSpacing": 0.76, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false, + "spotlight": true + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "max": 100, + "min": 10, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1, + "spread": 12, + "startValue": 10 + } + ], + "title": "Backend", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "red", + "mode": "fixed" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 14, + "y": 59 + }, + "id": 16, + "maxDataPoints": 20, + "options": { + "barWidth": 12, + "barWidthFactor": 0.66, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "glow": "both", + "gradient": "hue", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 81, + "segmentSpacing": 0.28, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false, + "spotlight": true + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "max": 100, + "min": 10, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1, + "spread": 12, + "startValue": 10 + } + ], + "title": "Backend", + "type": "radialbar" + } + ], + "preload": false, + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Panel tests - Gauge (new)", + "uid": "panel-tests-gauge-new", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_old_to_new.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_old_to_new.v42.json new file mode 100644 index 00000000000..d4dd7980100 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_old_to_new.v42.json @@ -0,0 +1,1165 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "description": "To verify that the new gauge behaves the same and that migration is handled properly", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 531, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 7, + "panels": [], + "title": "Tests", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 0, + "y": 1 + }, + "id": 8, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,22" + } + ], + "title": "Plain", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 4, + "y": 1 + }, + "id": 9, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,55.5" + } + ], + "title": "With unit", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "very small\n", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 2, + "x": 8, + "y": 1 + }, + "id": 11, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "decimals": 3, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "accMS2" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 10, + "y": 1 + }, + "id": 10, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,80" + } + ], + "title": "long value", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 3, + "x": 14, + "y": 1 + }, + "id": 18, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "no_data_points" + } + ], + "title": "No data", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 16, + "w": 7, + "x": 17, + "y": 1 + }, + "id": 13, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,80.5" + } + ], + "title": "Tall", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 10, + "x": 0, + "y": 6 + }, + "id": 12, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto", + "text": { + "valueSize": 100 + } + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,47" + } + ], + "title": "custom font size", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "links": [ + { + "targetBlank": true, + "title": "Single link", + "url": "http://www.google.com" + } + ], + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 7, + "x": 10, + "y": 6 + }, + "id": 16, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,44" + } + ], + "title": "Single data link", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "links": [ + { + "targetBlank": true, + "title": "first link", + "url": "http://www.google.com" + }, + { + "targetBlank": true, + "title": "second link", + "url": "http://www.google.com" + } + ], + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 7, + "x": 10, + "y": 11 + }, + "id": 17, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,78" + } + ], + "title": "Multiple data links", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 17 + }, + "id": 14, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto", + "text": {} + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,20.5" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "hide": false, + "refId": "B", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,40.5" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "hide": false, + "refId": "C", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,60.5" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "hide": false, + "refId": "D", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,90.5" + } + ], + "title": "Multi series", + "type": "gauge" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 25 + }, + "id": 6, + "panels": [], + "title": "Thresholds", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "should not show any threshold markers", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "fixed" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 26 + }, + "id": 1, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,66" + } + ], + "title": "Old gauge with static blue color and show threshold markers enabled", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "should not show any threshold markers", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "yellow", + "value": 30 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "accFS2" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 26 + }, + "id": 2, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": true, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,20" + } + ], + "title": "Many thresholds with labels", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 90, + "min": 20, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "yellow", + "value": 30 + }, + { + "color": "orange", + "value": 50 + }, + { + "color": "red", + "value": 70 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 26 + }, + "id": 19, + "options": { + "barWidthFactor": 0.5, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "segmentCount": 70, + "segmentSpacing": 0.3, + "shape": "gauge", + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sparkline": false + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "max": 90, + "min": 20, + "refId": "A", + "scenarioId": "random_walk" + } + ], + "title": "Segmented w/ thresholds (min != 0, max != 100)", + "type": "gauge" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 35 + }, + "id": 5, + "panels": [], + "title": "Neutral value (not sure we will implement it yet)", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "should not show any threshold markers", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": -100, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "yellow", + "value": 30 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "accFS2" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 7, + "x": 0, + "y": 36 + }, + "id": 3, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,-50" + } + ], + "title": "neutral value 0 (-100 =\u003e 100)", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "should not show any threshold markers", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 41, + "min": 33, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "yellow", + "value": 30 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "degree" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 9, + "x": 7, + "y": 36 + }, + "id": 4, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,38" + } + ], + "title": "neutral value 47 (33 =\u003e 41)", + "type": "gauge" + } + ], + "preload": false, + "schemaVersion": 42, + "tags": [ + "gdev", + "panel-tests" + ], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Panel tests - Old gauge to new", + "uid": "panel-tests-old-gauge-to-new", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_footer.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_footer.v42.json index 13c13c8bccd..21bbf7b4d39 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_footer.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_footer.v42.json @@ -1537,6 +1537,7 @@ "type": "table" } ], + "preload": false, "schemaVersion": 42, "tags": [], "templating": { diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_kitchen_sink.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_kitchen_sink.v42.json index 501fcdef0d6..515ab48b7bf 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_kitchen_sink.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_kitchen_sink.v42.json @@ -1848,6 +1848,7 @@ "type": "table" } ], + "preload": false, "schemaVersion": 42, "tags": [], "templating": { diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_markdown.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_markdown.v42.json index 3cd280f3c55..9ed4d3f873b 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_markdown.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_markdown.v42.json @@ -107,6 +107,7 @@ "type": "table" } ], + "preload": false, "schemaVersion": 42, "tags": [], "templating": { diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_sparkline_cell.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_sparkline_cell.v42.json index 11b54f3f3a5..3c8310630d7 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_sparkline_cell.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_sparkline_cell.v42.json @@ -576,6 +576,7 @@ "type": "table" } ], + "preload": false, "refresh": "", "schemaVersion": 42, "tags": [], diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_tests.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_tests.v42.json index bdac0888407..f2f7abc07d6 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_tests.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_tests.v42.json @@ -20,150 +20,12 @@ "links": [], "panels": [ { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "type": "grafana-testdata-datasource" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "ColorCell" - }, - "properties": [ - { - "id": "unit", - "value": "currencyUSD" - }, - { - "id": "decimals", - "value": 2 - }, - { - "id": "custom.cellOptions", - "value": { - "type": "color-background" - } - }, - { - "id": "custom.align" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "rgba(245, 54, 54, 0.9)", - "value": null - }, - { - "color": "rgba(237, 129, 40, 0.89)", - "value": 5 - }, - { - "color": "rgba(50, 172, 45, 0.97)", - "value": 10 - } - ] - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "ColorValue" - }, - "properties": [ - { - "id": "unit", - "value": "Bps" - }, - { - "id": "decimals", - "value": 2 - }, - { - "id": "custom.cellOptions", - "value": { - "type": "color-text" - } - }, - { - "id": "custom.align" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "rgba(245, 54, 54, 0.9)", - "value": null - }, - { - "color": "rgba(237, 129, 40, 0.89)", - "value": 5 - }, - { - "color": "rgba(50, 172, 45, 0.97)", - "value": 10 - } - ] - } - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 11, "w": 12, @@ -171,11 +33,76 @@ "y": 0 }, "id": 3, - "options": { - "cellHeight": "sm", - "showHeader": true + "pageSize": 10, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colorMode": "cell", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "ColorCell", + "thresholds": [ + "5", + "10" + ], + "type": "number", + "unit": "currencyUSD" + }, + { + "alias": "", + "align": "auto", + "colorMode": "value", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "ColorValue", + "thresholds": [ + "5", + "10" + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "server1", @@ -200,161 +127,29 @@ } ], "title": "Time series to rows (2 pages)", - "transformations": [ - { - "id": "seriesToRows", - "options": { - "reducers": [] - } - } - ], + "transform": "timeseries_to_rows", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [ + { + "text": "Avg", + "value": "avg" + }, + { + "text": "Max", + "value": "max" + }, + { + "text": "Current", + "value": "current" + } + ], "datasource": { "type": "grafana-testdata-datasource" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "ColorCell" - }, - "properties": [ - { - "id": "unit", - "value": "currencyUSD" - }, - { - "id": "decimals", - "value": 2 - }, - { - "id": "custom.cellOptions", - "value": { - "type": "color-background" - } - }, - { - "id": "custom.align" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "rgba(245, 54, 54, 0.9)", - "value": null - }, - { - "color": "rgba(237, 129, 40, 0.89)", - "value": 5 - }, - { - "color": "rgba(50, 172, 45, 0.97)", - "value": 10 - } - ] - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "ColorValue" - }, - "properties": [ - { - "id": "unit", - "value": "Bps" - }, - { - "id": "decimals", - "value": 2 - }, - { - "id": "custom.cellOptions", - "value": { - "type": "color-text" - } - }, - { - "id": "custom.align" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "rgba(245, 54, 54, 0.9)", - "value": null - }, - { - "color": "rgba(237, 129, 40, 0.89)", - "value": 5 - }, - { - "color": "rgba(50, 172, 45, 0.97)", - "value": 10 - } - ] - } - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 11, "w": 12, @@ -362,11 +157,76 @@ "y": 0 }, "id": 4, - "options": { - "cellHeight": "sm", - "showHeader": true + "pageSize": 10, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colorMode": "cell", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "ColorCell", + "thresholds": [ + "5", + "10" + ], + "type": "number", + "unit": "currencyUSD" + }, + { + "alias": "", + "align": "auto", + "colorMode": "value", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "ColorValue", + "thresholds": [ + "5", + "10" + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "server1", @@ -391,121 +251,16 @@ } ], "title": "Time series aggregations", - "transformations": [ - { - "id": "reduce", - "options": { - "includeTimeField": false, - "reducers": [ - "mean", - "max", - "lastNotNull" - ] - } - } - ], + "transform": "timeseries_aggregations", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "type": "grafana-testdata-datasource" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/Color/" - }, - "properties": [ - { - "id": "unit", - "value": "currencyUSD" - }, - { - "id": "decimals", - "value": 2 - }, - { - "id": "custom.cellOptions", - "value": { - "type": "color-background" - } - }, - { - "id": "custom.align" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "rgba(245, 54, 54, 0.9)", - "value": null - }, - { - "color": "rgba(237, 129, 40, 0.89)", - "value": 5 - }, - { - "color": "rgba(50, 172, 45, 0.97)", - "value": 10 - } - ] - } - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 7, "w": 24, @@ -513,11 +268,55 @@ "y": 11 }, "id": 5, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colorMode": "row", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/Color/", + "thresholds": [ + "5", + "10" + ], + "type": "number", + "unit": "currencyUSD" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "ColorValue", @@ -533,161 +332,16 @@ } ], "title": "color row by threshold", - "transformations": [ - { - "id": "seriesToColumns", - "options": { - "reducers": [] - } - } - ], + "transform": "timeseries_to_columns", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "type": "grafana-testdata-datasource" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "ColorCell" - }, - "properties": [ - { - "id": "unit", - "value": "currencyUSD" - }, - { - "id": "decimals", - "value": 2 - }, - { - "id": "custom.cellOptions", - "value": { - "type": "color-background" - } - }, - { - "id": "custom.align" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "rgba(245, 54, 54, 0.9)", - "value": null - }, - { - "color": "rgba(237, 129, 40, 0.89)", - "value": 5 - }, - { - "color": "rgba(50, 172, 45, 0.97)", - "value": 10 - } - ] - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "ColorValue" - }, - "properties": [ - { - "id": "unit", - "value": "Bps" - }, - { - "id": "decimals", - "value": 2 - }, - { - "id": "custom.cellOptions", - "value": { - "type": "color-text" - } - }, - { - "id": "custom.align" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "rgba(245, 54, 54, 0.9)", - "value": null - }, - { - "color": "rgba(237, 129, 40, 0.89)", - "value": 5 - }, - { - "color": "rgba(50, 172, 45, 0.97)", - "value": 10 - } - ] - } - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 8, "w": 24, @@ -695,11 +349,75 @@ "y": 18 }, "id": 2, - "options": { - "cellHeight": "sm", - "showHeader": true + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colorMode": "cell", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "ColorCell", + "thresholds": [ + "5", + "10" + ], + "type": "number", + "unit": "currencyUSD" + }, + { + "alias": "", + "align": "auto", + "colorMode": "value", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "ColorValue", + "thresholds": [ + "5", + "10" + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "ColorValue", @@ -724,181 +442,16 @@ } ], "title": "Column style thresholds \u0026 units", - "transformations": [ - { - "id": "seriesToColumns", - "options": { - "reducers": [] - } - } - ], + "transform": "timeseries_to_columns", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [], "datasource": { "type": "grafana-testdata-datasource" }, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 2, - "displayName": "", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Time" - }, - "properties": [ - { - "id": "displayName", - "value": "Time" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - }, - { - "id": "custom.align" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "ColorCell" - }, - "properties": [ - { - "id": "unit", - "value": "currencyUSD" - }, - { - "id": "decimals", - "value": 2 - }, - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "", - "url": "http://www.grafana.com" - } - ] - }, - { - "id": "custom.cellOptions", - "value": { - "type": "color-background" - } - }, - { - "id": "custom.align" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "rgba(245, 54, 54, 0.5)", - "value": null - }, - { - "color": "rgba(237, 129, 40, 0.5)", - "value": 5 - }, - { - "color": "rgba(50, 172, 45, 0.5)", - "value": 10 - } - ] - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "ColorValue" - }, - "properties": [ - { - "id": "unit", - "value": "Bps" - }, - { - "id": "decimals", - "value": 2 - }, - { - "id": "links", - "value": [ - { - "targetBlank": false, - "title": "", - "url": "http://www.grafana.com" - } - ] - }, - { - "id": "custom.cellOptions", - "value": { - "type": "color-text" - } - }, - { - "id": "custom.align" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "rgba(245, 54, 54, 0.5)", - "value": null - }, - { - "color": "rgba(237, 129, 40, 0.5)", - "value": 5 - }, - { - "color": "rgba(50, 172, 45, 0.5)", - "value": 10 - } - ] - } - } - ] - } - ] - }, + "fontSize": "100%", "gridPos": { "h": 10, "w": 24, @@ -906,11 +459,82 @@ "y": 26 }, "id": 6, - "options": { - "cellHeight": "sm", - "showHeader": true + "pageSize": 20, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true }, - "pluginVersion": "12.1.0", + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colorMode": "cell", + "colors": [ + "rgba(245, 54, 54, 0.5)", + "rgba(237, 129, 40, 0.5)", + "rgba(50, 172, 45, 0.5)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": true, + "linkTooltip": "", + "linkUrl": "http://www.grafana.com", + "mappingType": 1, + "pattern": "ColorCell", + "thresholds": [ + "5", + "10" + ], + "type": "number", + "unit": "currencyUSD" + }, + { + "alias": "", + "align": "auto", + "colorMode": "value", + "colors": [ + "rgba(245, 54, 54, 0.5)", + "rgba(237, 129, 40, 0.5)", + "rgba(50, 172, 45, 0.5)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkUrl": "http://www.grafana.com", + "mappingType": 1, + "pattern": "ColorValue", + "thresholds": [ + "5", + "10" + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], "targets": [ { "alias": "ColorValue", @@ -935,14 +559,7 @@ } ], "title": "Column style thresholds and links", - "transformations": [ - { - "id": "seriesToColumns", - "options": { - "reducers": [] - } - } - ], + "transform": "timeseries_to_columns", "type": "table" } ], diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_tests_new.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_tests_new.v42.json index 9a7ac8fcfc9..b00ef6aa5ab 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_tests_new.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_tests_new.v42.json @@ -982,6 +982,7 @@ "type": "table" } ], + "preload": false, "refresh": "", "schemaVersion": 42, "tags": [ diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_v12_2_migrations.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_v12_2_migrations.v42.json index 7160b7d4af2..5054b2e1325 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_v12_2_migrations.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-table/table_v12_2_migrations.v42.json @@ -2172,6 +2172,7 @@ "type": "table" } ], + "preload": false, "schemaVersion": 42, "tags": [], "templating": { diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-timeline/timeline-thresholds-mappings.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-timeline/timeline-thresholds-mappings.v42.json index f1d9ec747cd..c5102363f3f 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-timeline/timeline-thresholds-mappings.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-timeline/timeline-thresholds-mappings.v42.json @@ -1071,6 +1071,7 @@ "type": "state-timeline" } ], + "preload": false, "refresh": "", "schemaVersion": 42, "tags": [ diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-timeseries/timeseries-nulls.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-timeseries/timeseries-nulls.v42.json index a75a3d47ee4..1e8a8b30326 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-timeseries/timeseries-nulls.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-timeseries/timeseries-nulls.v42.json @@ -3409,6 +3409,7 @@ "type": "state-timeline" } ], + "preload": false, "refresh": false, "schemaVersion": 42, "tags": [ diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-trend/trend_example.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-trend/trend_example.v42.json index 21c283d5596..212565adbca 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-trend/trend_example.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-trend/trend_example.v42.json @@ -196,6 +196,7 @@ "type": "trend" } ], + "preload": false, "refresh": "", "schemaVersion": 42, "tags": [ diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-xychart/xychart-demo.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-xychart/xychart-demo.v42.json index 2c9d0b026b4..3a6f7e88133 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-xychart/xychart-demo.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-xychart/xychart-demo.v42.json @@ -1433,6 +1433,7 @@ "type": "xychart" } ], + "preload": false, "refresh": "", "schemaVersion": 42, "tags": [ diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/scenarios/mostly-blank-dashboard.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/scenarios/mostly-blank-dashboard.v42.json index b264fc91cb9..7902e41bb2e 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/scenarios/mostly-blank-dashboard.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/scenarios/mostly-blank-dashboard.v42.json @@ -79,6 +79,7 @@ "type": "debug" } ], + "preload": false, "refresh": "", "schemaVersion": 42, "tags": [], diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/transforms/regression-analysis.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/transforms/regression-analysis.v42.json index caa608c1732..00309402356 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/transforms/regression-analysis.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/transforms/regression-analysis.v42.json @@ -1049,6 +1049,7 @@ "type": "xychart" } ], + "preload": false, "refresh": "", "schemaVersion": 42, "tags": [ diff --git a/apps/dashboard/pkg/migration/testdata/input/v10.table_thresholds.json b/apps/dashboard/pkg/migration/testdata/input/v10.table_thresholds.json new file mode 100644 index 00000000000..065423b9fea --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/input/v10.table_thresholds.json @@ -0,0 +1,36 @@ +{ + "title": "V10 Table Thresholds Test", + "schemaVersion": 9, + "panels": [ + { + "id": 1, + "type": "table", + "styles": [ + { + "thresholds": ["10", "20", "30"] + }, + { + "thresholds": ["100", "200", "300"] + } + ] + }, + { + "id": 2, + "type": "table", + "styles": [ + { + "thresholds": ["50", "75"] + } + ] + }, + { + "id": 3, + "type": "graph", + "styles": [ + { + "thresholds": ["5", "10", "15"] + } + ] + } + ] +} diff --git a/apps/dashboard/pkg/migration/testdata/input/v11.no-op-migration.json b/apps/dashboard/pkg/migration/testdata/input/v11.no-op-migration.json new file mode 100644 index 00000000000..82b054d9d11 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/input/v11.no-op-migration.json @@ -0,0 +1,58 @@ +{ + "title": "V11 No-Op Migration Test Dashboard", + "schemaVersion": 10, + "panels": [ + { + "type": "graph", + "title": "CPU Usage", + "id": 1, + "yAxes": [ + { + "show": true, + "min": null, + "max": null + } + ] + }, + { + "type": "singlestat", + "title": "Memory Usage", + "id": 2, + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ] + } + ], + "templating": { + "list": [ + { + "name": "server", + "type": "query", + "datasource": "prometheus", + "query": "label_values(server)", + "refresh": 1, + "options": [] + } + ] + }, + "annotations": { + "list": [ + { + "name": "Annotations & Alerts", + "datasource": "grafana", + "enable": true + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] + } + } diff --git a/apps/dashboard/pkg/migration/testdata/input/v12.template-variables.json b/apps/dashboard/pkg/migration/testdata/input/v12.template-variables.json new file mode 100644 index 00000000000..e851b6908a7 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/input/v12.template-variables.json @@ -0,0 +1,38 @@ +{ + "title": "V12 Template Variables Migration Test", + "schemaVersion": 11, + "templating": { + "list": [ + { + "type": "query", + "name": "refresh_true_var", + "refresh": true + }, + { + "type": "query", + "name": "refresh_false_var", + "refresh": false + }, + { + "type": "query", + "name": "hide_variable_var", + "hideVariable": true + }, + { + "type": "query", + "name": "hide_label_var", + "hideLabel": true + }, + { + "type": "query", + "name": "priority_var", + "hideVariable": true, + "hideLabel": true + }, + { + "type": "query", + "name": "no_properties_var" + } + ] + } + } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/input/v13.graph_thresholds.json b/apps/dashboard/pkg/migration/testdata/input/v13.graph_thresholds.json new file mode 100644 index 00000000000..27a83b9a232 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/input/v13.graph_thresholds.json @@ -0,0 +1,62 @@ +{ + "title": "V13 Graph Thresholds Migration Test", + "schemaVersion": 12, + "panels": [ + { + "type": "graph", + "id": 1, + "title": "Graph with Line Thresholds", + "grid": { + "threshold1": 200, + "threshold2": 400, + "threshold1Color": "yellow", + "threshold2Color": "red", + "thresholdLine": true + } + }, + { + "type": "graph", + "id": 2, + "title": "Graph with Fill Thresholds", + "grid": { + "threshold1": 100, + "threshold2": 300, + "threshold1Color": "green", + "threshold2Color": "blue", + "thresholdLine": false + } + }, + { + "type": "graph", + "id": 3, + "title": "Graph with Single Threshold", + "grid": { + "threshold1": 150, + "threshold1Color": "orange", + "thresholdLine": true + } + }, + { + "type": "graph", + "id": 4, + "title": "Graph with Existing Thresholds", + "thresholds": [ + { + "value": 50, + "color": "purple", + "colorMode": "custom" + } + ], + "grid": { + "threshold1": 200, + "threshold1Color": "yellow", + "thresholdLine": false + } + }, + { + "type": "singlestat", + "id": 5, + "title": "Non-Graph Panel" + } + ] +} diff --git a/apps/dashboard/pkg/migration/testdata/input/v13.minimal_graph_config.json b/apps/dashboard/pkg/migration/testdata/input/v13.minimal_graph_config.json new file mode 100644 index 00000000000..9911e340073 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/input/v13.minimal_graph_config.json @@ -0,0 +1,34 @@ +{ + "title": "Dashboard with minimal graph panel settings", + "tags": [], + "timezone": "browser", + "editable": true, + "panels": [ + { + "id": 4, + "type": "graph", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "editorMode": "builder", + "expr": "{\"a.utf8.metric ๐Ÿค˜\", job=\"prometheus-utf8\"}", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ] + } + ], + "schemaVersion": 12, + "time": { + "from": "now-6h", + "to": "now" + }, + "templating": { + "list": [] + } +} diff --git a/apps/dashboard/pkg/migration/testdata/input/v2.panels-and-services.json b/apps/dashboard/pkg/migration/testdata/input/v2.panels-and-services.json new file mode 100644 index 00000000000..9053a37e5aa --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/input/v2.panels-and-services.json @@ -0,0 +1,89 @@ +{ + "schemaVersion": 1, + "title": "V2 Comprehensive Migration Test Dashboard", + "services": { + "filter": { + "time": { + "from": "now-6h", + "to": "now" + }, + "list": [ + { + "name": "server", + "type": "query", + "datasource": "prometheus", + "query": "label_values(server)" + }, + { + "name": "env", + "type": "custom", + "options": [ + {"text": "Production", "value": "prod"}, + {"text": "Staging", "value": "stage"} + ] + } + ] + } + }, + "panels": [ + { + "id": 1, + "type": "graphite", + "title": "CPU Usage", + "legend": true, + "grid": { + "min": 0, + "max": 100 + }, + "y_format": "percent", + "y2_format": "short", + "targets": [ + { + "refId": "A", + "target": "cpu.usage" + } + ] + }, + { + "id": 2, + "type": "graph", + "title": "Memory Usage", + "legend": false, + "grid": { + "min": 0 + }, + "y_format": "bytes", + "targets": [ + { + "refId": "A", + "target": "memory.usage" + } + ] + }, + { + "id": 3, + "type": "table", + "title": "Server Stats", + "legend": true, + "grid": { + "min": 0, + "max": 100 + }, + "y_format": "short", + "y2_format": "bytes" + }, + { + "id": 4, + "type": "graphite", + "title": "Disk I/O", + "legend": true, + "y2_format": "Bps", + "targets": [ + { + "refId": "A", + "target": "disk.io" + } + ] + } + ] +} diff --git a/apps/dashboard/pkg/migration/testdata/input/v3.no-op.json b/apps/dashboard/pkg/migration/testdata/input/v3.no-op.json new file mode 100644 index 00000000000..4fd95fc5353 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/input/v3.no-op.json @@ -0,0 +1,21 @@ +{ + "title": "V3 No-Op Migration - but tests ensuring panel IDs are unique", + "schemaVersion": 2, + "panels": [ + { + "id": 1, + "type": "timeseries" + }, + { + "id": 2, + "type": "timeseries" + }, + { + "id": 2, + "type": "barchart" + }, + { + "type": "barchart" + } + ] +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/input/v4.no-op.json b/apps/dashboard/pkg/migration/testdata/input/v4.no-op.json new file mode 100644 index 00000000000..62ce65ca2a8 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/input/v4.no-op.json @@ -0,0 +1,18 @@ +{ + "title": "V4 No-Op Migration Test", + "schemaVersion": 3, + "panels": [ + { + "id": 1, + "type": "singlestat" + }, + { + "id": 2, + "type": "singlestat" + }, + { + "id": 3, + "type": "graph" + } + ] +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/input/v5.no-op.json b/apps/dashboard/pkg/migration/testdata/input/v5.no-op.json new file mode 100644 index 00000000000..64132050b11 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/input/v5.no-op.json @@ -0,0 +1,18 @@ +{ + "title": "V5 No-Op Migration Test", + "schemaVersion": 4, + "panels": [ + { + "id": 1, + "type": "singlestat" + }, + { + "id": 2, + "type": "singlestat" + }, + { + "id": 3, + "type": "graph" + } + ] +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/input/v6.pulldowns_and_templating.json b/apps/dashboard/pkg/migration/testdata/input/v6.pulldowns_and_templating.json new file mode 100644 index 00000000000..73c1db88803 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/input/v6.pulldowns_and_templating.json @@ -0,0 +1,106 @@ +{ + "title": "V6 Pulldowns and Template Variables Migration Test", + "schemaVersion": 5, + "pulldowns": [ + { + "type": "filtering", + "enable": true + }, + { + "type": "annotations", + "enable": true, + "annotations": [ + { + "name": "deployment", + "datasource": "prometheus", + "enable": true, + "iconColor": "red", + "query": "ALERTS{alertname=\"DeploymentStarted\"}" + }, + { + "name": "alerts", + "datasource": "loki", + "enable": false, + "iconColor": "yellow", + "query": "{job=\"alertmanager\"}" + } + ] + } + ], + "templating": { + "list": [ + { + "name": "environment", + "type": "filter", + "allFormat": null + }, + { + "name": "service", + "datasource": "prometheus", + "allFormat": "glob" + }, + { + "name": "region", + "type": "custom", + "options": [ + { + "text": "us-east-1", + "value": "us-east-1" + }, + { + "text": "us-west-2", + "value": "us-west-2" + } + ] + }, + { + "name": "instance", + "type": "query", + "datasource": "prometheus", + "query": "label_values(up, instance)", + "refresh": 1 + } + ] + }, + "panels": [ + { + "id": 1, + "title": "CPU Usage", + "type": "graph", + "targets": [ + { + "expr": "cpu_usage{environment=\"$environment\", service=\"$service\"}", + "refId": "A" + } + ], + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + } + }, + { + "id": 2, + "title": "Memory Usage", + "type": "singlestat", + "targets": [ + { + "expr": "memory_usage{region=\"$region\"}", + "refId": "B" + } + ], + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + } + } + ], + "time": { + "from": "now-1h", + "to": "now" + }, + "refresh": "30s" +} diff --git a/apps/dashboard/pkg/migration/testdata/input/v7.timepicker.json b/apps/dashboard/pkg/migration/testdata/input/v7.timepicker.json new file mode 100644 index 00000000000..6bd43ba7e34 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/input/v7.timepicker.json @@ -0,0 +1,23 @@ +{ + "schemaVersion": 6, + "nav": [ + { + "enable": true, + "type": "timepicker", + "status": "Stable", + "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"], + "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"], + "now": true, + "collapse": false, + "notice": false + } + ], + "panels": [ + { + "targets": [ + {"expr": "up"}, + {"expr": "cpu_usage", "refId": "B"} + ] + } + ] +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/input/v8.influxdb_query.json b/apps/dashboard/pkg/migration/testdata/input/v8.influxdb_query.json new file mode 100644 index 00000000000..5cad1ac187a --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/input/v8.influxdb_query.json @@ -0,0 +1,67 @@ +{ + "title": "V8 InfluxDB Query Test", + "schemaVersion": 7, + "panels": [ + { + "id": 1, + "type": "graph", + "targets": [ + { + "fields": [ + { + "name": "value", + "func": "mean", + "mathExpr": "*2", + "asExpr": "doubled" + } + ], + "tags": [ + { + "key": "host", + "value": "server1" + } + ], + "groupBy": [ + { + "type": "time", + "interval": "1m" + }, + { + "type": "tag", + "key": "host" + } + ], + "fill": "null" + } + ] + }, + { + "id": 2, + "type": "graph", + "targets": [ + { + "rawQuery": true, + "fields": [ + { + "name": "value", + "func": "mean" + } + ], + "tags": [ + { + "key": "host", + "value": "server1" + } + ], + "groupBy": [ + { + "type": "time", + "interval": "1m" + } + ], + "fill": "null" + } + ] + } + ] +} diff --git a/apps/dashboard/pkg/migration/testdata/input/v9.no-op.json b/apps/dashboard/pkg/migration/testdata/input/v9.no-op.json new file mode 100644 index 00000000000..51f9dca7b59 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/input/v9.no-op.json @@ -0,0 +1,18 @@ +{ + "title": "V9 No-Op Migration Test", + "schemaVersion": 8, + "panels": [ + { + "id": 1, + "type": "singlestat" + }, + { + "id": 2, + "type": "singlestat" + }, + { + "id": 3, + "type": "graph" + } + ] + } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v10.table_thresholds.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v10.table_thresholds.v42.json new file mode 100644 index 00000000000..3f17bcd374c --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v10.table_thresholds.v42.json @@ -0,0 +1,132 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "table-old", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 1, + "styles": [ + { + "align": "auto", + "thresholds": [ + "20", + "30" + ] + }, + { + "align": "auto", + "thresholds": [ + "200", + "300" + ] + } + ], + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "table" + }, + { + "autoMigrateFrom": "table-old", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 2, + "styles": [ + { + "align": "auto", + "thresholds": [ + "50", + "75" + ] + } + ], + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "table" + }, + { + "autoMigrateFrom": "graph", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 3, + "styles": [ + { + "thresholds": [ + "5", + "10", + "15" + ] + } + ], + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V10 Table Thresholds Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v11.no-op-migration.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v11.no-op-migration.v42.json new file mode 100644 index 00000000000..cde0f37b8a3 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v11.no-op-migration.v42.json @@ -0,0 +1,121 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + }, + { + "datasource": { + "uid": "grafana" + }, + "enable": true, + "name": "Annotations \u0026 Alerts" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "graph", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 1, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "CPU Usage", + "type": "timeseries", + "yAxes": [ + { + "show": true + } + ] + }, + { + "autoMigrateFrom": "singlestat", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 2, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Memory Usage", + "type": "stat", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ] + } + ], + "refresh": "", + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [ + { + "datasource": "prometheus", + "name": "server", + "options": [], + "query": "label_values(server)", + "refresh": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V11 No-Op Migration Test Dashboard", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v12.template-variables.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v12.template-variables.v42.json new file mode 100644 index 00000000000..85b7de371d5 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v12.template-variables.v42.json @@ -0,0 +1,81 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [], + "refresh": "", + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [ + { + "name": "refresh_true_var", + "options": [], + "refresh": 1, + "type": "query" + }, + { + "name": "refresh_false_var", + "options": [], + "refresh": 1, + "type": "query" + }, + { + "hide": 2, + "hideVariable": true, + "name": "hide_variable_var", + "options": [], + "refresh": 1, + "type": "query" + }, + { + "hide": 1, + "hideLabel": true, + "name": "hide_label_var", + "options": [], + "refresh": 1, + "type": "query" + }, + { + "hide": 2, + "hideLabel": true, + "hideVariable": true, + "name": "priority_var", + "options": [], + "refresh": 1, + "type": "query" + }, + { + "name": "no_properties_var", + "options": [], + "refresh": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V12 Template Variables Migration Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v13.graph_thresholds.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v13.graph_thresholds.v42.json new file mode 100644 index 00000000000..c799c1cb6b8 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v13.graph_thresholds.v42.json @@ -0,0 +1,174 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "graph", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "grid": { + "threshold1": 200, + "threshold1Color": "yellow", + "threshold2": 400, + "threshold2Color": "red", + "thresholdLine": true + }, + "id": 1, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Graph with Line Thresholds", + "type": "timeseries" + }, + { + "autoMigrateFrom": "graph", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "grid": { + "threshold1": 100, + "threshold1Color": "green", + "threshold2": 300, + "threshold2Color": "blue", + "thresholdLine": false + }, + "id": 2, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Graph with Fill Thresholds", + "type": "timeseries" + }, + { + "autoMigrateFrom": "graph", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "grid": { + "threshold1": 150, + "threshold1Color": "orange", + "thresholdLine": true + }, + "id": 3, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Graph with Single Threshold", + "type": "timeseries" + }, + { + "autoMigrateFrom": "graph", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "grid": { + "threshold1": 200, + "threshold1Color": "yellow", + "thresholdLine": false + }, + "id": 4, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "thresholds": [ + { + "color": "purple", + "colorMode": "custom", + "value": 50 + } + ], + "title": "Graph with Existing Thresholds", + "type": "timeseries" + }, + { + "autoMigrateFrom": "singlestat", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 5, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Non-Graph Panel", + "type": "stat" + } + ], + "refresh": "", + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V13 Graph Thresholds Migration Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v13.minimal_graph_config.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v13.minimal_graph_config.v42.json new file mode 100644 index 00000000000..e40a580b6ed --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v13.minimal_graph_config.v42.json @@ -0,0 +1,61 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "graph", + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "id": 4, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "editorMode": "builder", + "expr": "{\"a.utf8.metric ๐Ÿค˜\", job=\"prometheus-utf8\"}", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Dashboard with minimal graph panel settings", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v15.no-op-migration.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v15.no-op-migration.v42.json index 05bac4cb246..1cda544d3fd 100644 --- a/apps/dashboard/pkg/migration/testdata/output/latest_version/v15.no-op-migration.v42.json +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v15.no-op-migration.v42.json @@ -54,59 +54,13 @@ ] }, { + "autoMigrateFrom": "singlestat", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, - "fieldConfig": { - "defaults": { - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, "id": 2, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", "targets": [ { "datasource": { @@ -118,7 +72,14 @@ } ], "title": "Memory Usage", - "type": "stat" + "type": "stat", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ] } ], "refresh": "", diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v16.grid_layout_upgrade.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v16.grid_layout_upgrade.v42.json index 31cb9895cf4..e9d3b12001d 100644 --- a/apps/dashboard/pkg/migration/testdata/output/latest_version/v16.grid_layout_upgrade.v42.json +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v16.grid_layout_upgrade.v42.json @@ -75,30 +75,12 @@ "type": "timeseries" }, { + "autoMigrateFrom": "singlestat", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, "gridPos": { "h": 7, "w": 12, @@ -106,24 +88,6 @@ "y": 1 }, "id": 2, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", "targets": [ { "datasource": { diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v17.minspan_to_maxperrow.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v17.minspan_to_maxperrow.v42.json index f52bfb99cf5..9b0ddbb85df 100644 --- a/apps/dashboard/pkg/migration/testdata/output/latest_version/v17.minspan_to_maxperrow.v42.json +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v17.minspan_to_maxperrow.v42.json @@ -77,30 +77,12 @@ "type": "timeseries" }, { + "autoMigrateFrom": "singlestat", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, "gridPos": { "h": 4, "w": 6, @@ -108,24 +90,7 @@ "y": 8 }, "id": 2, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", + "maxPerRow": 6, "targets": [ { "datasource": { diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v19.panel_links.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v19.panel_links.v42.json index d92b346e5a6..51072542d22 100644 --- a/apps/dashboard/pkg/migration/testdata/output/latest_version/v19.panel_links.v42.json +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v19.panel_links.v42.json @@ -153,49 +153,13 @@ "type": "gauge" }, { + "autoMigrateFrom": "singlestat", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, "id": 6, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", "targets": [ { "datasource": { diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v2.panels-and-services.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v2.panels-and-services.v42.json new file mode 100644 index 00000000000..9bf896f9bab --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v2.panels-and-services.v42.json @@ -0,0 +1,168 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "graphite", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "grid": { + "max": 100, + "min": 0 + }, + "id": 1, + "legend": true, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A", + "target": "cpu.usage" + } + ], + "title": "CPU Usage", + "type": "timeseries", + "y2_format": "short", + "y_format": "percent" + }, + { + "autoMigrateFrom": "graph", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "grid": { + "min": 0 + }, + "id": 2, + "legend": false, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A", + "target": "memory.usage" + } + ], + "title": "Memory Usage", + "type": "timeseries", + "y_format": "bytes" + }, + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "grid": { + "max": 100, + "min": 0 + }, + "id": 3, + "legend": true, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Server Stats", + "type": "table", + "y2_format": "bytes", + "y_format": "short" + }, + { + "autoMigrateFrom": "graphite", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 4, + "legend": true, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A", + "target": "disk.io" + } + ], + "title": "Disk I/O", + "type": "timeseries", + "y2_format": "Bps" + } + ], + "refresh": "", + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [ + { + "datasource": "prometheus", + "name": "server", + "options": [], + "query": "label_values(server)", + "refresh": 1, + "type": "query" + }, + { + "name": "env", + "options": [ + { + "text": "Production", + "value": "prod" + }, + { + "text": "Staging", + "value": "stage" + } + ], + "type": "custom" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V2 Comprehensive Migration Test Dashboard", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v22.table_panel_align.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v22.table_panel_align.v42.json index 22524901c13..d284282e97c 100644 --- a/apps/dashboard/pkg/migration/testdata/output/latest_version/v22.table_panel_align.v42.json +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v22.table_panel_align.v42.json @@ -21,69 +21,25 @@ "links": [], "panels": [ { + "autoMigrateFrom": "table-old", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Time" - }, - "properties": [ - { - "id": "custom.align" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.align" - } - ] - } - ] - }, "id": 1, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "styles": [ + { + "align": "auto", + "pattern": "Time", + "type": "number" + }, + { + "align": "auto", + "pattern": "Value", + "type": "string" + } + ], "targets": [ { "datasource": { diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v24.table-angular.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v24.table-angular.v42.json index 420965dffb4..443ad1f6eb1 100644 --- a/apps/dashboard/pkg/migration/testdata/output/latest_version/v24.table-angular.v42.json +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v24.table-angular.v42.json @@ -21,54 +21,30 @@ "links": [], "panels": [ { + "autoMigrateFrom": "table-old", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, "description": "Tests basic migration with default style pattern (/.*/) containing thresholds and colors. Should convert styles to fieldConfig.defaults with threshold steps.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null - }, - { - "color": "yellow", - "value": 10 - }, - { - "color": "green", - "value": 20 - }, - { - "value": 30 - } - ] - } - }, - "overrides": [] - }, "id": 1, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "legend": true, + "styles": [ + { + "colors": [ + "red", + "yellow", + "green" + ], + "pattern": "/.*/", + "thresholds": [ + "10", + "20", + "30" + ] + } + ], "targets": [ { "datasource": { @@ -91,136 +67,58 @@ "type": "table" }, { + "autoMigrateFrom": "table-old", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, "description": "Tests comprehensive migration including: default style with thresholds/colors/unit/decimals/align/colorMode, column overrides with exact name and regex patterns, date formatting, hidden columns, and links with tooltips.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "center", - "cellOptions": { - "type": "color-background" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, + "id": 2, + "styles": [ + { + "align": "center", + "colorMode": "cell", + "colors": [ + "green", + "yellow", + "red" + ], "decimals": 2, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "yellow", - "value": 100 - }, - { - "color": "red", - "value": 500 - } - ] - }, + "pattern": "/.*/", + "thresholds": [ + "100", + "500" + ], "unit": "bytes" }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Status" - }, - "properties": [ - { - "id": "displayName", - "value": "Current Status" - }, - { - "id": "unit", - "value": "short" - }, - { - "id": "decimals", - "value": 0 - }, - { - "id": "custom.cellOptions", - "value": { - "type": "color-text" - } - }, - { - "id": "custom.align", - "value": "left" - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/Error.*/" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "View error details", - "url": "http://example.com/errors" - } - ] - }, - { - "id": "custom.cellOptions", - "value": { - "type": "color-background" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Time" - }, - "properties": [ - { - "id": "displayName", - "value": "Timestamp" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Hidden" - }, - "properties": [ - { - "id": "custom.hideFrom.viz", - "value": true - } - ] - } - ] - }, - "id": 2, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + { + "alias": "Current Status", + "align": "left", + "colorMode": "value", + "decimals": 0, + "pattern": "Status", + "unit": "short" + }, + { + "colorMode": "row", + "link": true, + "linkTargetBlank": true, + "linkTooltip": "View error details", + "linkUrl": "http://example.com/errors", + "pattern": "/Error.*/" + }, + { + "alias": "Timestamp", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "pattern": "Hidden", + "type": "hidden" + } + ], "targets": [ { "datasource": { @@ -235,49 +133,47 @@ "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [ + { + "text": "Average", + "value": "avg" + }, + { + "text": "Maximum", + "value": "max" + }, + { + "text": "Minimum", + "value": "min" + }, + { + "text": "Total", + "value": "total" + }, + { + "text": "Current", + "value": "current" + }, + { + "text": "Count", + "value": "count" + } + ], "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, "description": "Tests migration of timeseries_aggregations transform to reduce transformation with column mappings (avg-\u003emean, max-\u003emax, min-\u003emin, total-\u003esum, current-\u003elastNotNull, count-\u003ecount).", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 1, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, "id": 3, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "styles": [ + { + "decimals": 1, + "pattern": "/.*/", + "unit": "percent" + } + ], "targets": [ { "datasource": { @@ -289,67 +185,24 @@ } ], "title": "Table with Timeseries Aggregations Transform", - "transformations": [ - { - "id": "reduce", - "options": { - "includeTimeField": false, - "reducers": [ - "mean", - "max", - "min", - "sum", - "lastNotNull", - "count" - ] - } - } - ], + "transform": "timeseries_aggregations", "type": "table" }, { + "autoMigrateFrom": "table-old", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, "description": "Tests migration of timeseries_to_rows transform to seriesToRows transformation.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, "id": 4, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "styles": [ + { + "pattern": "/.*/", + "unit": "short" + } + ], "targets": [ { "datasource": { @@ -361,59 +214,24 @@ } ], "title": "Table with Timeseries to Rows Transform", - "transformations": [ - { - "id": "seriesToRows", - "options": { - "reducers": [] - } - } - ], + "transform": "timeseries_to_rows", "type": "table" }, { + "autoMigrateFrom": "table-old", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, "description": "Tests migration of timeseries_to_columns transform to seriesToColumns transformation.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, "id": 5, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "styles": [ + { + "pattern": "/.*/", + "unit": "bytes" + } + ], "targets": [ { "datasource": { @@ -425,57 +243,24 @@ } ], "title": "Table with Timeseries to Columns Transform", - "transformations": [ - { - "id": "seriesToColumns", - "options": { - "reducers": [] - } - } - ], + "transform": "timeseries_to_columns", "type": "table" }, { + "autoMigrateFrom": "table-old", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, "description": "Tests migration of table transform to merge transformation. Also tests auto alignment conversion to empty string.", - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, "id": 6, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "styles": [ + { + "align": "auto", + "pattern": "/.*/" + } + ], "targets": [ { "datasource": { @@ -487,59 +272,24 @@ } ], "title": "Table with Merge Transform", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], + "transform": "table", "type": "table" }, { + "autoMigrateFrom": "table-old", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, "description": "Tests that existing transformations are preserved and new transformation from old format is appended to the list.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, "id": 7, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "styles": [ + { + "pattern": "/.*/", + "unit": "short" + } + ], "targets": [ { "datasource": { @@ -551,6 +301,7 @@ } ], "title": "Table with Existing Transformations", + "transform": "timeseries_to_rows", "transformations": [ { "id": "filterFieldsByName", @@ -562,66 +313,35 @@ ] } } - }, - { - "id": "seriesToRows", - "options": { - "reducers": [] - } } ], "type": "table" }, { + "autoMigrateFrom": "table-old", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, "description": "Tests handling of mixed numeric and string threshold values (int, string, float) with proper type conversion.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "yellow", - "value": 10 - }, - { - "color": "orange", - "value": 20 - }, - { - "color": "red", - "value": 30.5 - } - ] - } - }, - "overrides": [] - }, "id": 8, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "styles": [ + { + "colors": [ + "green", + "yellow", + "orange", + "red" + ], + "pattern": "/.*/", + "thresholds": [ + 10, + "20", + 30.5 + ] + } + ], "targets": [ { "datasource": { @@ -636,90 +356,32 @@ "type": "table" }, { + "autoMigrateFrom": "table-old", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, "description": "Tests all color mode mappings: cell-\u003ecolor-background, row-\u003ecolor-background, value-\u003ecolor-text.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "color-background" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "CellColumn" - }, - "properties": [ - { - "id": "custom.cellOptions", - "value": { - "type": "color-background" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "RowColumn" - }, - "properties": [ - { - "id": "custom.cellOptions", - "value": { - "type": "color-background" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "ValueColumn" - }, - "properties": [ - { - "id": "custom.cellOptions", - "value": { - "type": "color-text" - } - } - ] - } - ] - }, "id": 9, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "styles": [ + { + "colorMode": "cell", + "pattern": "/.*/" + }, + { + "colorMode": "cell", + "pattern": "CellColumn" + }, + { + "colorMode": "row", + "pattern": "RowColumn" + }, + { + "colorMode": "value", + "pattern": "ValueColumn" + } + ], "targets": [ { "datasource": { @@ -734,83 +396,32 @@ "type": "table" }, { + "autoMigrateFrom": "table-old", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, "description": "Tests all alignment options: left, center, right, and auto (should convert to empty string).", - "fieldConfig": { - "defaults": { - "custom": { - "align": "center", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "LeftColumn" - }, - "properties": [ - { - "id": "custom.align", - "value": "left" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "RightColumn" - }, - "properties": [ - { - "id": "custom.align", - "value": "right" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "AutoColumn" - }, - "properties": [ - { - "id": "custom.align" - } - ] - } - ] - }, "id": 10, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "styles": [ + { + "align": "center", + "pattern": "/.*/" + }, + { + "align": "left", + "pattern": "LeftColumn" + }, + { + "align": "right", + "pattern": "RightColumn" + }, + { + "align": "auto", + "pattern": "AutoColumn" + } + ], "targets": [ { "datasource": { @@ -825,97 +436,36 @@ "type": "table" }, { + "autoMigrateFrom": "table-old", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, "description": "Tests both field matcher types: byName for exact matches and byRegexp for regex patterns.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, + "id": 11, + "styles": [ + { + "pattern": "/.*/", "unit": "short" }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "ExactColumnName" - }, - "properties": [ - { - "id": "displayName", - "value": "Exact Match" - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/Regex.*Pattern/" - }, - "properties": [ - { - "id": "displayName", - "value": "Regex Match" - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/^Start/" - }, - "properties": [ - { - "id": "displayName", - "value": "Start Pattern" - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/End$/" - }, - "properties": [ - { - "id": "displayName", - "value": "End Pattern" - } - ] - } - ] - }, - "id": 11, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + { + "alias": "Exact Match", + "pattern": "ExactColumnName" + }, + { + "alias": "Regex Match", + "pattern": "/Regex.*Pattern/" + }, + { + "alias": "Start Pattern", + "pattern": "/^Start/" + }, + { + "alias": "End Pattern", + "pattern": "/End$/" + } + ], "targets": [ { "datasource": { @@ -930,103 +480,38 @@ "type": "table" }, { + "autoMigrateFrom": "table-old", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, "description": "Tests various link configurations: with and without tooltip, with and without target blank.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, + "id": 12, + "styles": [ + { + "pattern": "/.*/", "unit": "short" }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "LinkWithTooltip" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "Click to view details", - "url": "http://example.com/with-tooltip" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "LinkWithoutTooltip" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": false, - "title": "", - "url": "http://example.com/no-tooltip" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "LinkMinimal" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": false, - "title": "", - "url": "http://example.com/minimal" - } - ] - } - ] - } - ] - }, - "id": 12, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + { + "link": true, + "linkTargetBlank": true, + "linkTooltip": "Click to view details", + "linkUrl": "http://example.com/with-tooltip", + "pattern": "LinkWithTooltip" + }, + { + "link": true, + "linkTargetBlank": false, + "linkUrl": "http://example.com/no-tooltip", + "pattern": "LinkWithoutTooltip" + }, + { + "link": true, + "linkUrl": "http://example.com/minimal", + "pattern": "LinkMinimal" + } + ], "targets": [ { "datasource": { @@ -1041,97 +526,38 @@ "type": "table" }, { + "autoMigrateFrom": "table-old", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, "description": "Tests various date format patterns and aliases.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, + "id": 13, + "styles": [ + { + "pattern": "/.*/", "unit": "short" }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "DateISO" - }, - "properties": [ - { - "id": "displayName", - "value": "ISO Date" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "DateTime" - }, - "properties": [ - { - "id": "displayName", - "value": "Full DateTime" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "TimeOnly" - }, - "properties": [ - { - "id": "displayName", - "value": "Time Only" - }, - { - "id": "unit", - "value": "time: HH:mm:ss" - } - ] - } - ] - }, - "id": 13, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + { + "alias": "ISO Date", + "dateFormat": "YYYY-MM-DD", + "pattern": "DateISO", + "type": "date" + }, + { + "alias": "Full DateTime", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "DateTime", + "type": "date" + }, + { + "alias": "Time Only", + "dateFormat": "HH:mm:ss", + "pattern": "TimeOnly", + "type": "date" + } + ], "targets": [ { "datasource": { @@ -1226,50 +652,14 @@ "type": "timeseries" }, { + "autoMigrateFrom": "singlestat", "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, "description": "Other panel types should not be affected by table migration.", - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, "id": 17, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", "targets": [ { "datasource": { diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v28.singlestat_and_variable_properties.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v28.singlestat_and_variable_properties.v42.json index 51ee2142199..efacbd5dc24 100644 --- a/apps/dashboard/pkg/migration/testdata/output/latest_version/v28.singlestat_and_variable_properties.v42.json +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v28.singlestat_and_variable_properties.v42.json @@ -21,53 +21,23 @@ "links": [], "panels": [ { + "autoMigrateFrom": "singlestat", + "colors": [ + "#FF0000", + "green", + "orange" + ], "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "#FF0000", - "value": null - }, - { - "color": "green", - "value": 10 - }, - { - "color": "orange", - "value": 20 - } - ] - } - }, - "overrides": [] + "grid": { + "max": 10, + "min": 1 }, "id": 1, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", + "legend": true, "targets": [ { "datasource": { @@ -86,56 +56,31 @@ "refId": "B" } ], + "thresholds": "10,20,30", "type": "stat" }, { + "autoMigrateFrom": "singlestat", + "colors": [ + "#FF0000", + "green", + "orange" + ], "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "#FF0000", - "value": null - }, - { - "color": "green", - "value": 10 - }, - { - "color": "orange", - "value": 20 - } - ] - } - }, - "overrides": [] + "gauge": { + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "grid": { + "max": 10, + "min": 1 }, "id": 2, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", "targets": [ { "datasource": { @@ -146,82 +91,33 @@ "refId": "A" } ], + "thresholds": "10,20,30", "type": "stat" }, { + "autoMigrateFrom": "singlestat", + "colors": [ + "#FF0000", + "green", + "orange" + ], "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, - "fieldConfig": { - "defaults": { - "mappings": [ - { - "options": { - "20": { - "text": "test" - } - }, - "type": "value" - }, - { - "options": { - "30": { - "text": "test1" - } - }, - "type": "value" - }, - { - "options": { - "40": { - "color": "orange", - "text": "50" - } - }, - "type": "value" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "#FF0000", - "value": null - }, - { - "color": "green", - "value": 10 - }, - { - "color": "orange", - "value": 20 - } - ] - } - }, - "overrides": [] + "grid": { + "max": 10, + "min": 1 }, "id": 3, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", + "legend": true, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + } + ], "targets": [ { "datasource": { @@ -240,7 +136,25 @@ "refId": "B" } ], - "type": "stat" + "thresholds": "10,20,30", + "type": "stat", + "valueMaps": [ + { + "op": "=", + "text": "test", + "value": "20" + }, + { + "op": "=", + "text": "test1", + "value": "30" + }, + { + "op": "=", + "text": "50", + "value": "40" + } + ] }, { "datasource": { diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v28.singlestat_migration.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v28.singlestat_migration.v42.json index d541cf4751b..c08136b1926 100644 --- a/apps/dashboard/pkg/migration/testdata/output/latest_version/v28.singlestat_migration.v42.json +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v28.singlestat_migration.v42.json @@ -21,53 +21,23 @@ "links": [], "panels": [ { + "autoMigrateFrom": "singlestat", + "colors": [ + "#FF0000", + "green", + "orange" + ], "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "#FF0000", - "value": null - }, - { - "color": "green", - "value": 10 - }, - { - "color": "orange", - "value": 20 - } - ] - } - }, - "overrides": [] + "grid": { + "max": 10, + "min": 1 }, "id": 1, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", + "legend": true, "targets": [ { "datasource": { @@ -86,52 +56,27 @@ "refId": "B" } ], + "thresholds": "10,20,30", "type": "stat" }, { + "autoMigrateFrom": "singlestat", + "colors": [ + "#FF0000", + "green", + "orange" + ], "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] + "grid": { + "max": 10, + "min": 1 }, "id": 2, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", + "legend": true, "targets": [ { "datasource": { @@ -150,56 +95,31 @@ "refId": "B" } ], + "thresholds": "", "type": "stat" }, { + "autoMigrateFrom": "singlestat", + "colors": [ + "#FF0000", + "green", + "orange" + ], "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "#FF0000", - "value": null - }, - { - "color": "green", - "value": 10 - }, - { - "color": "orange", - "value": 20 - } - ] - } - }, - "overrides": [] + "gauge": { + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "grid": { + "max": 10, + "min": 1 }, "id": 3, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", "targets": [ { "datasource": { @@ -210,82 +130,33 @@ "refId": "A" } ], + "thresholds": "10,20,30", "type": "stat" }, { + "autoMigrateFrom": "singlestat", + "colors": [ + "#FF0000", + "green", + "orange" + ], "datasource": { "apiVersion": "v1", "type": "prometheus", "uid": "default-ds-uid" }, - "fieldConfig": { - "defaults": { - "mappings": [ - { - "options": { - "20": { - "text": "test" - } - }, - "type": "value" - }, - { - "options": { - "30": { - "text": "test1" - } - }, - "type": "value" - }, - { - "options": { - "40": { - "color": "orange", - "text": "50" - } - }, - "type": "value" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "#FF0000", - "value": null - }, - { - "color": "green", - "value": 10 - }, - { - "color": "orange", - "value": 20 - } - ] - } - }, - "overrides": [] + "grid": { + "max": 10, + "min": 1 }, "id": 4, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", + "legend": true, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + } + ], "targets": [ { "datasource": { @@ -304,7 +175,25 @@ "refId": "B" } ], - "type": "stat" + "thresholds": "10,20,30", + "type": "stat", + "valueMaps": [ + { + "op": "=", + "text": "test", + "value": "20" + }, + { + "op": "=", + "text": "test1", + "value": "30" + }, + { + "op": "=", + "text": "50", + "value": "40" + } + ] }, { "datasource": { @@ -327,38 +216,24 @@ "type": "timeseries" }, { + "autoMigrateFrom": "grafana-singlestat-panel", + "colorBackground": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], "datasource": { "type": "prometheus" }, - "fieldConfig": { - "defaults": { - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "areaF2" - }, - "overrides": [] + "format": "areaF2", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true }, "gridPos": { "h": 8, @@ -367,25 +242,37 @@ "y": 43 }, "id": 5, - "maxDataPoints": 100, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "postfix": "b", + "postfixFontSize": "50%", + "prefix": "a", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": true }, - "pluginVersion": "12.1.0", + "tableColumn": "", "targets": [ { "datasource": { @@ -395,8 +282,18 @@ "refId": "A" } ], + "thresholds": "", "title": "grafana-singlestat-panel", - "type": "stat" + "type": "stat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" }, { "datasource": { diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v3.no-op.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v3.no-op.v42.json new file mode 100644 index 00000000000..e4f06710eed --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v3.no-op.v42.json @@ -0,0 +1,114 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 1, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "timeseries" + }, + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 2, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "timeseries" + }, + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 3, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "barchart" + }, + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 4, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "barchart" + } + ], + "refresh": "", + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V3 No-Op Migration - but tests ensuring panel IDs are unique", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v4.no-op.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v4.no-op.v42.json new file mode 100644 index 00000000000..8a7d37dc08e --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v4.no-op.v42.json @@ -0,0 +1,98 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "singlestat", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 1, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "stat" + }, + { + "autoMigrateFrom": "singlestat", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 2, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "stat" + }, + { + "autoMigrateFrom": "graph", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 3, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V4 No-Op Migration Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v5.no-op.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v5.no-op.v42.json new file mode 100644 index 00000000000..09f15a0f5c1 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v5.no-op.v42.json @@ -0,0 +1,98 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "singlestat", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 1, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "stat" + }, + { + "autoMigrateFrom": "singlestat", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 2, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "stat" + }, + { + "autoMigrateFrom": "graph", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 3, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V5 No-Op Migration Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v6.pulldowns_and_templating.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v6.pulldowns_and_templating.v42.json new file mode 100644 index 00000000000..1a18f9b01c2 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v6.pulldowns_and_templating.v42.json @@ -0,0 +1,154 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + }, + { + "datasource": { + "uid": "prometheus" + }, + "enable": true, + "iconColor": "red", + "name": "deployment", + "query": "ALERTS{alertname=\"DeploymentStarted\"}" + }, + { + "datasource": { + "uid": "loki" + }, + "enable": false, + "iconColor": "yellow", + "name": "alerts", + "query": "{job=\"alertmanager\"}" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "graph", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "expr": "cpu_usage{environment=\"$environment\", service=\"$service\"}", + "refId": "A" + } + ], + "title": "CPU Usage", + "type": "timeseries" + }, + { + "autoMigrateFrom": "singlestat", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 2, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "expr": "memory_usage{region=\"$region\"}", + "refId": "B" + } + ], + "title": "Memory Usage", + "type": "stat" + } + ], + "refresh": "30s", + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "name": "environment", + "options": [], + "refresh": 1, + "type": "query" + }, + { + "allFormat": "glob", + "datasource": "prometheus", + "name": "service", + "options": [], + "refresh": 1, + "type": "query" + }, + { + "name": "region", + "options": [ + { + "text": "us-east-1", + "value": "us-east-1" + }, + { + "text": "us-west-2", + "value": "us-west-2" + } + ], + "type": "custom" + }, + { + "datasource": "prometheus", + "name": "instance", + "options": [], + "query": "label_values(up, instance)", + "refresh": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V6 Pulldowns and Template Variables Migration Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v7.timepicker.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v7.timepicker.v42.json new file mode 100644 index 00000000000..15e27073fe7 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v7.timepicker.v42.json @@ -0,0 +1,85 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 1, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "expr": "up", + "refId": "A" + }, + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "expr": "cpu_usage", + "refId": "B" + } + ] + } + ], + "refresh": "", + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "collapse": false, + "enable": true, + "notice": false, + "now": true, + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "status": "Stable", + "type": "timepicker" + }, + "timezone": "", + "title": "No Title", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v8.influxdb_query.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v8.influxdb_query.v42.json new file mode 100644 index 00000000000..307a9d86a96 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v8.influxdb_query.v42.json @@ -0,0 +1,143 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "graph", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 1, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "groupBy": [ + { + "params": [ + "1m" + ], + "type": "time" + }, + { + "params": [ + "host" + ], + "type": "tag" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "*2" + ], + "type": "math" + }, + { + "params": [ + "doubled" + ], + "type": "alias" + } + ] + ], + "tags": [ + { + "key": "host", + "value": "server1" + } + ] + } + ], + "type": "timeseries" + }, + { + "autoMigrateFrom": "graph", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 2, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "groupBy": [ + { + "interval": "1m", + "type": "time" + } + ], + "rawQuery": true, + "refId": "A", + "tags": [ + { + "key": "host", + "value": "server1" + } + ] + } + ], + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V8 InfluxDB Query Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/latest_version/v9.no-op.v42.json b/apps/dashboard/pkg/migration/testdata/output/latest_version/v9.no-op.v42.json new file mode 100644 index 00000000000..12d4a1383e0 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/latest_version/v9.no-op.v42.json @@ -0,0 +1,98 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "singlestat", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 1, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "stat" + }, + { + "autoMigrateFrom": "singlestat", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 2, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "stat" + }, + { + "autoMigrateFrom": "graph", + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "id": 3, + "targets": [ + { + "datasource": { + "apiVersion": "v1", + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V9 No-Op Migration Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v10.table_thresholds.v10.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v10.table_thresholds.v10.json new file mode 100644 index 00000000000..2e178e2e129 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v10.table_thresholds.v10.json @@ -0,0 +1,81 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "id": 1, + "styles": [ + { + "thresholds": [ + "20", + "30" + ] + }, + { + "thresholds": [ + "200", + "300" + ] + } + ], + "type": "table" + }, + { + "id": 2, + "styles": [ + { + "thresholds": [ + "50", + "75" + ] + } + ], + "type": "table" + }, + { + "autoMigrateFrom": "graph", + "id": 3, + "styles": [ + { + "thresholds": [ + "5", + "10", + "15" + ] + } + ], + "type": "timeseries" + } + ], + "schemaVersion": 10, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V10 Table Thresholds Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v11.no-op-migration.v11.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v11.no-op-migration.v11.json new file mode 100644 index 00000000000..7e6680140e0 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v11.no-op-migration.v11.json @@ -0,0 +1,88 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + }, + { + "datasource": "grafana", + "enable": true, + "name": "Annotations \u0026 Alerts" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "graph", + "id": 1, + "title": "CPU Usage", + "type": "timeseries", + "yAxes": [ + { + "show": true + } + ] + }, + { + "autoMigrateFrom": "singlestat", + "id": 2, + "title": "Memory Usage", + "type": "stat", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ] + } + ], + "schemaVersion": 11, + "tags": [], + "templating": { + "list": [ + { + "datasource": "prometheus", + "name": "server", + "options": [], + "query": "label_values(server)", + "refresh": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V11 No-Op Migration Test Dashboard", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v12.template-variables.v12.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v12.template-variables.v12.json new file mode 100644 index 00000000000..b1de134895f --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v12.template-variables.v12.json @@ -0,0 +1,75 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [], + "schemaVersion": 12, + "tags": [], + "templating": { + "list": [ + { + "name": "refresh_true_var", + "options": [], + "refresh": 1, + "type": "query" + }, + { + "name": "refresh_false_var", + "refresh": 0, + "type": "query" + }, + { + "hide": 2, + "hideVariable": true, + "name": "hide_variable_var", + "options": [], + "type": "query" + }, + { + "hide": 1, + "hideLabel": true, + "name": "hide_label_var", + "options": [], + "type": "query" + }, + { + "hide": 2, + "hideLabel": true, + "hideVariable": true, + "name": "priority_var", + "options": [], + "type": "query" + }, + { + "name": "no_properties_var", + "options": [], + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V12 Template Variables Migration Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v13.graph_thresholds.v13.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v13.graph_thresholds.v13.json new file mode 100644 index 00000000000..62545df022a --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v13.graph_thresholds.v13.json @@ -0,0 +1,98 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "graph", + "grid": { + "threshold1": 200, + "threshold1Color": "yellow", + "threshold2": 400, + "threshold2Color": "red", + "thresholdLine": true + }, + "id": 1, + "title": "Graph with Line Thresholds", + "type": "timeseries" + }, + { + "autoMigrateFrom": "graph", + "grid": { + "threshold1": 100, + "threshold1Color": "green", + "threshold2": 300, + "threshold2Color": "blue", + "thresholdLine": false + }, + "id": 2, + "title": "Graph with Fill Thresholds", + "type": "timeseries" + }, + { + "autoMigrateFrom": "graph", + "grid": { + "threshold1": 150, + "threshold1Color": "orange", + "thresholdLine": true + }, + "id": 3, + "title": "Graph with Single Threshold", + "type": "timeseries" + }, + { + "autoMigrateFrom": "graph", + "grid": { + "threshold1": 200, + "threshold1Color": "yellow", + "thresholdLine": false + }, + "id": 4, + "thresholds": [ + { + "color": "purple", + "colorMode": "custom", + "value": 50 + } + ], + "title": "Graph with Existing Thresholds", + "type": "timeseries" + }, + { + "autoMigrateFrom": "singlestat", + "id": 5, + "title": "Non-Graph Panel", + "type": "stat" + } + ], + "schemaVersion": 13, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V13 Graph Thresholds Migration Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v13.minimal_graph_config.v13.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v13.minimal_graph_config.v13.json new file mode 100644 index 00000000000..ab364ee3075 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v13.minimal_graph_config.v13.json @@ -0,0 +1,56 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "graph", + "id": 4, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "editorMode": "builder", + "expr": "{\"a.utf8.metric ๐Ÿค˜\", job=\"prometheus-utf8\"}", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "type": "timeseries" + } + ], + "schemaVersion": 13, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Dashboard with minimal graph panel settings", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v2.panels-and-services.v2.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v2.panels-and-services.v2.json new file mode 100644 index 00000000000..c4059848635 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v2.panels-and-services.v2.json @@ -0,0 +1,121 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "graphite", + "grid": { + "max": 100, + "min": 0 + }, + "id": 1, + "legend": true, + "targets": [ + { + "refId": "A", + "target": "cpu.usage" + } + ], + "title": "CPU Usage", + "type": "timeseries", + "y2_format": "short", + "y_format": "percent" + }, + { + "autoMigrateFrom": "graph", + "grid": { + "min": 0 + }, + "id": 2, + "legend": false, + "targets": [ + { + "refId": "A", + "target": "memory.usage" + } + ], + "title": "Memory Usage", + "type": "timeseries", + "y_format": "bytes" + }, + { + "grid": { + "max": 100, + "min": 0 + }, + "id": 3, + "legend": true, + "title": "Server Stats", + "type": "table", + "y2_format": "bytes", + "y_format": "short" + }, + { + "autoMigrateFrom": "graphite", + "id": 4, + "legend": true, + "targets": [ + { + "refId": "A", + "target": "disk.io" + } + ], + "title": "Disk I/O", + "type": "timeseries", + "y2_format": "Bps" + } + ], + "schemaVersion": 2, + "tags": [], + "templating": { + "list": [ + { + "datasource": "prometheus", + "name": "server", + "options": [], + "query": "label_values(server)", + "type": "query" + }, + { + "name": "env", + "options": [ + { + "text": "Production", + "value": "prod" + }, + { + "text": "Staging", + "value": "stage" + } + ], + "type": "custom" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V2 Comprehensive Migration Test Dashboard", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v24.table-angular.v24.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v24.table-angular.v24.json index 665c477506f..6091c413889 100644 --- a/apps/dashboard/pkg/migration/testdata/output/single_version/v24.table-angular.v24.json +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v24.table-angular.v24.json @@ -21,49 +21,25 @@ "links": [], "panels": [ { + "autoMigrateFrom": "table-old", "description": "Tests basic migration with default style pattern (/.*/) containing thresholds and colors. Should convert styles to fieldConfig.defaults with threshold steps.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null - }, - { - "color": "yellow", - "value": 10 - }, - { - "color": "green", - "value": 20 - }, - { - "value": 30 - } - ] - } - }, - "overrides": [] - }, "id": 1, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "legend": true, + "styles": [ + { + "colors": [ + "red", + "yellow", + "green" + ], + "pattern": "/.*/", + "thresholds": [ + "10", + "20", + "30" + ] + } + ], "targets": [ { "refId": "A" @@ -76,376 +52,151 @@ "type": "table" }, { + "autoMigrateFrom": "table-old", "description": "Tests comprehensive migration including: default style with thresholds/colors/unit/decimals/align/colorMode, column overrides with exact name and regex patterns, date formatting, hidden columns, and links with tooltips.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "center", - "cellOptions": { - "type": "color-background" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, + "id": 2, + "styles": [ + { + "align": "center", + "colorMode": "cell", + "colors": [ + "green", + "yellow", + "red" + ], "decimals": 2, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "yellow", - "value": 100 - }, - { - "color": "red", - "value": 500 - } - ] - }, + "pattern": "/.*/", + "thresholds": [ + "100", + "500" + ], "unit": "bytes" }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Status" - }, - "properties": [ - { - "id": "displayName", - "value": "Current Status" - }, - { - "id": "unit", - "value": "short" - }, - { - "id": "decimals", - "value": 0 - }, - { - "id": "custom.cellOptions", - "value": { - "type": "color-text" - } - }, - { - "id": "custom.align", - "value": "left" - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/Error.*/" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "View error details", - "url": "http://example.com/errors" - } - ] - }, - { - "id": "custom.cellOptions", - "value": { - "type": "color-background" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Time" - }, - "properties": [ - { - "id": "displayName", - "value": "Timestamp" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Hidden" - }, - "properties": [ - { - "id": "custom.hideFrom.viz", - "value": true - } - ] - } - ] - }, - "id": 2, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + { + "alias": "Current Status", + "align": "left", + "colorMode": "value", + "decimals": 0, + "pattern": "Status", + "unit": "short" + }, + { + "colorMode": "row", + "link": true, + "linkTargetBlank": true, + "linkTooltip": "View error details", + "linkUrl": "http://example.com/errors", + "pattern": "/Error.*/" + }, + { + "alias": "Timestamp", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "pattern": "Hidden", + "type": "hidden" + } + ], "title": "Complex Table with All Style Features", "type": "table" }, { + "autoMigrateFrom": "table-old", + "columns": [ + { + "text": "Average", + "value": "avg" + }, + { + "text": "Maximum", + "value": "max" + }, + { + "text": "Minimum", + "value": "min" + }, + { + "text": "Total", + "value": "total" + }, + { + "text": "Current", + "value": "current" + }, + { + "text": "Count", + "value": "count" + } + ], "description": "Tests migration of timeseries_aggregations transform to reduce transformation with column mappings (avg-\u003emean, max-\u003emax, min-\u003emin, total-\u003esum, current-\u003elastNotNull, count-\u003ecount).", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "decimals": 1, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, "id": 3, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "styles": [ + { + "decimals": 1, + "pattern": "/.*/", + "unit": "percent" + } + ], "title": "Table with Timeseries Aggregations Transform", - "transformations": [ - { - "id": "reduce", - "options": { - "includeTimeField": false, - "reducers": [ - "mean", - "max", - "min", - "sum", - "lastNotNull", - "count" - ] - } - } - ], + "transform": "timeseries_aggregations", "type": "table" }, { + "autoMigrateFrom": "table-old", "description": "Tests migration of timeseries_to_rows transform to seriesToRows transformation.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, "id": 4, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", - "title": "Table with Timeseries to Rows Transform", - "transformations": [ + "styles": [ { - "id": "seriesToRows", - "options": { - "reducers": [] - } - } - ], - "type": "table" - }, - { - "description": "Tests migration of timeseries_to_columns transform to seriesToColumns transformation.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "id": 5, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", - "title": "Table with Timeseries to Columns Transform", - "transformations": [ - { - "id": "seriesToColumns", - "options": { - "reducers": [] - } - } - ], - "type": "table" - }, - { - "description": "Tests migration of table transform to merge transformation. Also tests auto alignment conversion to empty string.", - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "id": 6, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", - "title": "Table with Merge Transform", - "transformations": [ - { - "id": "merge", - "options": { - "reducers": [] - } - } - ], - "type": "table" - }, - { - "description": "Tests that existing transformations are preserved and new transformation from old format is appended to the list.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, + "pattern": "/.*/", "unit": "short" - }, - "overrides": [] - }, + } + ], + "title": "Table with Timeseries to Rows Transform", + "transform": "timeseries_to_rows", + "type": "table" + }, + { + "autoMigrateFrom": "table-old", + "description": "Tests migration of timeseries_to_columns transform to seriesToColumns transformation.", + "id": 5, + "styles": [ + { + "pattern": "/.*/", + "unit": "bytes" + } + ], + "title": "Table with Timeseries to Columns Transform", + "transform": "timeseries_to_columns", + "type": "table" + }, + { + "autoMigrateFrom": "table-old", + "description": "Tests migration of table transform to merge transformation. Also tests auto alignment conversion to empty string.", + "id": 6, + "styles": [ + { + "align": "auto", + "pattern": "/.*/" + } + ], + "title": "Table with Merge Transform", + "transform": "table", + "type": "table" + }, + { + "autoMigrateFrom": "table-old", + "description": "Tests that existing transformations are preserved and new transformation from old format is appended to the list.", "id": 7, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "styles": [ + { + "pattern": "/.*/", + "unit": "short" + } + ], "title": "Table with Existing Transformations", + "transform": "timeseries_to_rows", "transformations": [ { "id": "filterFieldsByName", @@ -457,496 +208,171 @@ ] } } - }, - { - "id": "seriesToRows", - "options": { - "reducers": [] - } } ], "type": "table" }, { + "autoMigrateFrom": "table-old", "description": "Tests handling of mixed numeric and string threshold values (int, string, float) with proper type conversion.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "yellow", - "value": 10 - }, - { - "color": "orange", - "value": 20 - }, - { - "color": "red", - "value": 30.5 - } - ] - } - }, - "overrides": [] - }, "id": 8, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "styles": [ + { + "colors": [ + "green", + "yellow", + "orange", + "red" + ], + "pattern": "/.*/", + "thresholds": [ + 10, + "20", + 30.5 + ] + } + ], "title": "Mixed Threshold Types", "type": "table" }, { + "autoMigrateFrom": "table-old", "description": "Tests all color mode mappings: cell-\u003ecolor-background, row-\u003ecolor-background, value-\u003ecolor-text.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "color-background" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "CellColumn" - }, - "properties": [ - { - "id": "custom.cellOptions", - "value": { - "type": "color-background" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "RowColumn" - }, - "properties": [ - { - "id": "custom.cellOptions", - "value": { - "type": "color-background" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "ValueColumn" - }, - "properties": [ - { - "id": "custom.cellOptions", - "value": { - "type": "color-text" - } - } - ] - } - ] - }, "id": 9, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "styles": [ + { + "colorMode": "cell", + "pattern": "/.*/" + }, + { + "colorMode": "cell", + "pattern": "CellColumn" + }, + { + "colorMode": "row", + "pattern": "RowColumn" + }, + { + "colorMode": "value", + "pattern": "ValueColumn" + } + ], "title": "All Color Modes Test", "type": "table" }, { + "autoMigrateFrom": "table-old", "description": "Tests all alignment options: left, center, right, and auto (should convert to empty string).", - "fieldConfig": { - "defaults": { - "custom": { - "align": "center", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "LeftColumn" - }, - "properties": [ - { - "id": "custom.align", - "value": "left" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "RightColumn" - }, - "properties": [ - { - "id": "custom.align", - "value": "right" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "AutoColumn" - }, - "properties": [ - { - "id": "custom.align" - } - ] - } - ] - }, "id": 10, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + "styles": [ + { + "align": "center", + "pattern": "/.*/" + }, + { + "align": "left", + "pattern": "LeftColumn" + }, + { + "align": "right", + "pattern": "RightColumn" + }, + { + "align": "auto", + "pattern": "AutoColumn" + } + ], "title": "All Alignment Options", "type": "table" }, { + "autoMigrateFrom": "table-old", "description": "Tests both field matcher types: byName for exact matches and byRegexp for regex patterns.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, + "id": 11, + "styles": [ + { + "pattern": "/.*/", "unit": "short" }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "ExactColumnName" - }, - "properties": [ - { - "id": "displayName", - "value": "Exact Match" - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/Regex.*Pattern/" - }, - "properties": [ - { - "id": "displayName", - "value": "Regex Match" - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/^Start/" - }, - "properties": [ - { - "id": "displayName", - "value": "Start Pattern" - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/End$/" - }, - "properties": [ - { - "id": "displayName", - "value": "End Pattern" - } - ] - } - ] - }, - "id": 11, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + { + "alias": "Exact Match", + "pattern": "ExactColumnName" + }, + { + "alias": "Regex Match", + "pattern": "/Regex.*Pattern/" + }, + { + "alias": "Start Pattern", + "pattern": "/^Start/" + }, + { + "alias": "End Pattern", + "pattern": "/End$/" + } + ], "title": "Field Matcher Types Test", "type": "table" }, { + "autoMigrateFrom": "table-old", "description": "Tests various link configurations: with and without tooltip, with and without target blank.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, + "id": 12, + "styles": [ + { + "pattern": "/.*/", "unit": "short" }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "LinkWithTooltip" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "Click to view details", - "url": "http://example.com/with-tooltip" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "LinkWithoutTooltip" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": false, - "title": "", - "url": "http://example.com/no-tooltip" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "LinkMinimal" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": false, - "title": "", - "url": "http://example.com/minimal" - } - ] - } - ] - } - ] - }, - "id": 12, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + { + "link": true, + "linkTargetBlank": true, + "linkTooltip": "Click to view details", + "linkUrl": "http://example.com/with-tooltip", + "pattern": "LinkWithTooltip" + }, + { + "link": true, + "linkTargetBlank": false, + "linkUrl": "http://example.com/no-tooltip", + "pattern": "LinkWithoutTooltip" + }, + { + "link": true, + "linkUrl": "http://example.com/minimal", + "pattern": "LinkMinimal" + } + ], "title": "Link Configuration Test", "type": "table" }, { + "autoMigrateFrom": "table-old", "description": "Tests various date format patterns and aliases.", - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, + "id": 13, + "styles": [ + { + "pattern": "/.*/", "unit": "short" }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "DateISO" - }, - "properties": [ - { - "id": "displayName", - "value": "ISO Date" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "DateTime" - }, - "properties": [ - { - "id": "displayName", - "value": "Full DateTime" - }, - { - "id": "unit", - "value": "time: YYYY-MM-DD HH:mm:ss" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "TimeOnly" - }, - "properties": [ - { - "id": "displayName", - "value": "Time Only" - }, - { - "id": "unit", - "value": "time: HH:mm:ss" - } - ] - } - ] - }, - "id": 13, - "options": { - "cellHeight": "sm", - "showHeader": true - }, - "pluginVersion": "12.1.0", + { + "alias": "ISO Date", + "dateFormat": "YYYY-MM-DD", + "pattern": "DateISO", + "type": "date" + }, + { + "alias": "Full DateTime", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "DateTime", + "type": "date" + }, + { + "alias": "Time Only", + "dateFormat": "HH:mm:ss", + "pattern": "TimeOnly", + "type": "date" + } + ], "title": "Date Format Variations", "type": "table" }, diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v28.singlestat_and_variable_properties.v28.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v28.singlestat_and_variable_properties.v28.json index ba43b6785d3..2b7b8e83aa3 100644 --- a/apps/dashboard/pkg/migration/testdata/output/single_version/v28.singlestat_and_variable_properties.v28.json +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v28.singlestat_and_variable_properties.v28.json @@ -21,48 +21,18 @@ "links": [], "panels": [ { - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "#FF0000", - "value": null - }, - { - "color": "green", - "value": 10 - }, - { - "color": "orange", - "value": 20 - } - ] - } - }, - "overrides": [] + "autoMigrateFrom": "singlestat", + "colors": [ + "#FF0000", + "green", + "orange" + ], + "grid": { + "max": 10, + "min": 1 }, "id": 1, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", + "legend": true, "targets": [ { "refId": "A" @@ -71,122 +41,48 @@ "refId": "B" } ], + "thresholds": "10,20,30", "type": "stat" }, { - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "#FF0000", - "value": null - }, - { - "color": "green", - "value": 10 - }, - { - "color": "orange", - "value": 20 - } - ] - } - }, - "overrides": [] + "autoMigrateFrom": "singlestat", + "colors": [ + "#FF0000", + "green", + "orange" + ], + "gauge": { + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "grid": { + "max": 10, + "min": 1 }, "id": 2, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", + "thresholds": "10,20,30", "type": "stat" }, { - "fieldConfig": { - "defaults": { - "mappings": [ - { - "options": { - "20": { - "text": "test" - } - }, - "type": "value" - }, - { - "options": { - "30": { - "text": "test1" - } - }, - "type": "value" - }, - { - "options": { - "40": { - "color": "orange", - "text": "50" - } - }, - "type": "value" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "#FF0000", - "value": null - }, - { - "color": "green", - "value": 10 - }, - { - "color": "orange", - "value": 20 - } - ] - } - }, - "overrides": [] + "autoMigrateFrom": "singlestat", + "colors": [ + "#FF0000", + "green", + "orange" + ], + "grid": { + "max": 10, + "min": 1 }, "id": 3, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", + "legend": true, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + } + ], "targets": [ { "refId": "A" @@ -195,7 +91,25 @@ "refId": "B" } ], - "type": "stat" + "thresholds": "10,20,30", + "type": "stat", + "valueMaps": [ + { + "op": "=", + "text": "test", + "value": "20" + }, + { + "op": "=", + "text": "test1", + "value": "30" + }, + { + "op": "=", + "text": "50", + "value": "40" + } + ] }, { "id": 4, diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v28.singlestat_migration.v28.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v28.singlestat_migration.v28.json index 55a93c8a0f1..77f8ce45a63 100644 --- a/apps/dashboard/pkg/migration/testdata/output/single_version/v28.singlestat_migration.v28.json +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v28.singlestat_migration.v28.json @@ -21,48 +21,18 @@ "links": [], "panels": [ { - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "#FF0000", - "value": null - }, - { - "color": "green", - "value": 10 - }, - { - "color": "orange", - "value": 20 - } - ] - } - }, - "overrides": [] + "autoMigrateFrom": "singlestat", + "colors": [ + "#FF0000", + "green", + "orange" + ], + "grid": { + "max": 10, + "min": 1 }, "id": 1, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", + "legend": true, "targets": [ { "refId": "A" @@ -71,47 +41,22 @@ "refId": "B" } ], + "thresholds": "10,20,30", "type": "stat" }, { - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] + "autoMigrateFrom": "singlestat", + "colors": [ + "#FF0000", + "green", + "orange" + ], + "grid": { + "max": 10, + "min": 1 }, "id": 2, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", + "legend": true, "targets": [ { "refId": "A" @@ -120,122 +65,48 @@ "refId": "B" } ], + "thresholds": "", "type": "stat" }, { - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "#FF0000", - "value": null - }, - { - "color": "green", - "value": 10 - }, - { - "color": "orange", - "value": 20 - } - ] - } - }, - "overrides": [] + "autoMigrateFrom": "singlestat", + "colors": [ + "#FF0000", + "green", + "orange" + ], + "gauge": { + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "grid": { + "max": 10, + "min": 1 }, "id": 3, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", + "thresholds": "10,20,30", "type": "stat" }, { - "fieldConfig": { - "defaults": { - "mappings": [ - { - "options": { - "20": { - "text": "test" - } - }, - "type": "value" - }, - { - "options": { - "30": { - "text": "test1" - } - }, - "type": "value" - }, - { - "options": { - "40": { - "color": "orange", - "text": "50" - } - }, - "type": "value" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "#FF0000", - "value": null - }, - { - "color": "green", - "value": 10 - }, - { - "color": "orange", - "value": 20 - } - ] - } - }, - "overrides": [] + "autoMigrateFrom": "singlestat", + "colors": [ + "#FF0000", + "green", + "orange" + ], + "grid": { + "max": 10, + "min": 1 }, "id": 4, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "12.1.0", + "legend": true, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + } + ], "targets": [ { "refId": "A" @@ -244,7 +115,25 @@ "refId": "B" } ], - "type": "stat" + "thresholds": "10,20,30", + "type": "stat", + "valueMaps": [ + { + "op": "=", + "text": "test", + "value": "20" + }, + { + "op": "=", + "text": "test1", + "value": "30" + }, + { + "op": "=", + "text": "50", + "value": "40" + } + ] }, { "id": 8, @@ -257,38 +146,24 @@ "type": "timeseries" }, { + "autoMigrateFrom": "grafana-singlestat-panel", + "colorBackground": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], "datasource": { "type": "prometheus" }, - "fieldConfig": { - "defaults": { - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "areaF2" - }, - "overrides": [] + "format": "areaF2", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true }, "gridPos": { "h": 8, @@ -297,25 +172,37 @@ "y": 43 }, "id": 5, - "maxDataPoints": 100, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "postfix": "b", + "postfixFontSize": "50%", + "prefix": "a", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": true }, - "pluginVersion": "12.1.0", + "tableColumn": "", "targets": [ { "datasource": { @@ -325,8 +212,18 @@ "refId": "A" } ], + "thresholds": "", "title": "grafana-singlestat-panel", - "type": "stat" + "type": "stat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" }, { "datasource": { diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v3.no-op.v3.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v3.no-op.v3.json new file mode 100644 index 00000000000..14e9dc81daf --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v3.no-op.v3.json @@ -0,0 +1,53 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "id": 1, + "type": "timeseries" + }, + { + "id": 2, + "type": "timeseries" + }, + { + "id": 3, + "type": "barchart" + }, + { + "id": 4, + "type": "barchart" + } + ], + "schemaVersion": 3, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V3 No-Op Migration - but tests ensuring panel IDs are unique", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v4.no-op.v4.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v4.no-op.v4.json new file mode 100644 index 00000000000..cc1caec781f --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v4.no-op.v4.json @@ -0,0 +1,52 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "singlestat", + "id": 1, + "type": "stat" + }, + { + "autoMigrateFrom": "singlestat", + "id": 2, + "type": "stat" + }, + { + "autoMigrateFrom": "graph", + "id": 3, + "type": "timeseries" + } + ], + "schemaVersion": 4, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V4 No-Op Migration Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v5.no-op.v5.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v5.no-op.v5.json new file mode 100644 index 00000000000..7d9a3d9866f --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v5.no-op.v5.json @@ -0,0 +1,52 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "singlestat", + "id": 1, + "type": "stat" + }, + { + "autoMigrateFrom": "singlestat", + "id": 2, + "type": "stat" + }, + { + "autoMigrateFrom": "graph", + "id": 3, + "type": "timeseries" + } + ], + "schemaVersion": 5, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V5 No-Op Migration Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v6.pulldowns_and_templating.v6.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v6.pulldowns_and_templating.v6.json new file mode 100644 index 00000000000..8cdf9a36a40 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v6.pulldowns_and_templating.v6.json @@ -0,0 +1,123 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + }, + { + "datasource": "prometheus", + "enable": true, + "iconColor": "red", + "name": "deployment", + "query": "ALERTS{alertname=\"DeploymentStarted\"}" + }, + { + "datasource": "loki", + "enable": false, + "iconColor": "yellow", + "name": "alerts", + "query": "{job=\"alertmanager\"}" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "graph", + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "targets": [ + { + "expr": "cpu_usage{environment=\"$environment\", service=\"$service\"}", + "refId": "A" + } + ], + "title": "CPU Usage", + "type": "timeseries" + }, + { + "autoMigrateFrom": "singlestat", + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 2, + "targets": [ + { + "expr": "memory_usage{region=\"$region\"}", + "refId": "B" + } + ], + "title": "Memory Usage", + "type": "stat" + } + ], + "refresh": "30s", + "schemaVersion": 6, + "tags": [], + "templating": { + "list": [ + { + "name": "environment", + "options": [], + "type": "query" + }, + { + "allFormat": "glob", + "datasource": "prometheus", + "name": "service", + "options": [], + "type": "query" + }, + { + "name": "region", + "options": [ + { + "text": "us-east-1", + "value": "us-east-1" + }, + { + "text": "us-west-2", + "value": "us-west-2" + } + ], + "type": "custom" + }, + { + "datasource": "prometheus", + "name": "instance", + "options": [], + "query": "label_values(up, instance)", + "refresh": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V6 Pulldowns and Template Variables Migration Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v7.timepicker.v7.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v7.timepicker.v7.json new file mode 100644 index 00000000000..2f0c571d3b4 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v7.timepicker.v7.json @@ -0,0 +1,80 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "id": 1, + "targets": [ + { + "expr": "up", + "refId": "A" + }, + { + "expr": "cpu_usage", + "refId": "B" + } + ] + } + ], + "schemaVersion": 7, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "collapse": false, + "enable": true, + "notice": false, + "now": true, + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "status": "Stable", + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ], + "type": "timepicker" + }, + "timezone": "", + "title": "No Title", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v8.influxdb_query.v8.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v8.influxdb_query.v8.json new file mode 100644 index 00000000000..a098d59850c --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v8.influxdb_query.v8.json @@ -0,0 +1,122 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "graph", + "id": 1, + "targets": [ + { + "groupBy": [ + { + "params": [ + "1m" + ], + "type": "time" + }, + { + "params": [ + "host" + ], + "type": "tag" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "*2" + ], + "type": "math" + }, + { + "params": [ + "doubled" + ], + "type": "alias" + } + ] + ], + "tags": [ + { + "key": "host", + "value": "server1" + } + ] + } + ], + "type": "timeseries" + }, + { + "autoMigrateFrom": "graph", + "id": 2, + "targets": [ + { + "groupBy": [ + { + "interval": "1m", + "type": "time" + } + ], + "rawQuery": true, + "refId": "A", + "tags": [ + { + "key": "host", + "value": "server1" + } + ] + } + ], + "type": "timeseries" + } + ], + "schemaVersion": 8, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V8 InfluxDB Query Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/output/single_version/v9.no-op.v9.json b/apps/dashboard/pkg/migration/testdata/output/single_version/v9.no-op.v9.json new file mode 100644 index 00000000000..cb73f4b25aa --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/output/single_version/v9.no-op.v9.json @@ -0,0 +1,52 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "autoMigrateFrom": "singlestat", + "id": 1, + "type": "stat" + }, + { + "autoMigrateFrom": "singlestat", + "id": 2, + "type": "stat" + }, + { + "autoMigrateFrom": "graph", + "id": 3, + "type": "timeseries" + } + ], + "schemaVersion": 9, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "V9 No-Op Migration Test", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/folder/go.mod b/apps/folder/go.mod index 6db44655eeb..e8f03f93d54 100644 --- a/apps/folder/go.mod +++ b/apps/folder/go.mod @@ -1,9 +1,9 @@ module github.com/grafana/grafana/apps/folder -go 1.24.6 +go 1.25.3 require ( - github.com/grafana/grafana-app-sdk v0.46.0 + github.com/grafana/grafana-app-sdk v0.47.0 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e k8s.io/apimachinery v0.34.1 k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b @@ -23,7 +23,7 @@ require ( github.com/go-test/deep v1.1.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/gnostic-models v0.7.0 // indirect - github.com/grafana/grafana-app-sdk/logging v0.45.0 // indirect + github.com/grafana/grafana-app-sdk/logging v0.46.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -49,13 +49,13 @@ require ( go.opentelemetry.io/otel/trace v1.38.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.13.0 // indirect - google.golang.org/protobuf v1.36.9 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/client-go v0.34.1 // indirect diff --git a/apps/folder/go.sum b/apps/folder/go.sum index ab3cbcecbb1..4ef325bbb17 100644 --- a/apps/folder/go.sum +++ b/apps/folder/go.sum @@ -31,10 +31,10 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grafana/grafana-app-sdk v0.46.0 h1:gvzQvCQgZJ/73BfAcbDt/6TAMhnVikVPxZt/UwDl+oc= -github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= -github.com/grafana/grafana-app-sdk/logging v0.45.0 h1:0SH6nYZpiLBZRwUq4J6+1vo8xuHKJjnO95/2pGOoA8w= -github.com/grafana/grafana-app-sdk/logging v0.45.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= +github.com/grafana/grafana-app-sdk/logging v0.46.0 h1:JhQ+ZK5orcmM+dZ3YZdT9uCizJEFU2I6JBNUSFWvCC8= +github.com/grafana/grafana-app-sdk/logging v0.46.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e h1:BTKk7LHuG1kmAkucwTA7DuMbKpKvJTKrGdBmUNO4dfQ= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e/go.mod h1:IA4SOwun8QyST9c5UNs/fN37XL6boXXDvRYFcFwbipg= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -124,10 +124,10 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -140,8 +140,8 @@ golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -152,8 +152,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/apps/folder/pkg/apis/folder_manifest.go b/apps/folder/pkg/apis/folder_manifest.go index 4fcb76837ed..df164aa6ebc 100644 --- a/apps/folder/pkg/apis/folder_manifest.go +++ b/apps/folder/pkg/apis/folder_manifest.go @@ -13,6 +13,7 @@ import ( "github.com/grafana/grafana-app-sdk/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kube-openapi/pkg/spec3" + "k8s.io/kube-openapi/pkg/validation/spec" v1beta1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1" ) @@ -36,6 +37,7 @@ var appManifestData = app.ManifestData{ Routes: app.ManifestVersionRoutes{ Namespaced: map[string]spec3.PathProps{}, Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{}, }, }, }, diff --git a/apps/iam/go.mod b/apps/iam/go.mod index 30fa2ce8562..cd46e92a15f 100644 --- a/apps/iam/go.mod +++ b/apps/iam/go.mod @@ -1,6 +1,6 @@ module github.com/grafana/grafana/apps/iam -go 1.24.6 +go 1.25.3 replace github.com/grafana/grafana => ../../ @@ -12,6 +12,30 @@ replace github.com/grafana/grafana/apps/secret => ../secret replace github.com/grafana/grafana/apps/provisioning => ../provisioning +replace github.com/grafana/grafana/apps/advisor => ../advisor + +replace github.com/grafana/grafana/apps/alerting/alertenrichment => ../alerting/alertenrichment + +replace github.com/grafana/grafana/apps/alerting/notifications => ../alerting/notifications + +replace github.com/grafana/grafana/apps/alerting/rules => ../alerting/rules + +replace github.com/grafana/grafana/apps/correlations => ../correlations + +replace github.com/grafana/grafana/apps/investigations => ../investigations + +replace github.com/grafana/grafana/apps/logsdrilldown => ../logsdrilldown + +replace github.com/grafana/grafana/apps/playlist => ../playlist + +replace github.com/grafana/grafana/apps/plugins => ../plugins + +replace github.com/grafana/grafana/apps/preferences => ../preferences + +replace github.com/grafana/grafana/apps/scope => ../scope + +replace github.com/grafana/grafana/apps/shorturl => ../shorturl + replace github.com/grafana/grafana/pkg/apimachinery => ../../pkg/apimachinery replace github.com/grafana/grafana/pkg/apiserver => ../../pkg/apiserver @@ -22,8 +46,8 @@ replace github.com/prometheus/alertmanager => github.com/grafana/prometheus-aler require ( github.com/grafana/grafana v0.0.0-00010101000000-000000000000 - github.com/grafana/grafana-app-sdk v0.46.0 - github.com/grafana/grafana-app-sdk/logging v0.45.0 + github.com/grafana/grafana-app-sdk v0.47.0 + github.com/grafana/grafana-app-sdk/logging v0.46.0 github.com/grafana/grafana/apps/folder v0.0.0 github.com/grafana/grafana/pkg/apimachinery v0.0.0 github.com/prometheus/client_golang v1.23.2 @@ -45,14 +69,14 @@ require ( cuelang.org/go v0.11.1 // indirect dario.cat/mergo v1.0.2 // indirect filippo.io/edwards25519 v1.1.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.12.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest/to v0.4.1 // indirect github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0 // indirect github.com/BurntSushi/toml v1.5.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 // indirect @@ -94,7 +118,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sso v1.28.2 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.2 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.38.0 // indirect - github.com/aws/smithy-go v1.22.5 // indirect + github.com/aws/smithy-go v1.23.1 // indirect github.com/axiomhq/hyperloglog v0.0.0-20240507144631-af9851f82b27 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df // indirect @@ -173,7 +197,6 @@ require ( github.com/go-openapi/strfmt v0.23.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/go-openapi/validate v0.24.0 // indirect - github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-sql-driver/mysql v1.9.3 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect @@ -201,13 +224,13 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect github.com/googleapis/gax-go/v2 v2.14.2 // indirect github.com/gorilla/mux v1.8.1 // indirect - github.com/grafana/alerting v0.0.0-20251007160934-e642236ea9eb // indirect + github.com/grafana/alerting v0.0.0-20251009192429-9427c24835ae // indirect github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f // indirect github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 // indirect github.com/grafana/dataplane/sdata v0.0.9 // indirect github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 // indirect github.com/grafana/grafana-aws-sdk v1.2.0 // indirect - github.com/grafana/grafana-azure-sdk-go/v2 v2.2.0 // indirect + github.com/grafana/grafana-azure-sdk-go/v2 v2.3.1 // indirect github.com/grafana/grafana-plugin-sdk-go v0.279.0 // indirect github.com/grafana/grafana/apps/dashboard v0.0.0 // indirect github.com/grafana/grafana/apps/provisioning v0.0.0 // indirect @@ -217,7 +240,7 @@ require ( github.com/grafana/grafana/pkg/promlib v0.0.8 // indirect github.com/grafana/grafana/pkg/semconv v0.0.0-20250804150913-990f1c69ecc2 // indirect github.com/grafana/otel-profiling-go v0.5.1 // indirect - github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // indirect github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect github.com/grafana/sqlds/v4 v4.2.7 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect @@ -272,7 +295,7 @@ require ( github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/mattn/go-sqlite3 v1.14.22 // indirect + github.com/mattn/go-sqlite3 v1.14.32 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mdlayher/socket v0.4.1 // indirect github.com/mdlayher/vsock v1.2.1 // indirect @@ -302,9 +325,9 @@ require ( github.com/oklog/ulid v1.3.1 // indirect github.com/oklog/ulid/v2 v2.1.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/open-feature/go-sdk v1.14.1 // indirect - github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.3 // indirect - github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5 // indirect + github.com/open-feature/go-sdk v1.16.0 // indirect + github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.6 // indirect + github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.6 // indirect github.com/openfga/api/proto v0.0.0-20250909172242-b4b2a12f5c67 // indirect github.com/openfga/language/pkg/go v0.2.0-beta.2.0.20250428093642-7aeebe78bbfe // indirect github.com/openfga/openfga v1.10.0 // indirect @@ -327,6 +350,7 @@ require ( github.com/prometheus/procfs v0.16.1 // indirect github.com/prometheus/prometheus v0.303.1 // indirect github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect + github.com/redis/go-redis/v9 v9.14.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rs/cors v1.11.1 // indirect @@ -373,10 +397,10 @@ require ( go.opentelemetry.io/contrib/detectors/gcp v1.36.0 // indirect go.opentelemetry.io/contrib/exporters/autoexport v0.61.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.62.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.63.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect - go.opentelemetry.io/contrib/propagators/jaeger v1.37.0 // indirect - go.opentelemetry.io/contrib/samplers/jaegerremote v0.31.0 // indirect + go.opentelemetry.io/contrib/propagators/jaeger v1.38.0 // indirect + go.opentelemetry.io/contrib/samplers/jaegerremote v0.32.0 // indirect go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2 // indirect @@ -405,13 +429,13 @@ require ( golang.org/x/crypto v0.42.0 // indirect golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect golang.org/x/mod v0.28.0 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 // indirect golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.13.0 // indirect golang.org/x/tools v0.37.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect @@ -421,8 +445,8 @@ require ( google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect - google.golang.org/grpc v1.75.1 // indirect - google.golang.org/protobuf v1.36.9 // indirect + google.golang.org/grpc v1.76.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect @@ -442,10 +466,10 @@ require ( k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kms v0.34.1 // indirect k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect - modernc.org/libc v1.66.3 // indirect + modernc.org/libc v1.66.10 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.11.0 // indirect - modernc.org/sqlite v1.38.2 // indirect + modernc.org/sqlite v1.39.1 // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/randfill v1.0.0 // indirect diff --git a/apps/iam/go.sum b/apps/iam/go.sum index 8761accef79..704a0c2efe7 100644 --- a/apps/iam/go.sum +++ b/apps/iam/go.sum @@ -1,3 +1,7 @@ +buf.build/gen/go/parca-dev/parca/connectrpc/go v1.18.1-20250703125925-3f0fcf4bff96.1 h1:MXQkdpJwbCwskYLQ3dUv/5gmk8fSsUwu78u+kXebbek= +buf.build/gen/go/parca-dev/parca/connectrpc/go v1.18.1-20250703125925-3f0fcf4bff96.1/go.mod h1:pjl83IqpNF7Lm/lOPMLQ5IIfCg+yTu2A9OgYTcEncCs= +buf.build/gen/go/parca-dev/parca/protocolbuffers/go v1.36.2-20250703125925-3f0fcf4bff96.1 h1:9nqE/pDc/HXAXiD5pZncPywjAzWgKuBkFFYgdK2lVU8= +buf.build/gen/go/parca-dev/parca/protocolbuffers/go v1.36.2-20250703125925-3f0fcf4bff96.1/go.mod h1:1M7nlq2ljfzb95x9LaA2j1gYIvDkVZii58mGvTa9ExM= cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= @@ -56,6 +60,8 @@ cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1 cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= cloud.google.com/go/iam v1.5.2 h1:qgFRAGEmd8z6dJ/qyEchAuL9jpswyODjA2lS+w234g8= cloud.google.com/go/iam v1.5.2/go.mod h1:SE1vg0N81zQqLzQEwxL2WI6yhetBdbNQuTvIKCSkUHE= +cloud.google.com/go/kms v1.22.0 h1:dBRIj7+GDeeEvatJeTB19oYZNV0aj6wEqSIT/7gLqtk= +cloud.google.com/go/kms v1.22.0/go.mod h1:U7mf8Sva5jpOb4bxYZdtw/9zsbIjrklYwPcvMk34AL8= cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc= cloud.google.com/go/logging v1.13.0/go.mod h1:36CoKh6KA/M0PbhPKMq6/qety2DCAErbhXT62TuXALA= cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE= @@ -76,6 +82,8 @@ cloud.google.com/go/storage v1.55.0 h1:NESjdAToN9u1tmhVqhXCaCwYBuvEhZLLv0gBr+2zn cloud.google.com/go/storage v1.55.0/go.mod h1:ztSmTTwzsdXe5syLVS0YsbFxXuvEmEyZj7v7zChEmuY= cloud.google.com/go/trace v1.11.6 h1:2O2zjPzqPYAHrn3OKl029qlqG6W8ZdYaOWRyr8NgMT4= cloud.google.com/go/trace v1.11.6/go.mod h1:GA855OeDEBiBMzcckLPE2kDunIpC72N+Pq8WFieFjnI= +connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw= +connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= cuelabs.dev/go/oci/ociregistry v0.0.0-20240906074133-82eb438dd565 h1:R5wwEcbEZSBmeyg91MJZTxfd7WpBo2jPof3AYjRbxwY= cuelabs.dev/go/oci/ociregistry v0.0.0-20240906074133-82eb438dd565/go.mod h1:5A4xfTzHTXfeVJBU6RAUf+QrlfTCW+017q/QiW+sMLg= cuelang.org/go v0.11.1 h1:pV+49MX1mmvDm8Qh3Za3M786cty8VKPWzQ1Ho4gZRP0= @@ -83,37 +91,64 @@ cuelang.org/go v0.11.1/go.mod h1:PBY6XvPUswPPJ2inpvUozP9mebDVTXaeehQikhZPBz0= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/age v1.2.1 h1:X0TZjehAZylOIj4DubWYU1vWQxv9bJpo+Uu2/LGhi1o= +filippo.io/age v1.2.1/go.mod h1:JL9ew2lTN+Pyft4RiNGguFfOpewKwSHm5ayKD/A4004= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/1NCE-GmbH/grpc-go-pool v0.0.0-20231117122434-2a5bb974daa2 h1:qFYgLH2zZe3WHpQgUrzeazC+ebDebwAQqS9yE1cP5Bs= +github.com/1NCE-GmbH/grpc-go-pool v0.0.0-20231117122434-2a5bb974daa2/go.mod h1:09/ALd1AXCTCOfcJYD8+jIYKmFmi6PVCkTsipC18F7E= +github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U= +github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1 h1:Wc1ml6QlJs2BHQ/9Bqu1jiyggbsSjramq2oUmp5WeIo= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 h1:5YTBM8QDVIBN3sxBil89WfdAAqDZbyJTgh688DSxX5w= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1/go.mod h1:YD5h/ldMsG0XiIw7PdyNhLxaM317eFh5yNLccNfGdyw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.12.0 h1:wL5IEG5zb7BVv1Kv0Xm92orq+5hB5Nipn3B5tn4Rqfk= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.12.0/go.mod h1:J7MUC/wtRpfGVbQ5sIItY5/FuVWmvzlY21WAOfQnq/I= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI= +github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 h1:m/sWOGCREuSBqg2htVQTBY8nOZpyajYztF0vUvSZTuM= +github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0/go.mod h1:Pu5Zksi2KrU7LPbZbNINx6fuVrUp/ffvpxdDj+i8LeE= +github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 h1:FbH3BbSb4bvGluTesZZ+ttN/MDsnMmQP36OSnDuSXqw= +github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0 h1:LR0kAX9ykz8G4YgLCaRDVJ3+n43R8MneB5dTy2konZo= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0/go.mod h1:DWAciXemNf++PQJLeXUB4HHH5OpsAh12HZnu2wXE1jA= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 h1:lhZdRq7TIx0GJQvSyX2Si406vrYsov2FXGp/RnSEtcs= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1/go.mod h1:8cl44BDmi+effbARHMQjgOKA2AYvcohNm7KEt42mSV8= +github.com/Azure/azure-storage-blob-go v0.15.0 h1:rXtgp8tN1p29GvpGgfJetavIG0V7OgcSXPpwp3tx6qk= +github.com/Azure/azure-storage-blob-go v0.15.0/go.mod h1:vbjsVbX0dlxnRc4FFMPsS9BsJWPcne7GB7onqlPvz58= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= +github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs= +github.com/Azure/go-autorest/autorest/adal v0.9.24 h1:BHZfgGsGwdkHDyZdtQRQk1WeUdW0m2WPAwuHZwUi5i4= +github.com/Azure/go-autorest/autorest/adal v0.9.24/go.mod h1:7T1+g0PYFmACYW5LlG2fcoPiPlFHjClyRGL7dRlP5c8= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/to v0.4.1 h1:CxNHBqdzTr7rLtdrtb5CMjJcDut+WNGCVv7OmS5+lTc= github.com/Azure/go-autorest/autorest/to v0.4.1/go.mod h1:EtaofgU4zmtvn1zT2ARsjRFdq9vXx0YWtmElwL+GZ9M= +github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= +github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= +github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e h1:NeAW1fUYUEWhft7pkxDf6WoUvEZJ/uOKsvtpjLnn8MU= github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= -github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= -github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0 h1:XkkQbfMyuH2jTSjQjSoihryI8GINRcs4xp8lNawg0FI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/FZambia/eagle v0.2.0 h1:1kQaZpJvbkvAXFRE/9K2ucBMuVqo+E29EMLYB74hIis= +github.com/FZambia/eagle v0.2.0/go.mod h1:LKMYBwGYhao5sJI0TppvQ4SvvldFj9gITxrl8NvGwG0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 h1:UQUsRi8WTzhZntp5313l+CHIAT95ojUI2lpP/ExlZa4= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0/go.mod h1:Cz6ft6Dkn3Et6l2v2a9/RpN7epQ1GtDlO6lj8bEcOvw= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 h1:fYE9p3esPxA/C0rQ0AHhP0drtPXDRhaWiwg1DPqO7IU= @@ -157,6 +192,8 @@ github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f h1:HR5nRmUQgX github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f/go.mod h1:f3HiCrHjHBdcm6E83vGaXh1KomZMA2P6aeo3hKx/wg0= github.com/Yiling-J/theine-go v0.6.2 h1:1GeoXeQ0O0AUkiwj2S9Jc0Mzx+hpqzmqsJ4kIC4M9AY= github.com/Yiling-J/theine-go v0.6.2/go.mod h1:08QpMa5JZ2pKN+UJCRrCasWYO1IKCdl54Xa836rpmDU= +github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8= +github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -175,6 +212,10 @@ github.com/apache/arrow-go/v18 v18.4.0/go.mod h1:Aawvwhj8x2jURIzD9Moy72cF0FyJXOp github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.22.0 h1:r7mTJdj51TMDe6RtcmNdQxgn9XcyfGDOzegMDRg47uc= github.com/apache/thrift v0.22.0/go.mod h1:1e7J/O1Ae6ZQMTYdy9xa3w9k+XHWPfRvdPyJeynQ+/g= +github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= +github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -212,6 +253,12 @@ github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 h1:ZNTqv4nIdE/DiBfUUfXcLZ/Spcuz+RjeziUtNJackkM= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34/go.mod h1:zf7Vcd1ViW7cPqYWEHLHJkS50X0JS2IKz9Cgaj6ugrs= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.45.3 h1:Nn3qce+OHZuMj/edx4its32uxedAmquCDxtZkrdeiD4= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.45.3/go.mod h1:aqsLGsPs+rJfwDBwWHLcIV8F7AFcikFTPLwUD4RwORQ= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.51.0 h1:e5cbPZYTIY2nUEFieZUfVdINOiCTvChOMPfdLnmiLzs= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.51.0/go.mod h1:UseIHRfrm7PqeZo6fcTb6FUCXzCnh1KJbQbmOfxArGM= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.225.2 h1:IfMb3Ar8xEaWjgH/zeVHYD8izwJdQgRP5mKCTDt4GNk= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.225.2/go.mod h1:35jGWx7ECvCwTsApqicFYzZ7JFEnBc6oHUuOQ3xIS54= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.0 h1:lguz0bmOoGzozP9XfRJR1QIayEYo+2vP/No3OfLF0pU= @@ -220,6 +267,12 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.4 h1:ueB2Te0Na github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.4/go.mod h1:nLEfLnVMmLvyIG58/6gsSA03F1voKGaCfHV7+lR8S7s= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 h1:moLQUoVq91LiqT1nbvzDukyqAlCv89ZmwaHw/ZFlFZg= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15/go.mod h1:ZH34PJUc8ApjBIfgQCFvkWcUDBtl/WTD+uiYHjd8igA= +github.com/aws/aws-sdk-go-v2/service/kms v1.38.1 h1:tecq7+mAav5byF+Mr+iONJnCBf4B4gon8RSp4BrweSc= +github.com/aws/aws-sdk-go-v2/service/kms v1.38.1/go.mod h1:cQn6tAF77Di6m4huxovNM7NVAozWTZLsDRp9t8Z/WYk= +github.com/aws/aws-sdk-go-v2/service/oam v1.18.3 h1:teOWtElLARLOhpYWwupjLbY9j5I/yZ/H1I8jg41An78= +github.com/aws/aws-sdk-go-v2/service/oam v1.18.3/go.mod h1:wGhpdyftHX6/1U4egowHkYdypwBMjpb+KjAAprv6z20= +github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.26.6 h1:PwbxovpcJvb25k019bkibvJfCpCmIANOFrXZIFPmRzk= +github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.26.6/go.mod h1:Z4xLt5mXspLKjBV92i165wAJ/3T6TIv4n7RtIS8pWV0= github.com/aws/aws-sdk-go-v2/service/s3 v1.78.2 h1:jIiopHEV22b4yQP2q36Y0OmwLbsxNWdWwfZRR5QRRO4= github.com/aws/aws-sdk-go-v2/service/s3 v1.78.2/go.mod h1:U5SNqwhXB3Xe6F47kXvWihPl/ilGaEDe8HD/50Z9wxc= github.com/aws/aws-sdk-go-v2/service/sso v1.28.2 h1:ve9dYBB8CfJGTFqcQ3ZLAAb/KXWgYlgu/2R2TZL2Ko0= @@ -228,8 +281,8 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.2 h1:pd9G9HQaM6UZAZh19pYOkpKS github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.2/go.mod h1:eknndR9rU8UpE/OmFpqU78V1EcXPKFTTm5l/buZYgvM= github.com/aws/aws-sdk-go-v2/service/sts v1.38.0 h1:iV1Ko4Em/lkJIsoKyGfc0nQySi+v0Udxr6Igq+y9JZc= github.com/aws/aws-sdk-go-v2/service/sts v1.38.0/go.mod h1:bEPcjW7IbolPfK67G1nilqWyoxYMSPrDiIQ3RdIdKgo= -github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw= -github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= +github.com/aws/smithy-go v1.23.1 h1:sLvcH6dfAFwGkHLZ7dGiYF7aK6mg4CgKA/iDKjLDt9M= +github.com/aws/smithy-go v1.23.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= github.com/axiomhq/hyperloglog v0.0.0-20191112132149-a4c4c47bc57f/go.mod h1:2stgcRjl6QmW+gU2h5E7BQXg4HU0gzxKWDuT5HviN9s= github.com/axiomhq/hyperloglog v0.0.0-20240507144631-af9851f82b27 h1:60m4tnanN1ctzIu4V3bfCNJ39BiOPSm1gHFlFjTkRE0= github.com/axiomhq/hyperloglog v0.0.0-20240507144631-af9851f82b27/go.mod h1:k08r+Yj1PRAmuayFiRK6MYuR5Ve4IuZtTfxErMIh0+c= @@ -239,6 +292,8 @@ github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLo github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo4tARvBm7l6KA9iVMnE3NWizDeWSrps= github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3/go.mod h1:CIWtjkly68+yqLPbvwwR/fjNJA/idrtULjZWh2v1ys0= +github.com/beevik/etree v1.4.1 h1:PmQJDDYahBGNKDcpdX8uPy1xRCwoCGVUiW669MEirVI= +github.com/beevik/etree v1.4.1/go.mod h1:gPNJNaBGVZ9AwsidazFZyygnd+0pAU38N4D+WemwKNs= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -310,12 +365,18 @@ github.com/blugelabs/ice/v2 v2.0.1/go.mod h1:QxAWSPNwZwsIqS25c3lbIPFQrVvT1sphf5x github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous= github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw= github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0= github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE= +github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500 h1:6lhrsTEnloDPXyeZBvSYvQf8u86jbKehZPVDDlkgDl4= +github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= 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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= @@ -323,6 +384,11 @@ github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/centrifugal/centrifuge v0.37.2 h1:rerQNvDfYN2FZEkVtb/hvGV7SIrJfEQrKF3MaE8GDlo= +github.com/centrifugal/centrifuge v0.37.2/go.mod h1:aj4iRJGhzi3SlL8iUtVezxway1Xf8g+hmNQkLLO7sS8= +github.com/centrifugal/protocol v0.16.2 h1:KoIHgDeX1fFxyxQoKW+6E8ZTCf5mwGm8JyGoJ5NBMbQ= +github.com/centrifugal/protocol v0.16.2/go.mod h1:Q7OpS/8HMXDnL7f9DpNx24IhG96MP88WPpVTTCdrokI= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -374,6 +440,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6N github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/crewjam/saml v0.4.14 h1:g9FBNx62osKusnFzs3QTN5L9CVA/Egfgm+stJShzw/c= +github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1nl2mME= github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg= github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc= @@ -427,6 +495,8 @@ github.com/dolthub/go-mysql-server v0.19.1-0.20250410182021-5632d67cd46e h1:7pAt github.com/dolthub/go-mysql-server v0.19.1-0.20250410182021-5632d67cd46e/go.mod h1:KZyoO3jngyZCLyCf100FEQTrwAHj33AIMj4Zv4u3MNE= github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71 h1:bMGS25NWAGTEtT5tOBsCuCrlYnLRKpbJVJkDbrTRhwQ= github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71/go.mod h1:2/2zjLQ/JOOSbbSboojeg+cAwcRV0fDLzIiWch/lhqI= +github.com/dolthub/maphash v0.1.0 h1:bsQ7JsF4FkkWyrP3oCnFJgrCUAFbFf3kOl4L/QxPDyQ= +github.com/dolthub/maphash v0.1.0/go.mod h1:gkg4Ch4CdCDu5h6PMriVLawB7koZ+5ijb9puGMV50a4= github.com/dolthub/vitess v0.0.0-20250410090211-143e6b272ad4 h1:LGTt2LtYX8vaai32d+c9L0sMcP+Dg9w1kO6+lbsxxYg= github.com/dolthub/vitess v0.0.0-20250410090211-143e6b272ad4/go.mod h1:1gQZs/byeHLMSul3Lvl3MzioMtOW1je79QYGyi2fd70= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -436,6 +506,8 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.2.0 h1:hXLYlkbaPzt1SaQk+anYwKSRNhufIDCchSPkUD6dD84= +github.com/edsrzf/mmap-go v1.2.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= @@ -464,6 +536,8 @@ github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfU github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb h1:IT4JYU7k4ikYg1SCxNI1/Tieq/NFvh6dzLdgi7eu0tM= +github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW64qjjJq8M2u4dxNaBiDfKK+z/3eGDpXEQhc= 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= @@ -485,6 +559,8 @@ github.com/fullstorydev/grpchan v1.1.1 h1:heQqIJlAv5Cnks9a70GRL2EJke6QQoUB25VGR6 github.com/fullstorydev/grpchan v1.1.1/go.mod h1:f4HpiV8V6htfY/K44GWV1ESQzHBTq7DinhzqQ95lpgc= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0= +github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU= 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.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ= @@ -545,6 +621,8 @@ github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7 github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= 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-sourcemap/sourcemap v2.1.4+incompatible h1:a+iTbH5auLKxaNwQFg0B+TCYl6lbukKPc7b5x0n1s6Q= +github.com/go-sourcemap/sourcemap v2.1.4+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= @@ -585,6 +663,10 @@ github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9v github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang-migrate/migrate/v4 v4.7.0 h1:gONcHxHApDTKXDyLH/H97gEHmpu1zcnnbAaq2zgrPrs= github.com/golang-migrate/migrate/v4 v4.7.0/go.mod h1:Qvut3N4xKWjoH3sokBccML6WyHSnggXm/DvMMnTsQIc= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo= github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= @@ -658,7 +740,10 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-github/v70 v70.0.0 h1:/tqCp5KPrcvqCc7vIvYyFYTiCGrYvaWoYMGHSQbo55o= +github.com/google/go-github/v70 v70.0.0/go.mod h1:xBUZgo8MI3lUL/hwxl3hlceJW1U8MVnXP3zUyI+rhQY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= @@ -721,8 +806,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= -github.com/grafana/alerting v0.0.0-20251007160934-e642236ea9eb h1:ejpL3pI9t1ebEFtxaP7TMDKZagCu1nSq1O8op+sO4DY= -github.com/grafana/alerting v0.0.0-20251007160934-e642236ea9eb/go.mod h1:VGjS5gDwWEADPP6pF/drqLxEImgeuHlEW5u8E5EfIrM= +github.com/grafana/alerting v0.0.0-20251009192429-9427c24835ae h1:NLPwY3tIP0lg0g9wTRiMcypm6VRXW6W+MOLBsq8JSVA= +github.com/grafana/alerting v0.0.0-20251009192429-9427c24835ae/go.mod h1:VGjS5gDwWEADPP6pF/drqLxEImgeuHlEW5u8E5EfIrM= github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f h1:Cbm6OKkOcJ+7CSZsGsEJzktC/SIa5bxVeYKQLuYK86o= github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f/go.mod h1:axY0cdOg3q0TZHwpHnIz5x16xZ8ZBxJHShsSHHXcHQg= github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 h1:qEwZ+7MbPjzRvTi31iT9w7NBhKIpKwZrFbYmOZLqkwA= @@ -733,30 +818,54 @@ github.com/grafana/dataplane/sdata v0.0.9 h1:AGL1LZnCUG4MnQtnWpBPbQ8ZpptaZs14w6k github.com/grafana/dataplane/sdata v0.0.9/go.mod h1:Jvs5ddpGmn6vcxT7tCTWAZ1mgi4sbcdFt9utQx5uMAU= github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 h1:jSojuc7njleS3UOz223WDlXOinmuLAIPI0z2vtq8EgI= github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4/go.mod h1:VahT+GtfQIM+o8ht2StR6J9g+Ef+C2Vokh5uuSmOD/4= -github.com/grafana/grafana-app-sdk v0.46.0 h1:gvzQvCQgZJ/73BfAcbDt/6TAMhnVikVPxZt/UwDl+oc= -github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= -github.com/grafana/grafana-app-sdk/logging v0.45.0 h1:0SH6nYZpiLBZRwUq4J6+1vo8xuHKJjnO95/2pGOoA8w= -github.com/grafana/grafana-app-sdk/logging v0.45.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grafana/e2e v0.1.1 h1:/b6xcv5BtoBnx8cZnCiey9DbjEc8z7gXHO5edoeRYxc= +github.com/grafana/e2e v0.1.1/go.mod h1:RpNLgae5VT+BUHvPE+/zSypmOXKwEu4t+tnEMS1ATaE= +github.com/grafana/gofpdf v0.0.0-20250307124105-3b9c5d35577f h1:5xkjl5Y/j2QefJKOtTfyD1wXlVsQ2yEXmd0u82h5obs= +github.com/grafana/gofpdf v0.0.0-20250307124105-3b9c5d35577f/go.mod h1:+O5QxOwwgP10jedZHapzXY+IPKTnzHBtIs5UUb9G+kI= +github.com/grafana/gomemcache v0.0.0-20250828162811-a96f6acee2fe h1:q+QaVANzNZxvTovycpQvDTfsNZ2rHh4XIIaccMnrIR4= +github.com/grafana/gomemcache v0.0.0-20250828162811-a96f6acee2fe/go.mod h1:j/s0jkda4UXTemDs7Pgw/vMT06alWc42CHisvYac0qw= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= +github.com/grafana/grafana-app-sdk/logging v0.46.0 h1:JhQ+ZK5orcmM+dZ3YZdT9uCizJEFU2I6JBNUSFWvCC8= +github.com/grafana/grafana-app-sdk/logging v0.46.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= github.com/grafana/grafana-aws-sdk v1.2.0 h1:LLR4/g91WBuCRwm2cbWfCREq565+GxIFe08nqqIcIuw= github.com/grafana/grafana-aws-sdk v1.2.0/go.mod h1:bBo7qOmM3f61vO+2JxTolNUph1l2TmtzmWcU9/Im+8A= -github.com/grafana/grafana-azure-sdk-go/v2 v2.2.0 h1:0TYrkzAc3u0HX+9GK86cGrLTUAcmQfl3/LEB3tL+SOA= -github.com/grafana/grafana-azure-sdk-go/v2 v2.2.0/go.mod h1:H9sVh9A4yg5egMGZeh0mifxT1Q/uqwKe1LBjBJU6pN8= +github.com/grafana/grafana-azure-sdk-go/v2 v2.3.1 h1:FFcEA01tW+SmuJIuDbHOdgUBL+d7DPrZ2N4zwzPhfGk= +github.com/grafana/grafana-azure-sdk-go/v2 v2.3.1/go.mod h1:Oi4anANlCuTCc66jCyqIzfVbgLXFll8Wja+Y4vfANlc= +github.com/grafana/grafana-cloud-migration-snapshot v1.9.0 h1:JOzchPgptwJdruYoed7x28lFDwhzs7kssResYsnC0iI= +github.com/grafana/grafana-cloud-migration-snapshot v1.9.0/go.mod h1:nOHgq4Oa829qmBKA5KIXw5Ipo3rhLs0d6A8UI9Nw8Zk= +github.com/grafana/grafana-google-sdk-go v0.4.2 h1:F44hQF1y6UVJhlJPi+Mz+GCJsioVgezEgPMMEQbUZRo= +github.com/grafana/grafana-google-sdk-go v0.4.2/go.mod h1:U73+w9DlbEtUonhQUzERwlXnzWTtfRoyrtKH8d3VY40= +github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79 h1:r+mU5bGMzcXCRVAuOrTn54S80qbfVkvTdUJZfSfTNbs= +github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79/go.mod h1:wc6Hbh3K2TgCUSfBC/BOzabItujtHMESZeFk5ZhdxhQ= github.com/grafana/grafana-plugin-sdk-go v0.279.0 h1:/KCrsZkj9pEGwIGovqAz1A8rjI2A2YT+ZpvgfZN0LAA= github.com/grafana/grafana-plugin-sdk-go v0.279.0/go.mod h1:/7oGN6Z7DGTGaLHhgIYrRr6Wvmdsb3BLw5hL4Kbjy88= github.com/grafana/grafana/pkg/promlib v0.0.8 h1:VUWsqttdf0wMI4j9OX9oNrykguQpZcruudDAFpJJVw0= github.com/grafana/grafana/pkg/promlib v0.0.8/go.mod h1:U1ezG/MGaEPoThqsr3lymMPN5yIPdVTJnDZ+wcXT+ao= github.com/grafana/grafana/pkg/semconv v0.0.0-20250804150913-990f1c69ecc2 h1:A65jWgLk4Re28gIuZcpC0aTh71JZ0ey89hKGE9h543s= github.com/grafana/grafana/pkg/semconv v0.0.0-20250804150913-990f1c69ecc2/go.mod h1:2HRzUK/xQEYc+8d5If/XSusMcaYq9IptnBSHACiQcOQ= +github.com/grafana/jsonparser v0.0.0-20240425183733-ea80629e1a32 h1:NznuPwItog+rwdVg8hAuGKP29ndRSzJAwhxKldkP8oQ= +github.com/grafana/jsonparser v0.0.0-20240425183733-ea80629e1a32/go.mod h1:796sq+UcONnSlzA3RtlBZ+b/hrerkZXiEmO8oMjyRwY= +github.com/grafana/loki/pkg/push v0.0.0-20250823105456-332df2b20000 h1:/5LKSYgLmAhwA4m6iGUD4w1YkydEWWjazn9qxCFT8W0= +github.com/grafana/loki/pkg/push v0.0.0-20250823105456-332df2b20000/go.mod h1:/ZklAgE1i4f3Z8uriXwESmCr1VLF8lBGaJspuaGuf78= +github.com/grafana/loki/v3 v3.2.1 h1:VB7u+KHfvL5aHAxgoVBvz5wVhsdGuqKC7uuOFOOe7jw= +github.com/grafana/loki/v3 v3.2.1/go.mod h1:WvdLl6wOS+yahaeQY+xhD2m2XzkHDfKr5FZaX7D/X2Y= +github.com/grafana/nanogit v0.0.0-20250723104447-68f58f5ecec0 h1:cS0SlJGIlZbmDLctNj5vIYGemrJDLy25wwoiIyZWVN8= +github.com/grafana/nanogit v0.0.0-20250723104447-68f58f5ecec0/go.mod h1:ToqLjIdvV3AZQa3K6e5m9hy/nsGaUByc2dWQlctB9iA= github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8= github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls= github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604 h1:aXfUhVN/Ewfpbko2CCtL65cIiGgwStOo4lWH2b6gw2U= github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604/go.mod h1:O/QP1BCm0HHIzbKvgMzqb5sSyH88rzkFk84F4TfJjBU= -github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= -github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= +github.com/grafana/pyroscope-go/godeltaprof v0.1.9 h1:c1Us8i6eSmkW+Ez05d3co8kasnuOY813tbMN8i/a3Og= +github.com/grafana/pyroscope-go/godeltaprof v0.1.9/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= +github.com/grafana/pyroscope/api v1.2.1-0.20250415190842-3ff7247547ae h1:35W3Wjp9KWnSoV/DuymmyIj5aHE0CYlDQ5m2KeXUPAc= +github.com/grafana/pyroscope/api v1.2.1-0.20250415190842-3ff7247547ae/go.mod h1:6CJ1uXmLZ13ufpO9xE4pST+DyaBt0uszzrV0YnoaVLQ= github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248= github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk= github.com/grafana/sqlds/v4 v4.2.7 h1:sFQhsS7DBakNMdxa++yOfJ9BVvkZwFJ0B95o57K0/XA= github.com/grafana/sqlds/v4 v4.2.7/go.mod h1:BQRjUG8rOqrBI4NAaeoWrIMuoNgfi8bdhCJ+5cgEfLU= +github.com/grafana/tempo v1.5.1-0.20250529124718-87c2dc380cec h1:wnzJov9RhSHGaTYGzTygL4qq986fLen8xSqnQgaMd28= +github.com/grafana/tempo v1.5.1-0.20250529124718-87c2dc380cec/go.mod h1:j1IY7J2rUz7TcTjFVVx6HCpyTlYOJPtXuGRZ7sI+vSo= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o= @@ -806,6 +915,12 @@ github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVU github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 h1:U+kC2dOhMFQctRfhK0gRctKAPTloZdMU5ZJxaesJ/VM= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0= +github.com/hashicorp/go-secure-stdlib/plugincontainer v0.4.2 h1:gCNiM4T5xEc4IpT8vM50CIO+AtElr5kO9l2Rxbq+Sz8= +github.com/hashicorp/go-secure-stdlib/plugincontainer v0.4.2/go.mod h1:6ZM4ZdwClyAsiU2uDBmRHCvq0If/03BMbF9U+U7G5pA= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw= github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= @@ -823,7 +938,10 @@ github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iP github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQxvE= +github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= @@ -833,6 +951,8 @@ github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpT github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hashicorp/serf v0.10.2 h1:m5IORhuNSjaxeljg5DeQVDlQyVkhRIjJDimbkCa8aAc= github.com/hashicorp/serf v0.10.2/go.mod h1:T1CmSGfSeGfnfNy/w0odXQUR1rfECGd2Qdsp84DjOiY= +github.com/hashicorp/vault/api v1.16.0 h1:nbEYGJiAPGzT9U4oWgaaB0g+Rj8E59QuHKyA5LhwQN4= +github.com/hashicorp/vault/api v1.16.0/go.mod h1:KhuUhzOD8lDSk29AtzNjgAu2kxRA9jL9NAbkFlqvkBA= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -844,6 +964,12 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb v1.7.6/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= +github.com/influxdata/influxdb-client-go/v2 v2.13.0 h1:ioBbLmR5NMbAjP4UVA5r9b5xGjpABD7j65pI8kFphDM= +github.com/influxdata/influxdb-client-go/v2 v2.13.0/go.mod h1:k+spCbt9hcvqvUiz0sr5D8LolXHqAAOfPw9v/RIRHl4= +github.com/influxdata/influxql v1.4.0 h1:Lf62rbAF8KWQf+4Djqf4hVXgmQuGozUoSD6kNWjye44= +github.com/influxdata/influxql v1.4.0/go.mod h1:VqxAKyQz5p8GzgGsxWalCWYGxEqw6kvJo2IickMQiQk= +github.com/influxdata/line-protocol v0.0.0-20210922203350-b1ad95c89adf h1:7JTmneyiNEwVBOHSjoMxiWAqB992atOeepeFYegn5RU= +github.com/influxdata/line-protocol v0.0.0-20210922203350-b1ad95c89adf/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= @@ -856,8 +982,22 @@ github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk= github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jaegertracing/jaeger v1.67.0 h1:t0BiJZVW9D3Z16y3uHqKzV9bKFTusooTH1Kgr77xF2Q= +github.com/jaegertracing/jaeger v1.67.0/go.mod h1:tE/FEQfybCSdUbBgel51YaCSkc58O+Njih8oTl6j8vw= github.com/jaegertracing/jaeger-idl v0.5.0 h1:zFXR5NL3Utu7MhPg8ZorxtCBjHrL3ReM1VoB65FOFGE= github.com/jaegertracing/jaeger-idl v0.5.0/go.mod h1:ON90zFo9eoyXrt9F/KN8YeF3zxcnujaisMweFY/rg5k= +github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= +github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= +github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= +github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= +github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg= +github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo= +github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o= +github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= +github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8= +github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= +github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= +github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4= github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= github.com/jhump/gopoet v0.0.0-20190322174617-17282ff210b3/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= @@ -879,6 +1019,8 @@ github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbd github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531 h1:hgVxRoDDPtQE68PT4LFvNlPz2nBKd3OMlGKIQ69OmR4= +github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531/go.mod h1:fqTUQpVYBvhCNIsMXGl2GE9q6z94DIP6NtFKXCSTVbg= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -943,8 +1085,10 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/madflojo/testcerts v1.1.1 h1:YsSHWV79nMNZK0mJtwXjKoYHjJEbLPFefR8TxmmWupY= -github.com/madflojo/testcerts v1.1.1/go.mod h1:MW8sh39gLnkKh4K0Nc55AyHEDl9l/FBLDUsQhpmkuo0= +github.com/m3db/prometheus_remote_client_golang v0.4.4 h1:DsAIjVKoCp7Ym35tAOFL1OuMLIdIikAEHeNPHY+yyM8= +github.com/m3db/prometheus_remote_client_golang v0.4.4/go.mod h1:wHfVbA3eAK6dQvKjCkHhusWYegCk3bDGkA15zymSHdc= +github.com/madflojo/testcerts v1.4.0 h1:I09gN0C1ly9IgeVNcAqKk8RAKIJTe3QnFrrPBDyvzN4= +github.com/madflojo/testcerts v1.4.0/go.mod h1:MW8sh39gLnkKh4K0Nc55AyHEDl9l/FBLDUsQhpmkuo0= github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg= github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -953,6 +1097,8 @@ github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4 github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/mattbaird/jsonpatch v0.0.0-20240118010651-0ba75a80ca38 h1:hQWBtNqRYrI7CWIaUSXXtNKR90KzcUA5uiuxFVWw7sU= github.com/mattbaird/jsonpatch v0.0.0-20240118010651-0ba75a80ca38/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0= +github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU= +github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To= github.com/mattetti/filebuffer v1.0.1 h1:gG7pyfnSIZCxdoKq+cPa8T0hhYtD9NxCdI4D7PTjRLM= 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= @@ -963,6 +1109,8 @@ github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-ieproxy v0.0.12 h1:OZkUFJC3ESNZPQ+6LzC3VJIFSnreeFLQyqvBWtvfL2M= +github.com/mattn/go-ieproxy v0.0.12/go.mod h1:Vn+N61199DAnVeTgaF8eoB9PvLO8P3OBnG95ENh7B7c= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= @@ -976,17 +1124,21 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T github.com/mattn/go-runewidth v0.0.16/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.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= -github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs= +github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= 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/maypok86/otter v1.2.4 h1:HhW1Pq6VdJkmWwcZZq19BlEQkHtI8xgsQzBVXJU0nfc= +github.com/maypok86/otter v1.2.4/go.mod h1:mKLfoI7v1HOmQMwFgX4QkRk23mX6ge3RDvjdHOWG4R4= github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ= github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE= github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY= github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= +github.com/microsoft/go-mssqldb v1.9.2 h1:nY8TmFMQOHpm2qVWo6y4I2mAmVdZqlGiMGAYt64Ibbs= +github.com/microsoft/go-mssqldb v1.9.2/go.mod h1:GBbW9ASTiDC+mpgWDGKdm3FnFLTUsLYN3iFL90lQ+PA= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= @@ -1023,8 +1175,10 @@ github.com/mithrandie/ternary v1.1.1 h1:k/joD6UGVYxHixYmSR8EGgDFNONBMqyD373xT4QR github.com/mithrandie/ternary v1.1.1/go.mod h1:0D9Ba3+09K2TdSZO7/bFCC0GjSXetCvYuYq0u8FY/1g= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/mocktools/go-smtp-mock/v2 v2.3.1 h1:wq75NDSsOy5oHo/gEQQT0fRRaYKRqr1IdkjhIPXxagM= -github.com/mocktools/go-smtp-mock/v2 v2.3.1/go.mod h1:h9AOf/IXLSU2m/1u4zsjtOM/WddPwdOUBz56dV9f81M= +github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= +github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +github.com/mocktools/go-smtp-mock/v2 v2.5.1 h1:QcMJMChSgG1olVj4o6xxQFdrWzRjYNrcq660HAjd0wA= +github.com/mocktools/go-smtp-mock/v2 v2.5.1/go.mod h1:Rr8M2njlxx//l5INl2+uESnsL2lDsL24teEykCrGfmE= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -1043,6 +1197,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= github.com/natefinch/wrap v0.2.0 h1:IXzc/pw5KqxJv55gV0lSOcKHYuEZPGbQrOOXr/bamRk= github.com/natefinch/wrap v0.2.0/go.mod h1:6gMHlAl12DwYEfKP3TkuykYUfLSEAvHw67itm4/KAS8= @@ -1051,8 +1207,8 @@ github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJm github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nikunjy/rules v1.5.0 h1:KJDSLOsFhwt7kcXUyZqwkgrQg5YoUwj+TVu6ItCQShw= github.com/nikunjy/rules v1.5.0/go.mod h1:TlZtZdBChrkqi8Lr2AXocme8Z7EsbxtFdDoKeI6neBQ= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oapi-codegen/runtime v1.0.0 h1:P4rqFX5fMFWqRzY9M/3YF9+aPSPPB06IzP2P7oOxrWo= +github.com/oapi-codegen/runtime v1.0.0/go.mod h1:LmCUMQuPB4M/nLXilQXhHw+BLZdDb18B34OO356yJ/A= github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= @@ -1066,20 +1222,25 @@ github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNs github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= 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 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= -github.com/open-feature/go-sdk v1.14.1 h1:jcxjCIG5Up3XkgYwWN5Y/WWfc6XobOhqrIwjyDBsoQo= -github.com/open-feature/go-sdk v1.14.1/go.mod h1:t337k0VB/t/YxJ9S0prT30ISUHwYmUd/jhUZgFcOvGg= -github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.3 h1:6jpO63NCEZv4xunJj+aNlDuFVuRkVBPMcIuxvFPYRWQ= -github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.3/go.mod h1:dPUHjAIFzg+ci/wt6XxlNiiMkOh5Yw4SGyeRY0AFT0g= -github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5 h1:ZdqlGnNwhWf3luhBQlIpbglvcCzjkcuEgOEhYhr5Emc= -github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5/go.mod h1:jrD4UG3ZCzuwImKHlyuIN2iWeYjlOX5+zJ/sX45efuE= +github.com/open-feature/go-sdk v1.16.0 h1:5NCHYv5slvNBIZhYXAzAufo0OI59OACZ5tczVqSE+Tg= +github.com/open-feature/go-sdk v1.16.0/go.mod h1:EIF40QcoYT1VbQkMPy2ZJH4kvZeY+qGUXAorzSWgKSo= +github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.6 h1:megzzlQGjsRVWDX8oJnLaa5eEcsAHekiL4Uvl3jSAcY= +github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.6/go.mod h1:K1gDKvt76CGFLSUMHUydd5ba2V5Cv69gQZsdbnXhAm8= +github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.6 h1:WinefYxeVx5rV0uQmuWbxQf8iACu/JiRubo5w0saToc= +github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.6/go.mod h1:Dwcaoma6lZVqYwyfVlY7eB6RXbG+Ju3b9cnpTlUN+Hc= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.124.1 h1:NrjsoVPxI6lmV8jPImDcMeqYh+97Y71f/HB5Sfpfe3I= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.124.1/go.mod h1:AFMryJmht7dZxcAwc2sx/r4gxbriElWw49ugxKp2mcA= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/core/xidutils v0.124.1 h1:E1e96GTHmiAfIfeYfA5ZVnOxud3+vbisGp0gE1tfd4s= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/core/xidutils v0.124.1/go.mod h1:MOhFATtYSLad9nKunjh6uGf8nQUcWje2LPlhD2uu3do= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger v0.124.1 h1:9c6L4xlAMqhOg5y54Bc2B5t0i49yz7v2I6I8RY4Z0/o= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger v0.124.1/go.mod h1:6f0N58o0cOHC0ApSM/qrooVmQza1eQ7L53PDE91uO1Q= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -1092,12 +1253,16 @@ github.com/openfga/language/pkg/go v0.2.0-beta.2.0.20250428093642-7aeebe78bbfe h github.com/openfga/language/pkg/go v0.2.0-beta.2.0.20250428093642-7aeebe78bbfe/go.mod h1:5Z0pbTT7Jz/oQFLfadb+C5t5NwHrduAO7j7L07Ec1GM= github.com/openfga/openfga v1.10.0 h1:Ieq4fjJeT3KrxRiekgCnp9VCoXXnBvYITcTR35SPlYY= github.com/openfga/openfga v1.10.0/go.mod h1:6/m4GTwQsqECsGYQVD3t5sCX97rh3smnmxbMa3YAtJk= +github.com/opentracing-contrib/go-grpc v0.1.1 h1:Ws7IN1zyiL1DFqKQPhRXuKe5pLYzMfdxnC1qtajE2PE= +github.com/opentracing-contrib/go-grpc v0.1.1/go.mod h1:Nu6sz+4zzgxXu8rvKfnwjBEmHsuhTigxRwV2RhELrS8= github.com/opentracing-contrib/go-stdlib v1.0.0 h1:TBS7YuVotp8myLon4Pv7BtCBzOTo1DeZCld0Z63mW2w= github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg= +github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1111,9 +1276,13 @@ github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0 github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/phpdave11/gofpdi v1.0.14 h1:jlcDIJ6ObCh3X9nANGEK6RY5wbUKHJ5unBjrzG4i89A= +github.com/phpdave11/gofpdi v1.0.14/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs= +github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1180,14 +1349,20 @@ github.com/protocolbuffers/txtpbfmt v0.0.0-20241112170944-20d2c9ebc01d h1:HWfigq github.com/protocolbuffers/txtpbfmt v0.0.0-20241112170944-20d2c9ebc01d/go.mod h1:jgxiZysxFPM+iWKwQwPR+y+Jvo54ARd4EisXxKYpB5c= github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU= github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU= +github.com/puzpuzpuz/xsync/v4 v4.2.0 h1:dlxm77dZj2c3rxq0/XNvvUKISAmovoXF4a4qM6Wvkr0= +github.com/puzpuzpuz/xsync/v4 v4.2.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= -github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/redis/go-redis/v9 v9.14.0 h1:u4tNCjXOyzfgeLN+vAZaW1xUooqWDqVEsZN0U01jfAE= +github.com/redis/go-redis/v9 v9.14.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/redis/rueidis v1.0.64 h1:XqgbueDuNV3qFdVdQwAHJl1uNt90zUuAJuzqjH4cw6Y= +github.com/redis/rueidis v1.0.64/go.mod h1:Lkhr2QTgcoYBhxARU7kJRO8SyVlgUuEkcJO1Y8MCluA= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 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= @@ -1195,19 +1370,33 @@ github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0t github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/russellhaering/goxmldsig v1.4.0 h1:8UcDh/xGyQiyrW+Fq5t8f+l2DLB1+zlhYzkPUJ7Qhys= +github.com/russellhaering/goxmldsig v1.4.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/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.5.3 h1:OjMgICtcSFuNvQCdwqMCv9Tg7lEOXGwm1J5RPQccx6w= +github.com/segmentio/encoding v0.5.3/go.mod h1:HS1ZKa3kSN32ZHVZ7ZLPLXWvOVIiZtyJnO1gPH1sKt0= +github.com/sercand/kuberesolver/v6 v6.0.0 h1:ScvS2Ga9snVkpOahln/BCLySr3/iBAHJf25u66DweZ0= +github.com/sercand/kuberesolver/v6 v6.0.0/go.mod h1:Dxkqms3OJadP5zirIBPLi9FV8Qpys3T3w40XPEcVsu0= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE= github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas= +github.com/shadowspore/fossil-delta v0.0.0-20241213113458-1d797d70cbe3 h1:/4/IJi5iyTdh6mqOUaASW148HQpujYiHl0Wl78dSOSc= +github.com/shadowspore/fossil-delta v0.0.0-20241213113458-1d797d70cbe3/go.mod h1:aJIMhRsunltJR926EB2MUg8qHemFQDreSB33pyto2Ps= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= @@ -1230,6 +1419,8 @@ github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sS github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg= +github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -1257,6 +1448,8 @@ github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE= github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g= +github.com/spyzhov/ajson v0.9.6 h1:iJRDaLa+GjhCDAt1yFtU/LKMtLtsNVKkxqlpvrHHlpQ= +github.com/spyzhov/ajson v0.9.6/go.mod h1:a6oSw0MMb7Z5aD2tPoPO+jq11ETKgXUr2XktHdT8Wt8= github.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs= github.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -1296,6 +1489,8 @@ github.com/tjhop/slog-gokit v0.1.3/go.mod h1:Bbu5v2748qpAWH7k6gse/kw3076IJf6owJm 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/ua-parser/uap-go v0.0.0-20250213224047-9c035f085b90 h1:rB0J+hLNltG1Qv+UF+MkdFz89XMps5BOAFJN4xWjc+s= +github.com/ua-parser/uap-go v0.0.0-20250213224047-9c035f085b90/go.mod h1:BUbeWZiieNxAuuADTBNb3/aeje6on3DhU3rpWsQSB1E= 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= @@ -1313,6 +1508,12 @@ github.com/unknwon/log v0.0.0-20200308114134-929b1006e34a/go.mod h1:1xEUf2abjfP9 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.17 h1:SYzXoiPfQjHBbkYxbew5prZHS1TOLT3ierW8SYLqtVQ= github.com/urfave/cli v1.22.17/go.mod h1:b0ht0aqgH/6pBYzzxURyrM4xXNgsoT/n2ZzwQiEhNVo= +github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU= +github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4= +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/wk8/go-ordered-map v1.0.0 h1:BV7z+2PaK8LTSd/mWgY12HyMAo5CEgkHqbkVq2thqr8= +github.com/wk8/go-ordered-map v1.0.0/go.mod h1:9ZIbRunKbuvfPKyBP1SIKLcXNlv74YCOZ3t3VTS6gRk= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/woodsbury/decimal128 v1.3.0 h1:8pffMNWIlC0O5vbyHWFZAt5yWvWcrHA+3ovIIjVWss0= @@ -1324,12 +1525,24 @@ github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhe github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chqDkyE9Z4N61UnQd+KOfgp5Iu53llk= github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= +github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/zclconf/go-cty v1.16.3 h1:osr++gw2T61A8KVYHoQiFbFd1Lh3JOCXc/jFLJXKTxk= +github.com/zclconf/go-cty v1.16.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM= @@ -1370,6 +1583,12 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/collector/featuregate v1.43.0 h1:Aq8UR5qv1zNlbbkTyqv8kLJtnoQMq/sG1/jS9o1cCJI= +go.opentelemetry.io/collector/featuregate v1.43.0/go.mod h1:d0tiRzVYrytB6LkcYgz2ESFTv7OktRPQe0QEQcPt1L4= +go.opentelemetry.io/collector/pdata v1.43.0 h1:zVkj2hcjiMLwX+QDDNwb7iTh3LBjNXKv2qPSgj1Rzb4= +go.opentelemetry.io/collector/pdata v1.43.0/go.mod h1:KsJzdDG9e5BaHlmYr0sqdSEKeEiSfKzoF+rdWU7J//w= +go.opentelemetry.io/collector/semconv v0.124.0 h1:YTdo3UFwNyDQCh9DiSm2rbzAgBuwn/9dNZ0rv454goA= +go.opentelemetry.io/collector/semconv v0.124.0/go.mod h1:te6VQ4zZJO5Lp8dM2XIhDxDiL45mwX0YAQQWRQ0Qr9U= go.opentelemetry.io/contrib/bridges/prometheus v0.61.0 h1:RyrtJzu5MAmIcbRrwg75b+w3RlZCP0vJByDVzcpAe3M= go.opentelemetry.io/contrib/bridges/prometheus v0.61.0/go.mod h1:tirr4p9NXbzjlbruiRGp53IzlYrDk5CO2fdHj0sSSaY= go.opentelemetry.io/contrib/detectors/gcp v1.36.0 h1:F7q2tNlCaHY9nMKHR6XH9/qkp8FktLnIcy6jJNyOCQw= @@ -1378,14 +1597,14 @@ go.opentelemetry.io/contrib/exporters/autoexport v0.61.0 h1:XfzKtKSrbtYk9TNCF8dk go.opentelemetry.io/contrib/exporters/autoexport v0.61.0/go.mod h1:N6otC+qXTD5bAnbK2O1f/1SXq3cX+3KYSWrkBUqG0cw= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.62.0 h1:wCeciVlAfb5DC8MQl/DlmAv/FVPNpQgFvI/71+hatuc= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.62.0/go.mod h1:WfEApdZDMlLUAev/0QQpr8EJ/z0VWDKYZ5tF5RH5T1U= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.63.0 h1:2pn7OzMewmYRiNtv1doZnLo3gONcnMHlFnmOR8Vgt+8= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.63.0/go.mod h1:rjbQTDEPQymPE0YnRQp9/NuPwwtL0sesz/fnqRW/v84= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= -go.opentelemetry.io/contrib/propagators/jaeger v1.37.0 h1:pW+qDVo0jB0rLsNeaP85xLuz20cvsECUcN7TE+D8YTM= -go.opentelemetry.io/contrib/propagators/jaeger v1.37.0/go.mod h1:x7bd+t034hxLTve1hF9Yn9qQJlO/pP8H5pWIt7+gsFM= -go.opentelemetry.io/contrib/samplers/jaegerremote v0.31.0 h1:l8XCsDh7L6Z7PB+vlw1s4ufNab+ayT2RMNdvDE/UyPc= -go.opentelemetry.io/contrib/samplers/jaegerremote v0.31.0/go.mod h1:XAOSk4bqj5vtoiY08bexeiafzxdXeLlxKFnwscvn8Fc= +go.opentelemetry.io/contrib/propagators/jaeger v1.38.0 h1:nXGeLvT1QtCAhkASkP/ksjkTKZALIaQBIW+JSIw1KIc= +go.opentelemetry.io/contrib/propagators/jaeger v1.38.0/go.mod h1:oMvOXk78ZR3KEuPMBgp/ThAMDy9ku/eyUVztr+3G6Wo= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.32.0 h1:oPW/SRFyHgIgxrvNhSBzqvZER2N5kRlci3/rGTOuyWo= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.32.0/go.mod h1:B9Oka5QVD0bnmZNO6gBbBta6nohD/1Z+f9waH2oXyBs= go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= @@ -1452,8 +1671,12 @@ go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s= +go4.org/netipx v0.0.0-20230125063823-8449b0a6169f/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc= gocloud.dev v0.42.0 h1:qzG+9ItUL3RPB62/Amugws28n+4vGZXEoJEAMfjutzw= gocloud.dev v0.42.0/go.mod h1:zkaYAapZfQisXOA4bzhsbA4ckiStGQ3Psvs9/OQ5dPM= +gocloud.dev/secrets/hashivault v0.42.0 h1:kPWIIu1AP6ApHf7HwUrzGrwyRJEfTd46JNUNgnbpsFA= +gocloud.dev/secrets/hashivault v0.42.0/go.mod h1:LXprr1XLEAT7BVZ+Y66dJEHQMzDsowIExj5Ktr9HLvM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -1567,8 +1790,8 @@ golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1591,8 +1814,8 @@ golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1717,8 +1940,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 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= @@ -1977,8 +2200,8 @@ google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ5 google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1994,8 +2217,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= @@ -2023,7 +2246,6 @@ gopkg.in/src-d/go-errors.v1 v1.0.0 h1:cooGdZnCjYbeS1zb1s6pVAAimTdKceRrpn7aKOnNIf gopkg.in/src-d/go-errors.v1 v1.0.0/go.mod h1:q1cBlomlw2FnDBDNGlnh6X0jPihy+QxZfMMNxPCbdYg= gopkg.in/telebot.v3 v3.3.8 h1:uVDGjak9l824FN9YARWUHMsiNZnlohAVwUycw21k6t8= gopkg.in/telebot.v3 v3.3.8/go.mod h1:1mlbqcLTVSfK9dx7fdp+Nb5HZsy4LLPtpZTKmwhwtzM= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -2063,22 +2285,24 @@ k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kms v0.34.1 h1:iCFOvewDPzWM9fMTfyIPO+4MeuZ0tcZbugxLNSHFG4w= k8s.io/kms v0.34.1/go.mod h1:s1CFkLG7w9eaTYvctOxosx88fl4spqmixnNpys0JAtM= +k8s.io/kube-aggregator v0.34.1 h1:WNLV0dVNoFKmuyvdWLd92iDSyD/TSTjqwaPj0U9XAEU= +k8s.io/kube-aggregator v0.34.1/go.mod h1:RU8j+5ERfp0h+gIvWtxRPfsa5nK7rboDm8RST8BJfYQ= k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -modernc.org/cc/v4 v4.26.2 h1:991HMkLjJzYBIfha6ECZdjrIYz2/1ayr+FL8GN+CNzM= -modernc.org/cc/v4 v4.26.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= -modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU= -modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE= -modernc.org/fileutil v1.3.8 h1:qtzNm7ED75pd1C7WgAGcK4edm4fvhtBsEiI/0NQ54YM= -modernc.org/fileutil v1.3.8/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= +modernc.org/cc/v4 v4.26.5 h1:xM3bX7Mve6G8K8b+T11ReenJOT+BmVqQj0FY5T4+5Y4= +modernc.org/cc/v4 v4.26.5/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= +modernc.org/ccgo/v4 v4.28.1 h1:wPKYn5EC/mYTqBO373jKjvX2n+3+aK7+sICCv4Fjy1A= +modernc.org/ccgo/v4 v4.28.1/go.mod h1:uD+4RnfrVgE6ec9NGguUNdhqzNIeeomeXf6CL0GTE5Q= +modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA= +modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= -modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ= -modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8= +modernc.org/libc v1.66.10 h1:yZkb3YeLx4oynyR+iUsXsybsX4Ubx7MQlSYEw4yj59A= +modernc.org/libc v1.66.10/go.mod h1:8vGSEwvoUoltr4dlywvHqjtAqHBaw0j1jI7iFBTAr2I= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= @@ -2087,8 +2311,8 @@ modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= -modernc.org/sqlite v1.38.2 h1:Aclu7+tgjgcQVShZqim41Bbw9Cho0y/7WzYptXqkEek= -modernc.org/sqlite v1.38.2/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E= +modernc.org/sqlite v1.39.1 h1:H+/wGFzuSCIEVCvXYVHX5RQglwhMOvtHSv+VtidL2r4= +modernc.org/sqlite v1.39.1/go.mod h1:9fjQZ0mB1LLP0GYrp39oOJXx/I2sxEnZtzCmEQIKvGE= modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= diff --git a/apps/iam/kinds/v0alpha1/teambindingspec.cue b/apps/iam/kinds/v0alpha1/teambindingspec.cue index c20e592e458..0e16650d639 100644 --- a/apps/iam/kinds/v0alpha1/teambindingspec.cue +++ b/apps/iam/kinds/v0alpha1/teambindingspec.cue @@ -11,6 +11,8 @@ TeamBindingSpec: { // permission of the identity in the team permission: TeamPermission + + external: bool } TeamRef:{ diff --git a/apps/iam/local/Dockerfile b/apps/iam/local/Dockerfile index 28df71c2384..4777b0a466d 100644 --- a/apps/iam/local/Dockerfile +++ b/apps/iam/local/Dockerfile @@ -1,5 +1,5 @@ # Build stage -FROM golang:1.24.6-alpine AS builder +FROM golang:1.25.3-alpine AS builder # Set working directory WORKDIR /app diff --git a/apps/iam/pkg/apis/iam/v0alpha1/teambinding_spec_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_spec_gen.go index 13abd605168..87c976f7957 100644 --- a/apps/iam/pkg/apis/iam/v0alpha1/teambinding_spec_gen.go +++ b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_spec_gen.go @@ -38,6 +38,7 @@ type TeamBindingSpec struct { TeamRef TeamBindingTeamRef `json:"teamRef"` // permission of the identity in the team Permission TeamBindingTeamPermission `json:"permission"` + External bool `json:"external"` } // NewTeamBindingSpec creates a new TeamBindingSpec object. diff --git a/apps/iam/pkg/apis/iam/v0alpha1/zz_openapi_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/zz_openapi_gen.go index 2532b5df8cc..b0489baabb3 100644 --- a/apps/iam/pkg/apis/iam/v0alpha1/zz_openapi_gen.go +++ b/apps/iam/pkg/apis/iam/v0alpha1/zz_openapi_gen.go @@ -2123,8 +2123,15 @@ func schema_pkg_apis_iam_v0alpha1_TeamBindingSpec(ref common.ReferenceCallback) Format: "", }, }, + "external": { + SchemaProps: spec.SchemaProps{ + Default: false, + Type: []string{"boolean"}, + Format: "", + }, + }, }, - Required: []string{"subject", "teamRef", "permission"}, + Required: []string{"subject", "teamRef", "permission", "external"}, }, }, Dependencies: []string{ diff --git a/apps/iam/pkg/apis/iam_manifest.go b/apps/iam/pkg/apis/iam_manifest.go index 24aba9a1fd8..644ad2ea2d1 100644 --- a/apps/iam/pkg/apis/iam_manifest.go +++ b/apps/iam/pkg/apis/iam_manifest.go @@ -13,6 +13,7 @@ import ( "github.com/grafana/grafana-app-sdk/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kube-openapi/pkg/spec3" + "k8s.io/kube-openapi/pkg/validation/spec" v0alpha1 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1" ) @@ -99,6 +100,7 @@ var appManifestData = app.ManifestData{ Routes: app.ManifestVersionRoutes{ Namespaced: map[string]spec3.PathProps{}, Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{}, }, }, }, diff --git a/apps/investigations/go.mod b/apps/investigations/go.mod index 1652941eba8..203dd85f8b2 100644 --- a/apps/investigations/go.mod +++ b/apps/investigations/go.mod @@ -1,9 +1,9 @@ module github.com/grafana/grafana/apps/investigations -go 1.24.6 +go 1.25.3 require ( - github.com/grafana/grafana-app-sdk v0.46.0 + github.com/grafana/grafana-app-sdk v0.47.0 k8s.io/apimachinery v0.34.1 k8s.io/klog/v2 v2.130.1 k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b @@ -30,7 +30,7 @@ require ( github.com/google/go-cmp v0.7.0 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/grafana/grafana-app-sdk/logging v0.45.0 // indirect + github.com/grafana/grafana-app-sdk/logging v0.46.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -67,18 +67,18 @@ require ( go.opentelemetry.io/proto/otlp v1.7.1 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.13.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect - google.golang.org/grpc v1.75.1 // indirect - google.golang.org/protobuf v1.36.9 // indirect + google.golang.org/grpc v1.76.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.34.1 // indirect diff --git a/apps/investigations/go.sum b/apps/investigations/go.sum index dadd72070fd..eb6cf0ee83d 100644 --- a/apps/investigations/go.sum +++ b/apps/investigations/go.sum @@ -46,10 +46,10 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grafana/grafana-app-sdk v0.46.0 h1:gvzQvCQgZJ/73BfAcbDt/6TAMhnVikVPxZt/UwDl+oc= -github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= -github.com/grafana/grafana-app-sdk/logging v0.45.0 h1:0SH6nYZpiLBZRwUq4J6+1vo8xuHKJjnO95/2pGOoA8w= -github.com/grafana/grafana-app-sdk/logging v0.45.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= +github.com/grafana/grafana-app-sdk/logging v0.46.0 h1:JhQ+ZK5orcmM+dZ3YZdT9uCizJEFU2I6JBNUSFWvCC8= +github.com/grafana/grafana-app-sdk/logging v0.46.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -161,10 +161,10 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -179,8 +179,8 @@ golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -201,10 +201,10 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 h1: google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090/go.mod h1:U8EXRNSd8sUYyDfs/It7KVWodQr+Hf9xtxyxWudSwEw= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/apps/investigations/pkg/apis/investigations_manifest.go b/apps/investigations/pkg/apis/investigations_manifest.go index 04c52dbd9ac..2d3e9c7bdd3 100644 --- a/apps/investigations/pkg/apis/investigations_manifest.go +++ b/apps/investigations/pkg/apis/investigations_manifest.go @@ -14,6 +14,7 @@ import ( "github.com/grafana/grafana-app-sdk/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kube-openapi/pkg/spec3" + "k8s.io/kube-openapi/pkg/validation/spec" v0alpha1 "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1" ) @@ -55,6 +56,7 @@ var appManifestData = app.ManifestData{ Routes: app.ManifestVersionRoutes{ Namespaced: map[string]spec3.PathProps{}, Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{}, }, }, }, diff --git a/apps/logsdrilldown/Makefile b/apps/logsdrilldown/Makefile new file mode 100644 index 00000000000..230bfd4149a --- /dev/null +++ b/apps/logsdrilldown/Makefile @@ -0,0 +1,9 @@ +include ../sdk.mk + +.PHONY: generate # Run Grafana App SDK code generation +generate: install-app-sdk update-app-sdk + @$(APP_SDK_BIN) generate \ + --source=./kinds/ \ + --gogenpath=./pkg/apis \ + --grouping=group \ + --defencoding=none \ No newline at end of file diff --git a/apps/logsdrilldown/go.mod b/apps/logsdrilldown/go.mod new file mode 100644 index 00000000000..e6dcedddf17 --- /dev/null +++ b/apps/logsdrilldown/go.mod @@ -0,0 +1,94 @@ +module github.com/grafana/grafana/apps/logsdrilldown + +go 1.24.0 + +toolchain go1.24.6 + +require ( + github.com/grafana/grafana-app-sdk v0.47.0 + github.com/grafana/grafana-app-sdk/logging v0.46.0 + k8s.io/apimachinery v0.34.1 + k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/go-restful/v3 v3.13.0 // indirect + github.com/evanphx/json-patch v5.9.11+incompatible // indirect + github.com/fxamacker/cbor/v2 v2.9.0 // indirect + github.com/getkin/kin-openapi v0.133.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-test/deep v1.1.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/gnostic-models v0.7.0 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mailru/easyjson v0.9.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect + github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect + github.com/onsi/ginkgo/v2 v2.22.2 // indirect + github.com/onsi/gomega v1.36.2 // indirect + github.com/perimeterx/marshmallow v1.1.5 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.66.1 // indirect + github.com/prometheus/procfs v0.16.1 // indirect + github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect + github.com/spf13/pflag v1.0.10 // indirect + github.com/woodsbury/decimal128 v1.3.0 // indirect + github.com/x448/float16 v0.8.4 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel v1.38.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 // indirect + go.opentelemetry.io/otel/metric v1.38.0 // indirect + go.opentelemetry.io/otel/sdk v1.38.0 // indirect + go.opentelemetry.io/otel/trace v1.38.0 // indirect + go.opentelemetry.io/proto/otlp v1.7.1 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/term v0.35.0 // indirect + golang.org/x/text v0.30.0 // indirect + golang.org/x/time v0.13.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect + google.golang.org/grpc v1.76.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.34.1 // indirect + k8s.io/apiextensions-apiserver v0.34.1 // indirect + k8s.io/client-go v0.34.1 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect + sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect +) diff --git a/apps/logsdrilldown/go.sum b/apps/logsdrilldown/go.sum new file mode 100644 index 00000000000..eb6cf0ee83d --- /dev/null +++ b/apps/logsdrilldown/go.sum @@ -0,0 +1,238 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous= +github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= +github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= +github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= +github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/getkin/kin-openapi v0.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ= +github.com/getkin/kin-openapi v0.133.0/go.mod h1:boAciF6cXk5FhPqe/NQeBTeenbjqU4LhWBf09ILVvWE= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= +github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= +github.com/grafana/grafana-app-sdk/logging v0.46.0 h1:JhQ+ZK5orcmM+dZ3YZdT9uCizJEFU2I6JBNUSFWvCC8= +github.com/grafana/grafana-app-sdk/logging v0.46.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= +github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= +github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= +github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= +github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= +github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU= +github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/woodsbury/decimal128 v1.3.0 h1:8pffMNWIlC0O5vbyHWFZAt5yWvWcrHA+3ovIIjVWss0= +github.com/woodsbury/decimal128 v1.3.0/go.mod h1:C5UTmyTjW3JftjUFzOVhC20BEQa2a4ZKOB5I6Zjb+ds= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 h1:lwI4Dc5leUqENgGuQImwLo4WnuXFPetmPpkLi2IrX54= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0/go.mod h1:Kz/oCE7z5wuyhPxsXDuaPteSWqjSBD5YaSdbxZYGbGk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= +go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= +golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0= +gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 h1:d8Nakh1G+ur7+P3GcMjpRDEkoLUcLW2iU92XVqR+XMQ= +google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090/go.mod h1:U8EXRNSd8sUYyDfs/It7KVWodQr+Hf9xtxyxWudSwEw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM= +k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk= +k8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJbII2CI= +k8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc= +k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4= +k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= +k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY= +k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= +k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/apps/logsdrilldown/kinds/cue.mod/module.cue b/apps/logsdrilldown/kinds/cue.mod/module.cue new file mode 100644 index 00000000000..641554da67c --- /dev/null +++ b/apps/logsdrilldown/kinds/cue.mod/module.cue @@ -0,0 +1,2 @@ +module: "github.com/grafana/grafana/apps/logsdrilldown/kinds" +language: version: "v0.8.2" diff --git a/apps/logsdrilldown/kinds/logsdrilldown.cue b/apps/logsdrilldown/kinds/logsdrilldown.cue new file mode 100644 index 00000000000..51f642b8a1e --- /dev/null +++ b/apps/logsdrilldown/kinds/logsdrilldown.cue @@ -0,0 +1,10 @@ +package kinds + +logsdrilldownv0alpha1: { + kind: "LogsDrilldown" // note: must be uppercase + schema: { + spec: { + defaultFields: [...string] | *[] + } + } +} diff --git a/apps/logsdrilldown/kinds/manifest.cue b/apps/logsdrilldown/kinds/manifest.cue new file mode 100644 index 00000000000..8decd54666b --- /dev/null +++ b/apps/logsdrilldown/kinds/manifest.cue @@ -0,0 +1,67 @@ +package kinds + +manifest: { + // appName is the unique name of your app. It is used to reference the app from other config objects, + // and to generate the group used by your app in the app platform API. + appName: "logsdrilldown" + // groupOverride can be used to specify a non-appName-based API group. + // By default, an app's API group is LOWER(REPLACE(appName, '-', '')).ext.grafana.com, + // but there are cases where this needs to be changed. + // Keep in mind that changing this after an app is deployed can cause problems with clients and/or kind data. + groupOverride: "logsdrilldown.grafana.app" + + // versions is a map of versions supported by your app. Version names should follow the format "v" or + // "v(alpha|beta)". Each version contains the kinds your app manages for that version. + // If your app needs access to kinds managed by another app, use permissions.accessKinds to allow your app access. + versions: { + "v1alpha1": v1alpha1 + } + // extraPermissions contains any additional permissions your app may require to function. + // Your app will always have all permissions for each kind it manages (the items defined in 'kinds'). + extraPermissions: { + // If your app needs access to additional kinds supplied by other apps, you can list them here + accessKinds: [ + // Here is an example for your app accessing the playlist kind for reads and watch + // { + // group: "playlist.grafana.app" + // resource: "playlists" + // actions: ["get","list","watch"] + // } + ] + } +} + +// v1alpha1 is the v1alpha1 version of the app's API. +// It includes kinds which the v1alpha1 API serves, and (future) custom routes served globally from the v1alpha1 version. +v1alpha1: { + // kinds is the list of kinds served by this version + kinds: [logsdrilldownv0alpha1] + // [OPTIONAL] + // served indicates whether this particular version is served by the API server. + // served should be set to false before a version is removed from the manifest entirely. + // served defaults to true if not present. + served: true + // [OPTIONAL] + // Codegen is a trait that tells the grafana-app-sdk, or other code generation tooling, how to process this kind. + // If not present, default values within the codegen trait are used. + // If you wish to specify codegen per-version, put this section in the version's object + // (for example, v1alpha1) instead. + codegen: { + // [OPTIONAL] + // ts contains TypeScript code generation properties for the kind + ts: { + // [OPTIONAL] + // enabled indicates whether the CLI should generate front-end TypeScript code for the kind. + // Defaults to true if not present. + enabled: true + } + // [OPTIONAL] + // go contains go code generation properties for the kind + go: { + // [OPTIONAL] + // enabled indicates whether the CLI should generate back-end go code for the kind. + // Defaults to true if not present. + enabled: true + } + } +} \ No newline at end of file diff --git a/apps/logsdrilldown/pkg/apis/app/app.go b/apps/logsdrilldown/pkg/apis/app/app.go new file mode 100644 index 00000000000..8ae329eac69 --- /dev/null +++ b/apps/logsdrilldown/pkg/apis/app/app.go @@ -0,0 +1,55 @@ +package app + +import ( + "context" + + "github.com/grafana/grafana-app-sdk/app" + "github.com/grafana/grafana-app-sdk/logging" + "github.com/grafana/grafana-app-sdk/operator" + "github.com/grafana/grafana-app-sdk/resource" + "github.com/grafana/grafana-app-sdk/simple" + "k8s.io/apimachinery/pkg/runtime/schema" + + logsdrilldownv1alpha1 "github.com/grafana/grafana/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1" +) + +func New(cfg app.Config) (app.App, error) { + simpleConfig := simple.AppConfig{ + Name: "logsdrilldown", + KubeConfig: cfg.KubeConfig, + InformerConfig: simple.AppInformerConfig{ + InformerOptions: operator.InformerOptions{ + ErrorHandler: func(ctx context.Context, err error) { + logging.FromContext(ctx).Error("Informer processing error", "error", err) + }, + }, + }, + ManagedKinds: []simple.AppManagedKind{ + { + Kind: logsdrilldownv1alpha1.LogsDrilldownKind(), + }, + }, + } + + a, err := simple.NewApp(simpleConfig) + if err != nil { + return nil, err + } + + err = a.ValidateManifest(cfg.ManifestData) + if err != nil { + return nil, err + } + + return a, nil +} + +func GetKinds() map[schema.GroupVersion][]resource.Kind { + gv := schema.GroupVersion{ + Group: logsdrilldownv1alpha1.LogsDrilldownKind().Group(), + Version: logsdrilldownv1alpha1.LogsDrilldownKind().Version(), + } + return map[schema.GroupVersion][]resource.Kind{ + gv: {logsdrilldownv1alpha1.LogsDrilldownKind()}, + } +} diff --git a/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/constants.go b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/constants.go new file mode 100644 index 00000000000..082bec7c874 --- /dev/null +++ b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/constants.go @@ -0,0 +1,18 @@ +package v1alpha1 + +import "k8s.io/apimachinery/pkg/runtime/schema" + +const ( + // APIGroup is the API group used by all kinds in this package + APIGroup = "logsdrilldown.grafana.app" + // APIVersion is the API version used by all kinds in this package + APIVersion = "v1alpha1" +) + +var ( + // GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package + GroupVersion = schema.GroupVersion{ + Group: APIGroup, + Version: APIVersion, + } +) diff --git a/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_client_gen.go b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_client_gen.go new file mode 100644 index 00000000000..0447f252b4c --- /dev/null +++ b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_client_gen.go @@ -0,0 +1,99 @@ +package v1alpha1 + +import ( + "context" + + "github.com/grafana/grafana-app-sdk/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type LogsDrilldownClient struct { + client *resource.TypedClient[*LogsDrilldown, *LogsDrilldownList] +} + +func NewLogsDrilldownClient(client resource.Client) *LogsDrilldownClient { + return &LogsDrilldownClient{ + client: resource.NewTypedClient[*LogsDrilldown, *LogsDrilldownList](client, LogsDrilldownKind()), + } +} + +func NewLogsDrilldownClientFromGenerator(generator resource.ClientGenerator) (*LogsDrilldownClient, error) { + c, err := generator.ClientFor(LogsDrilldownKind()) + if err != nil { + return nil, err + } + return NewLogsDrilldownClient(c), nil +} + +func (c *LogsDrilldownClient) Get(ctx context.Context, identifier resource.Identifier) (*LogsDrilldown, error) { + return c.client.Get(ctx, identifier) +} + +func (c *LogsDrilldownClient) List(ctx context.Context, namespace string, opts resource.ListOptions) (*LogsDrilldownList, error) { + return c.client.List(ctx, namespace, opts) +} + +func (c *LogsDrilldownClient) ListAll(ctx context.Context, namespace string, opts resource.ListOptions) (*LogsDrilldownList, error) { + resp, err := c.client.List(ctx, namespace, resource.ListOptions{ + ResourceVersion: opts.ResourceVersion, + Limit: opts.Limit, + LabelFilters: opts.LabelFilters, + FieldSelectors: opts.FieldSelectors, + }) + if err != nil { + return nil, err + } + for resp.GetContinue() != "" { + page, err := c.client.List(ctx, namespace, resource.ListOptions{ + Continue: resp.GetContinue(), + ResourceVersion: opts.ResourceVersion, + Limit: opts.Limit, + LabelFilters: opts.LabelFilters, + FieldSelectors: opts.FieldSelectors, + }) + if err != nil { + return nil, err + } + resp.SetContinue(page.GetContinue()) + resp.SetResourceVersion(page.GetResourceVersion()) + resp.SetItems(append(resp.GetItems(), page.GetItems()...)) + } + return resp, nil +} + +func (c *LogsDrilldownClient) Create(ctx context.Context, obj *LogsDrilldown, opts resource.CreateOptions) (*LogsDrilldown, error) { + // Make sure apiVersion and kind are set + obj.APIVersion = GroupVersion.Identifier() + obj.Kind = LogsDrilldownKind().Kind() + return c.client.Create(ctx, obj, opts) +} + +func (c *LogsDrilldownClient) Update(ctx context.Context, obj *LogsDrilldown, opts resource.UpdateOptions) (*LogsDrilldown, error) { + return c.client.Update(ctx, obj, opts) +} + +func (c *LogsDrilldownClient) Patch(ctx context.Context, identifier resource.Identifier, req resource.PatchRequest, opts resource.PatchOptions) (*LogsDrilldown, error) { + return c.client.Patch(ctx, identifier, req, opts) +} + +func (c *LogsDrilldownClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus LogsDrilldownStatus, opts resource.UpdateOptions) (*LogsDrilldown, error) { + return c.client.Update(ctx, &LogsDrilldown{ + TypeMeta: metav1.TypeMeta{ + Kind: LogsDrilldownKind().Kind(), + APIVersion: GroupVersion.Identifier(), + }, + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: opts.ResourceVersion, + Namespace: identifier.Namespace, + Name: identifier.Name, + }, + Status: newStatus, + }, resource.UpdateOptions{ + Subresource: "status", + ResourceVersion: opts.ResourceVersion, + }) +} + +func (c *LogsDrilldownClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error { + return c.client.Delete(ctx, identifier, opts) +} diff --git a/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_codec_gen.go b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_codec_gen.go new file mode 100644 index 00000000000..54f04db8526 --- /dev/null +++ b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_codec_gen.go @@ -0,0 +1,28 @@ +// +// Code generated by grafana-app-sdk. DO NOT EDIT. +// + +package v1alpha1 + +import ( + "encoding/json" + "io" + + "github.com/grafana/grafana-app-sdk/resource" +) + +// LogsDrilldownJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding +type LogsDrilldownJSONCodec struct{} + +// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into` +func (*LogsDrilldownJSONCodec) Read(reader io.Reader, into resource.Object) error { + return json.NewDecoder(reader).Decode(into) +} + +// Write writes JSON-encoded bytes into `writer` marshaled from `from` +func (*LogsDrilldownJSONCodec) Write(writer io.Writer, from resource.Object) error { + return json.NewEncoder(writer).Encode(from) +} + +// Interface compliance checks +var _ resource.Codec = &LogsDrilldownJSONCodec{} diff --git a/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_metadata_gen.go b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_metadata_gen.go new file mode 100644 index 00000000000..1a598f54c2d --- /dev/null +++ b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_metadata_gen.go @@ -0,0 +1,31 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +package v1alpha1 + +import ( + time "time" +) + +// metadata contains embedded CommonMetadata and can be extended with custom string fields +// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here +// without external reference as using the CommonMetadata reference breaks thema codegen. +type LogsDrilldownMetadata struct { + UpdateTimestamp time.Time `json:"updateTimestamp"` + CreatedBy string `json:"createdBy"` + Uid string `json:"uid"` + CreationTimestamp time.Time `json:"creationTimestamp"` + DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"` + Finalizers []string `json:"finalizers"` + ResourceVersion string `json:"resourceVersion"` + Generation int64 `json:"generation"` + UpdatedBy string `json:"updatedBy"` + Labels map[string]string `json:"labels"` +} + +// NewLogsDrilldownMetadata creates a new LogsDrilldownMetadata object. +func NewLogsDrilldownMetadata() *LogsDrilldownMetadata { + return &LogsDrilldownMetadata{ + Finalizers: []string{}, + Labels: map[string]string{}, + } +} diff --git a/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_object_gen.go b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_object_gen.go new file mode 100644 index 00000000000..4ede8bb4ee6 --- /dev/null +++ b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_object_gen.go @@ -0,0 +1,319 @@ +// +// Code generated by grafana-app-sdk. DO NOT EDIT. +// + +package v1alpha1 + +import ( + "fmt" + "github.com/grafana/grafana-app-sdk/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "time" +) + +// +k8s:openapi-gen=true +type LogsDrilldown struct { + metav1.TypeMeta `json:",inline" yaml:",inline"` + metav1.ObjectMeta `json:"metadata" yaml:"metadata"` + + // Spec is the spec of the LogsDrilldown + Spec LogsDrilldownSpec `json:"spec" yaml:"spec"` + + Status LogsDrilldownStatus `json:"status" yaml:"status"` +} + +func (o *LogsDrilldown) GetSpec() any { + return o.Spec +} + +func (o *LogsDrilldown) SetSpec(spec any) error { + cast, ok := spec.(LogsDrilldownSpec) + if !ok { + return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec) + } + o.Spec = cast + return nil +} + +func (o *LogsDrilldown) GetSubresources() map[string]any { + return map[string]any{ + "status": o.Status, + } +} + +func (o *LogsDrilldown) GetSubresource(name string) (any, bool) { + switch name { + case "status": + return o.Status, true + default: + return nil, false + } +} + +func (o *LogsDrilldown) SetSubresource(name string, value any) error { + switch name { + case "status": + cast, ok := value.(LogsDrilldownStatus) + if !ok { + return fmt.Errorf("cannot set status type %#v, not of type LogsDrilldownStatus", value) + } + o.Status = cast + return nil + default: + return fmt.Errorf("subresource '%s' does not exist", name) + } +} + +func (o *LogsDrilldown) GetStaticMetadata() resource.StaticMetadata { + gvk := o.GroupVersionKind() + return resource.StaticMetadata{ + Name: o.ObjectMeta.Name, + Namespace: o.ObjectMeta.Namespace, + Group: gvk.Group, + Version: gvk.Version, + Kind: gvk.Kind, + } +} + +func (o *LogsDrilldown) SetStaticMetadata(metadata resource.StaticMetadata) { + o.Name = metadata.Name + o.Namespace = metadata.Namespace + o.SetGroupVersionKind(schema.GroupVersionKind{ + Group: metadata.Group, + Version: metadata.Version, + Kind: metadata.Kind, + }) +} + +func (o *LogsDrilldown) GetCommonMetadata() resource.CommonMetadata { + dt := o.DeletionTimestamp + var deletionTimestamp *time.Time + if dt != nil { + deletionTimestamp = &dt.Time + } + // Legacy ExtraFields support + extraFields := make(map[string]any) + if o.Annotations != nil { + extraFields["annotations"] = o.Annotations + } + if o.ManagedFields != nil { + extraFields["managedFields"] = o.ManagedFields + } + if o.OwnerReferences != nil { + extraFields["ownerReferences"] = o.OwnerReferences + } + return resource.CommonMetadata{ + UID: string(o.UID), + ResourceVersion: o.ResourceVersion, + Generation: o.Generation, + Labels: o.Labels, + CreationTimestamp: o.CreationTimestamp.Time, + DeletionTimestamp: deletionTimestamp, + Finalizers: o.Finalizers, + UpdateTimestamp: o.GetUpdateTimestamp(), + CreatedBy: o.GetCreatedBy(), + UpdatedBy: o.GetUpdatedBy(), + ExtraFields: extraFields, + } +} + +func (o *LogsDrilldown) SetCommonMetadata(metadata resource.CommonMetadata) { + o.UID = types.UID(metadata.UID) + o.ResourceVersion = metadata.ResourceVersion + o.Generation = metadata.Generation + o.Labels = metadata.Labels + o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp) + if metadata.DeletionTimestamp != nil { + dt := metav1.NewTime(*metadata.DeletionTimestamp) + o.DeletionTimestamp = &dt + } else { + o.DeletionTimestamp = nil + } + o.Finalizers = metadata.Finalizers + if o.Annotations == nil { + o.Annotations = make(map[string]string) + } + if !metadata.UpdateTimestamp.IsZero() { + o.SetUpdateTimestamp(metadata.UpdateTimestamp) + } + if metadata.CreatedBy != "" { + o.SetCreatedBy(metadata.CreatedBy) + } + if metadata.UpdatedBy != "" { + o.SetUpdatedBy(metadata.UpdatedBy) + } + // Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields + if metadata.ExtraFields != nil { + if annotations, ok := metadata.ExtraFields["annotations"]; ok { + if cast, ok := annotations.(map[string]string); ok { + o.Annotations = cast + } + } + if managedFields, ok := metadata.ExtraFields["managedFields"]; ok { + if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok { + o.ManagedFields = cast + } + } + if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok { + if cast, ok := ownerReferences.([]metav1.OwnerReference); ok { + o.OwnerReferences = cast + } + } + } +} + +func (o *LogsDrilldown) GetCreatedBy() string { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + return o.ObjectMeta.Annotations["grafana.com/createdBy"] +} + +func (o *LogsDrilldown) SetCreatedBy(createdBy string) { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy +} + +func (o *LogsDrilldown) GetUpdateTimestamp() time.Time { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"]) + return parsed +} + +func (o *LogsDrilldown) SetUpdateTimestamp(updateTimestamp time.Time) { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339) +} + +func (o *LogsDrilldown) GetUpdatedBy() string { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + return o.ObjectMeta.Annotations["grafana.com/updatedBy"] +} + +func (o *LogsDrilldown) SetUpdatedBy(updatedBy string) { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy +} + +func (o *LogsDrilldown) Copy() resource.Object { + return resource.CopyObject(o) +} + +func (o *LogsDrilldown) DeepCopyObject() runtime.Object { + return o.Copy() +} + +func (o *LogsDrilldown) DeepCopy() *LogsDrilldown { + cpy := &LogsDrilldown{} + o.DeepCopyInto(cpy) + return cpy +} + +func (o *LogsDrilldown) DeepCopyInto(dst *LogsDrilldown) { + dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion + dst.TypeMeta.Kind = o.TypeMeta.Kind + o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta) + o.Spec.DeepCopyInto(&dst.Spec) + o.Status.DeepCopyInto(&dst.Status) +} + +// Interface compliance compile-time check +var _ resource.Object = &LogsDrilldown{} + +// +k8s:openapi-gen=true +type LogsDrilldownList struct { + metav1.TypeMeta `json:",inline" yaml:",inline"` + metav1.ListMeta `json:"metadata" yaml:"metadata"` + Items []LogsDrilldown `json:"items" yaml:"items"` +} + +func (o *LogsDrilldownList) DeepCopyObject() runtime.Object { + return o.Copy() +} + +func (o *LogsDrilldownList) Copy() resource.ListObject { + cpy := &LogsDrilldownList{ + TypeMeta: o.TypeMeta, + Items: make([]LogsDrilldown, len(o.Items)), + } + o.ListMeta.DeepCopyInto(&cpy.ListMeta) + for i := 0; i < len(o.Items); i++ { + if item, ok := o.Items[i].Copy().(*LogsDrilldown); ok { + cpy.Items[i] = *item + } + } + return cpy +} + +func (o *LogsDrilldownList) GetItems() []resource.Object { + items := make([]resource.Object, len(o.Items)) + for i := 0; i < len(o.Items); i++ { + items[i] = &o.Items[i] + } + return items +} + +func (o *LogsDrilldownList) SetItems(items []resource.Object) { + o.Items = make([]LogsDrilldown, len(items)) + for i := 0; i < len(items); i++ { + o.Items[i] = *items[i].(*LogsDrilldown) + } +} + +func (o *LogsDrilldownList) DeepCopy() *LogsDrilldownList { + cpy := &LogsDrilldownList{} + o.DeepCopyInto(cpy) + return cpy +} + +func (o *LogsDrilldownList) DeepCopyInto(dst *LogsDrilldownList) { + resource.CopyObjectInto(dst, o) +} + +// Interface compliance compile-time check +var _ resource.ListObject = &LogsDrilldownList{} + +// Copy methods for all subresource types + +// DeepCopy creates a full deep copy of Spec +func (s *LogsDrilldownSpec) DeepCopy() *LogsDrilldownSpec { + cpy := &LogsDrilldownSpec{} + s.DeepCopyInto(cpy) + return cpy +} + +// DeepCopyInto deep copies Spec into another Spec object +func (s *LogsDrilldownSpec) DeepCopyInto(dst *LogsDrilldownSpec) { + resource.CopyObjectInto(dst, s) +} + +// DeepCopy creates a full deep copy of LogsDrilldownStatus +func (s *LogsDrilldownStatus) DeepCopy() *LogsDrilldownStatus { + cpy := &LogsDrilldownStatus{} + s.DeepCopyInto(cpy) + return cpy +} + +// DeepCopyInto deep copies LogsDrilldownStatus into another LogsDrilldownStatus object +func (s *LogsDrilldownStatus) DeepCopyInto(dst *LogsDrilldownStatus) { + resource.CopyObjectInto(dst, s) +} diff --git a/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_schema_gen.go b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_schema_gen.go new file mode 100644 index 00000000000..e6864c965a7 --- /dev/null +++ b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_schema_gen.go @@ -0,0 +1,34 @@ +// +// Code generated by grafana-app-sdk. DO NOT EDIT. +// + +package v1alpha1 + +import ( + "github.com/grafana/grafana-app-sdk/resource" +) + +// schema is unexported to prevent accidental overwrites +var ( + schemaLogsDrilldown = resource.NewSimpleSchema("logsdrilldown.grafana.app", "v1alpha1", &LogsDrilldown{}, &LogsDrilldownList{}, resource.WithKind("LogsDrilldown"), + resource.WithPlural("logsdrilldowns"), resource.WithScope(resource.NamespacedScope)) + kindLogsDrilldown = resource.Kind{ + Schema: schemaLogsDrilldown, + Codecs: map[resource.KindEncoding]resource.Codec{ + resource.KindEncodingJSON: &LogsDrilldownJSONCodec{}, + }, + } +) + +// Kind returns a resource.Kind for this Schema with a JSON codec +func LogsDrilldownKind() resource.Kind { + return kindLogsDrilldown +} + +// Schema returns a resource.SimpleSchema representation of LogsDrilldown +func LogsDrilldownSchema() *resource.SimpleSchema { + return schemaLogsDrilldown +} + +// Interface compliance checks +var _ resource.Schema = kindLogsDrilldown diff --git a/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_spec_gen.go b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_spec_gen.go new file mode 100644 index 00000000000..4ae319cf080 --- /dev/null +++ b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_spec_gen.go @@ -0,0 +1,15 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +package v1alpha1 + +// +k8s:openapi-gen=true +type LogsDrilldownSpec struct { + DefaultFields []string `json:"defaultFields"` +} + +// NewLogsDrilldownSpec creates a new LogsDrilldownSpec object. +func NewLogsDrilldownSpec() *LogsDrilldownSpec { + return &LogsDrilldownSpec{ + DefaultFields: []string{}, + } +} diff --git a/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_status_gen.go b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_status_gen.go new file mode 100644 index 00000000000..da33d92e7f6 --- /dev/null +++ b/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1/logsdrilldown_status_gen.go @@ -0,0 +1,44 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +package v1alpha1 + +// +k8s:openapi-gen=true +type LogsDrilldownstatusOperatorState struct { + // lastEvaluation is the ResourceVersion last evaluated + LastEvaluation string `json:"lastEvaluation"` + // state describes the state of the lastEvaluation. + // It is limited to three possible states for machine evaluation. + State LogsDrilldownStatusOperatorStateState `json:"state"` + // descriptiveState is an optional more descriptive state field which has no requirements on format + DescriptiveState *string `json:"descriptiveState,omitempty"` + // details contains any extra information that is operator-specific + Details map[string]interface{} `json:"details,omitempty"` +} + +// NewLogsDrilldownstatusOperatorState creates a new LogsDrilldownstatusOperatorState object. +func NewLogsDrilldownstatusOperatorState() *LogsDrilldownstatusOperatorState { + return &LogsDrilldownstatusOperatorState{} +} + +// +k8s:openapi-gen=true +type LogsDrilldownStatus struct { + // operatorStates is a map of operator ID to operator state evaluations. + // Any operator which consumes this kind SHOULD add its state evaluation information to this field. + OperatorStates map[string]LogsDrilldownstatusOperatorState `json:"operatorStates,omitempty"` + // additionalFields is reserved for future use + AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"` +} + +// NewLogsDrilldownStatus creates a new LogsDrilldownStatus object. +func NewLogsDrilldownStatus() *LogsDrilldownStatus { + return &LogsDrilldownStatus{} +} + +// +k8s:openapi-gen=true +type LogsDrilldownStatusOperatorStateState string + +const ( + LogsDrilldownStatusOperatorStateStateSuccess LogsDrilldownStatusOperatorStateState = "success" + LogsDrilldownStatusOperatorStateStateInProgress LogsDrilldownStatusOperatorStateState = "in_progress" + LogsDrilldownStatusOperatorStateStateFailed LogsDrilldownStatusOperatorStateState = "failed" +) diff --git a/apps/logsdrilldown/pkg/apis/logsdrilldown_manifest.go b/apps/logsdrilldown/pkg/apis/logsdrilldown_manifest.go new file mode 100644 index 00000000000..8afc6c75711 --- /dev/null +++ b/apps/logsdrilldown/pkg/apis/logsdrilldown_manifest.go @@ -0,0 +1,122 @@ +// +// This file is generated by grafana-app-sdk +// DO NOT EDIT +// + +package apis + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/grafana/grafana-app-sdk/app" + "github.com/grafana/grafana-app-sdk/resource" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kube-openapi/pkg/spec3" + + v1alpha1 "github.com/grafana/grafana/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1" +) + +var ( + rawSchemaLogsDrilldownv1alpha1 = []byte(`{"LogsDrilldown":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"defaultFields":{"items":{"type":"string"},"type":"array"}},"required":["defaultFields"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`) + versionSchemaLogsDrilldownv1alpha1 app.VersionSchema + _ = json.Unmarshal(rawSchemaLogsDrilldownv1alpha1, &versionSchemaLogsDrilldownv1alpha1) +) + +var appManifestData = app.ManifestData{ + AppName: "logsdrilldown", + Group: "logsdrilldown.grafana.app", + PreferredVersion: "v1alpha1", + Versions: []app.ManifestVersion{ + { + Name: "v1alpha1", + Served: true, + Kinds: []app.ManifestVersionKind{ + { + Kind: "LogsDrilldown", + Plural: "LogsDrilldowns", + Scope: "Namespaced", + Conversion: false, + Schema: &versionSchemaLogsDrilldownv1alpha1, + }, + }, + Routes: app.ManifestVersionRoutes{ + Namespaced: map[string]spec3.PathProps{}, + Cluster: map[string]spec3.PathProps{}, + }, + }, + }, +} + +func LocalManifest() app.Manifest { + return app.NewEmbeddedManifest(appManifestData) +} + +func RemoteManifest() app.Manifest { + return app.NewAPIServerManifest("logsdrilldown") +} + +var kindVersionToGoType = map[string]resource.Kind{ + "LogsDrilldown/v1alpha1": v1alpha1.LogsDrilldownKind(), +} + +// ManifestGoTypeAssociator returns the associated resource.Kind instance for a given Kind and Version, if one exists. +// If there is no association for the provided Kind and Version, exists will return false. +func ManifestGoTypeAssociator(kind, version string) (goType resource.Kind, exists bool) { + goType, exists = kindVersionToGoType[fmt.Sprintf("%s/%s", kind, version)] + return goType, exists +} + +var customRouteToGoResponseType = map[string]any{} + +// ManifestCustomRouteResponsesAssociator returns the associated response go type for a given kind, version, custom route path, and method, if one exists. +// kind may be empty for custom routes which are not kind subroutes. Leading slashes are removed from subroute paths. +// If there is no association for the provided kind, version, custom route path, and method, exists will return false. +// Resource routes (those without a kind) should prefix their route with "/" if the route is namespaced (otherwise the route is assumed to be cluster-scope) +func ManifestCustomRouteResponsesAssociator(kind, version, path, verb string) (goType any, exists bool) { + if len(path) > 0 && path[0] == '/' { + path = path[1:] + } + goType, exists = customRouteToGoResponseType[fmt.Sprintf("%s|%s|%s|%s", version, kind, path, strings.ToUpper(verb))] + return goType, exists +} + +var customRouteToGoParamsType = map[string]runtime.Object{} + +func ManifestCustomRouteQueryAssociator(kind, version, path, verb string) (goType runtime.Object, exists bool) { + if len(path) > 0 && path[0] == '/' { + path = path[1:] + } + goType, exists = customRouteToGoParamsType[fmt.Sprintf("%s|%s|%s|%s", version, kind, path, strings.ToUpper(verb))] + return goType, exists +} + +var customRouteToGoRequestBodyType = map[string]any{} + +func ManifestCustomRouteRequestBodyAssociator(kind, version, path, verb string) (goType any, exists bool) { + if len(path) > 0 && path[0] == '/' { + path = path[1:] + } + goType, exists = customRouteToGoRequestBodyType[fmt.Sprintf("%s|%s|%s|%s", version, kind, path, strings.ToUpper(verb))] + return goType, exists +} + +type GoTypeAssociator struct{} + +func NewGoTypeAssociator() *GoTypeAssociator { + return &GoTypeAssociator{} +} + +func (g *GoTypeAssociator) KindToGoType(kind, version string) (goType resource.Kind, exists bool) { + return ManifestGoTypeAssociator(kind, version) +} +func (g *GoTypeAssociator) CustomRouteReturnGoType(kind, version, path, verb string) (goType any, exists bool) { + return ManifestCustomRouteResponsesAssociator(kind, version, path, verb) +} +func (g *GoTypeAssociator) CustomRouteQueryGoType(kind, version, path, verb string) (goType runtime.Object, exists bool) { + return ManifestCustomRouteQueryAssociator(kind, version, path, verb) +} +func (g *GoTypeAssociator) CustomRouteRequestBodyGoType(kind, version, path, verb string) (goType any, exists bool) { + return ManifestCustomRouteRequestBodyAssociator(kind, version, path, verb) +} diff --git a/apps/logsdrilldown/pkg/app/app.go b/apps/logsdrilldown/pkg/app/app.go new file mode 100644 index 00000000000..8ae329eac69 --- /dev/null +++ b/apps/logsdrilldown/pkg/app/app.go @@ -0,0 +1,55 @@ +package app + +import ( + "context" + + "github.com/grafana/grafana-app-sdk/app" + "github.com/grafana/grafana-app-sdk/logging" + "github.com/grafana/grafana-app-sdk/operator" + "github.com/grafana/grafana-app-sdk/resource" + "github.com/grafana/grafana-app-sdk/simple" + "k8s.io/apimachinery/pkg/runtime/schema" + + logsdrilldownv1alpha1 "github.com/grafana/grafana/apps/logsdrilldown/pkg/apis/logsdrilldown/v1alpha1" +) + +func New(cfg app.Config) (app.App, error) { + simpleConfig := simple.AppConfig{ + Name: "logsdrilldown", + KubeConfig: cfg.KubeConfig, + InformerConfig: simple.AppInformerConfig{ + InformerOptions: operator.InformerOptions{ + ErrorHandler: func(ctx context.Context, err error) { + logging.FromContext(ctx).Error("Informer processing error", "error", err) + }, + }, + }, + ManagedKinds: []simple.AppManagedKind{ + { + Kind: logsdrilldownv1alpha1.LogsDrilldownKind(), + }, + }, + } + + a, err := simple.NewApp(simpleConfig) + if err != nil { + return nil, err + } + + err = a.ValidateManifest(cfg.ManifestData) + if err != nil { + return nil, err + } + + return a, nil +} + +func GetKinds() map[schema.GroupVersion][]resource.Kind { + gv := schema.GroupVersion{ + Group: logsdrilldownv1alpha1.LogsDrilldownKind().Group(), + Version: logsdrilldownv1alpha1.LogsDrilldownKind().Version(), + } + return map[schema.GroupVersion][]resource.Kind{ + gv: {logsdrilldownv1alpha1.LogsDrilldownKind()}, + } +} diff --git a/apps/logsdrilldown/plugin/src/generated/logsdrilldown/v1alpha1/logsdrilldown_object_gen.ts b/apps/logsdrilldown/plugin/src/generated/logsdrilldown/v1alpha1/logsdrilldown_object_gen.ts new file mode 100644 index 00000000000..6d3eca5637a --- /dev/null +++ b/apps/logsdrilldown/plugin/src/generated/logsdrilldown/v1alpha1/logsdrilldown_object_gen.ts @@ -0,0 +1,49 @@ +/* + * This file was generated by grafana-app-sdk. DO NOT EDIT. + */ +import { Spec } from './types.spec.gen'; +import { Status } from './types.status.gen'; + +export interface Metadata { + name: string; + namespace: string; + generateName?: string; + selfLink?: string; + uid?: string; + resourceVersion?: string; + generation?: number; + creationTimestamp?: string; + deletionTimestamp?: string; + deletionGracePeriodSeconds?: number; + labels?: Record; + annotations?: Record; + ownerReferences?: OwnerReference[]; + finalizers?: string[]; + managedFields?: ManagedFieldsEntry[]; +} + +export interface OwnerReference { + apiVersion: string; + kind: string; + name: string; + uid: string; + controller?: boolean; + blockOwnerDeletion?: boolean; +} + +export interface ManagedFieldsEntry { + manager?: string; + operation?: string; + apiVersion?: string; + time?: string; + fieldsType?: string; + subresource?: string; +} + +export interface LogsDrilldown { + kind: string; + apiVersion: string; + metadata: Metadata; + spec: Spec; + status: Status; +} diff --git a/apps/logsdrilldown/plugin/src/generated/logsdrilldown/v1alpha1/types.metadata.gen.ts b/apps/logsdrilldown/plugin/src/generated/logsdrilldown/v1alpha1/types.metadata.gen.ts new file mode 100644 index 00000000000..4377f3c1d08 --- /dev/null +++ b/apps/logsdrilldown/plugin/src/generated/logsdrilldown/v1alpha1/types.metadata.gen.ts @@ -0,0 +1,30 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +// metadata contains embedded CommonMetadata and can be extended with custom string fields +// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here +// without external reference as using the CommonMetadata reference breaks thema codegen. +export interface Metadata { + updateTimestamp: string; + createdBy: string; + uid: string; + creationTimestamp: string; + deletionTimestamp?: string; + finalizers: string[]; + resourceVersion: string; + generation: number; + updatedBy: string; + labels: Record; +} + +export const defaultMetadata = (): Metadata => ({ + updateTimestamp: "", + createdBy: "", + uid: "", + creationTimestamp: "", + finalizers: [], + resourceVersion: "", + generation: 0, + updatedBy: "", + labels: {}, +}); + diff --git a/apps/logsdrilldown/plugin/src/generated/logsdrilldown/v1alpha1/types.spec.gen.ts b/apps/logsdrilldown/plugin/src/generated/logsdrilldown/v1alpha1/types.spec.gen.ts new file mode 100644 index 00000000000..6c43e041fbe --- /dev/null +++ b/apps/logsdrilldown/plugin/src/generated/logsdrilldown/v1alpha1/types.spec.gen.ts @@ -0,0 +1,10 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +export interface Spec { + defaultFields: string[]; +} + +export const defaultSpec = (): Spec => ({ + defaultFields: [], +}); + diff --git a/apps/logsdrilldown/plugin/src/generated/logsdrilldown/v1alpha1/types.status.gen.ts b/apps/logsdrilldown/plugin/src/generated/logsdrilldown/v1alpha1/types.status.gen.ts new file mode 100644 index 00000000000..01be8df7961 --- /dev/null +++ b/apps/logsdrilldown/plugin/src/generated/logsdrilldown/v1alpha1/types.status.gen.ts @@ -0,0 +1,30 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +export interface OperatorState { + // lastEvaluation is the ResourceVersion last evaluated + lastEvaluation: string; + // state describes the state of the lastEvaluation. + // It is limited to three possible states for machine evaluation. + state: "success" | "in_progress" | "failed"; + // descriptiveState is an optional more descriptive state field which has no requirements on format + descriptiveState?: string; + // details contains any extra information that is operator-specific + details?: Record; +} + +export const defaultOperatorState = (): OperatorState => ({ + lastEvaluation: "", + state: "success", +}); + +export interface Status { + // operatorStates is a map of operator ID to operator state evaluations. + // Any operator which consumes this kind SHOULD add its state evaluation information to this field. + operatorStates?: Record; + // additionalFields is reserved for future use + additionalFields?: Record; +} + +export const defaultStatus = (): Status => ({ +}); + diff --git a/apps/playlist/go.mod b/apps/playlist/go.mod index 4419785540a..4346a5ac8c6 100644 --- a/apps/playlist/go.mod +++ b/apps/playlist/go.mod @@ -1,9 +1,9 @@ module github.com/grafana/grafana/apps/playlist -go 1.24.6 +go 1.25.3 require ( - github.com/grafana/grafana-app-sdk v0.46.0 + github.com/grafana/grafana-app-sdk v0.47.0 k8s.io/apimachinery v0.34.1 k8s.io/client-go v0.34.1 k8s.io/klog/v2 v2.130.1 @@ -31,7 +31,7 @@ require ( github.com/google/go-cmp v0.7.0 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/grafana/grafana-app-sdk/logging v0.45.0 // indirect + github.com/grafana/grafana-app-sdk/logging v0.46.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -68,18 +68,18 @@ require ( go.opentelemetry.io/proto/otlp v1.7.1 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.13.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect - google.golang.org/grpc v1.75.1 // indirect - google.golang.org/protobuf v1.36.9 // indirect + google.golang.org/grpc v1.76.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.34.1 // indirect diff --git a/apps/playlist/go.sum b/apps/playlist/go.sum index dadd72070fd..eb6cf0ee83d 100644 --- a/apps/playlist/go.sum +++ b/apps/playlist/go.sum @@ -46,10 +46,10 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grafana/grafana-app-sdk v0.46.0 h1:gvzQvCQgZJ/73BfAcbDt/6TAMhnVikVPxZt/UwDl+oc= -github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= -github.com/grafana/grafana-app-sdk/logging v0.45.0 h1:0SH6nYZpiLBZRwUq4J6+1vo8xuHKJjnO95/2pGOoA8w= -github.com/grafana/grafana-app-sdk/logging v0.45.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= +github.com/grafana/grafana-app-sdk/logging v0.46.0 h1:JhQ+ZK5orcmM+dZ3YZdT9uCizJEFU2I6JBNUSFWvCC8= +github.com/grafana/grafana-app-sdk/logging v0.46.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -161,10 +161,10 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -179,8 +179,8 @@ golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -201,10 +201,10 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 h1: google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090/go.mod h1:U8EXRNSd8sUYyDfs/It7KVWodQr+Hf9xtxyxWudSwEw= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/apps/playlist/pkg/apis/playlist_manifest.go b/apps/playlist/pkg/apis/playlist_manifest.go index 1baede5a7a4..7c215c8354e 100644 --- a/apps/playlist/pkg/apis/playlist_manifest.go +++ b/apps/playlist/pkg/apis/playlist_manifest.go @@ -14,6 +14,7 @@ import ( "github.com/grafana/grafana-app-sdk/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kube-openapi/pkg/spec3" + "k8s.io/kube-openapi/pkg/validation/spec" v0alpha1 "github.com/grafana/grafana/apps/playlist/pkg/apis/playlist/v0alpha1" ) @@ -58,6 +59,7 @@ var appManifestData = app.ManifestData{ Routes: app.ManifestVersionRoutes{ Namespaced: map[string]spec3.PathProps{}, Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{}, }, }, }, diff --git a/apps/plugins/go.mod b/apps/plugins/go.mod index 35ed57d995b..f84f2a8db9f 100644 --- a/apps/plugins/go.mod +++ b/apps/plugins/go.mod @@ -1,10 +1,10 @@ module github.com/grafana/grafana/apps/plugins -go 1.24.4 +go 1.25.3 require ( github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 - github.com/grafana/grafana-app-sdk v0.46.0 + github.com/grafana/grafana-app-sdk v0.47.0 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250428110029-a8ea72012bde k8s.io/apimachinery v0.34.1 k8s.io/apiserver v0.34.1 @@ -37,7 +37,7 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f // indirect github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 // indirect - github.com/grafana/grafana-app-sdk/logging v0.45.0 // indirect + github.com/grafana/grafana-app-sdk/logging v0.46.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -75,18 +75,18 @@ require ( go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/crypto v0.42.0 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.13.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect - google.golang.org/grpc v1.75.1 // indirect - google.golang.org/protobuf v1.36.9 // indirect + google.golang.org/grpc v1.76.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.34.1 // indirect diff --git a/apps/plugins/go.sum b/apps/plugins/go.sum index ca929862af5..99ff636a78c 100644 --- a/apps/plugins/go.sum +++ b/apps/plugins/go.sum @@ -56,10 +56,10 @@ github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 h1:qEwZ+7MbP github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37/go.mod h1:qeWYbnWzaYGl88JlL9+DsP1GT2Cudm58rLtx13fKZdw= github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 h1:jSojuc7njleS3UOz223WDlXOinmuLAIPI0z2vtq8EgI= github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4/go.mod h1:VahT+GtfQIM+o8ht2StR6J9g+Ef+C2Vokh5uuSmOD/4= -github.com/grafana/grafana-app-sdk v0.46.0 h1:gvzQvCQgZJ/73BfAcbDt/6TAMhnVikVPxZt/UwDl+oc= -github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= -github.com/grafana/grafana-app-sdk/logging v0.45.0 h1:0SH6nYZpiLBZRwUq4J6+1vo8xuHKJjnO95/2pGOoA8w= -github.com/grafana/grafana-app-sdk/logging v0.45.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= +github.com/grafana/grafana-app-sdk/logging v0.46.0 h1:JhQ+ZK5orcmM+dZ3YZdT9uCizJEFU2I6JBNUSFWvCC8= +github.com/grafana/grafana-app-sdk/logging v0.46.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250428110029-a8ea72012bde h1:ydSrBIOCxJQ84+JU+cyYsOLL40QeXrB7rYfsY/ezU4w= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250428110029-a8ea72012bde/go.mod h1:3MwgP0ISxGviTy3ZUJZsNz/56NNtHztMlH+gcxDt6Tw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= @@ -177,10 +177,10 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -195,8 +195,8 @@ golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -217,10 +217,10 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 h1: google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090/go.mod h1:U8EXRNSd8sUYyDfs/It7KVWodQr+Hf9xtxyxWudSwEw= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/apps/plugins/pkg/apis/plugins_manifest.go b/apps/plugins/pkg/apis/plugins_manifest.go index 3965a906139..4b0771aca29 100644 --- a/apps/plugins/pkg/apis/plugins_manifest.go +++ b/apps/plugins/pkg/apis/plugins_manifest.go @@ -14,6 +14,7 @@ import ( "github.com/grafana/grafana-app-sdk/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kube-openapi/pkg/spec3" + "k8s.io/kube-openapi/pkg/validation/spec" v0alpha1 "github.com/grafana/grafana/apps/plugins/pkg/apis/plugins/v0alpha1" ) @@ -55,6 +56,7 @@ var appManifestData = app.ManifestData{ Routes: app.ManifestVersionRoutes{ Namespaced: map[string]spec3.PathProps{}, Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{}, }, }, }, diff --git a/apps/preferences/go.mod b/apps/preferences/go.mod index 3c4b1af454b..3b667d390a2 100644 --- a/apps/preferences/go.mod +++ b/apps/preferences/go.mod @@ -1,9 +1,9 @@ module github.com/grafana/grafana/apps/preferences -go 1.24.6 +go 1.25.3 require ( - github.com/grafana/grafana-app-sdk v0.46.0 + github.com/grafana/grafana-app-sdk v0.47.0 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250804150913-990f1c69ecc2 github.com/stretchr/testify v1.11.1 k8s.io/apimachinery v0.34.1 @@ -24,7 +24,7 @@ require ( github.com/go-test/deep v1.1.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/gnostic-models v0.7.0 // indirect - github.com/grafana/grafana-app-sdk/logging v0.45.0 // indirect + github.com/grafana/grafana-app-sdk/logging v0.46.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -49,13 +49,13 @@ require ( go.opentelemetry.io/otel/trace v1.38.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.13.0 // indirect - google.golang.org/protobuf v1.36.9 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/client-go v0.34.1 // indirect diff --git a/apps/preferences/go.sum b/apps/preferences/go.sum index 112d7cb18ab..6cf5030bbf5 100644 --- a/apps/preferences/go.sum +++ b/apps/preferences/go.sum @@ -31,10 +31,10 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grafana/grafana-app-sdk v0.46.0 h1:gvzQvCQgZJ/73BfAcbDt/6TAMhnVikVPxZt/UwDl+oc= -github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= -github.com/grafana/grafana-app-sdk/logging v0.45.0 h1:0SH6nYZpiLBZRwUq4J6+1vo8xuHKJjnO95/2pGOoA8w= -github.com/grafana/grafana-app-sdk/logging v0.45.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= +github.com/grafana/grafana-app-sdk/logging v0.46.0 h1:JhQ+ZK5orcmM+dZ3YZdT9uCizJEFU2I6JBNUSFWvCC8= +github.com/grafana/grafana-app-sdk/logging v0.46.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250804150913-990f1c69ecc2 h1:X0cnaFdR+iz+sDSuoZmkryFSjOirchHe2MdKSRwBWgM= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250804150913-990f1c69ecc2/go.mod h1:RRvSjHH12/PnQaXraMO65jUhVu8n59mzvhfIMBETnV4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -124,10 +124,10 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -140,8 +140,8 @@ golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -152,8 +152,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/apps/preferences/pkg/apis/preferences_manifest.go b/apps/preferences/pkg/apis/preferences_manifest.go index 3912bc12866..dbbbc8d4ab0 100644 --- a/apps/preferences/pkg/apis/preferences_manifest.go +++ b/apps/preferences/pkg/apis/preferences_manifest.go @@ -14,6 +14,7 @@ import ( "github.com/grafana/grafana-app-sdk/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kube-openapi/pkg/spec3" + "k8s.io/kube-openapi/pkg/validation/spec" v1alpha1 "github.com/grafana/grafana/apps/preferences/pkg/apis/preferences/v1alpha1" ) @@ -71,6 +72,7 @@ var appManifestData = app.ManifestData{ Routes: app.ManifestVersionRoutes{ Namespaced: map[string]spec3.PathProps{}, Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{}, }, }, }, diff --git a/apps/provisioning/go.mod b/apps/provisioning/go.mod index 9a3cd99c066..a181626f40e 100644 --- a/apps/provisioning/go.mod +++ b/apps/provisioning/go.mod @@ -1,18 +1,19 @@ module github.com/grafana/grafana/apps/provisioning -go 1.24.6 +go 1.25.3 require ( + github.com/fsnotify/fsnotify v1.9.0 github.com/google/go-github/v70 v70.0.0 github.com/google/uuid v1.6.0 github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f - github.com/grafana/grafana-app-sdk/logging v0.45.0 + github.com/grafana/grafana-app-sdk/logging v0.46.0 github.com/grafana/grafana/apps/secret v0.0.0-20250902093454-b56b7add012f github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250804150913-990f1c69ecc2 github.com/grafana/nanogit v0.0.0-20250723104447-68f58f5ecec0 github.com/migueleliasweb/go-github-mock v1.1.0 github.com/stretchr/testify v1.11.1 - golang.org/x/oauth2 v0.30.0 + golang.org/x/oauth2 v0.31.0 k8s.io/apimachinery v0.34.1 k8s.io/apiserver v0.34.1 k8s.io/client-go v0.34.1 @@ -42,7 +43,7 @@ require ( github.com/gorilla/mux v1.8.1 // indirect github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 // indirect github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 // indirect - github.com/grafana/grafana-app-sdk v0.46.0 // indirect + github.com/grafana/grafana-app-sdk v0.47.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.18.0 // indirect @@ -67,15 +68,15 @@ require ( go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/crypto v0.42.0 // indirect - golang.org/x/net v0.44.0 // indirect + golang.org/x/net v0.45.0 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.13.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect - google.golang.org/grpc v1.75.1 // indirect - google.golang.org/protobuf v1.36.9 // indirect + google.golang.org/grpc v1.76.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/apps/provisioning/go.sum b/apps/provisioning/go.sum index 93819002c42..def68c4762a 100644 --- a/apps/provisioning/go.sum +++ b/apps/provisioning/go.sum @@ -10,6 +10,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY= @@ -58,10 +60,10 @@ github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 h1:qEwZ+7MbP github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37/go.mod h1:qeWYbnWzaYGl88JlL9+DsP1GT2Cudm58rLtx13fKZdw= github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 h1:jSojuc7njleS3UOz223WDlXOinmuLAIPI0z2vtq8EgI= github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4/go.mod h1:VahT+GtfQIM+o8ht2StR6J9g+Ef+C2Vokh5uuSmOD/4= -github.com/grafana/grafana-app-sdk v0.46.0 h1:gvzQvCQgZJ/73BfAcbDt/6TAMhnVikVPxZt/UwDl+oc= -github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= -github.com/grafana/grafana-app-sdk/logging v0.45.0 h1:0SH6nYZpiLBZRwUq4J6+1vo8xuHKJjnO95/2pGOoA8w= -github.com/grafana/grafana-app-sdk/logging v0.45.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= +github.com/grafana/grafana-app-sdk/logging v0.46.0 h1:JhQ+ZK5orcmM+dZ3YZdT9uCizJEFU2I6JBNUSFWvCC8= +github.com/grafana/grafana-app-sdk/logging v0.46.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= github.com/grafana/grafana/apps/secret v0.0.0-20250902093454-b56b7add012f h1:f+Z5Xpfp1WNYjUe23ginerWsHWUsRgOWrr3WGu3SlWs= github.com/grafana/grafana/apps/secret v0.0.0-20250902093454-b56b7add012f/go.mod h1:RA8mP8KVIwKXBx3Ssqa/uEBABib5LvUWYPVMxrNvnP0= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250804150913-990f1c69ecc2 h1:X0cnaFdR+iz+sDSuoZmkryFSjOirchHe2MdKSRwBWgM= @@ -166,10 +168,10 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -202,8 +204,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -222,10 +224,10 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/apps/provisioning/pkg/repository/git/repository.go b/apps/provisioning/pkg/repository/git/repository.go index 27247991017..4d002e4f831 100644 --- a/apps/provisioning/pkg/repository/git/repository.go +++ b/apps/provisioning/pkg/repository/git/repository.go @@ -756,28 +756,26 @@ func (r *gitRepository) createSignature(ctx context.Context) (nanogit.Author, na Email: "noreply@grafana.com", Time: time.Now(), } - committer := nanogit.Committer{ - Name: "Grafana", - Email: "noreply@grafana.com", - Time: time.Now(), - } // Use signature from context if available - if sig := repository.GetAuthorSignature(ctx); sig != nil && sig.Name != "" { - author.Name = sig.Name - author.Email = sig.Email - author.Time = sig.When - committer.Name = sig.Name - committer.Email = sig.Email - committer.Time = sig.When + if sig := repository.GetAuthorSignature(ctx); sig != nil { + if sig.Name != "" { + author.Name = sig.Name + } + if sig.Email != "" { + author.Email = sig.Email + } + if !sig.When.IsZero() { + author.Time = sig.When + } } if author.Time.IsZero() { author.Time = time.Now() - committer.Time = time.Now() } - return author, committer + // Author and committer are always the same (for now) + return author, nanogit.Committer(author) } func (r *gitRepository) commit(ctx context.Context, writer nanogit.StagedWriter, comment string) error { diff --git a/apps/provisioning/pkg/repository/git/repository_test.go b/apps/provisioning/pkg/repository/git/repository_test.go index e49d0f293e7..d3946b7b6d4 100644 --- a/apps/provisioning/pkg/repository/git/repository_test.go +++ b/apps/provisioning/pkg/repository/git/repository_test.go @@ -346,25 +346,6 @@ func TestCreateSignature(t *testing.T) { require.Equal(t, time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC), committer.Time) }) - t.Run("should fallback to default when context signature has empty name", func(t *testing.T) { - sig := repository.CommitSignature{ - Name: "", - Email: "john@example.com", - When: time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC), - } - ctx := repository.WithAuthorSignature(context.Background(), sig) - - author, committer := gitRepo.createSignature(ctx) - - require.Equal(t, "Grafana", author.Name) - require.Equal(t, "noreply@grafana.com", author.Email) - require.False(t, author.Time.IsZero()) - - require.Equal(t, "Grafana", committer.Name) - require.Equal(t, "noreply@grafana.com", committer.Email) - require.False(t, committer.Time.IsZero()) - }) - t.Run("should use current time when signature time is zero", func(t *testing.T) { sig := repository.CommitSignature{ Name: "John Doe", @@ -1787,23 +1768,22 @@ func TestGitRepository_createSignature(t *testing.T) { require.Equal(t, time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC), committer.Time) }) - t.Run("should fallback to default when context signature has empty name", func(t *testing.T) { + t.Run("should fill in missing signature properties from default values", func(t *testing.T) { sig := repository.CommitSignature{ Name: "", Email: "john@example.com", - When: time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC), } ctx := repository.WithAuthorSignature(context.Background(), sig) author, committer := gitRepo.createSignature(ctx) - require.Equal(t, "Grafana", author.Name) - require.Equal(t, "noreply@grafana.com", author.Email) + require.Equal(t, "Grafana", author.Name) // The default name + require.Equal(t, sig.Email, author.Email) require.False(t, author.Time.IsZero()) require.Equal(t, "Grafana", committer.Name) - require.Equal(t, "noreply@grafana.com", committer.Email) - require.False(t, committer.Time.IsZero()) + require.Equal(t, sig.Email, author.Email) + require.False(t, author.Time.IsZero()) }) t.Run("should use current time when signature time is zero", func(t *testing.T) { diff --git a/apps/provisioning/pkg/repository/github/webhook.go b/apps/provisioning/pkg/repository/github/webhook.go index 40f87ddc93d..0da826fe9de 100644 --- a/apps/provisioning/pkg/repository/github/webhook.go +++ b/apps/provisioning/pkg/repository/github/webhook.go @@ -7,7 +7,6 @@ import ( "log/slog" "net/http" "slices" - "strings" "github.com/google/go-github/v70/github" "github.com/google/uuid" @@ -16,7 +15,6 @@ import ( "github.com/grafana/grafana-app-sdk/logging" provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/apps/provisioning/pkg/repository" - "github.com/grafana/grafana/apps/provisioning/pkg/safepath" common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1" ) @@ -125,27 +123,13 @@ func (r *githubWebhookRepository) parsePushEvent(event *github.PushEvent) (*prov // however, if we get an event where just a .keep file is being deleted, and no other files in the folder // are being deleted, the folder could be gone from git, but not from grafana and we do not have a way // to get the grafana uid to delete the folder. so, instead, we will queue a full sync to clean things up. - dirsWithKeepDeletes := make(map[string]struct{}) - dirsWithOtherDeletes := make(map[string]struct{}) + var deletedPaths []string for _, change := range event.GetCommits() { - for _, removedFile := range change.Removed { - dir := safepath.Dir(removedFile) - if strings.HasSuffix(removedFile, ".keep") { - dirsWithKeepDeletes[dir] = struct{}{} - } else { - dirsWithOtherDeletes[dir] = struct{}{} - } - } - } - // if there are any keep files deleted that do not have other files deleted in the same folder, we need to queue a full sync - incremental := true - for dir := range dirsWithKeepDeletes { - if _, exists := dirsWithOtherDeletes[dir]; !exists { - incremental = false - break - } + deletedPaths = append(deletedPaths, change.Removed...) } + incremental := repository.CanUseIncrementalSync(deletedPaths) + return &provisioning.WebhookResponse{ Code: http.StatusAccepted, Job: &provisioning.JobSpec{ diff --git a/apps/provisioning/pkg/repository/local/watch.go b/apps/provisioning/pkg/repository/local/watch.go new file mode 100644 index 00000000000..91caed9a1d3 --- /dev/null +++ b/apps/provisioning/pkg/repository/local/watch.go @@ -0,0 +1,130 @@ +package local + +import ( + "context" + "fmt" + "io/fs" + "math" + "os" + "path/filepath" + "strings" + "sync" + "time" + + "github.com/fsnotify/fsnotify" + + "github.com/grafana/grafana-app-sdk/logging" +) + +type FileWatcher interface { + Watch(ctx context.Context, events chan<- string) +} + +type fileWatcher struct { + prefix string + accept func(string) bool + waitFor time.Duration + timersMu sync.Mutex + timers map[string]*time.Timer + watcher *fsnotify.Watcher + logger logging.Logger +} + +// File watcher that buffers events for 100ms before actually firing them +// this is helpful because editing a file may often update the same file many many times +// for what seems like a single operation. +// See: https://github.com/fsnotify/fsnotify/blob/main/cmd/fsnotify/dedup.go +func NewFileWatcher(path string, accept func(string) bool) (FileWatcher, error) { + info, _ := os.Stat(path) + if info == nil || !info.IsDir() { + return nil, fmt.Errorf("expecting to watch a folder") + } + + w, err := fsnotify.NewWatcher() + if err != nil { + return nil, err + } + + if err := w.Add(path); err != nil { + _ = w.Close() + return nil, err + } + + if err = filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if d.IsDir() { + if err = w.Add(path); err != nil { + return err + } + } + return nil + }); err != nil { + _ = w.Close() + return nil, err + } + + return &fileWatcher{ + prefix: path + "/", + accept: accept, + waitFor: 100 * time.Millisecond, + timers: make(map[string]*time.Timer), + watcher: w, + logger: logging.DefaultLogger.With("watch", path), + }, nil +} + +// Keep watching for changes until the context is done +func (f *fileWatcher) Watch(ctx context.Context, events chan<- string) { + for { + select { + case <-ctx.Done(): + close(events) + return + + case _, ok := <-f.watcher.Errors: + if !ok { // Channel was closed (i.e. Watcher.Close() was called). + close(events) + return + } + + // Read from Events. + case e, ok := <-f.watcher.Events: + if !ok { // Channel was closed (i.e. Watcher.Close() was called). + close(events) + return + } + name := filepath.Base(e.Name) + if strings.HasPrefix(name, ".") { + continue // ignore hidden files+folders + } + if !f.accept(name) { + info, _ := os.Stat(e.Name) + if info != nil && info.IsDir() { + if err := f.watcher.Add(e.Name); err != nil { + f.logger.Warn("error adding folder", "folder", e.Name, "error", err) + } + } + continue + } + + f.timersMu.Lock() + t, ok := f.timers[e.Name] + if !ok { + nameCopy := e.Name + t = time.AfterFunc(math.MaxInt64, func() { + path, _ := strings.CutPrefix(nameCopy, f.prefix) + events <- path + + f.timersMu.Lock() + delete(f.timers, nameCopy) + f.timersMu.Unlock() + }) + f.timers[e.Name] = t + } + f.timersMu.Unlock() + t.Reset(f.waitFor) + } + } +} diff --git a/apps/provisioning/pkg/repository/local/watch_test.go b/apps/provisioning/pkg/repository/local/watch_test.go new file mode 100644 index 00000000000..ef271d345a9 --- /dev/null +++ b/apps/provisioning/pkg/repository/local/watch_test.go @@ -0,0 +1,84 @@ +package local + +import ( + "context" + "os" + "path/filepath" + "slices" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestWatch_TempFiles(t *testing.T) { + tmpdir := t.TempDir() + sub1 := filepath.Join(tmpdir, "sub1") + err := os.MkdirAll(sub1, 0700) + require.NoError(t, err) + + watcher, err := NewFileWatcher(tmpdir, func(name string) bool { + return filepath.Ext(name) == ".txt" + }) + require.NoError(t, err) + + ctx, cancel := context.WithCancel(context.Background()) + events := make(chan string, 10) + go func() { + watcher.Watch(ctx, events) + }() + + go func() { + time.Sleep(20 * time.Millisecond) + err = os.WriteFile(filepath.Join(tmpdir, "aaa.txt"), []byte("aaa"), 0600) + require.NoError(t, err) + err = os.WriteFile(filepath.Join(tmpdir, ".hidden.txt"), []byte("hidden"), 0600) + require.NoError(t, err) + err = os.WriteFile(filepath.Join(tmpdir, "bbb.txt"), []byte("bbb"), 0600) + require.NoError(t, err) + err = os.WriteFile(filepath.Join(tmpdir, "xxx.json"), []byte("ignore"), 0600) + require.NoError(t, err) + err = os.WriteFile(filepath.Join(sub1, "ccc.txt"), []byte("ccc"), 0600) + require.NoError(t, err) + + // make a sub folder + sub2 := filepath.Join(tmpdir, "sub2") + err = os.MkdirAll(sub2, 0700) + require.NoError(t, err) + time.Sleep(50 * time.Millisecond) + err = os.WriteFile(filepath.Join(sub2, "ddd.txt"), []byte("ddd"), 0600) + require.NoError(t, err) + + // Check all the paths we are watching + w, ok := watcher.(*fileWatcher) + require.True(t, ok, "explicit cast") + watching := w.watcher.WatchList() + slices.Sort(watching) + require.Equal(t, []string{ + tmpdir, sub1, sub2, + }, watching) + + // Removing the subfolder should trigger the event again + time.Sleep(time.Millisecond * 150) + err = os.RemoveAll(sub2) + require.NoError(t, err) + + // Finish all the events + time.Sleep(time.Millisecond * 250) + cancel() // stops the context + }() + + received := []string{} + for event := range events { + received = append(received, event) + } + slices.Sort(received) + + require.Equal(t, []string{ + "aaa.txt", + "bbb.txt", + "sub1/ccc.txt", + "sub2/ddd.txt", // first time because we added it + "sub2/ddd.txt", // second time because we removed it + }, received) +} diff --git a/apps/provisioning/pkg/repository/workflows.go b/apps/provisioning/pkg/repository/workflows.go index 48ba1319a62..5657de9dc5e 100644 --- a/apps/provisioning/pkg/repository/workflows.go +++ b/apps/provisioning/pkg/repository/workflows.go @@ -1,9 +1,12 @@ package repository import ( + "strings" + apierrors "k8s.io/apimachinery/pkg/api/errors" provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + "github.com/grafana/grafana/apps/provisioning/pkg/safepath" ) func IsWriteAllowed(repo *provisioning.Repository, ref string) error { @@ -40,3 +43,32 @@ func IsWriteAllowed(repo *provisioning.Repository, ref string) error { return nil } } + +// CanUseIncrementalSync checks if an incremental sync can be performed or if a full sync is needed, +// given a list of deleted file paths. It will return true if a .keep file is deleted without +// other files being deleted in the same directory. This is because the folder will not be a part of the +// deleted files, and the .keep file is not a resource in grafana, so we can't get the folder uid. +// A full sync will clean that up. +func CanUseIncrementalSync(deletedPaths []string) bool { + dirsWithKeepDeletes := make(map[string]struct{}) + dirsWithOtherDeletes := make(map[string]struct{}) + + for _, path := range deletedPaths { + dir := safepath.Dir(path) + if strings.HasSuffix(path, ".keep") { + dirsWithKeepDeletes[dir] = struct{}{} + } else { + dirsWithOtherDeletes[dir] = struct{}{} + } + } + + // if there are any .keep files deleted that don't have other files deleted in the same folder, + // we need to do a full sync + for dir := range dirsWithKeepDeletes { + if _, exists := dirsWithOtherDeletes[dir]; !exists { + return false + } + } + + return true +} diff --git a/apps/provisioning/pkg/repository/workflows_test.go b/apps/provisioning/pkg/repository/workflows_test.go index 995c85e0eb5..91a69daf35a 100644 --- a/apps/provisioning/pkg/repository/workflows_test.go +++ b/apps/provisioning/pkg/repository/workflows_test.go @@ -345,3 +345,58 @@ func TestIsWriteAllowed(t *testing.T) { }) } } + +func TestCanUseIncrementalSync(t *testing.T) { + tests := []struct { + name string + deletedPaths []string + want bool + }{ + { + name: "no deleted paths", + deletedPaths: []string{}, + want: true, + }, + { + name: "no keep file deletions", + deletedPaths: []string{"test.json"}, + want: true, + }, + { + name: "keep file deletion at root without other deletions", + deletedPaths: []string{".keep"}, + want: false, + }, + { + name: "keep file deletion with other deletions in same folder", + deletedPaths: []string{"test/.keep", "test/test.json"}, + want: true, + }, + { + name: "multiple keep files in different folders without other deletions", + deletedPaths: []string{"folder1/.keep", "folder2/.keep"}, + want: false, + }, + { + name: "nested folder with only keep file deleted", + deletedPaths: []string{"parent/child/.keep"}, + want: false, + }, + { + name: "some folders with only keep, some with other files", + deletedPaths: []string{"folder1/.keep", "folder2/.keep", "folder2/dashboard.json"}, + want: false, + }, + { + name: "only regular files deleted from multiple folders", + deletedPaths: []string{"folder1/file1.json", "folder2/file2.json", "folder3/file3.json"}, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := CanUseIncrementalSync(tt.deletedPaths) + require.Equal(t, tt.want, got) + }) + } +} diff --git a/apps/scope/README.md b/apps/scope/README.md new file mode 100644 index 00000000000..034ae1eda36 --- /dev/null +++ b/apps/scope/README.md @@ -0,0 +1,11 @@ +# Updating OpenAPI spec + +Change the desired types, then run these commands, with the linked Enterprise repo: + +``` +go test --tags "pro" -timeout 30s -run ^TestIntegrationOpenAPIs$ github.com/grafana/grafana/pkg/extensions/apiserver/tests -count=1 +``` + +``` +./hack/update-codegen.sh scope +``` diff --git a/apps/scope/go.mod b/apps/scope/go.mod index 435e401adba..d3924c83c95 100644 --- a/apps/scope/go.mod +++ b/apps/scope/go.mod @@ -1,6 +1,6 @@ module github.com/grafana/grafana/apps/scope -go 1.24.6 +go 1.25.3 require ( github.com/grafana/grafana/pkg/apimachinery v0.0.0-20251007081214-26e147d01f0a @@ -29,9 +29,9 @@ require ( github.com/x448/float16 v0.8.4 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/text v0.29.0 // indirect - google.golang.org/protobuf v1.36.9 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/text v0.30.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/apps/scope/go.sum b/apps/scope/go.sum index 25bae6f532a..98414ba2f0a 100644 --- a/apps/scope/go.sum +++ b/apps/scope/go.sum @@ -71,8 +71,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -81,8 +81,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -91,8 +91,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/apps/scope/pkg/apis/scope/v0alpha1/types.go b/apps/scope/pkg/apis/scope/v0alpha1/types.go index fcd7812c8da..f4c18dbb729 100644 --- a/apps/scope/pkg/apis/scope/v0alpha1/types.go +++ b/apps/scope/pkg/apis/scope/v0alpha1/types.go @@ -153,6 +153,9 @@ type ScopeNodeSpec struct { LinkType LinkType `json:"linkType,omitempty"` // scope (later more things) LinkID string `json:"linkId,omitempty"` // the k8s name // ?? should this be a slice of links + + // Redirect to a specific URL when this node is selected. + RedirectUrl string `json:"redirectUrl,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/apps/scope/pkg/apis/scope/v0alpha1/zz_generated.openapi.go b/apps/scope/pkg/apis/scope/v0alpha1/zz_generated.openapi.go index 3f31343d82a..7cd7d1287b2 100644 --- a/apps/scope/pkg/apis/scope/v0alpha1/zz_generated.openapi.go +++ b/apps/scope/pkg/apis/scope/v0alpha1/zz_generated.openapi.go @@ -866,6 +866,13 @@ func schema_pkg_apis_scope_v0alpha1_ScopeNodeSpec(ref common.ReferenceCallback) Format: "", }, }, + "redirectUrl": { + SchemaProps: spec.SchemaProps{ + Description: "Redirect to a specific URL when this node is selected.", + Type: []string{"string"}, + Format: "", + }, + }, }, Required: []string{"nodeType", "title", "disableMultiSelect"}, }, diff --git a/apps/sdk.mk b/apps/sdk.mk index 2b1f6c8b34d..04e8f4ade70 100644 --- a/apps/sdk.mk +++ b/apps/sdk.mk @@ -1,4 +1,4 @@ -APP_SDK_VERSION = v0.46.0 +APP_SDK_VERSION = v0.47.0 APP_SDK_DIR = $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION) APP_SDK_BIN = $(APP_SDK_DIR)/grafana-app-sdk diff --git a/apps/secret/go.mod b/apps/secret/go.mod index 1a6b9ecc824..23f020e05f0 100644 --- a/apps/secret/go.mod +++ b/apps/secret/go.mod @@ -1,13 +1,13 @@ module github.com/grafana/grafana/apps/secret -go 1.24.6 +go 1.25.3 require ( - github.com/grafana/grafana-app-sdk v0.46.0 + github.com/grafana/grafana-app-sdk v0.47.0 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250710134100-1f3dc0533caf github.com/stretchr/testify v1.11.1 - google.golang.org/grpc v1.75.1 - google.golang.org/protobuf v1.36.9 + google.golang.org/grpc v1.76.0 + google.golang.org/protobuf v1.36.10 gopkg.in/yaml.v3 v3.0.1 k8s.io/apimachinery v0.34.1 k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b @@ -28,7 +28,7 @@ require ( github.com/go-test/deep v1.1.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/gnostic-models v0.7.0 // indirect - github.com/grafana/grafana-app-sdk/logging v0.45.0 // indirect + github.com/grafana/grafana-app-sdk/logging v0.46.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -54,11 +54,11 @@ require ( go.opentelemetry.io/otel/trace v1.38.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.13.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/apps/secret/go.sum b/apps/secret/go.sum index 712a7a12807..5da1a84d326 100644 --- a/apps/secret/go.sum +++ b/apps/secret/go.sum @@ -35,10 +35,10 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grafana/grafana-app-sdk v0.46.0 h1:gvzQvCQgZJ/73BfAcbDt/6TAMhnVikVPxZt/UwDl+oc= -github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= -github.com/grafana/grafana-app-sdk/logging v0.45.0 h1:0SH6nYZpiLBZRwUq4J6+1vo8xuHKJjnO95/2pGOoA8w= -github.com/grafana/grafana-app-sdk/logging v0.45.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= +github.com/grafana/grafana-app-sdk/logging v0.46.0 h1:JhQ+ZK5orcmM+dZ3YZdT9uCizJEFU2I6JBNUSFWvCC8= +github.com/grafana/grafana-app-sdk/logging v0.46.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250710134100-1f3dc0533caf h1:BBGDHffvVNLoYQlXEpbXcxE0vbpq7pm/8OWF5I+UDZg= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250710134100-1f3dc0533caf/go.mod h1:eAlOam2uWhrsEZlOoAr7XZ9hbBP7SyYGYn31/aQAPs8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -136,10 +136,10 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -152,8 +152,8 @@ golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -168,10 +168,10 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/apps/secret/pkg/apis/secret_manifest.go b/apps/secret/pkg/apis/secret_manifest.go index e83afe68aee..0b881ca7867 100644 --- a/apps/secret/pkg/apis/secret_manifest.go +++ b/apps/secret/pkg/apis/secret_manifest.go @@ -13,6 +13,7 @@ import ( "github.com/grafana/grafana-app-sdk/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kube-openapi/pkg/spec3" + "k8s.io/kube-openapi/pkg/validation/spec" v1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1" ) @@ -43,6 +44,7 @@ var appManifestData = app.ManifestData{ Routes: app.ManifestVersionRoutes{ Namespaced: map[string]spec3.PathProps{}, Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{}, }, }, }, diff --git a/apps/shorturl/go.mod b/apps/shorturl/go.mod index 7eb91409ca0..9fb2a9e4f38 100644 --- a/apps/shorturl/go.mod +++ b/apps/shorturl/go.mod @@ -1,10 +1,10 @@ module github.com/grafana/grafana/apps/shorturl -go 1.24.6 +go 1.25.3 require ( - github.com/grafana/grafana-app-sdk v0.46.0 - github.com/grafana/grafana-app-sdk/logging v0.45.0 + github.com/grafana/grafana-app-sdk v0.47.0 + github.com/grafana/grafana-app-sdk/logging v0.46.0 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250915132226-585b53bc7dba k8s.io/apimachinery v0.34.1 k8s.io/klog/v2 v2.130.1 @@ -73,18 +73,18 @@ require ( go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/crypto v0.42.0 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/net v0.45.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.13.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect - google.golang.org/grpc v1.75.1 // indirect - google.golang.org/protobuf v1.36.9 // indirect + google.golang.org/grpc v1.76.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.34.1 // indirect diff --git a/apps/shorturl/go.sum b/apps/shorturl/go.sum index 06c31439b6e..b8eee0c64c0 100644 --- a/apps/shorturl/go.sum +++ b/apps/shorturl/go.sum @@ -54,10 +54,10 @@ github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 h1:qEwZ+7MbP github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37/go.mod h1:qeWYbnWzaYGl88JlL9+DsP1GT2Cudm58rLtx13fKZdw= github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 h1:jSojuc7njleS3UOz223WDlXOinmuLAIPI0z2vtq8EgI= github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4/go.mod h1:VahT+GtfQIM+o8ht2StR6J9g+Ef+C2Vokh5uuSmOD/4= -github.com/grafana/grafana-app-sdk v0.46.0 h1:gvzQvCQgZJ/73BfAcbDt/6TAMhnVikVPxZt/UwDl+oc= -github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= -github.com/grafana/grafana-app-sdk/logging v0.45.0 h1:0SH6nYZpiLBZRwUq4J6+1vo8xuHKJjnO95/2pGOoA8w= -github.com/grafana/grafana-app-sdk/logging v0.45.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= +github.com/grafana/grafana-app-sdk/logging v0.46.0 h1:JhQ+ZK5orcmM+dZ3YZdT9uCizJEFU2I6JBNUSFWvCC8= +github.com/grafana/grafana-app-sdk/logging v0.46.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250915132226-585b53bc7dba h1:Qam8QzVRsyZN39zgZ9Vj6e8PEfswvv2McnqCZ/v5NcI= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250915132226-585b53bc7dba/go.mod h1:rlJ/mmE0RQolOB2+HV3+bw+ZifHyPDQurBwZEus+Wm0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= @@ -175,10 +175,10 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -193,8 +193,8 @@ golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -215,10 +215,10 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 h1: google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090/go.mod h1:U8EXRNSd8sUYyDfs/It7KVWodQr+Hf9xtxyxWudSwEw= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/apps/shorturl/pkg/apis/shorturl_manifest.go b/apps/shorturl/pkg/apis/shorturl_manifest.go index c4446d924e9..8cc2e9acf90 100644 --- a/apps/shorturl/pkg/apis/shorturl_manifest.go +++ b/apps/shorturl/pkg/apis/shorturl_manifest.go @@ -91,6 +91,7 @@ var appManifestData = app.ManifestData{ Routes: app.ManifestVersionRoutes{ Namespaced: map[string]spec3.PathProps{}, Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{}, }, }, }, diff --git a/conf/defaults.ini b/conf/defaults.ini index 1c47f30e6f3..977d0fa8783 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -1194,11 +1194,39 @@ facility = tag = [log.frontend] -# Should Faro javascript agent be initialized +# Enables the Grafana Faro javascript agent integration for capturing frontend performance and error events. enabled = false -# Custom HTTP endpoint to send events to. Default will log the events to stdout. -custom_endpoint = +# Custom HTTP endpoint to send Grafana Faro events to. Default will send events to /log-grafana-javascript-agent and log the events to stdout. +custom_endpoint = /log-grafana-javascript-agent + +# API Key for Grafana Faro custom endpoint +api_key = + +# level of internal logging for debugging Grafana Javascript Agent. +# possible values are: 0 = OFF, 1 = ERROR, 2 = WARN, 3 = INFO, 4 = VERBOSE +# more details: https://github.com/grafana/faro-web-sdk/blob/v1.3.7/docs/sources/tutorials/quick-start-browser.md#how-to-activate-debugging +internal_logger_level = 0 + +# Enables the Console instrumentation for Grafana Faro +# See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/console-instrumentation/ +instrumentations_console_enabled = true + +# Enables the Performance instrumentation for Grafana Faro. +# See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/performance-instrumentation/ +instrumentations_performance_enabled = true + +# Enables the Content Security Policy Violations instrumentation for Grafana Faro. +# See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/csp-violation-tracking/ +instrumentations_csp_enabled = true + +# Enables the Tracing instrumentation for Grafana Faro. +# See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/tracing-instrumentation/ +instrumentations_tracing_enabled = true + +# Enables sending attribution data for web vitals with the Performance instrumentation. +# See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/web-vitals/#web-vitals-attribution-data +web_vitals_attribution_enabled = true # Requests per second limit enforced per an extended period, for Grafana backend log ingestion endpoint (/log). log_endpoint_requests_per_second_limit = 3 @@ -1206,28 +1234,8 @@ log_endpoint_requests_per_second_limit = 3 # Max requests accepted per short interval of time for Grafana backend log ingestion endpoint (/log) log_endpoint_burst_limit = 15 -# Enables all Faro default instrumentation by using `getWebInstrumentations`. Overrides other instrumentation flags. -instrumentations_all_enabled = false - -# Should error instrumentation be enabled, only affects Grafana Javascript Agent -instrumentations_errors_enabled = true - -# Should console instrumentation be enabled, only affects Grafana Javascript Agent -instrumentations_console_enabled = false - -# Should webvitals instrumentation be enabled, only affects Grafana Javascript Agent -instrumentations_webvitals_enabled = false - -# Should tracing instrumentation be enabled, only affects Grafana Javascript Agent -instrumentations_tracing_enabled = false - -# level of internal logging for debugging Grafana Javascript Agent. -# possible values are: 0 = OFF, 1 = ERROR, 2 = WARN, 3 = INFO, 4 = VERBOSE -# more details: https://github.com/grafana/faro-web-sdk/blob/v1.3.7/docs/sources/tutorials/quick-start-browser.md#how-to-activate-debugging -internal_logger_level = 0 - -# Api Key, only applies to Grafana Javascript Agent provider -api_key = +# Enables the bot filter for the Grafana Faro JavaScript agent integration. Default is `false`. When enabled, it will filter out requests from known bots and crawlers. +bot_filter_enabled = false #################################### Usage Quotas ######################## [quota] diff --git a/conf/sample.ini b/conf/sample.ini index 964b3df5196..5518290525e 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -1172,35 +1172,42 @@ ;tag = [log.frontend] -# Should Faro javascript agent be initialized +# Enables the Grafana Faro javascript agent integration for capturing frontend performance and error events. ;enabled = false -# Custom HTTP endpoint to send events to. Default will log the events to stdout. +# Custom HTTP endpoint to send Grafana Faro events to. Default will send events to /log-grafana-javascript-agent and log the events to stdout. ;custom_endpoint = /log-grafana-javascript-agent -# Requests per second limit enforced an extended period, for Grafana backend log ingestion endpoint (/log). -;log_endpoint_requests_per_second_limit = 3 +# API Key for Grafana Faro custom endpoint +;api_key = -# Max requests accepted per short interval of time for Grafana backend log ingestion endpoint (/log). -;log_endpoint_burst_limit = 15 +# level of internal logging for debugging Grafana Javascript Agent. +# possible values are: 0 = OFF, 1 = ERROR, 2 = WARN, 3 = INFO, 4 = VERBOSE +# more details: https://github.com/grafana/faro-web-sdk/blob/v1.3.7/docs/sources/tutorials/quick-start-browser.md#how-to-activate-debugging +;internal_logger_level = -# Enables all Faro default instrumentation by using `getWebInstrumentations`. Overrides other instrumentation flags. -;instrumentations_all_enabled = false +# Enables the Console instrumentation for Grafana Faro +# See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/console-instrumentation/ +;instrumentations_console_enabled = true -# Should error instrumentation be enabled, only affects Grafana Javascript Agent -;instrumentations_errors_enabled = true +# Enables the Performance instrumentation for Grafana Faro. +# See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/performance-instrumentation/ +;instrumentations_performance_enabled = true -# Should console instrumentation be enabled, only affects Grafana Javascript Agent -;instrumentations_console_enabled = false +# Enables the Content Security Policy Violations instrumentation for Grafana Faro. +# See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/csp-violation-tracking/ +; instrumentations_csp_enabled = true -# Should webvitals instrumentation be enabled, only affects Grafana Javascript Agent -;instrumentations_webvitals_enabled = false +# Enables the Tracing instrumentation for Grafana Faro. +# See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/tracing-instrumentation/ +;instrumentations_tracing_enabled = true -# Should tracing instrumentation be enabled, only affects Grafana Javascript Agent -;instrumentations_tracing_enabled = false +# Enables sending attribution data for web vitals with the Performance instrumentation. +# See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/web-vitals/#web-vitals-attribution-data +;web_vitals_attribution_enabled = true -# Api Key, only applies to Grafana Javascript Agent provider -;api_key = testApiKey +# Enables the bot filter for the Grafana Faro JavaScript agent integration. Default is `false`. When enabled, it will filter out requests from known bots and crawlers. +;bot_filter_enabled = false #################################### Usage Quotas ######################## [quota] diff --git a/devenv/create_docker_compose.sh b/devenv/create_docker_compose.sh index 2acdd0836a1..21bd7d88055 100755 --- a/devenv/create_docker_compose.sh +++ b/devenv/create_docker_compose.sh @@ -2,18 +2,23 @@ shopt -s nullglob # Enable nullglob -blocks_dir=docker/blocks -docker_dir=docker -template_dir=templates +# Get the directory where this script is located (works from any execution directory) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -grafana_config_file=conf.tmp +blocks_dir="${SCRIPT_DIR}/docker/blocks" +docker_dir="${SCRIPT_DIR}/docker" +template_dir="${SCRIPT_DIR}/templates" + +grafana_config_file="${SCRIPT_DIR}/conf.tmp" grafana_config=config -compose_header_file=docker/compose_header.yml -compose_volume_section_file=docker/compose_volume_section.yml +compose_header_file="${SCRIPT_DIR}/docker/compose_header.yml" +compose_volume_section_file="${SCRIPT_DIR}/docker/compose_volume_section.yml" compose_volume_section_create_flag=docker_volume_create_true -compose_file=docker-compose.yaml -env_file=.env +compose_file="${SCRIPT_DIR}/docker-compose.yaml" +compose_file_name="docker-compose.yaml" +env_file="${SCRIPT_DIR}/.env" +env_file_name=".env" if [ "$#" == 0 ]; then blocks=`ls $blocks_dir` @@ -51,16 +56,16 @@ for dir in $@; do echo "" >> $grafana_config_file fi - if [ -e $current_dir/$compose_file ]; then - echo "Adding $current_dir/$compose_file to $compose_file" - cat $current_dir/$compose_file >> $compose_file + if [ -e $current_dir/$compose_file_name ]; then + echo "Adding $current_dir/$compose_file_name to $compose_file" + cat $current_dir/$compose_file_name >> $compose_file echo "" >> $compose_file fi - if [ -e $current_dir/$env_file ]; then - echo "Adding $current_dir/$env_file to .env" - cat $current_dir/$env_file >> .env - echo "" >> .env + if [ -e $current_dir/$env_file_name ]; then + echo "Adding $current_dir/$env_file_name to $env_file" + cat $current_dir/$env_file_name >> $env_file + echo "" >> $env_file fi done diff --git a/devenv/dev-dashboards/panel-gauge/gauge_tests_new.json b/devenv/dev-dashboards/panel-gauge/gauge_tests_new.json new file mode 100644 index 00000000000..2eb527326e7 --- /dev/null +++ b/devenv/dev-dashboards/panel-gauge/gauge_tests_new.json @@ -0,0 +1,2150 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 525, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [], + "title": "Basic single ", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 0, + "y": 1 + }, + "id": 1, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.4, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": true, + "spotlight": false + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Plain", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 4, + "y": 1 + }, + "id": 4, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.4, + "effects": { + "barGlow": false, + "centerGlow": true, + "rounded": true, + "spotlight": false + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Center glow", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 8, + "y": 1 + }, + "id": 3, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.4, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": false + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Center and bar glow", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 12, + "y": 1 + }, + "id": 5, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.4, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Spotlight", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 16, + "y": 1 + }, + "id": 8, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.4, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": true + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Sparkline", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 0, + "y": 7 + }, + "id": 22, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.72, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": false, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Square butts", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 4, + "y": 7 + }, + "id": 23, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.72, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": false, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "gauge", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Square butts gauge", + "type": "radialbar" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 13 + }, + "id": 17, + "panels": [], + "title": "Bar width", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 0, + "y": 14 + }, + "id": 18, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.1, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Bar width 0,1", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 5, + "y": 14 + }, + "id": 19, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.32, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Bar width 0,32", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 10, + "y": 14 + }, + "id": 20, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.57, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Bar width 0,57", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 15, + "y": 14 + }, + "id": 21, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.8, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "max": 100, + "min": 1, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "spread": 22, + "startValue": 1 + } + ], + "title": "Bar width 0,8", + "type": "radialbar" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 20 + }, + "id": 24, + "panels": [], + "title": "Thresholds", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 0, + "y": 21 + }, + "id": 25, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.9, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "gauge", + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Plain thresholds", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 6, + "y": 21 + }, + "id": 26, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.72, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 37, + "segmentSpacing": 0.31, + "shape": "gauge", + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Thresholds segmented", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 12, + "y": 21 + }, + "id": 29, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.72, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 46, + "segmentSpacing": 0.3, + "shape": "gauge", + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Segmented + gradient", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 27 + }, + "id": 30, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.9, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "gauge", + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Plain thresholds", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 27 + }, + "id": 28, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.72, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "none", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 62, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Thresholds circle segmented", + "type": "radialbar" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 34 + }, + "id": 31, + "panels": [], + "title": "Threshold labels", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "semi-dark-yellow", + "value": 40 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 7, + "x": 0, + "y": 35 + }, + "id": 32, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.9, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 62, + "segmentSpacing": 0.3, + "shape": "gauge", + "showThresholdLabels": true, + "showThresholdMarkers": true, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Thresholds labels", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "semi-dark-yellow", + "value": 40 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 7, + "x": 7, + "y": 35 + }, + "id": 34, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.9, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 62, + "segmentSpacing": 0.3, + "shape": "gauge", + "showThresholdLabels": true, + "showThresholdMarkers": false, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Thresholds labels only", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "semi-dark-yellow", + "value": 40 + }, + { + "color": "orange", + "value": 65 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 6, + "x": 14, + "y": 35 + }, + "id": 33, + "maxDataPoints": 20, + "options": { + "barWidthFactor": 0.9, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + }, + "gradient": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 80, + "segmentSpacing": 0.59, + "shape": "circle", + "showThresholdLabels": true, + "showThresholdMarkers": true, + "sparkline": false + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "alias": "1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "Thresholds labels + circle", + "type": "radialbar" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 45 + }, + "id": 6, + "panels": [], + "title": "Gradient modes", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "palette-classic" + }, + "mappings": [], + "max": 100, + "min": 1, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 9, + "maxDataPoints": 20, + "options": { + "barWidth": 12, + "barWidthFactor": 0.4, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "glow": "both", + "gradient": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false, + "spotlight": true + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "max": 98, + "min": 5, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 5, + "spread": 12, + "startValue": 50 + } + ], + "title": "Auto gradient + classic palette", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "continuous-GrYlRd" + }, + "mappings": [], + "max": 100, + "min": 1, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 52 + }, + "id": 11, + "maxDataPoints": 20, + "options": { + "barWidth": 12, + "barWidthFactor": 0.4, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "glow": "both", + "gradient": "scheme", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 1, + "segmentSpacing": 0.3, + "shape": "gauge", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": true, + "spotlight": true + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "max": 98, + "min": 5, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 5, + "spread": 12, + "startValue": 50 + } + ], + "title": "Continuous color scheme ", + "type": "radialbar" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 58 + }, + "id": 12, + "panels": [], + "title": "Segmented", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "continuous-GrYlRd" + }, + "decimals": 0, + "mappings": [], + "max": 8, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "suffix:/ 8 " + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 59 + }, + "id": 13, + "maxDataPoints": 20, + "options": { + "barWidth": 12, + "barWidthFactor": 0.49, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "glow": "both", + "gradient": "scheme", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 8, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false, + "spotlight": true + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "max": 8, + "min": 1, + "noise": 2, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1, + "spread": 6, + "startValue": 0 + } + ], + "title": "Active gateways", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "continuous-GrYlRd" + }, + "decimals": 0, + "mappings": [], + "max": 12, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "suffix:/ 12" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 5, + "x": 4, + "y": 59 + }, + "id": 14, + "maxDataPoints": 20, + "options": { + "barWidth": 12, + "barWidthFactor": 0.49, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "sparkline": false, + "spotlight": true + }, + "glow": "both", + "gradient": "scheme", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 12, + "segmentSpacing": 0.3, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false, + "spotlight": true + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "max": 12, + "min": 1, + "noise": 2, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1, + "spread": 6, + "startValue": 0 + } + ], + "title": "Active pods", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "red", + "mode": "fixed" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 5, + "x": 9, + "y": 59 + }, + "id": 15, + "maxDataPoints": 20, + "options": { + "barWidth": 12, + "barWidthFactor": 0.84, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "glow": "both", + "gradient": "hue", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 39, + "segmentSpacing": 0.76, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false, + "spotlight": true + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "max": 100, + "min": 10, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1, + "spread": 12, + "startValue": 10 + } + ], + "title": "Backend", + "type": "radialbar" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "red", + "mode": "fixed" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 14, + "y": 59 + }, + "id": 16, + "maxDataPoints": 20, + "options": { + "barWidth": 12, + "barWidthFactor": 0.66, + "effects": { + "barGlow": true, + "centerGlow": true, + "rounded": true, + "spotlight": true + }, + "glow": "both", + "gradient": "hue", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "segmentCount": 81, + "segmentSpacing": 0.28, + "shape": "circle", + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sparkline": false, + "spotlight": true + }, + "pluginVersion": "12.2.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "max": 100, + "min": 10, + "noise": 22, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1, + "spread": 12, + "startValue": 10 + } + ], + "title": "Backend", + "type": "radialbar" + } + ], + "preload": false, + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Panel tests - Gauge (new)", + "uid": "panel-tests-gauge-new", + "version": 6 +} diff --git a/devenv/dev-dashboards/panel-gauge/gauge_tests_old_to_new.json b/devenv/dev-dashboards/panel-gauge/gauge_tests_old_to_new.json new file mode 100644 index 00000000000..61bec02a59b --- /dev/null +++ b/devenv/dev-dashboards/panel-gauge/gauge_tests_old_to_new.json @@ -0,0 +1,1134 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "To verify that the new gauge behaves the same and that migration is handled properly", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 531, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 7, + "panels": [], + "title": "Tests", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 0, + "y": 1 + }, + "id": 8, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,22" + } + ], + "title": "Plain", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 4, + "y": 1 + }, + "id": 9, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,55.5" + } + ], + "title": "With unit", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "very small\n", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 2, + "x": 8, + "y": 1 + }, + "id": 11, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,70" + } + ], + "title": "", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "decimals": 3, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "accMS2" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 10, + "y": 1 + }, + "id": 10, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,80" + } + ], + "title": "long value", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 3, + "x": 14, + "y": 1 + }, + "id": 18, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "no_data_points" + } + ], + "title": "No data", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 16, + "w": 7, + "x": 17, + "y": 1 + }, + "id": 13, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,80.5" + } + ], + "title": "Tall", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 10, + "x": 0, + "y": 6 + }, + "id": 12, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto", + "text": { + "valueSize": 100 + } + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,47" + } + ], + "title": "custom font size", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "links": [ + { + "targetBlank": true, + "title": "Single link", + "url": "http://www.google.com" + } + ], + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 7, + "x": 10, + "y": 6 + }, + "id": 16, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,44" + } + ], + "title": "Single data link", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "links": [ + { + "targetBlank": true, + "title": "first link", + "url": "http://www.google.com" + }, + { + "targetBlank": true, + "title": "second link", + "url": "http://www.google.com" + } + ], + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 7, + "x": 10, + "y": 11 + }, + "id": 17, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,78" + } + ], + "title": "Multiple data links", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 17 + }, + "id": 14, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto", + "text": {} + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,20.5" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "hide": false, + "refId": "B", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,40.5" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "hide": false, + "refId": "C", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,60.5" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "hide": false, + "refId": "D", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,90.5" + } + ], + "title": "Multi series", + "type": "gauge" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 25 + }, + "id": 6, + "panels": [], + "title": "Thresholds", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "should not show any threshold markers", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "fixed" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 26 + }, + "id": 1, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,66" + } + ], + "title": "Old gauge with static blue color and show threshold markers enabled", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "should not show any threshold markers", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "yellow", + "value": 30 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "accFS2" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 26 + }, + "id": 2, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": true, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,20" + } + ], + "title": "Many thresholds with labels", + "type": "gauge" + }, + { + "id": 19, + "type": "gauge", + "title": "Segmented w/ thresholds (min != 0, max != 100)", + "gridPos": { + "x": 16, + "y": 26, + "h": 9, + "w": 8 + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": null, + "color": "green" + }, + { + "value": 30, + "color": "yellow" + }, + { + "value": 50, + "color": "orange" + }, + { + "value": 70, + "color": "red" + } + ] + }, + "color": { + "mode": "thresholds" + }, + "min": 20, + "max": 90 + }, + "overrides": [] + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "scenarioId": "random_walk", + "refId": "A", + "min": 20, + "max": 90 + } + ], + "datasource": { + "type": "grafana-testdata-datasource" + }, + "options": { + "reduceOptions": { + "values": false, + "calcs": ["lastNotNull"], + "fields": "" + }, + "orientation": "auto", + "shape": "gauge", + "gradient": "none", + "barWidthFactor": 0.5, + "segmentCount": 70, + "segmentSpacing": 0.3, + "sparkline": false, + "showThresholdMarkers": true, + "showThresholdLabels": false, + "effects": { + "barGlow": false, + "centerGlow": false, + "rounded": false, + "spotlight": false + } + } + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 35 + }, + "id": 5, + "panels": [], + "title": "Neutral value (not sure we will implement it yet)", + "type": "row" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "should not show any threshold markers", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": -100, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "yellow", + "value": 30 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "accFS2" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 7, + "x": 0, + "y": 36 + }, + "id": 3, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,-50" + } + ], + "title": "neutral value 0 (-100 => 100)", + "type": "gauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "should not show any threshold markers", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "mappings": [], + "max": 41, + "min": 33, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "yellow", + "value": 30 + }, + { + "color": "orange", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "degree" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 9, + "x": 7, + "y": 36 + }, + "id": 4, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "12.3.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,38" + } + ], + "title": "neutral value 47 (33 => 41)", + "type": "gauge" + } + ], + "preload": false, + "schemaVersion": 42, + "tags": ["gdev", "panel-tests"], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Panel tests - Old gauge to new", + "uid": "panel-tests-old-gauge-to-new", + "version": 4 +} diff --git a/devenv/docker/blocks/prometheus_high_card/go.mod b/devenv/docker/blocks/prometheus_high_card/go.mod index a6d2b78e072..1e3709bbe66 100644 --- a/devenv/docker/blocks/prometheus_high_card/go.mod +++ b/devenv/docker/blocks/prometheus_high_card/go.mod @@ -1,6 +1,6 @@ module high-card -go 1.24.6 +go 1.25.3 require github.com/prometheus/client_golang v1.22.0 @@ -13,6 +13,6 @@ require ( github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect - golang.org/x/sys v0.33.0 // indirect + golang.org/x/sys v0.36.0 // indirect google.golang.org/protobuf v1.36.6 // indirect ) diff --git a/devenv/docker/blocks/prometheus_high_card/go.sum b/devenv/docker/blocks/prometheus_high_card/go.sum index ebbd18eaeef..d2e136dfd38 100644 --- a/devenv/docker/blocks/prometheus_high_card/go.sum +++ b/devenv/docker/blocks/prometheus_high_card/go.sum @@ -24,8 +24,8 @@ github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzM github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/devenv/docker/blocks/prometheus_utf8/go.mod b/devenv/docker/blocks/prometheus_utf8/go.mod index 7f7bb1f3b44..2ecc8267f24 100644 --- a/devenv/docker/blocks/prometheus_utf8/go.mod +++ b/devenv/docker/blocks/prometheus_utf8/go.mod @@ -1,6 +1,6 @@ module utf8-support -go 1.24.6 +go 1.25.3 require ( github.com/prometheus/client_golang v1.22.0 @@ -15,6 +15,6 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/procfs v0.16.1 // indirect - golang.org/x/sys v0.33.0 // indirect + golang.org/x/sys v0.36.0 // indirect google.golang.org/protobuf v1.36.6 // indirect ) diff --git a/devenv/docker/blocks/prometheus_utf8/go.sum b/devenv/docker/blocks/prometheus_utf8/go.sum index ebbd18eaeef..d2e136dfd38 100644 --- a/devenv/docker/blocks/prometheus_utf8/go.sum +++ b/devenv/docker/blocks/prometheus_utf8/go.sum @@ -24,8 +24,8 @@ github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzM github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/devenv/docker/blocks/stateful_webhook/Dockerfile b/devenv/docker/blocks/stateful_webhook/Dockerfile index 258eec3d891..f4eaaa14256 100644 --- a/devenv/docker/blocks/stateful_webhook/Dockerfile +++ b/devenv/docker/blocks/stateful_webhook/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.24.6 +FROM golang:1.25.3 ADD main.go /go/src/webhook/main.go diff --git a/devenv/jsonnet/dev-dashboards.libsonnet b/devenv/jsonnet/dev-dashboards.libsonnet index 2338d8c7f8a..80be668ecc4 100644 --- a/devenv/jsonnet/dev-dashboards.libsonnet +++ b/devenv/jsonnet/dev-dashboards.libsonnet @@ -37,6 +37,8 @@ "filter": (import '../dev-dashboards/transforms/filter.json'), "gauge-multi-series": (import '../dev-dashboards/panel-gauge/gauge-multi-series.json'), "gauge_tests": (import '../dev-dashboards/panel-gauge/gauge_tests.json'), + "gauge_tests_new": (import '../dev-dashboards/panel-gauge/gauge_tests_new.json'), + "gauge_tests_old_to_new": (import '../dev-dashboards/panel-gauge/gauge_tests_old_to_new.json'), "geomap-color-field": (import '../dev-dashboards/panel-geomap/geomap-color-field.json'), "geomap-photo-layer": (import '../dev-dashboards/panel-geomap/geomap-photo-layer.json'), "geomap-route-layer": (import '../dev-dashboards/panel-geomap/geomap-route-layer.json'), diff --git a/docs/sources/administration/roles-and-permissions/_index.md b/docs/sources/administration/roles-and-permissions/_index.md index eb2850eab15..d6cca1b7eb9 100644 --- a/docs/sources/administration/roles-and-permissions/_index.md +++ b/docs/sources/administration/roles-and-permissions/_index.md @@ -119,7 +119,7 @@ You can specify the following permissions to dashboards and folders. - **Edit**: Can create, edit, or delete a dashboard. Can edit or delete a folder, and create dashboards and subfolders in a folder. Editors _cannot_ change folder or dashboard permissions. - **View**: Can only view dashboards and folders. -> Important: When a user creates a dashboard or a folder they are automatically granted **Admin** permissions for it. +> Important: When a user creates a dashboard or folder at the top level, they are automatically granted Admin permissions for it. This does not apply to dashboards within a folder or to subfolders. For more information about assigning dashboard folder permissions, refer to [Grant dashboard folder permissions](../user-management/manage-dashboard-permissions/#grant-dashboard-folder-permissions). diff --git a/docs/sources/administration/roles-and-permissions/access-control/rbac-fixed-basic-role-definitions/index.md b/docs/sources/administration/roles-and-permissions/access-control/rbac-fixed-basic-role-definitions/index.md index 1495886a032..43b6e9c74a1 100644 --- a/docs/sources/administration/roles-and-permissions/access-control/rbac-fixed-basic-role-definitions/index.md +++ b/docs/sources/administration/roles-and-permissions/access-control/rbac-fixed-basic-role-definitions/index.md @@ -181,3 +181,15 @@ The following table lists the default RBAC OnCall role assignments to the basic | Admin | `plugins:grafana-oncall-app:admin` | Default [Grafana organization administrator](ref:rbac-basic-roles) assignments. | | Editor | `plugins:grafana-oncall-app:editor` | Default [Editor](ref:rbac-basic-roles) assignments. | | Viewer | `plugins:grafana-oncall-app:reader` | Default [Viewer](ref:rbac-basic-roles) assignments. | + +### Private data source connect roles + +The following table lists how private data source connect fixed roles are assigned to the basic roles: + +| Basic role | Associated fixed roles | Description | +| ------------- | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Grafana Admin | `plugins:grafana-pdc-app.private-networks:write`, `plugins:grafana-pdc-app.private-networks:read` | Default [Grafana server administrator](/docs/grafana//administration/roles-and-permissions/#grafana-server-administrators) assignments. | + +{{< admonition type="note" >}} +These private data source connect fixed roles must be granted alongside the `fixed:datasources:writer` role for the permissions to take effect. +{{< /admonition >}} diff --git a/docs/sources/administration/roles-and-permissions/access-control/rbac-for-app-plugins/index.md b/docs/sources/administration/roles-and-permissions/access-control/rbac-for-app-plugins/index.md index 7ffb3c3d26a..de442b3d5d6 100644 --- a/docs/sources/administration/roles-and-permissions/access-control/rbac-for-app-plugins/index.md +++ b/docs/sources/administration/roles-and-permissions/access-control/rbac-for-app-plugins/index.md @@ -5,6 +5,7 @@ description: Learn about how to configure access to app plugins using RBAC labels: products: - cloud + - enterprise menuTitle: RBAC for app plugins title: RBAC for app plugins weight: 90 @@ -39,7 +40,7 @@ refs: # RBAC for app plugins {{< admonition type="note" >}} -Available in [Grafana Cloud](/docs/grafana-cloud). +Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud). {{< /admonition >}} RBAC can be used to manage access to [app plugins](https://grafana.com/docs/grafana/latest/administration/plugin-management/#app-plugins). diff --git a/docs/sources/administration/roles-and-permissions/access-control/rbac-terraform-provisioning/index.md b/docs/sources/administration/roles-and-permissions/access-control/rbac-terraform-provisioning/index.md index 8dde070b315..3f3f6da58b0 100644 --- a/docs/sources/administration/roles-and-permissions/access-control/rbac-terraform-provisioning/index.md +++ b/docs/sources/administration/roles-and-permissions/access-control/rbac-terraform-provisioning/index.md @@ -95,7 +95,7 @@ provider "grafana" { ## Provision basic roles -The following example shows how to assign basic roles to users, teams, and service accounts. Basic roles are predefined in Grafana and provide a set of permissions for common use cases. +The following example shows how to assign basic roles to users and service accounts. Basic roles are predefined in Grafana and provide a set of permissions for common use cases. | Basic role | UID | | --------------- | --------------------- | @@ -107,11 +107,11 @@ The following example shows how to assign basic roles to users, teams, and servi You can use any of the basic role UIDs from the table above in your role assignments. For example, to assign the "None" role, use `basic_none` as the `role_uid`. -```terraform -resource "grafana_team" "viewer_team" { - name = "terraform_viewer_team" -} +{{< admonition type="note" >}} +You can't assign basic roles to teams. To grant team permissions, assign a fixed or custom role to the team. +{{< /admonition >}} +```terraform resource "grafana_user" "editor_user" { email = "terraform_editor@example.com" login = "terraform_editor_user" @@ -122,12 +122,6 @@ resource "grafana_service_account" "admin_sa" { name = "terraform_admin_sa" } -# Assign Viewer role to a team -resource "grafana_role_assignment" "viewer_role_assignment" { - role_uid = "basic_viewer" - teams = [grafana_team.viewer_team.id] -} - # Assign Editor role to a user resource "grafana_role_assignment" "editor_role_assignment" { role_uid = "basic_editor" @@ -141,6 +135,22 @@ resource "grafana_role_assignment" "admin_role_assignment" { } ``` +### Assign a fixed or custom role to a team + +Use fixed or custom roles to grant permissions to teams: + +```terraform +resource "grafana_team" "writers_team" { + name = "terraform_writers_team" +} + +# Assign a fixed role to a team +resource "grafana_role_assignment" "writers_team_fixed_role" { + role_uid = "fixed:dashboards:writer" + teams = [grafana_team.writers_team.id] +} +``` + ### Provision basic role to multiple users ```terraform diff --git a/docs/sources/alerting/alerting-rules/templates/_index.md b/docs/sources/alerting/alerting-rules/templates/_index.md index f66781f01e5..a2afde85de7 100644 --- a/docs/sources/alerting/alerting-rules/templates/_index.md +++ b/docs/sources/alerting/alerting-rules/templates/_index.md @@ -220,24 +220,6 @@ To preview label values, select `Use notification policy`, and then click on `Pr {{< figure src="/media/docs/alerting/alert-instance-routing-preview.png" max-width="1200px" alt="Routing preview displays label values" >}} -## Grafana Cloud AI-generated templates - -Grafana Cloud users can use built-in AI tool to generate templates in the appropriate [alerting template language](/docs/grafana-cloud/alerting-and-irm/alerting/configure-notifications/template-notifications/language/) for you. - -To use AI to create your template, follow these steps: - -1. Go to **Alerting -> Contact points**. - -1. Click the Notification Templates tab then, click the **+ Add notification template group** button. - -1. Name your template. - -1. In the Template group section, click the **Generate with AI** button. - -1. Supply the AI tool with a prompt or select from one of the example prompts and edit that if necessary. - -1. Click **Save**. - ## More information For further details on how to template alert rules, refer to: diff --git a/docs/sources/alerting/best-practices/high-cardinality-alerts.md b/docs/sources/alerting/best-practices/high-cardinality-alerts.md new file mode 100644 index 00000000000..9df60ac6bc6 --- /dev/null +++ b/docs/sources/alerting/best-practices/high-cardinality-alerts.md @@ -0,0 +1,223 @@ +--- +canonical: https://grafana.com/docs/grafana/latest/alerting/best-practices/high-cardinality-alerts/ +description: Learn how to detect and alert on high-cardinality metrics that can overload your metrics backend and increase observability costs. +keywords: + - grafana +labels: + products: + - cloud + - enterprise + - oss +menuTitle: Examples of high-cardinality alerts +title: Examples of high-cardinality alerts +weight: 1105 +refs: + usage-cost-alerts: + - pattern: /docs/ + destination: /docs/grafana-cloud/cost-management-and-billing/usage-cost-alerts/ + planning-mimir-capacity: + - pattern: /docs/ + destination: /docs/mimir/latest/manage/run-production-environment/planning-capacity/ + adaptative-metrics: + - pattern: /docs/ + destination: /docs/grafana-cloud/adaptive-telemetry/adaptive-metrics/introduction/ + cloud-metrics-invoice: + - pattern: /docs/ + destination: /docs/grafana-cloud/cost-management-and-billing/manage-invoices/understand-your-invoice/metrics-invoice/ + multi-dimensional-example: + - pattern: /docs/grafana/ + destination: /docs/grafana//alerting/best-practices/multi-dimensional-alerts/ + - pattern: /docs/grafana-cloud/ + destination: /docs/grafana-cloud/alerting-and-irm/alerting/best-practices/multi-dimensional-alerts/ +--- + +# Examples of high-cardinality alerts + +In Prometheus and Mimir, metrics are stored as time series, where each unique set of labels defines a distinct series. + +A large number of unique series (_high cardinality_) can overload your metrics backend, slow down dashboard and alert queries, and quickly increase your observability costs or exceed the limits of your Grafana Cloud plan. + +These examples show how to detect and alert on early signs of high cardinality: + +- **Total active series near limits**: detect when your Prometheus, Mimir, or Grafana Cloud Metrics instance approaches soft or hard limits. +- **Series increase per metric or scope:** fine-tune detection to identify growth in a particular metric or domain. +- **Sudden series growth**: detect runaway cardinality increases caused by misconfigured exporters or new deployments. +- **High ingestion rate**: detect when too many samples per second are being ingested, even if the total series count is stable. + +Use these alert patterns to act on high-cardinality growth, and consider implementing [Adaptive Metrics recommendations](ref:adaptative-metrics) to keep your observability costs under control. + +## Choose metrics to monitor active series + +First, identify which metric reports the number of active time series. + +Prometheus, Mimir, and Grafana Cloud expose this information differently: + +| Environment | Metric | Description | +| :---------------------- | :------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **Prometheus** | `prometheus_tsdb_head_series` | Reports the number of active series currently stored in memory (the head block) of a single Prometheus instance. It includes series that have stopped receiving samples for up to one hour. | +| **Grafana Cloud** | `grafanacloud_instance_active_series` | Tracks the number of [active series in your Grafana Cloud Metrics backend (Mimir](ref:cloud-metrics-invoice)). | +| **Prometheus or Mimir** | `count({__name__!=""})` | Counts the number of series with recent samples by scanning the TSDB index. This query is expensive and should be exposed through a recording rule. | + +## Detect total active series near limits + +A high number of active series increases memory usage and can impact performance. Grafana Cloud enforces usage limits to prevent your instance from running into these performance issues. + +In Prometheus, you can alert when the total number of active series exceeds a threshold: + +```shell +prometheus_tsdb_head_series > 1.5e6 +``` + +This fires when the instance exceeds 1.5 million active series. +Adjust the threshold based on the capacity of your Prometheus host and observed load. + +In Grafana Cloud, use the `grafanacloud_instance_active_series` metric to monitor active series across your managed Mimir backend: + +```shell +grafanacloud_instance_active_series > 1.5e6 +``` + +Grafana Cloud also provides account-level limits through the `grafanacloud_instance_metrics_limits` metric. + +For more robust alerting, you can compare your current usage to the `max_global_series_per_user` limit: + +```shell +( + grafanacloud_instance_active_series + / on (id) + grafanacloud_instance_metrics_limits{limit_name="max_global_series_per_user"} +) +* on (id) group_left(name) grafanacloud_instance_info +> 0.9 + +``` + +- `grafanacloud_instance_active_series` + Returns the current number of active series per your Mimir (Prometheus) data source instance (`id`). + +- `/ on (id) grafanacloud_instance_metrics_limits{limit_name="max_global_series_per_user"}` + Divides current usage by the account limit to calculate a utilization ratio between 0 and 1 (where `1` means the limit is reached). + +- `* on (id) group_left(name) grafanacloud_instance_info` + Joins instance metadata to display the instance name. + +- `> 0.9` + Defines the threshold condition to fire when usage exceeds 90% of the limit. + Adjust this value according to your alert goal. Alternatively, you can set the threshold as a Grafana Alerting expression in the UI. + +## Detect high-cardinality per metric + +Instead of monitoring the total number of active series, you can fine-tune alerts to detect high cardinality within a specific scope โ€” for example, by filtering on certain namespaces, services, or metrics known to generate many label combinations. + +[Multi-dimensional alerts](ref:multi-dimensional-example) let you evaluate each metric independently, so you can identify which metric is responsible for the label explosion instead of only tracking the overall total. + +You can apply label filters, or use `{__name__=~"regex"}` to select specific metrics. Then, use `count by (__name__)` to group results per metric name. + +Because the `__name__` selector queries the entire TSDB index, itโ€™s recommended to query this using a **recording rule**: + +```shell +# Only HTTP/RPC-style metrics +active_series_per_metric:http_rpc = +label_replace( + count by (__name__) ({__name__=~"http_.*|rpc_.*"}), + "metric", "$1", "__name__", "(.*)" +) +``` + +This recording rule stores the number of active series per metric name. + +- `count by (__name__) ({__name__=~"http_.*|rpc_.*"})` + Counts the number of active series per metric matching the `http_.*` or `rpc_.*` regex. + +- `label_replace(..., "metric", "$1", "__name__", "(.*)")` + Copies the metric name into a new label called `metric`. + This enables generating one alert instance per metric because `__name__` is not treated as a regular label. + +Adjust the threshold and recording rule scope based on the label usage and normal behavior of your observed metrics. + +After the recording rule is available, you can define this multi-dimensional alert rule as follows: + +```shell +active_series_per_metric:http_rpc > 100 +``` + +Grafana Alerting evaluates each row (or time series) returned by the `active_series_per_metric:http_rpc` recording rule as a separate alert instance, producing independent alert instance states: + +| Alert instance | Value | State | +| :----------------------------------- | :---- | :----- | +| `{metric="http_requests_total"}` | 320 | Firing | +| `{metric="rpc_client_calls_total"}` | 45 | Normal | +| `{metric="rpc_server_errors_total"}` | 110 | Firing | + +Each metric name (`__name__`) becomes a separate alert instance, so you immediately see which metric exceeds the expected limit. + +## Detect sudden cardinality growth + +Even if the number of active series stays within proper limits, a sudden increase can signal a misbehaving exporter, a new deployment, or an unexpected label explosion. These peaks can help you prevent potential issues, or just inform you of deployment changes that might need adjustments. + +You can use any of the metrics from the previous examples to track short-term changes in the total active series: + +```shell +delta(active_series_metric[10m]) > 1000 +``` + +This alert fires when the number of active series increases by more than **1000** within the last 10 minutes. +Adjust the time window (for example, `[5m]` or `[30m]`) and threshold to match your environmentโ€™s normal variability. + +## Detect high ingestion rate + +Even if label cardinality remains under control, a high ingestion rate can affect Prometheus performance or increase observability costs. + +In Prometheus, this usually happens when scrapes occur too frequently or when exporters generate large numbers of samples in short intervals. + +To find an appropriate threshold to be alerted, start by monitoring normal ingestion peaks and set the threshold to a value that stays below the point where scrapes or WAL operations begin to slow down. + +In Prometheus, use the `prometheus_tsdb_head_samples_appended_total` metric to measure the number of samples appended per scrape: + +```shell +rate(prometheus_tsdb_head_samples_appended_total[10m]) > 1e5 +``` + +The alert rule query returns the average ingestion rate per second over the last 10 minutes and fires when the value exceeds 100 000 samples per second. + +In Grafana Cloud, use the `grafanacloud_instance_samples_per_second` metric to monitor total ingestion rate of your Mimir instances: + +```shell +grafanacloud_instance_samples_per_second + * on (id) group_left(name) grafanacloud_instance_info +> 1e5 +``` + +Alternatively, Grafana Cloud metrics limits are based on [data points per minute (DPM)](ref:cloud-metrics-invoice): the number of samples sent per minute across all your active series. + +To monitor when your actual data-point rate approaches your DPM limit, you can compare total ingestion to your planโ€™s DPM limit: + +```shell +( + (grafanacloud_instance_samples_per_second * 60) + / grafanacloud_org_metrics_included_dpm_per_series +) +> 0.9 + +``` + +- `(grafanacloud_instance_samples_per_second * 60)` + Converts ingestion rate from data points per second to minutes. + +- `/ grafanacloud_org_metrics_included_dpm_per_series` + Divides current DPM usage by the DPM limit to calculate a utilization ratio between 0 and 1 (where `1` means the limit is reached). + +- `> 0.9` + Defines the threshold condition to fire when the usage exceeds 90% of the DPM limit. + +This alert helps you detect when your organization is ingesting data faster and approaching its limits. Use ingestion rate alerts to detect workload spikes, exporter misconfigurations, or rapid increases in ingestion volume and cost. + +## Learn more + +Hereโ€™s list of additional resources related to this example: + +- [Multi-dimensional alerting example](ref:multi-dimensional-example) โ€“ Learn how Grafana creates separate alert instances for each unique label set. +- [Understand Grafana Cloud active series and DPM](ref:cloud-metrics-invoice)โ€“ See how active series and data points per minute (DPM) are used to calculate metrics usage in Grafana Cloud. +- [Create Grafana Cloud usage alerts](ref:usage-cost-alerts) โ€“ Set up alerts when your usage or costs approach your predefined limits. +- [Plan capacity for Mimir](ref:planning-mimir-capacity)โ€“ Learn how to plan ingestion rate and memory capacity for Mimir or Prometheus environments. +- [Adaptive Metrics recommendations](ref:adaptative-metrics) โ€“ Use Adaptive Metrics to automatically reduce high-cardinality metrics and control observability costs. diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md index 2829b14e235..fdfbca1bb85 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md @@ -241,17 +241,20 @@ The Alert object represents an alert included in the notification group, as prov ## Custom Payload +The `Custom Payload` option allows you to completely customize the webhook payload using [templates](ref:notification-templates). This gives you full control over the structure and content of the webhook request. + +For detailed information about how to create and manage notification templates, refer to [notification templates](ref:notification-templates). + {{< admonition type="note" >}} -Custom Payload is not yet [generally available](https://grafana.com/docs/release-life-cycle/#general-availability) in Grafana Cloud. +- When using Custom Payload, the [`Title` and `Message` fields](#optional-notification-settings) are ignored as the entire payload structure is determined by your template. +- Custom Payload is not yet [generally available](https://grafana.com/docs/release-life-cycle/#general-availability) in Grafana Cloud. {{< /admonition >}} -The `Custom Payload` option allows you to completely customize the webhook payload using templates. This gives you full control over the structure and content of the webhook request. - | Option | Description | | ----------------- | --------------------------------------------------------------------------------------------------------- | -| Payload Template | Template string that defines the structure of the webhook payload. | +| Payload Template | [Notification template](ref:notification-templates) that defines the structure of the webhook payload. | | Payload Variables | Key-value pairs that define additional variables available in the template under `.Vars.`. | Example of a custom payload template that includes variables: @@ -265,10 +268,6 @@ Example of a custom payload template that includes variables: } ``` -{{< admonition type="note" >}} -When using Custom Payload, the Title and Message fields are ignored as the entire payload structure is determined by your template. -{{< /admonition >}} - ### JSON Template Functions When creating custom payloads, several template functions are available to help generate valid JSON structures. These include functions for creating dictionaries (`coll.Dict`), arrays (`coll.Slice`, `coll.Append`), and converting between JSON strings and objects (`data.ToJSON`, `data.JSON`). diff --git a/docs/sources/alerting/configure-notifications/template-notifications/_index.md b/docs/sources/alerting/configure-notifications/template-notifications/_index.md index 0eb2ecb210d..75b110a9764 100644 --- a/docs/sources/alerting/configure-notifications/template-notifications/_index.md +++ b/docs/sources/alerting/configure-notifications/template-notifications/_index.md @@ -101,6 +101,24 @@ The notification template is assigned to the contact point to determine the noti By default, Grafana provides default templates, such as `{{define "default.title"}}` and `{{define "default.message"}}`, to format notification messages. +## Grafana Cloud AI-generated templates + +Grafana Cloud users can use built-in AI tool to generate templates in the appropriate [alerting template language](/docs/grafana-cloud/alerting-and-irm/alerting/configure-notifications/template-notifications/language/) for you. + +To use AI to create your template, follow these steps: + +1. Go to **Alerting -> Contact points**. + +1. Click the Notification Templates tab then, click the **+ Add notification template group** button. + +1. Name your template. + +1. In the Template group section, click the **Generate with AI** button. + +1. Supply the AI tool with a prompt or select from one of the example prompts and edit that if necessary. + +1. Click **Save**. + ## More information For further details on how to write notification templates, refer to: diff --git a/docs/sources/alerting/configure-notifications/template-notifications/examples.md b/docs/sources/alerting/configure-notifications/template-notifications/examples.md index 7927d367c94..f44ada3c4bf 100644 --- a/docs/sources/alerting/configure-notifications/template-notifications/examples.md +++ b/docs/sources/alerting/configure-notifications/template-notifications/examples.md @@ -89,7 +89,53 @@ This page provides various examples illustrating how to template common notifica Notification templates can access the [notification data](ref:reference-notification-data) using the dot (`.`). The following examples demonstrate some basic uses of the [template language](ref:language). -For instance, to check if there are common labels (`.CommonLabels`) for all alerts in the notification, use `if`: +### Text formatting examples + +Text formatting in notification templates varies by contact point type. Each platform has its own formatting syntax: + +#### Slack formatting + +For Slack contact points, you can use: + +```go +{{ define "slack_formatted_message" -}} +*This text will be bold in Slack* +_This text will be italic in Slack_ +Regular text without formatting +{{ end }} +``` + +Execute the template: + +```go +{{ template "slack_formatted_message" . }} +``` + +```template_output +*This text will be bold in Slack* +_This text will be italic in Slack_ +Regular text without formatting +``` + +#### Additional contact point types + +{{< admonition type="note" >}} +Each contact point type has its own formatting requirements: + +- Some support Markdown-style formatting +- Others use HTML tags +- Some may not support formatting at all + +Check your specific contact point's documentation for supported formatting syntax. +{{< /admonition >}} + +## Template logic examples + +Beyond text formatting, you can use template logic to create dynamic notification content. The following examples demonstrate basic template operations: + +### Conditional logic + +To check if there are common labels (`.CommonLabels`) for all alerts in the notification, use `if`: ```go {{ define "custom_message" -}} @@ -101,6 +147,8 @@ There are no common labels {{ end }} ``` +### Iterating over alerts + To iterate on the alerts in the notification and print a specific label, use `range` and `index`: ```go diff --git a/docs/sources/alerting/configure-notifications/template-notifications/manage-notification-templates.md b/docs/sources/alerting/configure-notifications/template-notifications/manage-notification-templates.md index e449bb6ecff..c2ac3c8fffc 100644 --- a/docs/sources/alerting/configure-notifications/template-notifications/manage-notification-templates.md +++ b/docs/sources/alerting/configure-notifications/template-notifications/manage-notification-templates.md @@ -62,6 +62,8 @@ To add an existing notification template to your contact point, complete the fol 1. Click **Save contact point**. +You can create custom notification templates using the **Enter custom message** tab. For reusable and consistent notifications, a best practice is to custom notification templates as described in the following section. + ## Create a notification template and notification template group Create notification templates to customize notification messages and reuse them in contact points. diff --git a/docs/sources/datasources/elasticsearch/_index.md b/docs/sources/datasources/elasticsearch/_index.md index 371d7282388..656182b251a 100644 --- a/docs/sources/datasources/elasticsearch/_index.md +++ b/docs/sources/datasources/elasticsearch/_index.md @@ -55,8 +55,9 @@ The following will help you get started working with Elasticsearch and Grafana: This data source supports these versions of Elasticsearch: -- v7.17+ +- โ‰ฅ v7.17 - v8.x +- v9.x Our maintenance policy for Elasticsearch data source is aligned with the [Elastic Product End of Life Dates](https://www.elastic.co/support/eol) and we ensure proper functionality for supported versions. If you are using an Elasticsearch with version that is past its end-of-life (EOL), you can still execute queries, but you will receive a notification in the query builder indicating that the version of Elasticsearch you are using is no longer supported. It's important to note that in such cases, we do not guarantee the correctness of the functionality, and we will not be addressing any related issues. diff --git a/docs/sources/developers/contribute.md b/docs/sources/developers/contribute.md index 8e54d7f044c..6f828a049ca 100644 --- a/docs/sources/developers/contribute.md +++ b/docs/sources/developers/contribute.md @@ -16,25 +16,43 @@ weight: 300 This page lists resources for developers who want to contribute to the Grafana software ecosystem or build plugins for Grafana. -## General resources +## Make technical contributions -These resources are useful for all developers. +Choose how you want to contribute to Grafana, from code to plugins to community support. -- [Contributing to Grafana](https://github.com/grafana/grafana/blob/main/CONTRIBUTING.md): Start here to learn how you can contribute your skills to make Grafana even better. +### Contribute Code to Grafana -- [Developer guide](https://github.com/grafana/grafana/blob/main/contribute/developer-guide.md): A guide to help you get started developing Grafana software, includes instructions for how to configure Grafana for development. +- [Contributing to Grafana](https://github.com/grafana/grafana/blob/main/CONTRIBUTING.md) introduces the contribution process and community resources. +- [Developer guide](https://github.com/grafana/grafana/blob/main/contribute/developer-guide.md) shows how to set up your environment and run Grafana in development. +- [Architecture guides](https://github.com/grafana/grafana/tree/main/contribute/architecture) explain Grafanaโ€™s background architecture. +- [Create a pull request](https://github.com/grafana/grafana/blob/main/contribute/create-pull-request.md) walks you through preparing a clear, descriptive pull request. +- Browse all [issues](https://github.com/grafana/grafana/issues) to find a good first task. You can also filter by [help wanted](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22). +- Use the [REST APIs](https://www.grafana.com/docs/grafana/next/developers/http_api) to interact programmatically with the Grafana backend. -- [Contributing to documentation](https://github.com/grafana/grafana/blob/main/contribute/documentation): A guide to help you contribute to Grafana documentation, includes links to beginner-friendly issues. +### Develop a Plugin -- [Architecture guides](https://github.com/grafana/grafana/tree/main/contribute/architecture): These guides explain Grafanaโ€™s background architecture. +- Read the [plugin development guide](https://grafana.com/developers/plugin-tools) to choose a plugin type, scaffold your project, and develop locally. -- [Create a pull request](https://github.com/grafana/grafana/blob/main/contribute/create-pull-request.md): A guide for new contributors about how to create your first Grafana pull request. +### Contribute without code -- [REST APIs](https://grafana.com/docs/grafana/next/developers/http_api) allow you to interact programmatically with the Grafana backend. +- Report a bug with the [bug report template](https://github.com/grafana/grafana/issues/new?template=0-bug-report.yaml) and include steps to reproduce. +- Submit a [feature request](https://github.com/grafana/grafana/issues/new?template=1-feature_requests.md) to propose improvements. +- Improve our docs with the [documentation contribution guide](https://github.com/grafana/grafana/blob/main/contribute/documentation). +- Help with [issue triage](https://github.com/grafana/grafana/blob/main/contribute/triage-issues.md) by reviewing, labeling, and clarifying open issues. +- Report security vulnerabilities following our [security policy](https://github.com/grafana/grafana/security/policy). + +## Choose the right channel + +Use the right place to ask questions, report problems, and propose changes. + +- **GitHub issues and pull requests**: Use for reproducible bugs in core Grafana and maintained plugins, small and actionable feature requests, and code or docs changes via pull requests. Avoid general โ€œhow do Iโ€ questions. For security issues, follow the [security policy](https://github.com/grafana/grafana/security/policy). +- **Grafana community forums**: Use for questions, troubleshooting, best practices, plugin development Q&A, and early idea discussion. Forums create a searchable public knowledge base that helps others with the same problems and questions. Start here if you are unsure: [Grafana community forums](https://community.grafana.com/). +- **Grafana Community Slack**: Use for quick, time-sensitive chats and networking. Do not rely on Slack for long troubleshooting or decisions. Share outcomes back to a forum topic or GitHub issue/PR to keep a public record: [Grafana Community Slack](https://slack.grafana.com). +- **Not sure where to start?** Start with a forum topic. Maintainers and community members will redirect you if a GitHub issue or pull request is more appropriate. ## Best practices and style -Our [style guides](https://github.com/grafana/grafana/tree/main/contribute/style-guides) outline Grafana style for frontend, backend, documentation, and more, including best practices. Please read through them before you start editing or coding! +Our [style guides](https://www.github.com/grafana/grafana/tree/main/contribute/style-guides) outline Grafana style for frontend, backend, documentation, and more, including best practices. Please read through them before you start editing or coding! - [Backend style guide](https://github.com/grafana/grafana/blob/main/contribute/backend/style-guide.md) explains how we want to write Go code in the future. diff --git a/docs/sources/developers/http_api/apis.md b/docs/sources/developers/http_api/apis.md index c00d34b4de7..5dc90cba139 100644 --- a/docs/sources/developers/http_api/apis.md +++ b/docs/sources/developers/http_api/apis.md @@ -42,11 +42,27 @@ Groups organize related functionality into logical collections. For example `das These APIs will also uses semantic versioning with three stability levels: -| Level | Format | Description | Use Case | -| ----- | ---------- | --------------------------------------------------------------------------- | ------------------------ | -| Alpha | `v1alpha1` | Early development stage. Unstable, may contain bugs, and subject to removal | For testing new features | -| Beta | `v1beta1` | More stable than alpha, but may still have some changes | For early production use | -| GA | `v1` | Generally Available. Stable with backward compatibility guarantees | For production use | +| Level | Format | Description | Use Case | Enabled By Default? | +| ----- | ---------- | --------------------------------------------------------------------------- | ------------------------ | ------------------- | +| Alpha | `v1alpha1` | Early development stage. Unstable, may contain bugs, and subject to removal | For testing new features | No | +| Beta | `v1beta1` | More stable than alpha, but may still have some changes | For non-critical use | No | +| GA | `v1` | Generally Available. Stable with backward compatibility guarantees | For production use | Yes | + +#### Alpha + +Alpha versions should not be served unless explicitly enabled by a feature flag, and should be considered completely experimental and subject to major changes. +An alpha version may undergo breaking changes without adding an additional version, and should not be relied upon by production workflows. Alpha versions may be removed completely, even without being promoted to a more stable level (e.g. an experimental API may be introduced as alpha for a new feature and subsequently removed completely, in case that feature gets canceled). + +#### Beta + +Beta versions should not contain breaking changes in the schema, but still may be subject to changes in handling logic or semantics. +Breaking schema changes require a new published beta version (such as publishing `v1beta2` for breaking changes to the `v1beta1` schema). +While beta versions are no longer considered experimental like alpha versions, they should still be disabled by default. + +#### GA + +GA versions are enabled by default, and can be treated as completely stable. The only changes that can be made to these APIs are bug fixes, +and any other changes should instead result in a new published version of the API. ### Namespace (``) diff --git a/docs/sources/developers/http_api/dashboard_versions.md b/docs/sources/developers/http_api/dashboard_versions.md index 33b59b97e48..fd9d3b85293 100644 --- a/docs/sources/developers/http_api/dashboard_versions.md +++ b/docs/sources/developers/http_api/dashboard_versions.md @@ -24,7 +24,7 @@ title: 'Dashboard Versions HTTP API ' Query parameters: -- **limit** - Maximum number of results to return +- **limit** - Maximum number of results to return. Defaults to 1000 if not set, or if an invalid value is passed in. - **start** - Version to start from when returning queries `GET /api/dashboards/uid/:uid/versions` diff --git a/docs/sources/developers/http_api/snapshot.md b/docs/sources/developers/http_api/snapshot.md index 4c17a5b8239..cae3828f2c6 100644 --- a/docs/sources/developers/http_api/snapshot.md +++ b/docs/sources/developers/http_api/snapshot.md @@ -99,7 +99,7 @@ Keys: Query parameters: - **query** โ€“ Search Query -- **limit** โ€“ Limit the number of returned results +- **limit** โ€“ Limit the number of returned results. Default is 1000 is not set or provided an invalid value. **Example Request**: diff --git a/docs/sources/developers/plugins/plugin.schema.json b/docs/sources/developers/plugins/plugin.schema.json index 8cb3954f13d..bc34bdad71d 100644 --- a/docs/sources/developers/plugins/plugin.schema.json +++ b/docs/sources/developers/plugins/plugin.schema.json @@ -106,6 +106,11 @@ "type": "string", "format": "uri", "description": "URL value to use for this specific link." + }, + "target": { + "type": "string", + "description": "A string that indicates where to display the linked resource", + "enum": ["_blank", "_self", "_parent", "_top"] } } } @@ -499,8 +504,8 @@ }, "state": { "type": "string", - "description": "Marks a plugin as a pre-release.", - "enum": ["alpha", "beta"] + "description": "Describes plugins life cycle status", + "enum": ["alpha", "beta", "stable", "deprecated"] }, "streaming": { "type": "boolean", @@ -588,7 +593,7 @@ "properties": { "addedComponents": { "type": "array", - "description": "This list must contain all component extensions that your plugin registers to other extension points using [`.addComponent()`](https://grafana.com/developers/plugin-tools/reference/ui-extensions#addcomponent). **Components that are not listed here won't work.**", + "description": "This list must contain all component extensions that your plugin registers to other extension points using [`.addComponent()`](https://grafana.com/developers/plugin-tools/reference/ui-extensions-reference/ui-extensions#addcomponent). **Components that are not listed here won't work.**", "items": { "type": "object", "properties": { @@ -614,7 +619,7 @@ }, "addedLinks": { "type": "array", - "description": "This list must contain all link extensions that your plugin registers to other extension points using [`.addLink()`](https://grafana.com/developers/plugin-tools/reference/ui-extensions#addlink). **Links that are not listed here won't work.**", + "description": "This list must contain all link extensions that your plugin registers to other extension points using [`.addLink()`](https://grafana.com/developers/plugin-tools/reference/ui-extensions-reference/ui-extensions#addlink). **Links that are not listed here won't work.**", "items": { "type": "object", "properties": { @@ -638,9 +643,35 @@ "required": ["targets", "title"] } }, + "addedFunctions": { + "type": "array", + "description": "This list must contain all function extensions that your plugin registers to other extension points using [`.addedFunctions()`](https://grafana.com/developers/plugin-tools/reference/ui-extensions-reference/ui-extensions#addfunction). **Functions that are not listed here won't work.**", + "items": { + "type": "object", + "properties": { + "targets": { + "type": "array", + "description": "The extension point ids your plugin registers the extension to, e.g. `[\"grafana/dashboard/panel/menu\"]`", + "items": { + "type": "string" + } + }, + "title": { + "type": "string", + "description": "The title of your function extension.", + "minLength": 10 + }, + "description": { + "type": "string", + "description": "Additional information about your function extension." + } + }, + "required": ["targets", "title"] + } + }, "exposedComponents": { "type": "array", - "description": "This list must contain all components that your plugin exposes using [`.exposeComponent()`](https://grafana.com/developers/plugin-tools/reference/ui-extensions#exposecomponent). **Components that are not listed here won't work.**", + "description": "This list must contain all components that your plugin exposes using [`.exposeComponent()`](https://grafana.com/developers/plugin-tools/reference/ui-extensions-reference/ui-extensions#exposecomponent). **Components that are not listed here won't work.**", "items": { "type": "object", "properties": { @@ -663,7 +694,7 @@ }, "extensionPoints": { "type": "array", - "description": "This list must contain all extension points that your plugin defines using [`usePluginLinks()`](https://grafana.com/developers/plugin-tools/reference/ui-extensions#usepluginlinks) or [`usePluginComponents()`](https://grafana.com/developers/plugin-tools/reference/ui-extensions#useplugincomponents). **Extension points that are not listed in here won't work.**", + "description": "This list must contain all extension points that your plugin defines using [`usePluginLinks()`](https://grafana.com/developers/plugin-tools/reference/ui-extensions-reference/ui-extensions#usepluginlinks) or [`usePluginComponents()`](https://grafana.com/developers/plugin-tools/reference/ui-extensions-reference/ui-extensions#useplugincomponents). **Extension points that are not listed in here won't work.**", "items": { "type": "object", "properties": { diff --git a/docs/sources/fundamentals/getting-started/_index.md b/docs/sources/fundamentals/getting-started/_index.md index c453b3d9570..bc66d9796dc 100644 --- a/docs/sources/fundamentals/getting-started/_index.md +++ b/docs/sources/fundamentals/getting-started/_index.md @@ -2,7 +2,7 @@ aliases: - ../guides/what-is-grafana/ # /docs/grafana/latest/guides/what-is-grafana/ - ../getting-started/ # /docs/grafana/latest/getting-started/ -description: Learn how build your first dashboard after you have installed Grafana. +description: Learn how to build your first dashboard after you have installed Grafana. labels: products: - enterprise diff --git a/docs/sources/introduction/grafana-enterprise.md b/docs/sources/introduction/grafana-enterprise.md index ef8884f3c55..023aa5d6583 100644 --- a/docs/sources/introduction/grafana-enterprise.md +++ b/docs/sources/introduction/grafana-enterprise.md @@ -107,6 +107,7 @@ With a Grafana Enterprise license, you also get access to premium data sources, - [SAP HANAยฎ](/grafana/plugins/grafana-saphana-datasource) - [ServiceNow](/grafana/plugins/grafana-servicenow-datasource) - [Snowflake](/grafana/plugins/grafana-snowflake-datasource) +- [SolarWinds](/grafana/plugins/grafana-solarwinds-datasource) - [Splunk](/grafana/plugins/grafana-splunk-datasource) - [Splunk Infrastructure monitoring (SignalFx)](/grafana/plugins/grafana-splunk-monitoring-datasource) - [Sqlyze Datasource](/grafana/plugins/grafana-odbc-datasource) diff --git a/docs/sources/observability-as-code/grafana-cli/grafanacli-workflows.md b/docs/sources/observability-as-code/grafana-cli/grafanacli-workflows.md index b8128d211cd..33489050eed 100644 --- a/docs/sources/observability-as-code/grafana-cli/grafanacli-workflows.md +++ b/docs/sources/observability-as-code/grafana-cli/grafanacli-workflows.md @@ -95,7 +95,7 @@ This workflow helps you back up all Grafana resources from one instance and late With this workflow, you can define and manage dashboards as code, saving them to a version control system like Git. This is useful for teams that want to maintain a history of changes, collaborate on dashboard design, and ensure consistency across environments. -1. Use a dashboard generation script (for example, with the [Foundation SDK](https://github.com/grafana/grafana-foundation-sdk)). You can find an example implementation in the Grafana as code [hands-on lab repository](https://github.com/grafana/dashboards-as-code-workshop/tree/main/part-one-golang). +1. Use a dashboard generation script (for example, with the [Foundation SDK](https://github.com/grafana/grafana-foundation-sdk)). You can find an example implementation in the Grafana as code [hands-on lab repository](https://github.com/grafana/dashboards-as-code-workshop/tree/main/part-one-golang-starter). 1. Serve and preview the output of the dashboard generator locally: diff --git a/docs/sources/observability-as-code/provision-resources/_index.md b/docs/sources/observability-as-code/provision-resources/_index.md index c8e6b313eec..6e0f1665d67 100644 --- a/docs/sources/observability-as-code/provision-resources/_index.md +++ b/docs/sources/observability-as-code/provision-resources/_index.md @@ -1,5 +1,5 @@ --- -description: Learn about how to provision resource using Git Sync and local file provisioning administration. +description: Learn about how to provision resources using Git Sync and local file provisioning administration. keywords: - observability - configuration @@ -12,6 +12,7 @@ labels: - enterprise - oss title: Provision resources and sync dashboards +menuTitle: Provision resources weight: 300 --- diff --git a/docs/sources/observability-as-code/provision-resources/git-sync-setup.md b/docs/sources/observability-as-code/provision-resources/git-sync-setup.md index fbe43aa7a57..a4bbe8667e7 100644 --- a/docs/sources/observability-as-code/provision-resources/git-sync-setup.md +++ b/docs/sources/observability-as-code/provision-resources/git-sync-setup.md @@ -130,7 +130,7 @@ To connect your GitHub repository, follow these steps: {{< admonition type="caution" >}} -If you're using Git Sync in Grafana Cloud you can only sync specific folders for the moment. Git Sync will be available for your full instance soon. +Git Sync only works with specific folders for the moment. Full-instance sync is not currently supported. Refer to [Supported resources](/docs/grafana//observability-as-code/provision-resources/intro-git-sync#supported-resources) for more details about which resources you can sync. {{< /admonition >}} diff --git a/docs/sources/observability-as-code/provision-resources/intro-git-sync.md b/docs/sources/observability-as-code/provision-resources/intro-git-sync.md index d99fdbdca6e..25ec1d13806 100644 --- a/docs/sources/observability-as-code/provision-resources/intro-git-sync.md +++ b/docs/sources/observability-as-code/provision-resources/intro-git-sync.md @@ -9,6 +9,7 @@ labels: products: - enterprise - oss + - cloud title: Git Sync weight: 100 --- @@ -35,8 +36,18 @@ Using Git Sync, you can: ## How it works +{{< admonition type="caution" >}} + +Git Sync only works with specific folders for the moment. Full-instance sync is not currently supported. + +{{< /admonition >}} + Git Sync is bidirectional and works both with changes done directly in GitHub as well as in the Grafana UI. +### Provisioning folder + +Git Sync creates a folder for all the synchronized resources to live under. You can continue to have unprovisioned resources outside that folder. + ### Make changes in Grafana Whenever you modify a dashboard directly from the UI, Grafana can commit changes to Git upon saving. You can configure settings to either enforce PR approvals before merging in your repository, or allow direct commits. @@ -48,17 +59,41 @@ Grafana periodically polls GitHub at a regular internal to synchronize any chang ### Make changes in your GitHub repositories -With Git Sync, you can make changes in your provisioned files in GitHub and see them in Grafana. Automated workflows ensure those changes are automatically represented in the Grafana database by updating Git. The Grafana UI reads the database and updates the UI to reflect these changes. +With Git Sync, you can make changes to the files in the provisioned folder in GitHub and see them in Grafana. Automated workflows ensure those changes are automatically represented in the Grafana database by updating Git. The Grafana UI reads the database and updates the UI to reflect these changes. ## Known limitations Git Sync is under development and the following limitations apply: +- You can only sync dashboards and folders. Refer to [Supported resources](#supported-resources) for more information. + - If you're using Git Sync in Grafana OSS and Grafana Enterprise, some resources might be in an incompatible data format and can't be synced. - You can only authenticate in GitHub using your Personal Access Token token. - Support for native Git, Git app, and other providers, such as GitLab or Bitbucket, is on the roadmap. -- If you're using Git Sync in Grafana Cloud you can only sync specific folders for the moment. Git Sync will be available for your full instance soon. - Restoring resources from the UI is currently not possible. As an alternative, you can restore dashboards directly in your GitHub repository by raising a PR, and they will be updated in Grafana. +## Supported resources + +Git Sync only supports dashboards and folders. Alerts, panels, and other resources are not supported yet. + +If you're using Git Sync in Grafana OSS or Grafana Enterprise, some supported resources might be in an incompatible data format. If this happens, syncing will be blocked. Compatibility issues will be fixed with an upcoming migration tool. + +### Resource states + +A resource can be: + +| Is the resource? | **Compatible** | **Incompatible** | +| ---------------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| **Supported** | The resource can be managed with Git Sync. | The resource is supported but has compatibility issues. It **cannot** be managed with Git Sync. | +| **Unsupported** | The resource is **not** supported and **cannot** be managed with Git Sync. | Not applicable. | + +### Instance states + +An instance can be in one of the following states: + +- **Unprovisioned**: None of the instance's resources are being managed by Git Sync. +- **Partially provisioned**: Some of the resources are controlled by Git Sync. +- **Fully provisioned**: All supported resource types are managed by Git Sync. Note that unsupported resources are not managed. + ## Common use cases You can use Git Sync in the following scenarios. diff --git a/docs/sources/setup-grafana/configure-grafana/_index.md b/docs/sources/setup-grafana/configure-grafana/_index.md index 9702851cd19..b0b328866d6 100644 --- a/docs/sources/setup-grafana/configure-grafana/_index.md +++ b/docs/sources/setup-grafana/configure-grafana/_index.md @@ -1641,11 +1641,35 @@ Syslog tag. By default, the process's `argv[0]` is used. #### `enabled` -Faro JavaScript agent is initialized. Default is `false`. +Grafana Faro instrumentation is initialized. Default is `false`. Enables the default set of instrumentations from `getWebInstrumentations`. See the options below to selectively disable some of these. #### `custom_endpoint` -Custom HTTP endpoint to send events captured by the Faro agent to. Default, `/log-grafana-javascript-agent`, logs the events to standard output. +Custom HTTP endpoint to send events captured by the Grafana Faro agent to. Default, `/log-grafana-javascript-agent`, logs the events to standard output. + +#### `api_key` + +If `custom_endpoint` required authentication, you can set the API key here. Only relevant for Grafana JavaScript Agent provider. + +#### `instrumentations_console_enabled` + +Enables the [Console instrumentation](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/console-instrumentation/) for Grafana Faro, defaults to `true`. + +#### `instrumentations_performance_enabled` + +Enables the [Performance instrumentation](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/performance-instrumentation/) for Grafana Faro, defaults to `true`. + +#### `instrumentations_csp_enabled` + +Enables the [Content Security Policy Violations instrumentation](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/csp-violation-tracking/) for Grafana Faro, defaults to `true`. + +#### `instrumentations_tracing_enabled` + +Enables the [Tracing instrumentation](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/tracing-instrumentation/) for Grafana Faro, defaults to `true`. + +#### `web_vitals_attribution_enabled` + +Enables sending [attribution data for web vitals](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/web-vitals/#web-vitals-attribution-data) with the Performance instrumentation, defaults to `true`. #### `log_endpoint_requests_per_second_limit` @@ -1655,29 +1679,9 @@ Requests per second limit enforced per an extended period, for Grafana backend l Maximum requests accepted per short interval of time for Grafana backend log ingestion endpoint, `/log-grafana-javascript-agent`. Default is `15`. -#### `instrumentations_all_enabled` +#### `bot_filter_enabled` -Enables all Faro default instrumentation by using `getWebInstrumentations`. Overrides other instrumentation flags. - -#### `instrumentations_errors_enabled` - -Turn on error instrumentation. Only affects Grafana JavaScript Agent. - -#### `instrumentations_console_enabled` - -Turn on console instrumentation. Only affects Grafana JavaScript Agent - -#### `instrumentations_webvitals_enabled` - -Turn on web vitals instrumentation. Only affects Grafana JavaScript Agent - -#### `instrumentations_tracing_enabled` - -Turns on tracing instrumentation. Only affects Grafana JavaScript Agent. - -#### `api_key` - -If `custom_endpoint` required authentication, you can set the API key here. Only relevant for Grafana JavaScript Agent provider. +Enables the bot filter for the Grafana Faro JavaScript agent integration. Default is `false`. When enabled, it will filter out requests from known bots and crawlers.
diff --git a/docs/sources/setup-grafana/configure-grafana/enterprise-configuration/index.md b/docs/sources/setup-grafana/configure-grafana/enterprise-configuration/index.md index c7570c71eaa..82eec98249a 100644 --- a/docs/sources/setup-grafana/configure-grafana/enterprise-configuration/index.md +++ b/docs/sources/setup-grafana/configure-grafana/enterprise-configuration/index.md @@ -112,6 +112,22 @@ Decide whether or not to enable the TLS (Transport Layer Security) protocol when Set the tenant ID for Loki communication, which is disabled by default. The tenant ID is required to interact with Loki running in [multi-tenant mode](/docs/loki/latest/operations/multi-tenancy/). +### batch_wait_duration + +How long to wait before sending a request to Loki with the batch of events. Uses duration format: e.g. 5s, 1m. Defaults to 5s. + +Whatever happens first between `batch_wait_duration` and `batch_size_bytes` will trigger the batch to be sent to Loki. + +If the wait duration is very long and the `batch_size_bytes` is very high, events may take a long time to be sent. + +### batch_size_bytes + +How many events (in bytes) to accumulate in a single batch before sending it to Loki. Defaults to 100 KiB. + +Whatever happens first between `batch_wait_duration` and `batch_size_bytes` will trigger the batch to be sent to Loki. + +If you wish to always wait for the `batch_wait_duration`, set this to a very high number. + ## [analytics.summaries] ### buffer_write_interval diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index e8b12113400..9ab20621103 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -109,7 +109,9 @@ Most [generally available](https://grafana.com/docs/release-life-cycle/#general- | `azureMonitorLogsBuilderEditor` | Enables the logs builder mode for the Azure Monitor data source | | `localeFormatPreference` | Specifies the locale so the correct format for numbers and dates can be shown | | `logsPanelControls` | Enables a control component for the logs panel in Explore | +| `grafanaPathfinder` | Enables Pathfinder app | | `azureResourcePickerUpdates` | Enables the updated Azure Monitor resource picker | +| `preventPanelChromeOverflow` | Restrict PanelChrome contents with overflow: hidden; | ## Development feature toggles diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/saml/configure-saml-org-mapping/_index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/saml/configure-saml-org-mapping/_index.md index b2486a51b98..049f47b94f0 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/saml/configure-saml-org-mapping/_index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/saml/configure-saml-org-mapping/_index.md @@ -24,6 +24,10 @@ assertion_attribute_org = Org org_mapping = Engineering:2:Editor, Sales:3:Admin ``` +{{< admonition type="warning" >}} +The `org_mapping` option stores mappings in the database as JSON. Size limits depend on your database. In MySQL before Grafana 12.3, the limit is 65,535 bytes. From Grafana 12.3, the column uses `MEDIUMTEXT`, raising the MySQL limit to 16,777,215 bytes (~16 MB). If you need to split users into more granular control, we suggest using [Role and Team Sync](../configure-saml-team-role-mapping/) instead. +{{< /admonition >}} + Starting from Grafana version 11.5, you can use the organization name instead of the organization ID in the `org_mapping` option. Ensure that the organization name you configure matches exactly with the organization name in Grafana, as it is case-sensitive. If the organization name is not found in Grafana, the mapping will be ignored. If the external organization or the organization name contains spaces, use the JSON syntax for the `org_mapping` option: ```ini diff --git a/docs/sources/setup-grafana/configure-security/export-logs.md b/docs/sources/setup-grafana/configure-security/export-logs.md index f55336f8a67..e2ca4ad221c 100644 --- a/docs/sources/setup-grafana/configure-security/export-logs.md +++ b/docs/sources/setup-grafana/configure-security/export-logs.md @@ -94,6 +94,14 @@ tls = true # Set the tenant ID for Loki communication, which is disabled by default. # The tenant ID is required to interact with Loki running in multi-tenant mode. tenant_id = +# How long to wait before sending a request to Loki with the batch of events. Uses duration format: e.g. 5s, 1m +# Whatever happens first between `batch_wait_duration` and `batch_size_bytes` will trigger the batch to be sent to Loki. +# If the wait duration is very long and the `batch_size_bytes` is very high, events may take a long time to be sent. +batch_wait_duration = 5s +# How many events (in bytes) to accumulate in a single batch before sending it to Loki. +# Whatever happens first between `batch_wait_duration` and `batch_size_bytes` will trigger the batch to be sent to Loki. +# If you wish to always wait for the `batch_wait_duration`, set this to a very high number. +batch_size_bytes = 102400 # 100KiB ``` Using `logger` will print usage insights to your [Grafana server log](../../configure-grafana/#log). diff --git a/docs/sources/setup-grafana/configure-security/manage-single-access.md b/docs/sources/setup-grafana/configure-security/manage-single-access.md new file mode 100644 index 00000000000..1ca84d68960 --- /dev/null +++ b/docs/sources/setup-grafana/configure-security/manage-single-access.md @@ -0,0 +1,158 @@ +--- +aliases: + - ../../enterprise/manage-single-access/ +description: Manage multi-team access in a single Grafana instance +keywords: + - grafana + - rbac + - lbac + - auth + - access + - teams +labels: + products: + - cloud + - enterprise +title: Manage multi-team access in a single Grafana instance +weight: 1200 +refs: + create-folder: + - pattern: /docs/grafana/ + destination: /docs/grafana//dashboards/manage-dashboards/#create-a-dashboard-folder + - pattern: /docs/grafana-cloud/ + destination: /docs/grafana-cloud/visualizations/dashboards/manage-dashboards/#create-a-dashboard-folder + rbac: + - pattern: /docs/grafana/ + destination: /docs/grafana//administration/roles-and-permissions/access-control + - pattern: /docs/grafana-cloud/ + destination: /docs/grafana-cloud/security-and-account-management/authentication-and-permissions/access-control + rbac-assign: + - pattern: /docs/grafana/ + destination: /docs/grafana//administration/roles-and-permissions/access-control/assign-rbac-roles + - pattern: /docs/grafana-cloud/ + destination: /docs/grafana-cloud/security-and-account-management/authentication-and-permissions/access-control/assign-rbac-roles + rbac-fixed: + - pattern: /docs/grafana/ + destination: /docs/grafana//administration/roles-and-permissions/access-control/rbac-fixed-basic-role-definitions/#fixed-role-definitions + - pattern: /docs/grafana-cloud/ + destination: /docs/grafana-cloud/security-and-account-management/authentication-and-permissions/access-control/rbac-fixed-basic-role-definitions/#fixed-role-definitions + drilldown: + - pattern: /docs/grafana/ + destination: /docs/grafana/}} +For guidance on when to use one stack versus multiple, refer to [Stack architecture guidance](https://grafana.com/docs/grafana-cloud/security-and-account-management/cloud-stacks/stack-architecture-guidance/). +{{< /admonition >}} + +### Create teams and configure user access + +After youโ€™ve deployed your Grafana instance: + +- To follow the example in this doc, create three [Grafana Teams](../../../administration/team-management/configure-grafana-teams/#create-a-grafana-team) and add them to the Grafana instance. +- Determine the [RBAC](ref:rbac) strategy for your organization. RBAC extends default Grafana roles, provides more granular access rights, and simplifies how to grant, modify, or revoke user access to Grafana resources, such as users and reports. +- Assign each user to the [relevant team](../../../administration/user-management/manage-org-users/). By default [new users](../../configure-grafana/#auto_assign_org) are granted the **Viewer** role. +- Assign the [**Admin** role](ref:rbac-assign) to Team C so that they can manage all resources in the instance. + +### Design a folder structure to match your access needs + +To design a [folder](ref:create-folder) setup that helps users quickly understand where to go, what they can access, and what they can manage: + +- Create an โ€œEveryoneโ€ folder for shared items that all teams can manage, and grant teams Admin access to that folder. +- For each team, create a folder that they can manage and grant them the `fixed:teams:read` [fixed role](ref:rbac-assign). This means they can share items in their team folder with other teams, to encourage collaboration and learning from each other. +- For Team C, create an โ€œAdminsโ€ folder for sensitive content only Admins can access. +- Optionally, create a personal folder for each team member so that they can work on draft content before moving it into their team folder when ready. + +{{< figure src="/media/docs/grafana/oac/AccessTeams01.png" max-width="750px" alt="Teams and folders in the stack, and the related admin permissions Team A and Team B have been granted" >}} + +### Configure data access based on team requirements + +Next, focus on how teams interact with data to decide further access needs. + +#### Shared baseline data access + +Grant the `datasources:explorer` fixed role to all teams so they can use the [Drilldown apps](ref:drilldown) for easily exploring data sources. + +However, you may need to protect data in shared resources. For example, all teams can be forwarding metrics to a shared [data source](ref:add-data-source), but not everyone needs to see all of the data. In this case, grant each team query access to the data relevant for them, based on [label based access controls (LBAC) per team](ref:lbac). This way, youโ€™ll maintain a central observability pipeline but still preserve data separation. + +#### Autonomous team data management + +If any of your teams, Team A for example, need to build and manage their own data sources for product-specific use cases, grant the `datasources:creator` fixed role so they can create and manage their own data sources independently. + +{{< figure src="/media/docs/grafana/oac/AccessTeams02.png" max-width="750px" alt="Teams and data sources in the stack, and the related permissions Team A and Team B have been granted" >}} + +#### Resources at an instance level + +Some Grafana resources, such as service accounts, alert contact points, [Fleet Management collectors](https://grafana.com/docs/grafana-cloud/send-data/fleet-management/), and other feature resources, are not linked to teams but are managed at the stack level. For these type of resources, assign fixed roles to teams carefully. + +For example, users working in [Frontend Observability](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/) need a writer fixed role so that they can create and manage services. + +{{< figure src="/media/docs/grafana/oac/AccessTeams03.png" max-width="750px" alt="Grafana Cloud Frontend Observability resources in the stack, and the related permissions Team A have been granted" >}} + +### Scale access management with Terraform and SSO + +After you've made sure the model is working, you can codify it. + +You can add any new users to your Grafana instance with an Identity Provider through [SCIM](../../configure-security/configure-scim-provisioning/). Use [role sync](../../configure-security/configure-authentication/saml/configure-saml-team-role-mapping/#configure-role-sync-for-saml) to automatically assign users the correct basic role (Viewer, Editor, or Admin) based on their mapped attributes in the IdP.. + +You can also use Terraform to provision teams their folders, fixed roles, and shared data source LBAC rules. For example, if you need to add a new team (Team D), you only need to add the new team to Grafana and run the Terraform script, which will automatically set them up to start using Grafana. + +{{< figure src="/media/docs/grafana/oac/AccessTeams04.png" max-width="750px" alt="Add new Team D from Okta and automate the rest of their IAM setup using Terraform" >}} + +## Other resources + +Read on to learn more about access management: + +- The [Least privilege custom role explainer](https://grafana.com/blog/2024/09/10/grafana-access-management-how-to-use-teams-for-seamless-user-and-permission-management/) blog walks through how to design roles that keep things simple and safe, so your users have just the access they need. +- See the [LBAC for metrics data sources](https://www.youtube.com/watch?v=gj27qKPSVsM) demo to learn how you can give every team a clear view of their own data while still benefiting from a shared pipeline. +- The [Introducing SCIM](https://grafana.com/blog/2025/05/14/introducing-scim-provisioning-in-grafana-enterprise-grade-user-management-made-simple/) post covers how to connect Grafana to your identity provider, making it easy to bring new users on board and keep permissions in sync as your organization grows. diff --git a/docs/sources/shared/alerts/example-custom-json-payload.md b/docs/sources/shared/alerts/example-custom-json-payload.md index cebf6183fa5..7182d59abf2 100644 --- a/docs/sources/shared/alerts/example-custom-json-payload.md +++ b/docs/sources/shared/alerts/example-custom-json-payload.md @@ -8,6 +8,7 @@ title: 'Custom webhook example' --- ```go +{- /* Generates a pretty-printed JSON payload with alert group info and individual alerts metadata. */ -}} {{ define "webhook.custom.payload" -}} {{ coll.Dict "receiver" .Receiver diff --git a/docs/sources/tutorials/alerting-get-started-pt5/index.md b/docs/sources/tutorials/alerting-get-started-pt5/index.md index fe89a2a3b18..576763e1e16 100644 --- a/docs/sources/tutorials/alerting-get-started-pt5/index.md +++ b/docs/sources/tutorials/alerting-get-started-pt5/index.md @@ -23,6 +23,8 @@ killercoda: The Get started with Grafana Alerting - Dynamic routing tutorial is a continuation of the [Get started with Grafana Alerting - Templating](http://www.grafana.com/tutorials/alerting-get-started-pt4/) tutorial. +{{< youtube id="hSejnv1cdYY" >}} + Imagine you are managing a web application or a fleet of servers, tracking critical metrics such as CPU, memory, and disk usage. While monitoring is essential, managing alerts allows your team to act on issues without necessarily feeling overwhelmed by the noise. In this tutorial you will learn how to: diff --git a/docs/sources/visualizations/_index.md b/docs/sources/visualizations/_index.md new file mode 100644 index 00000000000..55c03c0f06d --- /dev/null +++ b/docs/sources/visualizations/_index.md @@ -0,0 +1,48 @@ +--- +aliases: + - /docs/grafana-cloud/visualization/ + - /docs/grafana-cloud/visualizations/ +description: Learn how to build dashboards and visualizations. +menuTitle: Visualize data +title: Visualize your data in Grafana +hero: + title: Visualize data + level: 1 + width: 100 + height: 100 + description: Easily collect, correlate, and visualize data with beautiful dashboards using Grafana—the solution that drives informed decisions, enhances system performance, and streamlines troubleshooting. +cards: + items: + - description: Allow you to query, transform, visualize, and understand your data no matter where itโ€™s stored. + height: 24 + href: /docs/grafana-cloud/visualizations/dashboards/ + title: Dashboards + - description: Allow you to easily collect, correlate, and visualize data so you can make informed decisions in real time. + height: 24 + href: /docs/grafana-cloud/visualizations/panels-visualizations/ + title: Panels and visualizations + - description: Use the Drilldown apps to explore your telemetry data with a queryless experience. + height: 24 + href: /docs/grafana-cloud/visualizations/simplified-exploration/ + title: Drilldown apps + +weight: 500 +--- + +{{< docs/hero-simple key="hero" >}} + +--- + +## Overview + +A Grafana dashboard is a set of one or more panels that provide an at-a-glance view of related information. These panels are the basic building block in Grafana dashboards, and they're created using components that query and transform raw data from a data source into charts, graphs, and other visualizations. + +A data source can be an SQL database, Grafana Loki, Grafana Mimir, or a JSON-based API. It can even be a basic CSV file. Queries allow you to reduce the entirety of your data to a specific dataset, providing a more manageable visualization. Data source plugins take a query you want answered, retrieve the data from the data source, and reconcile the differences between the data model of the data source and the data model of Grafana dashboards. + +The growing suite of Grafana visualizations, ranging from time series graphs to heatmaps to cutting-edge 3D charts, provide you several different ways to present your data within a panel, depending on what best suits the data and your needs. If the data format in a visualization doesnโ€™t meet your requirements, you can apply a transformation that manipulates the data returned by a query. + +With 150+ data source plugins, you can unify all your data sources into a single dashboard to streamline data monitoring and troubleshooting. With Grafana, you can translate, transform, and visualize data in flexible and versatile dashboards. + +## Explore + +{{< card-grid key="cards" type="simple" >}} diff --git a/docs/sources/dashboards/_index.md b/docs/sources/visualizations/dashboards/_index.md similarity index 94% rename from docs/sources/dashboards/_index.md rename to docs/sources/visualizations/dashboards/_index.md index c919c48debb..03c1b9724b7 100644 --- a/docs/sources/dashboards/_index.md +++ b/docs/sources/visualizations/dashboards/_index.md @@ -1,7 +1,8 @@ --- aliases: - - features/dashboard/dashboards/ # /docs/grafana/latest/features/dashboard/dashboards/ - - ./dashboards/previews/ # /docs/grafana/latest/dashboards/previews/ + - ../features/dashboard/dashboards/ # /docs/grafana/latest/features/dashboard/dashboards/ + - ../dashboards/previews/ # /docs/grafana/latest/dashboards/previews/ + - ../dashboards/ # /docs/grafana/next/dashboards/ labels: products: - cloud diff --git a/docs/sources/dashboards/assess-dashboard-usage/index.md b/docs/sources/visualizations/dashboards/assess-dashboard-usage/index.md similarity index 92% rename from docs/sources/dashboards/assess-dashboard-usage/index.md rename to docs/sources/visualizations/dashboards/assess-dashboard-usage/index.md index e989ec12470..2030cd1b2d8 100644 --- a/docs/sources/dashboards/assess-dashboard-usage/index.md +++ b/docs/sources/visualizations/dashboards/assess-dashboard-usage/index.md @@ -1,9 +1,10 @@ --- aliases: - - ../enterprise/usage-insights/ - - ../enterprise/usage-insights/dashboard-datasource-insights/ - - ../enterprise/usage-insights/improved-search/ - - ../enterprise/usage-insights/presence-indicator/ + - ../../enterprise/usage-insights/ # /docs/grafana/next/enterprise/usage-insights/ + - ../../enterprise/usage-insights/dashboard-datasource-insights/ # /docs/grafana/next/enterprise/usage-insights/dashboard-datasource-insights/ + - ../../enterprise/usage-insights/improved-search/ # /docs/grafana/next/enterprise/usage-insights/improved-search/ + - ../../enterprise/usage-insights/presence-indicator/ # /docs/grafana/next/enterprise/usage-insights/presence-indicator/ + - ../../dashboards/assess-dashboard-usage/ # /docs/grafana/next/dashboards/assess-dashboard-usage/ description: Understand how your Grafana instance is used keywords: - grafana diff --git a/docs/sources/dashboards/build-dashboards/_index.md b/docs/sources/visualizations/dashboards/build-dashboards/_index.md similarity index 86% rename from docs/sources/dashboards/build-dashboards/_index.md rename to docs/sources/visualizations/dashboards/build-dashboards/_index.md index 4978be9dd35..5432ff0671d 100644 --- a/docs/sources/dashboards/build-dashboards/_index.md +++ b/docs/sources/visualizations/dashboards/build-dashboards/_index.md @@ -21,6 +21,8 @@ refs: destination: /docs/grafana//dashboards/variables/ - pattern: /docs/grafana-cloud/ destination: /docs/grafana//dashboards/variables/ +aliases: + - ../../dashboards/build-dashboards/ # /docs/grafana/next/dashboards/build-dashboards/ --- # Build dashboards diff --git a/docs/sources/dashboards/build-dashboards/annotate-visualizations/index.md b/docs/sources/visualizations/dashboards/build-dashboards/annotate-visualizations/index.md similarity index 96% rename from docs/sources/dashboards/build-dashboards/annotate-visualizations/index.md rename to docs/sources/visualizations/dashboards/build-dashboards/annotate-visualizations/index.md index 81f6ce065f1..47f088783f5 100644 --- a/docs/sources/dashboards/build-dashboards/annotate-visualizations/index.md +++ b/docs/sources/visualizations/dashboards/build-dashboards/annotate-visualizations/index.md @@ -1,7 +1,9 @@ --- aliases: - - ../../reference/annotations/ - - ../annotations/ + - ../../../dashboards/annotations/ # /docs/grafana/next/annotations/ + - ../../../dashboards/build-dashboards/annotate-visualizations/ # /docs/grafana/next/dashboards/build-dashboards/annotate-visualizations/ + - ../../../panels/visualizations/annotations/ # /docs/grafana/next/panels/visualizations/annotations/ + - ../../../reference/annotations/ # /docs/grafana/latest/reference/annotations/ keywords: - grafana - annotations diff --git a/docs/sources/dashboards/build-dashboards/best-practices/index.md b/docs/sources/visualizations/dashboards/build-dashboards/best-practices/index.md similarity index 95% rename from docs/sources/dashboards/build-dashboards/best-practices/index.md rename to docs/sources/visualizations/dashboards/build-dashboards/best-practices/index.md index e67a1a87ead..df7f3f2e648 100644 --- a/docs/sources/dashboards/build-dashboards/best-practices/index.md +++ b/docs/sources/visualizations/dashboards/build-dashboards/best-practices/index.md @@ -1,11 +1,12 @@ --- aliases: - - ../../best-practices/ - - ../../best-practices/best-practices-for-creating-dashboards/ - - ../../best-practices/best-practices-for-managing-dashboards/ - - ../../best-practices/common-observability-strategies/ - - ../../best-practices/dashboard-management-maturity-levels/ - - ../../getting-started/strategies/ + - ../../../best-practices/ # /docs/grafana/next/best-practices/ + - ../../../best-practices/best-practices-for-creating-dashboards/ # /docs/grafana/next/best-practices/best-practices-for-creating-dashboards/ + - ../../../best-practices/best-practices-for-managing-dashboards/ # /docs/grafana/next/best-practices/best-practices-for-managing-dashboards/ + - ../../../best-practices/common-observability-strategies/ # /docs/grafana/next/best-practices/common-observability-strategies/ + - ../../../best-practices/dashboard-management-maturity-levels/ # /docs/grafana/next/best-practices/dashboard-management-maturity-levels/ + - ../../../getting-started/strategies/ # /docs/grafana/next/getting-started/strategies/ + - ../../../dashboards/build-dashboards/best-practices/ # /docs/grafana/next/dashboards/build-dashboards/best-practices/ description: Learn best practices for building and maintaining Grafana dashboards labels: products: diff --git a/docs/sources/dashboards/build-dashboards/create-dashboard-url-variables/index.md b/docs/sources/visualizations/dashboards/build-dashboards/create-dashboard-url-variables/index.md similarity index 93% rename from docs/sources/dashboards/build-dashboards/create-dashboard-url-variables/index.md rename to docs/sources/visualizations/dashboards/build-dashboards/create-dashboard-url-variables/index.md index 49639f74d01..b1f9d5ed609 100644 --- a/docs/sources/dashboards/build-dashboards/create-dashboard-url-variables/index.md +++ b/docs/sources/visualizations/dashboards/build-dashboards/create-dashboard-url-variables/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../../variables/url-variables/ - - ../../variables/variable-types/url-variables/ + - ../../../variables/url-variables/ # /docs/grafana/next/variables/url-variables/ + - ../../../variables/variable-types/url-variables/ # /docs/grafana/next/variables/variable-types/url-variables/ + - ../../../dashboards/build-dashboards/create-dashboard-url-variables/ # /docs/grafana/next/dashboards/build-dashboards/create-dashboard-url-variables/ keywords: - grafana - url variables diff --git a/docs/sources/dashboards/build-dashboards/create-dashboard/index.md b/docs/sources/visualizations/dashboards/build-dashboards/create-dashboard/index.md similarity index 97% rename from docs/sources/dashboards/build-dashboards/create-dashboard/index.md rename to docs/sources/visualizations/dashboards/build-dashboards/create-dashboard/index.md index 5368b509e59..33ac74c856d 100644 --- a/docs/sources/dashboards/build-dashboards/create-dashboard/index.md +++ b/docs/sources/visualizations/dashboards/build-dashboards/create-dashboard/index.md @@ -1,6 +1,7 @@ --- aliases: - - add-organize-panels/ + - ../../../dashboards/build-dashboards/add-organize-panels/ # /docs/grafana/next/dashboards/build-dashboards/add-organize-panels/ + - ../../../dashboards/build-dashboards/create-dashboard/ # /docs/grafana/next/dashboards/build-dashboards/create-dashboard/ keywords: - panel - dashboard diff --git a/docs/sources/dashboards/build-dashboards/create-dynamic-dashboard/index.md b/docs/sources/visualizations/dashboards/build-dashboards/create-dynamic-dashboard/index.md similarity index 99% rename from docs/sources/dashboards/build-dashboards/create-dynamic-dashboard/index.md rename to docs/sources/visualizations/dashboards/build-dashboards/create-dynamic-dashboard/index.md index 0e9f99946bc..a77e4ca988f 100644 --- a/docs/sources/dashboards/build-dashboards/create-dynamic-dashboard/index.md +++ b/docs/sources/visualizations/dashboards/build-dashboards/create-dynamic-dashboard/index.md @@ -72,6 +72,8 @@ refs: destination: /docs/grafana//panels-visualizations/configure-overrides/ - pattern: /docs/grafana-cloud/ destination: /docs/grafana-cloud/visualizations/panels-visualizations/configure-overrides/ +aliases: + - ../../../dashboards/build-dashboards/create-dynamic-dashboard/ # /docs/grafana/next/dashboards/build-dashboards/create-dynamic-dashboard/ --- # Create and edit dynamic dashboards diff --git a/docs/sources/dashboards/build-dashboards/import-dashboards/index.md b/docs/sources/visualizations/dashboards/build-dashboards/import-dashboards/index.md similarity index 89% rename from docs/sources/dashboards/build-dashboards/import-dashboards/index.md rename to docs/sources/visualizations/dashboards/build-dashboards/import-dashboards/index.md index df660d1b351..a51746e7b87 100644 --- a/docs/sources/dashboards/build-dashboards/import-dashboards/index.md +++ b/docs/sources/visualizations/dashboards/build-dashboards/import-dashboards/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../../reference/export_import/ # /docs/grafana//reference/export_import/ - - ../export-import/ # /docs/grafana//dashboards/export-import/ + - ../../../reference/export_import/ # /docs/grafana/next/reference/export_import/ + - ../../../dashboards/export-import/ # /docs/grafana/next/dashboards/export-import/ + - ../../../dashboards/build-dashboards/import-dashboards/ # /docs/grafana/next/dashboards/build-dashboards/import-dashboards/ canonical: https://grafana.com/docs/grafana/latest/dashboards/build-dashboards/import-dashboards/ keywords: - grafana diff --git a/docs/sources/dashboards/build-dashboards/manage-dashboard-links/index.md b/docs/sources/visualizations/dashboards/build-dashboards/manage-dashboard-links/index.md similarity index 94% rename from docs/sources/dashboards/build-dashboards/manage-dashboard-links/index.md rename to docs/sources/visualizations/dashboards/build-dashboards/manage-dashboard-links/index.md index 99f4cf3bf32..cddf9a5b9f5 100644 --- a/docs/sources/dashboards/build-dashboards/manage-dashboard-links/index.md +++ b/docs/sources/visualizations/dashboards/build-dashboards/manage-dashboard-links/index.md @@ -1,11 +1,12 @@ --- aliases: - - ../../features/navigation-links/ - - ../../linking/ - - ../../linking/dashboard-links/ - - ../../linking/linking-overview/ - - ../../panels/working-with-panels/add-link-to-panel/ - - ../manage-dashboard-links/ + - ../../../dashboards/build-dashboards/manage-dashboard-links/ # /docs/grafana/next/dashboards/build-dashboards/manage-dashboard-links/ + - ../../../features/navigation-links/ # /docs/grafana/next/features/navigation-links/ + - ../../../linking/ # /docs/grafana/next/linking/ + - ../../../linking/dashboard-links/ # /docs/grafana/next/linking/dashboard-links/ + - ../../../linking/linking-overview/ # /docs/grafana/next/linking/linking-overview/ + - ../../../panels/working-with-panels/add-link-to-panel/ # /docs/grafana/next/panels/working-with-panels/add-link-to-panel + - ../../../dashboards/manage-dashboard-links/ # /docs/grafana/next/dashboards/manage-dashboard-links/ description: Add links to your Grafana dashboards to connect to other dashboards, panels, and websites keywords: - link diff --git a/docs/sources/dashboards/build-dashboards/manage-library-panels/index.md b/docs/sources/visualizations/dashboards/build-dashboards/manage-library-panels/index.md similarity index 85% rename from docs/sources/dashboards/build-dashboards/manage-library-panels/index.md rename to docs/sources/visualizations/dashboards/build-dashboards/manage-library-panels/index.md index facbdfa92a2..d8b60fef667 100644 --- a/docs/sources/dashboards/build-dashboards/manage-library-panels/index.md +++ b/docs/sources/visualizations/dashboards/build-dashboards/manage-library-panels/index.md @@ -1,13 +1,14 @@ --- aliases: - - ../../panels/library-panels/ - - ../../panels/library-panels/add-library-panel/ - - ../../panels/library-panels/create-library-panel/ - - ../../panels/library-panels/delete-library-panel/ - - ../../panels/library-panels/manage-library-panel/ - - ../../panels/library-panels/unlink-library-panel/ - - ../../panels/panel-library/ - - ../manage-library-panels/ + - ../../../dashboards/build-dashboards/manage-library-panels/ # /docs/grafana/next/dashboards/build-dashboards/manage-library-panels/ + - ../../../panels/library-panels/ # /docs/grafana/next/panels/library-panels + - ../../../panels/library-panels/add-library-panel/ # /docs/grafana/next/panels/library-panels/add-library-panel + - ../../../panels/library-panels/create-library-panel/ # /docs/grafana/next/panels/library-panels/create-library-panel + - ../../../panels/library-panels/delete-library-panel/ # /docs/grafana/next/panels/library-panels/delete-library-panel + - ../../../panels/library-panels/manage-library-panel/ # /docs/grafana/next/panels/library-panels/manage-library-panel + - ../../../panels/library-panels/unlink-library-panel/ # /docs/grafana/next/panels/library-panels/unlink-library-panel + - ../../../panels/panel-library/ # /docs/grafana/next/panels/panels-library/ + - ../manage-library-panels/ # /docs/grafana/next/visualizations/dashboards/manage-library-panels/ labels: products: - cloud diff --git a/docs/sources/dashboards/build-dashboards/manage-version-history/index.md b/docs/sources/visualizations/dashboards/build-dashboards/manage-version-history/index.md similarity index 88% rename from docs/sources/dashboards/build-dashboards/manage-version-history/index.md rename to docs/sources/visualizations/dashboards/build-dashboards/manage-version-history/index.md index d1ed28efc3f..712cb4c4205 100644 --- a/docs/sources/dashboards/build-dashboards/manage-version-history/index.md +++ b/docs/sources/visualizations/dashboards/build-dashboards/manage-version-history/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../../reference/dashboard_history/ - - ../dashboard-history/ + - ../../../reference/dashboard_history/ # /docs/grafana/next/reference/dashboard_history/ + - ../../../dashboards/dashboard-history/ # /docs/grafana/next/dashboards/dashboard-history/ + - ../../../dashboards/build-dashboards/manage-version-history/ # /docs/grafana/next/dashboards/build-dashboards/manage-version-history/ keywords: - grafana - dashboard diff --git a/docs/sources/dashboards/build-dashboards/modify-dashboard-settings/index.md b/docs/sources/visualizations/dashboards/build-dashboards/modify-dashboard-settings/index.md similarity index 98% rename from docs/sources/dashboards/build-dashboards/modify-dashboard-settings/index.md rename to docs/sources/visualizations/dashboards/build-dashboards/modify-dashboard-settings/index.md index dbe77c05013..dbc49c40bde 100644 --- a/docs/sources/dashboards/build-dashboards/modify-dashboard-settings/index.md +++ b/docs/sources/visualizations/dashboards/build-dashboards/modify-dashboard-settings/index.md @@ -34,6 +34,8 @@ refs: destination: /docs/grafana//dashboards/build-dashboards/manage-dashboard-links/#dashboard-links - pattern: /docs/grafana-cloud/ destination: /docs/grafana-cloud/visualizations/dashboards/build-dashboards/manage-dashboard-links/#dashboard-links +aliases: + - ../../../dashboards/build-dashboards/modify-dashboard-settings/ # /docs/grafana/next/dashboards/build-dashboards/modify-dashboard-settings/ --- # Modify dashboard settings diff --git a/docs/sources/dashboards/build-dashboards/view-dashboard-json-model/index.md b/docs/sources/visualizations/dashboards/build-dashboards/view-dashboard-json-model/index.md similarity index 97% rename from docs/sources/dashboards/build-dashboards/view-dashboard-json-model/index.md rename to docs/sources/visualizations/dashboards/build-dashboards/view-dashboard-json-model/index.md index c2e95bbba00..7720a4c946a 100644 --- a/docs/sources/dashboards/build-dashboards/view-dashboard-json-model/index.md +++ b/docs/sources/visualizations/dashboards/build-dashboards/view-dashboard-json-model/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../../reference/dashboard/ - - ../json-model/ + - ../../../reference/dashboard/ # /docs/grafana/next/reference/dashboard/ + - ../../../dashboards/json-model/ # /docs/grafana/next/dashboards/json-model/ + - ../../../dashboards/build-dashboards/view-dashboard-json-model/ # /docs/grafana/next/dashboards/build-dashboards/view-dashboard-json-model/ keywords: - grafana - dashboard diff --git a/docs/sources/dashboards/create-manage-playlists/index.md b/docs/sources/visualizations/dashboards/create-manage-playlists/index.md similarity index 96% rename from docs/sources/dashboards/create-manage-playlists/index.md rename to docs/sources/visualizations/dashboards/create-manage-playlists/index.md index 4f2d7831350..a61238e029d 100644 --- a/docs/sources/dashboards/create-manage-playlists/index.md +++ b/docs/sources/visualizations/dashboards/create-manage-playlists/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../reference/playlist/ - - playlist/ + - ../../reference/playlist/ # /docs/grafana/next/reference/playlist/ + - ../../dashboards/playlist/ # /docs/grafana/next/dashboards/playlist/ + - ../../dashboards/create-manage-playlists/ # /docs/grafana/next/dashboards/create-manage-playlists/ keywords: - grafana - dashboard diff --git a/docs/sources/dashboards/create-reports/_index.md b/docs/sources/visualizations/dashboards/create-reports/_index.md similarity index 97% rename from docs/sources/dashboards/create-reports/_index.md rename to docs/sources/visualizations/dashboards/create-reports/_index.md index 0e9650f35ca..e55fd9e9fee 100644 --- a/docs/sources/dashboards/create-reports/_index.md +++ b/docs/sources/visualizations/dashboards/create-reports/_index.md @@ -1,10 +1,11 @@ --- aliases: - - ../administration/reports/ # /docs/grafana/latest/administration/reports/ - - ../enterprise/export-pdf/ # /docs/grafana/latest/enterprise/export-pdf/ - - ../enterprise/reporting/ # /docs/grafana/latest/enterprise/reporting/ - - ../panels/create-reports/ # /docs/grafana/latest/panels/create-reports/ - - reporting/ # /docs/grafana/latest/dashboards/reporting/ + - ../../administration/reports/ # /docs/grafana/next/administration/reports/ + - ../../enterprise/export-pdf/ # /docs/grafana/next/enterprise/export-pdf/ + - ../../enterprise/reporting/ # /docs/grafana/next/enterprise/reporting/ + - ../../panels/create-reports/ # /docs/grafana/next/panels/create-reports/ + - ../../dashboards/reporting/ # /docs/grafana/next/dashboards/reporting/ + - ../../dashboards/create-reports/ # /docs/grafana/next/dashboards/create-reports/ keywords: - grafana - reporting diff --git a/docs/sources/dashboards/create-reports/report-settings/index.md b/docs/sources/visualizations/dashboards/create-reports/report-settings/index.md similarity index 96% rename from docs/sources/dashboards/create-reports/report-settings/index.md rename to docs/sources/visualizations/dashboards/create-reports/report-settings/index.md index b63b636d809..6f131c676a2 100644 --- a/docs/sources/dashboards/create-reports/report-settings/index.md +++ b/docs/sources/visualizations/dashboards/create-reports/report-settings/index.md @@ -17,6 +17,8 @@ refs: destination: /docs/grafana//administration/organization-preferences/#change-grafana-ui-theme - pattern: /docs/grafana-cloud/ destination: /docs/grafana//administration/organization-preferences/#change-grafana-ui-theme +aliases: + - ../../../dashboards/create-reports/report-settings/ # /docs/grafana/next/dashboards/create-reports/report-settings/ --- # Reporting settings diff --git a/docs/sources/dashboards/manage-dashboards/index.md b/docs/sources/visualizations/dashboards/manage-dashboards/index.md similarity index 71% rename from docs/sources/dashboards/manage-dashboards/index.md rename to docs/sources/visualizations/dashboards/manage-dashboards/index.md index a5473c5a71f..268b7a7ad8e 100644 --- a/docs/sources/dashboards/manage-dashboards/index.md +++ b/docs/sources/visualizations/dashboards/manage-dashboards/index.md @@ -1,9 +1,10 @@ --- aliases: - - ../panels/working-with-panels/organize-dashboard/ - - ../reference/dashboard_folders/ - - dashboard-folders/ - - dashboard-manage/ + - ../../panels/working-with-panels/organize-dashboard/ # /docs/grafana/next/panels/working-with-panels/organize-dashboard/ + - ../../reference/dashboard_folders/ # /docs/grafana/next/reference/dashboard_folders/ + - ../../dashboards/dashboard-folders/ # /docs/grafana/next/dashboards/dashboard-folders/ + - ../../dashboards/dashboard-manage/ # /docs/grafana/next/dashboards/dashboard-manage/ + - ../../dashboards/manage-dashboards/ # /docs/grafana/next/dashboards/manage-dashboards/ canonical: https://grafana.com/docs/grafana/latest/dashboards/manage-dashboards/ keywords: - grafana @@ -114,6 +115,39 @@ Changes are saved automatically. For more information about dashboard permissions, refer to [Dashboard permissions](ref:dashboard-permissions). +## Dashboard and folder deletion + +**Folders** - When you delete folders, the action is immediate and can't be reversed. + +**Dashboards** - Deleted dashboards are stored in the deletion history and can be [restored](#restore-dashboards) if needed (Cloud only). + +## Restore deleted dashboards + +{{% admonition type="caution" %}} +The feature is only available in Grafana Cloud. +{{% /admonition %}} + +When you delete dashboards, theyโ€™re stored in the deletion history for up to 12 months, allowing you to restore them if needed. +The deletion history can contain a maximum of 1000 dashboards. +After this limit is reached, the oldest deleted dashboards are permanently removed even if the 12-month expiration period isn't over yet. + +You can access the list of deleted dashboards from the **Dashboards** page by clicking the **Recently deleted** button, or by navigating to **Dashboards > Recently deleted**. + +To restore one or more dashboards, follow these steps: + +1. In the main menu, click **Dashboards > Recently deleted** or click the **Recently deleted** button from the **Dashboards** page. +2. Select the dashboards you want to restore. +3. Click **Restore** and select a folder to which the dashboards will be moved: + - If you select one dashboard and its original folder still exists, that folder is preselected. + - If you select multiple dashboards from the _same_ folder, that folder is preselected. + - If you select dashboards from _different_ folders, youโ€™ll need to choose one target folder for all of them. + - If the original folder no longer exists, youโ€™ll need to select a new target folder. +4. Click **Restore**. + +{{% admonition type="note" %}} +Only users with admin rights can access the **Restore dashboards** page. +{{% /admonition %}} + ## Set up generative AI features for dashboards You can use generative AI to help you with the following tasks: diff --git a/docs/sources/dashboards/search-dashboards/index.md b/docs/sources/visualizations/dashboards/search-dashboards/index.md similarity index 98% rename from docs/sources/dashboards/search-dashboards/index.md rename to docs/sources/visualizations/dashboards/search-dashboards/index.md index 61126b9828c..63b3804fdeb 100644 --- a/docs/sources/dashboards/search-dashboards/index.md +++ b/docs/sources/visualizations/dashboards/search-dashboards/index.md @@ -28,6 +28,8 @@ refs: destination: /docs/grafana//setup-grafana/configure-grafana/#feature_toggles - pattern: /docs/grafana-cloud/ destination: /docs/grafana//setup-grafana/configure-grafana/#feature_toggles +aliases: + - ../../dashboards/search-dashboards/ # /docs/grafana/next/dashboards/search-dashboards/ --- # Search dashboards and folders diff --git a/docs/sources/dashboards/share-dashboards-panels/_index.md b/docs/sources/visualizations/dashboards/share-dashboards-panels/_index.md similarity index 96% rename from docs/sources/dashboards/share-dashboards-panels/_index.md rename to docs/sources/visualizations/dashboards/share-dashboards-panels/_index.md index 1b606ed8d0d..3454f719a0c 100644 --- a/docs/sources/dashboards/share-dashboards-panels/_index.md +++ b/docs/sources/visualizations/dashboards/share-dashboards-panels/_index.md @@ -1,13 +1,14 @@ --- aliases: - - ../reference/share_dashboard/ # /docs/grafana/latest/reference/share_dashboard/ - - ../reference/share_panel/ # /docs/grafana/latest/reference/share_panel/ - - ../share-dashboards-panels/ # /docs/grafana/latest/share-dashboards-panels/ - - ../sharing/ # /docs/grafana/latest/sharing/ - - ../sharing/playlists/ # /docs/grafana/latest/sharing/playlists/ - - ../sharing/share-dashboard/ # /docs/grafana/latest/sharing/share-dashboard/ - - ../sharing/share-panel/ # /docs/grafana/latest/sharing/share-panel/ - - share-dashboard/ # /docs/grafana/latest/dashboards/share-dashboard/ + - ../../reference/share_dashboard/ # /docs/grafana/next/reference/share_dashboard/ + - ../../reference/share_panel/ # /docs/grafana/next/reference/share_panel/ + - ../../share-dashboards-panels/ # /docs/grafana/next/share-dashboards-panels/ + - ../../sharing/ # /docs/grafana/next/sharing/ + - ../../sharing/playlists/ # /docs/grafana/next/sharing/playlists/ + - ../../sharing/share-dashboard/ # /docs/grafana/next/sharing/share-dashboard/ + - ../../sharing/share-panel/ # /docs/grafana/next/sharing/share-panel/ + - ../../dashboards/share-dashboard/ # /docs/grafana/next/dashboards/share-dashboard/ + - ../../dashboards/share-dashboards-panels/ # /docs/grafana/next/dashboards/share-dashboards-panels/ keywords: - grafana - dashboard diff --git a/docs/sources/dashboards/share-dashboards-panels/shared-dashboards/index.md b/docs/sources/visualizations/dashboards/share-dashboards-panels/shared-dashboards/index.md similarity index 98% rename from docs/sources/dashboards/share-dashboards-panels/shared-dashboards/index.md rename to docs/sources/visualizations/dashboards/share-dashboards-panels/shared-dashboards/index.md index 9ea6df4e47e..dc4b41ce1fd 100644 --- a/docs/sources/dashboards/share-dashboards-panels/shared-dashboards/index.md +++ b/docs/sources/visualizations/dashboards/share-dashboards-panels/shared-dashboards/index.md @@ -1,6 +1,7 @@ --- aliases: - - ../dashboard-public/ # /docs/grafana/latest/dashboards/dashboard-public/ + - ../../../dashboards/dashboard-public/ # /docs/grafana/next/dashboards/dashboard-public/ + - ../../../dashboards/share-dashboards-panels/shared-dashboards/ # /docs/grafana/next/dashboards/share-dashboards-panels/shared-dashboards/ labels: products: - cloud diff --git a/docs/sources/dashboards/troubleshoot-dashboards/index.md b/docs/sources/visualizations/dashboards/troubleshoot-dashboards/index.md similarity index 91% rename from docs/sources/dashboards/troubleshoot-dashboards/index.md rename to docs/sources/visualizations/dashboards/troubleshoot-dashboards/index.md index bb6530b7952..c04defe36c4 100644 --- a/docs/sources/dashboards/troubleshoot-dashboards/index.md +++ b/docs/sources/visualizations/dashboards/troubleshoot-dashboards/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../troubleshooting/troubleshoot-dashboards/ - - ../reference/timerange/ + - ../../troubleshooting/troubleshoot-dashboards/ # /docs/grafana/next/troubleshooting/troubleshoot-dashboards/ + - ../../reference/timerange/ # /docs/grafana/next/reference/timerange/ + - ../../dashboards/troubleshoot-dashboards/ # /docs/grafana/next/dashboards/troubleshoot-dashboards/ canonical: https://grafana.com/docs/grafana/latest/dashboards/troubleshoot-dashboards/ keywords: - grafana diff --git a/docs/sources/dashboards/use-dashboards/index.md b/docs/sources/visualizations/dashboards/use-dashboards/index.md similarity index 95% rename from docs/sources/dashboards/use-dashboards/index.md rename to docs/sources/visualizations/dashboards/use-dashboards/index.md index 5d956b4c380..108d6bc8136 100644 --- a/docs/sources/dashboards/use-dashboards/index.md +++ b/docs/sources/visualizations/dashboards/use-dashboards/index.md @@ -1,12 +1,13 @@ --- aliases: - - ../reference/search/ - - dashboard-ui/ - - dashboard-ui/dashboard-header/ - - dashboard-ui/dashboard-row/ - - search/ - - shortcuts/ - - time-range-controls/ + - ../../reference/search/ # /docs/grafana/next/reference/search/ + - ../../dashboards/dashboard-ui/ # /docs/grafana/next/dashboards/dashboard-ui/ + - ../../dashboards/dashboard-ui/dashboard-header/ # /docs/grafana/next/dashboards/dashboard-ui/dashboard-header/ + - ../../dashboards/dashboard-ui/dashboard-row/ # /docs/grafana/next/dashboards/dashboard-ui/dashboard-row/ + - ../../dashboards/search/ # /docs/grafana/next/dashboards/search/ + - ../../dashboards/shortcuts/ # /docs/grafana/next/dashboards/shortcuts/ + - ../../dashboards/time-range-controls/ # /docs/grafana/next/dashboards/time-range-controls/ + - ../../dashboards/use-dashboards/ # /docs/grafana/next/dashboards/use-dashboards/ keywords: - dashboard - search diff --git a/docs/sources/dashboards/variables/_index.md b/docs/sources/visualizations/dashboards/variables/_index.md similarity index 93% rename from docs/sources/dashboards/variables/_index.md rename to docs/sources/visualizations/dashboards/variables/_index.md index da7451271d2..df11c5d64ac 100644 --- a/docs/sources/dashboards/variables/_index.md +++ b/docs/sources/visualizations/dashboards/variables/_index.md @@ -1,8 +1,9 @@ --- aliases: - - ../variables/ # /docs/grafana//variables/ - - ../variables/templates-and-variables/ # /docs/grafana//variables/templates-and-variables/ - - ../variables/variable-examples/ # /docs/grafana//variables/variable-examples/ + - ../../variables/ # /docs/grafana/next/variables/ + - ../../variables/templates-and-variables/ # /docs/grafana/next/variables/templates-and-variables/ + - ../../variables/variable-examples/ # /docs/grafana/next/variables/variable-examples/ + - ../../dashboards/variables/ # /docs/grafana/next/dashboards/variables/ labels: products: - cloud diff --git a/docs/sources/dashboards/variables/add-template-variables/index.md b/docs/sources/visualizations/dashboards/variables/add-template-variables/index.md similarity index 94% rename from docs/sources/dashboards/variables/add-template-variables/index.md rename to docs/sources/visualizations/dashboards/variables/add-template-variables/index.md index b41615cd4e7..0343d78fb91 100644 --- a/docs/sources/dashboards/variables/add-template-variables/index.md +++ b/docs/sources/visualizations/dashboards/variables/add-template-variables/index.md @@ -1,30 +1,31 @@ --- aliases: - - ../../reference/templating/ - - ../../variables/add-ad-hoc-filters/ - - ../../variables/add-constant-variable/ - - ../../variables/add-custom-variable/ - - ../../variables/add-data-source-variable/ - - ../../variables/add-interval-variable/ - - ../../variables/add-query-variable/ - - ../../variables/add-template-variables/ - - ../../variables/add-text-box-variable/ - - ../../variables/chained-variables/ - - ../../variables/filter-variables-with-regex/ - - ../../variables/formatting-multi-value-variables/ - - ../../variables/global-variables/ - - ../../variables/manage-variable/ - - ../../variables/variable-selection-options/ - - ../../variables/variable-types/ - - ../../variables/variable-types/add-ad-hoc-filters/ - - ../../variables/variable-types/add-constant-variable/ - - ../../variables/variable-types/add-custom-variable/ - - ../../variables/variable-types/add-data-source-variable/ - - ../../variables/variable-types/add-interval-variable/ - - ../../variables/variable-types/add-query-variable/ - - ../../variables/variable-types/add-text-box-variable/ - - ../../variables/variable-types/chained-variables/ - - ../../variables/variable-types/global-variables/ + - ../../../reference/templating/ # /docs/grafana/next/reference/templating/ + - ../../../variables/add-ad-hoc-filters/ # /docs/grafana/next/variables/add-ad-hoc-filters/ + - ../../../variables/add-constant-variable/ # /docs/grafana/next/variables/add-constant-variable/ + - ../../../variables/add-custom-variable/ # /docs/grafana/next/variables/add-custom-variable/ + - ../../../variables/add-data-source-variable/ # /docs/grafana/next/variables/add-data-source-variable/ + - ../../../variables/add-interval-variable/ # /docs/grafana/next/variables/add-interval-variable/ + - ../../../variables/add-query-variable/ # /docs/grafana/next/variables/add-query-variable/ + - ../../../variables/add-template-variables/ # /docs/grafana/next/variables/add-template-variables/ + - ../../../variables/add-text-box-variable/ # /docs/grafana/next/variables/add-text-box-variable/ + - ../../../variables/chained-variables/ # /docs/grafana/next/variables/chained-variables/ + - ../../../variables/filter-variables-with-regex/ # /docs/grafana/next/variables/filter-variables-with-regex/ + - ../../../variables/formatting-multi-value-variables/ # /docs/grafana/next/variables/formatting-multi-value-variables/ + - ../../../variables/global-variables/ # /docs/grafana/next/variables/global-variables/ + - ../../../variables/manage-variable/ # /docs/grafana/next/variables/manage-variable/ + - ../../../variables/variable-selection-options/ # /docs/grafana/next/variables/variable-selection-options/ + - ../../../variables/variable-types/ # /docs/grafana/next/variables/variable-types/ + - ../../../variables/variable-types/add-ad-hoc-filters/ # /docs/grafana/next/variables/variable-types/add-ad-hoc-filters/ + - ../../../variables/variable-types/add-constant-variable/ # /docs/grafana/next/variables/variable-types/add-constant-variable/ + - ../../../variables/variable-types/add-custom-variable/ # /docs/grafana/next/variables/variable-types/add-custom-variable/ + - ../../../variables/variable-types/add-data-source-variable/ # /docs/grafana/next/variables/variable-types/add-data-source-variable/ + - ../../../variables/variable-types/add-interval-variable/ # /docs/grafana/next/variables/variable-types/add-interval-variable/ + - ../../../variables/variable-types/add-query-variable/ # /docs/grafana/next/variables/variable-types/add-query-variable/ + - ../../../variables/variable-types/add-text-box-variable/ # /docs/grafana/next/variables/variable-types/add-text-box-variable/ + - ../../../variables/variable-types/chained-variables/ # /docs/grafana/next/variables/variable-types/chained-variables/ + - ../../../variables/variable-types/global-variables/ # /docs/grafana/next/variables/variable-types/global-variables/ + - ../../../dashboards/variables/add-template-variables/ # /docs/grafana/next/dashboards/variables/add-template-variables/ keywords: - grafana - documentation diff --git a/docs/sources/dashboards/variables/inspect-variable/index.md b/docs/sources/visualizations/dashboards/variables/inspect-variable/index.md similarity index 90% rename from docs/sources/dashboards/variables/inspect-variable/index.md rename to docs/sources/visualizations/dashboards/variables/inspect-variable/index.md index bcdb8635141..8466a4228ce 100644 --- a/docs/sources/dashboards/variables/inspect-variable/index.md +++ b/docs/sources/visualizations/dashboards/variables/inspect-variable/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../../reference/templating/ - - ../../variables/inspect-variable/ + - ../../../reference/templating/ # /docs/grafana/next/reference/templating/ + - ../../../variables/inspect-variable/ # /docs/grafana/next/variables/inspect-variable/ + - ../../../dashboards/variables/inspect-variable/ # /docs/grafana/next/dashboards/variables/inspect-variable/ keywords: - grafana - templating diff --git a/docs/sources/dashboards/variables/variable-syntax/index.md b/docs/sources/visualizations/dashboards/variables/variable-syntax/index.md similarity index 94% rename from docs/sources/dashboards/variables/variable-syntax/index.md rename to docs/sources/visualizations/dashboards/variables/variable-syntax/index.md index 7d0fbc81993..2c0b4060921 100644 --- a/docs/sources/dashboards/variables/variable-syntax/index.md +++ b/docs/sources/visualizations/dashboards/variables/variable-syntax/index.md @@ -1,8 +1,9 @@ --- aliases: - - ../../reference/templating/ - - ../../variables/advanced-variable-format-options/ - - ../../variables/syntax/ + - ../../../reference/templating/ # /docs/grafana/next/reference/templating/ + - ../../../variables/advanced-variable-format-options/ # /docs/grafana/next/variables/advanced-variable-format-options/ + - ../../../variables/syntax/ # /docs/grafana/next/variables/syntax/ + - ../../../dashboards/variables/variable-syntax/ # /docs/grafana/next/dashboards/variables/variable-syntax/ keywords: - grafana - templating diff --git a/docs/sources/explore/_index.md b/docs/sources/visualizations/explore/_index.md similarity index 91% rename from docs/sources/explore/_index.md rename to docs/sources/visualizations/explore/_index.md index 0deda3011d3..3ef9659a165 100644 --- a/docs/sources/explore/_index.md +++ b/docs/sources/visualizations/explore/_index.md @@ -1,6 +1,8 @@ --- aliases: - - features/explore/ + - ../features/explore/ # /docs/grafana/next/features/explore/ + - ../explore/ # /docs/grafana/next/explore/ + - /docs/grafana-cloud/visualizations/explore/ keywords: - explore - loki diff --git a/docs/sources/explore/correlations-editor-in-explore.md b/docs/sources/visualizations/explore/correlations-editor-in-explore.md similarity index 98% rename from docs/sources/explore/correlations-editor-in-explore.md rename to docs/sources/visualizations/explore/correlations-editor-in-explore.md index 7f93fd30dc6..fde5d933103 100644 --- a/docs/sources/explore/correlations-editor-in-explore.md +++ b/docs/sources/visualizations/explore/correlations-editor-in-explore.md @@ -6,6 +6,8 @@ labels: - cloud title: Correlations Editor in Explore weight: 20 +aliases: + - ../../explore/correlations-editor-in-explore/ # /docs/grafana/next/explore/correlations-editor-in-explore/ --- # Correlations Editor in Explore diff --git a/docs/sources/explore/explore-inspector.md b/docs/sources/visualizations/explore/explore-inspector.md similarity index 96% rename from docs/sources/explore/explore-inspector.md rename to docs/sources/visualizations/explore/explore-inspector.md index 6880f292e82..17074a21fab 100644 --- a/docs/sources/explore/explore-inspector.md +++ b/docs/sources/visualizations/explore/explore-inspector.md @@ -9,6 +9,9 @@ keywords: - Explore title: Query inspector in Explore weight: 15 +aliases: + - ../../explore/explore-inspector/ # /docs/grafana/next/explore/explore-inspector/ + - /docs/grafana-cloud/visualizations/explore/explore-inspector/ --- # Query inspector in Explore diff --git a/docs/sources/explore/get-started-with-explore.md b/docs/sources/visualizations/explore/get-started-with-explore.md similarity index 99% rename from docs/sources/explore/get-started-with-explore.md rename to docs/sources/visualizations/explore/get-started-with-explore.md index 5b7a97b85d9..8874741cb44 100644 --- a/docs/sources/explore/get-started-with-explore.md +++ b/docs/sources/visualizations/explore/get-started-with-explore.md @@ -1,6 +1,6 @@ --- aliases: - - + - ../../explore/get-started-with-explore/ # /docs/grafana/next/explore/get-started-with-explore/ keywords: - explore - loki diff --git a/docs/sources/explore/logs-integration.md b/docs/sources/visualizations/explore/logs-integration.md similarity index 99% rename from docs/sources/explore/logs-integration.md rename to docs/sources/visualizations/explore/logs-integration.md index 42af2ccc0e0..8aa18f45616 100644 --- a/docs/sources/explore/logs-integration.md +++ b/docs/sources/visualizations/explore/logs-integration.md @@ -10,6 +10,8 @@ labels: - oss title: Logs in Explore weight: 25 +aliases: + - ../../explore/logs-integration/ # /docs/grafana/next/explore/logs-integration/ --- # Logs in Explore diff --git a/docs/sources/explore/query-management.md b/docs/sources/visualizations/explore/query-management.md similarity index 97% rename from docs/sources/explore/query-management.md rename to docs/sources/visualizations/explore/query-management.md index 11f86be67c9..4be1a932ea8 100644 --- a/docs/sources/explore/query-management.md +++ b/docs/sources/visualizations/explore/query-management.md @@ -16,6 +16,8 @@ refs: destination: /docs/grafana//panels-visualizations/query-transform-data/#saved-queries - pattern: /docs/grafana-cloud/ destination: /docs/grafana-cloud/visualizations/panels-visualizations/query-transform-data/#saved-queries +aliases: + - ../../explore/query-management/ # /docs/grafana/next/explore/query-management/ --- # Query management in Explore diff --git a/docs/sources/explore/trace-integration.md b/docs/sources/visualizations/explore/trace-integration.md similarity index 99% rename from docs/sources/explore/trace-integration.md rename to docs/sources/visualizations/explore/trace-integration.md index e1675c3d414..9a07f6ad18c 100644 --- a/docs/sources/explore/trace-integration.md +++ b/docs/sources/visualizations/explore/trace-integration.md @@ -9,6 +9,8 @@ labels: - oss title: Traces in Explore weight: 40 +aliases: + - ../../explore/trace-integration/ # /docs/grafana/next/explore/trace-integration/ --- # Traces in Explore diff --git a/docs/sources/panels-visualizations/_index.md b/docs/sources/visualizations/panels-visualizations/_index.md similarity index 89% rename from docs/sources/panels-visualizations/_index.md rename to docs/sources/visualizations/panels-visualizations/_index.md index d6f2e0982e8..642c1ba183b 100644 --- a/docs/sources/panels-visualizations/_index.md +++ b/docs/sources/visualizations/panels-visualizations/_index.md @@ -1,8 +1,9 @@ --- aliases: - - dashboards/configure-panels-visualizations/ - - features/panels/panels/ - - panels/ + - ../dashboards/configure-panels-visualizations/ # /docs/grafana/next/dashboards/configure-panels-visualizations/ + - ../features/panels/panels/ # /docs/grafana/next/features/panels/panels/ + - ../panels/ # /docs/grafana/next/panels/ + - ../panels-visualizations/ # /docs/grafana/next/panels-visualizations/ keywords: - grafana - configure diff --git a/docs/sources/panels-visualizations/configure-data-links/index.md b/docs/sources/visualizations/panels-visualizations/configure-data-links/index.md similarity index 96% rename from docs/sources/panels-visualizations/configure-data-links/index.md rename to docs/sources/visualizations/panels-visualizations/configure-data-links/index.md index ad1724acb09..7d72bcba934 100644 --- a/docs/sources/panels-visualizations/configure-data-links/index.md +++ b/docs/sources/visualizations/panels-visualizations/configure-data-links/index.md @@ -1,11 +1,12 @@ --- aliases: - - ../linking/data-link-variables/ - - ../linking/data-links/ - - ../panels/configure-data-links/ - - ../reference/datalinks/ - - ../variables/url-variables/ - - ../variables/variable-types/url-variables/ + - ../../linking/data-link-variables/ # /docs/grafana/next/linking/data-link-variables/ + - ../../linking/data-links/ # /docs/grafana/next/linking/data-links/ + - ../../panels/configure-data-links/ # /docs/grafana/next/panels/configure-data-links/ + - ../../reference/datalinks/ # /docs/grafana/next/reference/datalinks/ + - ../../variables/url-variables/ # /docs/grafana/next/variables/url-variables/ + - ../../variables/variable-types/url-variables/ # /docs/grafana/next/variables/variable-types/url-variables/ + - ../../panels-visualizations/configure-data-links/ # /docs/grafana/next/panels-visualizations/configure-data-links/ keywords: - grafana - url variables diff --git a/docs/sources/panels-visualizations/configure-legend/index.md b/docs/sources/visualizations/panels-visualizations/configure-legend/index.md similarity index 95% rename from docs/sources/panels-visualizations/configure-legend/index.md rename to docs/sources/visualizations/panels-visualizations/configure-legend/index.md index 4f7a6e27648..8c8baa81800 100644 --- a/docs/sources/panels-visualizations/configure-legend/index.md +++ b/docs/sources/visualizations/panels-visualizations/configure-legend/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../panels/working-with-panels/configure-legend/ - - visualizations/configure-legend/ + - ../../panels/working-with-panels/configure-legend/ # /docs/grafana/next/panels/working-with-panels/configure-legend/ + - ../../panels-visualizations/visualizations/configure-legend/ # /docs/grafana/next/panels-visualizations/visualizations/configure-legend/ + - ../../panels-visualizations/configure-legend/ # /docs/grafana/next/panels-visualizations/configure-legend/ labels: products: - cloud diff --git a/docs/sources/panels-visualizations/configure-overrides/index.md b/docs/sources/visualizations/panels-visualizations/configure-overrides/index.md similarity index 92% rename from docs/sources/panels-visualizations/configure-overrides/index.md rename to docs/sources/visualizations/panels-visualizations/configure-overrides/index.md index c01a72bd781..c46223ac73b 100644 --- a/docs/sources/panels-visualizations/configure-overrides/index.md +++ b/docs/sources/visualizations/panels-visualizations/configure-overrides/index.md @@ -1,13 +1,14 @@ --- aliases: - - ../panels/configure-overrides/ - - ../panels/field-overrides/ - - ../panels/override-field-values/ - - ../panels/override-field-values/about-field-overrides/ - - ../panels/override-field-values/add-a-field-override/ - - ../panels/override-field-values/delete-a-field-override/ - - ../panels/override-field-values/edit-field-override/ - - ../panels/override-field-values/view-field-override/ + - ../../panels/configure-overrides/ # /docs/grafana/next/panels/configure-overrides/ + - ../../panels/field-overrides/ # /docs/grafana/next/panels/field-overrides/ + - ../../panels/override-field-values/ # /docs/grafana/next/panels/override-field-values/ + - ../../panels/override-field-values/about-field-overrides/ # /docs/grafana/next/panels/override-field-values/about-field-overrides/ + - ../../panels/override-field-values/add-a-field-override/ # /docs/grafana/next/panels/override-field-values/add-a-field-override/ + - ../../panels/override-field-values/delete-a-field-override/ # /docs/grafana/next/panels/override-field-values/delete-a-field-override/ + - ../../panels/override-field-values/edit-field-override/ # /docs/grafana/next/panels/override-field-values/edit-field-override/ + - ../../panels/override-field-values/view-field-override/ # /docs/grafana/next/panels/override-field-values/view-field-override/ + - ../../panels-visualizations/configure-overrides/ # /docs/grafana/next/panels-visualizations/configure-overrides/ labels: products: - cloud diff --git a/docs/sources/panels-visualizations/configure-panel-options/index.md b/docs/sources/visualizations/panels-visualizations/configure-panel-options/index.md similarity index 91% rename from docs/sources/panels-visualizations/configure-panel-options/index.md rename to docs/sources/visualizations/panels-visualizations/configure-panel-options/index.md index dc7c8601c11..3a2185d699a 100644 --- a/docs/sources/panels-visualizations/configure-panel-options/index.md +++ b/docs/sources/visualizations/panels-visualizations/configure-panel-options/index.md @@ -1,10 +1,11 @@ --- aliases: - - ../panels/add-panels-dynamically/ - - ../panels/configure-panel-options/ - - ../panels/repeat-panels-or-rows/ - - ../panels/working-with-panels/add-title-and-description/ - - ../panels/working-with-panels/view-json-model/ + - ../../panels/add-panels-dynamically/ # /docs/grafana/next/panels/add-panels-dynamically/ + - ../../panels/configure-panel-options/ # /docs/grafana/next/panels/configure-panel-options/ + - ../../panels/repeat-panels-or-rows/ # /docs/grafana/next/panels/repeat-panels-or-rows/ + - ../../panels/working-with-panels/add-title-and-description/ # /docs/grafana/next/panels/working-with-panels/add-title-and-description/ + - ../../panels/working-with-panels/view-json-model/ # /docs/grafana/next/panels/working-with-panels/view-json-model/ + - ../../panels-visualizations/configure-panel-options/ # /docs/grafana/next/panels-visualizations/configure-panel-options/ keywords: - panel - dynamic diff --git a/docs/sources/panels-visualizations/configure-standard-options/index.md b/docs/sources/visualizations/panels-visualizations/configure-standard-options/index.md similarity index 95% rename from docs/sources/panels-visualizations/configure-standard-options/index.md rename to docs/sources/visualizations/panels-visualizations/configure-standard-options/index.md index c4ed1caa981..ca35f5df71c 100644 --- a/docs/sources/panels-visualizations/configure-standard-options/index.md +++ b/docs/sources/visualizations/panels-visualizations/configure-standard-options/index.md @@ -1,13 +1,14 @@ --- aliases: - - ../panels/apply-color-to-series/ - - ../panels/configure-standard-options/ - - ../panels/field-options/ - - ../panels/field-options/standard-field-options/ - - ../panels/reference-standard-field-definitions/ - - ../panels/standard-field-definitions/ - - ../panels/working-with-panels/format-standard-fields/ - - ../panels/field-configuration-options/ # /docs/grafana/latest/panels/field-configuration-options/ + - ../../panels/apply-color-to-series/ # /docs/grafana/next/panels/apply-color-to-series/ + - ../../panels/configure-standard-options/ # /docs/grafana/next/panels/configure-standard-options/ + - ../../panels/field-options/ # /docs/grafana/next/panels/field-options/ + - ../../panels/field-options/standard-field-options/ # /docs/grafana/next/panels/field-options/standard-field-options/ + - ../../panels/reference-standard-field-definitions/ # /docs/grafana/next/panels/reference-standard-field-definitions/ + - ../../panels/standard-field-definitions/ # /docs/grafana/next/panels/standard-field-definitions/ + - ../../panels/working-with-panels/format-standard-fields/ # /docs/grafana/next/panels/working-with-panels/format-standard-fields/ + - ../../panels/field-configuration-options/ # /docs/grafana/next/panels/field-configuration-options/ + - ../../panels-visualizations/configure-standard-options/ # /docs/grafana/next/panels-visualizations/configure-standard-options/ keywords: - panel - dashboard diff --git a/docs/sources/panels-visualizations/configure-thresholds/index.md b/docs/sources/visualizations/panels-visualizations/configure-thresholds/index.md similarity index 92% rename from docs/sources/panels-visualizations/configure-thresholds/index.md rename to docs/sources/visualizations/panels-visualizations/configure-thresholds/index.md index cf0805a5e93..d4ebc5c123c 100644 --- a/docs/sources/panels-visualizations/configure-thresholds/index.md +++ b/docs/sources/visualizations/panels-visualizations/configure-thresholds/index.md @@ -1,12 +1,13 @@ --- aliases: - - ../panels/ - - ../panels/configure-thresholds/ - - ../panels/specify-thresholds/about-thresholds/ - - ../panels/specify-thresholds/add-a-threshold/ - - ../panels/specify-thresholds/add-threshold-to-graph/ - - ../panels/specify-thresholds/delete-a-threshold/ - - ../panels/thresholds/ + - ../../panels/ # /docs/grafana/next/panels/ + - ../../panels/configure-thresholds/ # /docs/grafana/next/panels/configure-thresholds/ + - ../../panels/specify-thresholds/about-thresholds/ # /docs/grafana/next/panels/specify-thresholds/about-thresholds/ + - ../../panels/specify-thresholds/add-a-threshold/ # /docs/grafana/next/panels/specify-thresholds/add-a-threshold/ + - ../../panels/specify-thresholds/add-threshold-to-graph/ # /docs/grafana/next/panels/specify-thresholds/add-threshold-to-graph/ + - ../../panels/specify-thresholds/delete-a-threshold/ # /docs/grafana/next/panels/specify-thresholds/delete-a-threshold/ + - ../../panels/thresholds/ # /docs/grafana/next/panels/thresholds/ + - ../../panels-visualizations/configure-thresholds/ # /docs/grafana/next/panels-visualizations/configure-thresholds/ description: Configure thresholds in your visualizations labels: products: diff --git a/docs/sources/panels-visualizations/configure-tooltips/index.md b/docs/sources/visualizations/panels-visualizations/configure-tooltips/index.md similarity index 100% rename from docs/sources/panels-visualizations/configure-tooltips/index.md rename to docs/sources/visualizations/panels-visualizations/configure-tooltips/index.md diff --git a/docs/sources/panels-visualizations/configure-value-mappings/index.md b/docs/sources/visualizations/panels-visualizations/configure-value-mappings/index.md similarity index 90% rename from docs/sources/panels-visualizations/configure-value-mappings/index.md rename to docs/sources/visualizations/panels-visualizations/configure-value-mappings/index.md index 11223d3870b..1e8cb947a69 100644 --- a/docs/sources/panels-visualizations/configure-value-mappings/index.md +++ b/docs/sources/visualizations/panels-visualizations/configure-value-mappings/index.md @@ -1,14 +1,15 @@ --- aliases: - - ../panels/configure-value-mappings/ - - ../panels/format-data/ - - ../panels/format-data/about-value-mapping/ - - ../panels/format-data/edit-value-mapping/ - - ../panels/format-data/map-a-range/ - - ../panels/format-data/map-a-regular-expression/ - - ../panels/format-data/map-a-special-value/ - - ../panels/format-data/map-a-value/ - - ../panels/value-mappings/ + - ../../configure-value-mappings/ # /docs/grafana/next/panels/configure-value-mappings/ + - ../../panels/format-data/ # /docs/grafana/next/panels/format-data/ + - ../../panels/format-data/about-value-mapping/ # /docs/grafana/next/panels/format-data/about-value-mapping/ + - ../../panels/format-data/edit-value-mapping/ # /docs/grafana/next/panels/format-data/edit-value-mapping/ + - ../../panels/format-data/map-a-range/ # /docs/grafana/next/panels/format-data/map-a-range/ + - ../../panels/format-data/map-a-regular-expression/ # /docs/grafana/next/panels/format-data/map-a-regular-expression/ + - ../../panels/format-data/map-a-special-value/ # /docs/grafana/next/panels/format-data/map-a-special-value/ + - ../../panels/format-data/map-a-value/ # /docs/grafana/next/panels/format-data/map-a-value/ + - ../../panels/value-mappings/ # /docs/grafana/next/panels/value-mappings/ + - ../../panels-visualizations/configure-value-mappings/ # /docs/grafana/next/panels-visualizations/configure-value-mappings/ labels: products: - cloud diff --git a/docs/sources/panels-visualizations/panel-editor-overview/index.md b/docs/sources/visualizations/panels-visualizations/panel-editor-overview/index.md similarity index 77% rename from docs/sources/panels-visualizations/panel-editor-overview/index.md rename to docs/sources/visualizations/panels-visualizations/panel-editor-overview/index.md index fbde6ce7975..0a2247537cf 100644 --- a/docs/sources/panels-visualizations/panel-editor-overview/index.md +++ b/docs/sources/visualizations/panels-visualizations/panel-editor-overview/index.md @@ -1,15 +1,16 @@ --- aliases: - - ../dashboards/add-organize-panels/ - - ../dashboards/dashboard-create/ - - ../panels/add-panels-dynamically/about-repeating-panels-rows/ - - ../panels/add-panels-dynamically/configure-repeating-panels/ - - ../panels/add-panels-dynamically/configure-repeating-rows/ - - ../panels/working-with-panels/ - - ../panels/working-with-panels/add-panel/ - - ../panels/working-with-panels/navigate-inspector-panel/ - - ../panels/working-with-panels/navigate-panel-editor/ - - add-organize-panels/ + - ../../dashboards/add-organize-panels/ # /docs/grafana/next/dashboards/add-organize-panels/ + - ../../dashboards/dashboard-create/ # /docs/grafana/next/dashboards/dashboard-create/ + - ../../panels/add-panels-dynamically/about-repeating-panels-rows/ # /docs/grafana/next/panels/add-panels-dynamically/about-repeating-panels-rows/ + - ../../panels/add-panels-dynamically/configure-repeating-panels/ # /docs/grafana/next/panels/add-panels-dynamically/configure-repeating-panels/ + - ../../panels/add-panels-dynamically/configure-repeating-rows/ # /docs/grafana/next/panels/add-panels-dynamically/configure-repeating-rows/ + - ../../panels/working-with-panels/ # /docs/grafana/next/panels/working-with-panels/ + - ../../panels/working-with-panels/add-panel/ # /docs/grafana/next/panels/working-with-panels/add-panel/ + - ../../panels/working-with-panels/navigate-inspector-panel/ # /docs/grafana/next/panels/working-with-panels/navigate-inspector-panel/ + - ../../panels/working-with-panels/navigate-panel-editor/ # /docs/grafana/next/panels/working-with-panels/navigate-panel-editor/ + - ../../panels-visualizations/add-organize-panels/ # /docs/grafana/next/panels-visualizations/add-organize-panels/ + - ../../panels-visualizations/panel-editor-overview/ # /docs/grafana/next/panels-visualizations/panel-editor-overview/ keywords: - panel - dashboard diff --git a/docs/sources/panels-visualizations/panel-inspector/index.md b/docs/sources/visualizations/panels-visualizations/panel-inspector/index.md similarity index 83% rename from docs/sources/panels-visualizations/panel-inspector/index.md rename to docs/sources/visualizations/panels-visualizations/panel-inspector/index.md index d751957a171..15cfc8d7ed6 100644 --- a/docs/sources/panels-visualizations/panel-inspector/index.md +++ b/docs/sources/visualizations/panels-visualizations/panel-inspector/index.md @@ -1,9 +1,10 @@ --- aliases: - - ../panels/query-a-data-source/download-raw-query-results/ - - ../panels/query-a-data-source/inspect-query-performance/ - - ../panels/query-a-data-source/inspect-request-and-response-data/ - - ../panels/working-with-panels/navigate-inspector-panel/ + - ../../panels/query-a-data-source/download-raw-query-results/ # /docs/grafana/next/panels/query-a-data-source/download-raw-query-results/ + - ../../panels/query-a-data-source/inspect-query-performance/ # /docs/grafana/next/panels/query-a-data-source/inspect-query-performance/ + - ../../panels/query-a-data-source/inspect-request-and-response-data/ # /docs/grafana/next/panels/query-a-data-source/inspect-request-and-response-data/ + - ../../panels/working-with-panels/navigate-inspector-panel/ # /docs/grafana/next/panels/working-with-panels/navigate-inspector-panel/ + - ../../panels-visualizations/panel-inspector/ # /docs/grafana/next/panels-visualizations/panel-inspector/ labels: products: - cloud diff --git a/docs/sources/panels-visualizations/panel-overview/index.md b/docs/sources/visualizations/panels-visualizations/panel-overview/index.md similarity index 98% rename from docs/sources/panels-visualizations/panel-overview/index.md rename to docs/sources/visualizations/panels-visualizations/panel-overview/index.md index edb390ef143..299f3963e30 100644 --- a/docs/sources/panels-visualizations/panel-overview/index.md +++ b/docs/sources/visualizations/panels-visualizations/panel-overview/index.md @@ -102,6 +102,8 @@ refs: destination: /docs/grafana//panels-visualizations/configure-thresholds/ - pattern: /docs/grafana-cloud/ destination: /docs/grafana-cloud/visualizations/panels-visualizations/configure-thresholds/ +aliases: + - ../../panels-visualizations/panel-overview/ # /docs/grafana/next/panels-visualizations/panel-overview/ --- # Panel overview diff --git a/docs/sources/panels-visualizations/query-transform-data/_index.md b/docs/sources/visualizations/panels-visualizations/query-transform-data/_index.md similarity index 93% rename from docs/sources/panels-visualizations/query-transform-data/_index.md rename to docs/sources/visualizations/panels-visualizations/query-transform-data/_index.md index 10d810409c0..42dcf1338b7 100644 --- a/docs/sources/panels-visualizations/query-transform-data/_index.md +++ b/docs/sources/visualizations/panels-visualizations/query-transform-data/_index.md @@ -1,18 +1,19 @@ --- aliases: - - ../panels/expressions/ - - ../panels/inspect-panel/ - - ../panels/queries/ - - ../panels/query-a-data-source/ - - ../panels/query-a-data-source/about-queries/ - - ../panels/query-a-data-source/add-a-query/ - - ../panels/query-a-data-source/manage-queries/ - - ../panels/query-a-data-source/navigate-query-tab/ - - ../panels/query-options/ - - ../panels/reference-query-options/ - - ../panels/share-query-results/ - - manage-queries/ - - query-options/ + - ../../panels-visualizations/manage-queries/ # /docs/grafana/next/panels-visualizations/manage-queries/ + - ../../panels-visualizations/query-options/ # /docs/grafana/next/panels-visualizations/query-options/ + - ../../panels-visualizations/query-transform-data/ # /docs/grafana/next/panels-visualizations/query-transform-data/ + - ../../panels/expressions/ # /docs/grafana/next/panels/expressions/ + - ../../panels/inspect-panel/ # /docs/grafana/next/panels/inspect-panel/ + - ../../panels/queries/ # /docs/grafana/next/panels/queries/ + - ../../panels/query-a-data-source/ # /docs/grafana/next/panels/query-a-data-source/ + - ../../panels/query-a-data-source/about-queries/ # /docs/grafana/next/panels/query-a-data-source/about-queries/ + - ../../panels/query-a-data-source/add-a-query/ # /docs/grafana/next/panels/query-a-data-source/add-a-query/ + - ../../panels/query-a-data-source/manage-queries/ # /docs/grafana/next/panels/query-a-data-source/manage-queries/ + - ../../panels/query-a-data-source/navigate-query-tab/ # /docs/grafana/next/panels/query-a-data-source/navigate-query-tab/ + - ../../panels/query-options/ # /docs/grafana/next/panels/query-options/ + - ../../panels/reference-query-options/ # /docs/grafana/next/panels/reference-query-options/ + - ../../panels/share-query-results/ # /docs/grafana/next/panels/share-query-results/ labels: products: - cloud diff --git a/docs/sources/panels-visualizations/query-transform-data/calculation-types/index.md b/docs/sources/visualizations/panels-visualizations/query-transform-data/calculation-types/index.md similarity index 81% rename from docs/sources/panels-visualizations/query-transform-data/calculation-types/index.md rename to docs/sources/visualizations/panels-visualizations/query-transform-data/calculation-types/index.md index 1306197d901..6fe97955ba8 100644 --- a/docs/sources/panels-visualizations/query-transform-data/calculation-types/index.md +++ b/docs/sources/visualizations/panels-visualizations/query-transform-data/calculation-types/index.md @@ -1,9 +1,10 @@ --- aliases: - - ../../panels/calculation-types/ # /docs/grafana//panels/calculation-types/ - - ../../panels/calculations-list/ # /docs/grafana//panels/calculations-list/ - - ../../panels/reference-calculation-types/ # /docs/grafana//panels/reference-calculation-types/ - - ../calculation-types/ # /docs/grafana//panels-visualizations/calculation-types/ + - ../../../panels-visualizations/calculation-types/ # /docs/grafana/next/panels-visualizations/calculation-types/ + - ../../../panels-visualizations/query-transform-data/calculation-types/ # /docs/grafana/next/panels-visualizations/query-transform-data/calculation-types/ + - ../../../panels/calculation-types/ # /docs/grafana//panels/calculation-types/ + - ../../../panels/calculations-list/ # /docs/grafana//panels/calculations-list/ + - ../../../panels/reference-calculation-types/ # /docs/grafana//panels/reference-calculation-types/ labels: products: - cloud diff --git a/docs/sources/panels-visualizations/query-transform-data/expression-queries/index.md b/docs/sources/visualizations/panels-visualizations/query-transform-data/expression-queries/index.md similarity index 94% rename from docs/sources/panels-visualizations/query-transform-data/expression-queries/index.md rename to docs/sources/visualizations/panels-visualizations/query-transform-data/expression-queries/index.md index 652f668d106..cf6432be27a 100644 --- a/docs/sources/panels-visualizations/query-transform-data/expression-queries/index.md +++ b/docs/sources/visualizations/panels-visualizations/query-transform-data/expression-queries/index.md @@ -1,9 +1,10 @@ --- aliases: - - ../../panels/query-a-data-source/use-expressions-to-manipulate-data/ - - ../../panels/query-a-data-source/use-expressions-to-manipulate-data/about-expressions/ - - ../../panels/query-a-data-source/use-expressions-to-manipulate-data/write-an-expression/ - - ./ + - ../../../panels-visualizations/query-transform-data/ # /docs/grafana/next/panels-visualizations/query-transform-data/ + - ../../../panels-visualizations/query-transform-data/expression-queries/ # /docs/grafana/next/panels-visualizations/query-transform-data/expression-queries/ + - ../../../panels/query-a-data-source/use-expressions-to-manipulate-data/ # /docs/grafana/next/panels/query-a-data-source/use-expressions-to-manipulate-data/ + - ../../../panels/query-a-data-source/use-expressions-to-manipulate-data/about-expressions/ # /docs/grafana/next/panels/query-a-data-source/use-expressions-to-manipulate-data/about-expressions/ + - ../../../panels/query-a-data-source/use-expressions-to-manipulate-data/write-an-expression/ # /docs/grafana/next/panels/query-a-data-source/use-expressions-to-manipulate-data/write-an-expression/ labels: products: - cloud diff --git a/docs/sources/panels-visualizations/query-transform-data/share-query/index.md b/docs/sources/visualizations/panels-visualizations/query-transform-data/share-query/index.md similarity index 89% rename from docs/sources/panels-visualizations/query-transform-data/share-query/index.md rename to docs/sources/visualizations/panels-visualizations/query-transform-data/share-query/index.md index a7da8d12822..0dce820cc7b 100644 --- a/docs/sources/panels-visualizations/query-transform-data/share-query/index.md +++ b/docs/sources/visualizations/panels-visualizations/query-transform-data/share-query/index.md @@ -1,6 +1,7 @@ --- aliases: - - ../../panels/query-a-data-source/share-query/ + - ../../../panels/query-a-data-source/share-query/ # /docs/grafana/next/panels/query-a-data-source/share-query/ + - ../../../panels-visualizations/query-transform-data/share-query/ # /docs/grafana/next/panels-visualizations/query-transform-data/share-query/ labels: products: - cloud diff --git a/docs/sources/panels-visualizations/query-transform-data/sql-expressions/index.md b/docs/sources/visualizations/panels-visualizations/query-transform-data/sql-expressions/index.md similarity index 85% rename from docs/sources/panels-visualizations/query-transform-data/sql-expressions/index.md rename to docs/sources/visualizations/panels-visualizations/query-transform-data/sql-expressions/index.md index 2a23b882d93..7cb91aaeb7f 100644 --- a/docs/sources/panels-visualizations/query-transform-data/sql-expressions/index.md +++ b/docs/sources/visualizations/panels-visualizations/query-transform-data/sql-expressions/index.md @@ -60,12 +60,6 @@ A key capability of SQL expressions is the ability to JOIN data from multiple ta To work with SQL expressions, you must use data from a backend data source. In Grafana, a backend data source refers to a data source plugin or integration that communicates with a database, service, or API through the Grafana server, rather than directly from the browser (frontend). -## Known limitations - -- Currently, only one SQL expression is supported per panel or alert. -- Grafana supports certain data sources. Refer to [compatible data sources](#compatible-data-sources) for a current list. -- Autocomplete is available, but column/field autocomplete is only available after enabling the `sqlExpressionsColumnAutoComplete` feature toggle, which is provided on an experimental basis. - ## Compatible data sources The following are compatible data sources: @@ -238,6 +232,81 @@ During conversion: - The `metric_name` column stores the raw metric identifier. - For time series data, Grafana includes a `time` column with timestamps +## Known limitations + +- Currently, only one SQL expression is supported per panel or alert. +- Grafana supports certain data sources. Refer to [compatible data sources](#compatible-data-sources) for a current list. +- Autocomplete is available, but column/field autocomplete is only available after enabling the `sqlExpressionsColumnAutoComplete` feature toggle, which is provided on an experimental basis. + +### Schema changes and missing data + +SQL expressions have known limitations that may cause queries to fail or return unexpected results. These constraints are inherent to how the feature is implemented and should be understood when building queries. + +The following situations are affected: + +- Error responses โ€“ When a data source query returns an error, SQL expressions cannot interpret the result. + +- No data responses โ€“ If a query returns no rows, the SQL expression engine cannot infer a schema. + +- Dynamic schema responses โ€“ If the set of columns or labels changes between query executions, SQL expressions may fail because it treats column changes as schema changes. + +SQL expressions are powered by an embedded SQL engine where each query result is treated as a table. The schema of that table is derived from the columns returned by the underlying data source. + +Unlike traditional SQL databases, where schemas are usually fixed, many Grafana data sources (for example, Prometheus) can return results with varying label sets or no data at all. + +When this happens: + +- A missing column appears to the SQL engine as if it doesnโ€™t exist. +- A completely empty result provides no schema for subsequent SQL operations. +- Error responses break the assumption that the query returns tabular data. + +As a result, SQL expressions canโ€™t gracefully handle changes in schema or no-data conditions, since these cases violate the static schema model that SQL relies on. + +#### Workarounds + +You can mitigate these issues in the following ways: + +- Avoid `SELECT *` โ€“ Explicitly select only the columns you expect to exist. + +- Ensure a consistent schema โ€“ If possible, configure your query to always return columns, even when no data is present. + +#### Example: Handling Prometheus no data + +When joining results from the same Prometheus query across different data source instances, you can use this pattern: + +```sql +-- Prometheus query +sum by (cluster) (up{job=~".*zruler.*"}) +or on (cluster) ( + (0/0) * + ( + label_replace(vector(1), "cluster", "fake", "", "") + ) +) + +-- SQL expression +SELECT + COALESCE(a.time, b.time) AS time, + COALESCE(a.cluster, b.cluster) AS cluster, + COALESCE(a.up, 0) + COALESCE(b.up, 0) AS unified_up +FROM ( + SELECT time, cluster, __value__ AS up + FROM A + WHERE cluster != 'fake' + ORDER BY time + LIMIT 5 +) a +FULL OUTER JOIN ( + SELECT time, cluster, __value__ AS up + FROM B + WHERE cluster != 'fake' + ORDER BY time + LIMIT 5 +) b ON a.time = b.time; +``` + +This approach ensures that a schema exists even when one query returns no data. + ## SQL expressions examples 1. Create the following Prometheus query: diff --git a/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md b/docs/sources/visualizations/panels-visualizations/query-transform-data/transform-data/index.md similarity index 97% rename from docs/sources/panels-visualizations/query-transform-data/transform-data/index.md rename to docs/sources/visualizations/panels-visualizations/query-transform-data/transform-data/index.md index fda106213f9..b6b3499b4d7 100644 --- a/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md +++ b/docs/sources/visualizations/panels-visualizations/query-transform-data/transform-data/index.md @@ -18,21 +18,21 @@ comments: | Browse to http://localhost:3003/docs/grafana/latest/panels-visualizations/query-transform-data/transform-data/ Refer to ./docs/README.md "Content guidelines" for more information about editing and building these docs. - aliases: - - ../../panels/reference-transformation-functions/ - - ../../panels/transform-data/ - - ../../panels/transform-data/about-transformation/ - - ../../panels/transform-data/add-transformation-to-data/ - - ../../panels/transform-data/apply-transformation-to-data/ - - ../../panels/transform-data/debug-transformation/ - - ../../panels/transform-data/delete-transformation/ - - ../../panels/transform-data/transformation-functions/ - - ../../panels/transformations/ - - ../../panels/transformations/apply-transformations/ - - ../../panels/transformations/config-from-query/ - - ../../panels/transformations/rows-to-fields/ - - ../../panels/transformations/types-options/ + - ../../../panels/transform-data/ # /docs/grafana/next/panels/transform-data/ + - ../../../panels/transform-data/about-transformation/ # /docs/grafana/next/panels/transform-data/about-transformation/ + - ../../../panels/transform-data/add-transformation-to-data/ # /docs/grafana/next/panels/transform-data/add-transformation-to-data/ + - ../../../panels/transform-data/apply-transformation-to-data/ # /docs/grafana/next/panels/transform-data/apply-transformation-to-data/ + - ../../../panels/transform-data/debug-transformation/ # /docs/grafana/next/panels/transform-data/debug-transformation/ + - ../../../panels/transform-data/delete-transformation/ # /docs/grafana/next/panels/transform-data/delete-transformation/ + - ../../../panels/transform-data/transformation-functions/ # /docs/grafana/next/panels/transform-data/transformation-functions/ + - ../../../panels/transformations/ # /docs/grafana/next/panels/transformations/ + - ../../../panels/transformations/apply-transformations/ # /docs/grafana/next/panels/transformations/apply-transformations/ + - ../../../panels/transformations/config-from-query/ # /docs/grafana/next/panels/transformations/config-from-query/ + - ../../../panels/transformations/rows-to-fields/ # /docs/grafana/next/panels/transformations/rows-to-fields/ + - ../../../panels/transformations/types-options/ # /docs/grafana/next/panels/transformations/types-options/ + - ../../../panels/reference-transformation-functions/ # /docs/grafana/next/panels/reference-transformation-functions/ + - ../../../panels-visualizations/query-transform-data/transform-data/ # /docs/grafana/next/panels-visualizations/query-transform-data/transform-data/ labels: products: - cloud diff --git a/docs/sources/panels-visualizations/query-transform-data/troubleshoot-queries/index.md b/docs/sources/visualizations/panels-visualizations/query-transform-data/troubleshoot-queries/index.md similarity index 85% rename from docs/sources/panels-visualizations/query-transform-data/troubleshoot-queries/index.md rename to docs/sources/visualizations/panels-visualizations/query-transform-data/troubleshoot-queries/index.md index 5fd433320b9..d967aa9d80e 100644 --- a/docs/sources/panels-visualizations/query-transform-data/troubleshoot-queries/index.md +++ b/docs/sources/visualizations/panels-visualizations/query-transform-data/troubleshoot-queries/index.md @@ -1,6 +1,7 @@ --- aliases: - - ../../troubleshooting/troubleshoot-queries/ + - ../../../troubleshooting/troubleshoot-queries/ # /docs/grafana/next/troubleshooting/troubleshoot-queries/ + - ../../../panels-visualizations/query-transform-data/troubleshoot-queries/ # /docs/grafana/next/panels-visualizations/query-transform-data/troubleshoot-queries/ description: Troubleshoot Grafana queries keywords: - grafana diff --git a/docs/sources/panels-visualizations/visualizations/_index.md b/docs/sources/visualizations/panels-visualizations/visualizations/_index.md similarity index 95% rename from docs/sources/panels-visualizations/visualizations/_index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/_index.md index 454a9884dbc..a23a49ba713 100644 --- a/docs/sources/panels-visualizations/visualizations/_index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/_index.md @@ -1,11 +1,12 @@ --- aliases: - - ../features/panels/graph/ - - ../panels/visualizations/ - - ../panels/visualizations/graph-panel/ - - ../reference/graph/ - - ../visualizations/ - - ../visualizations/graph-panel/ + - ../../features/panels/graph/ # /docs/grafana/next/features/panels/graph/ + - ../../panels-visualizations/visualizations/ # /docs/grafana/next/panels-visualizations/visualizations/ + - ../../panels/visualizations/ # /docs/grafana/next/panels/visualizations/ + - ../../panels/visualizations/graph-panel/ # /docs/grafana/next/panels/visualizations/graph-panel/ + - ../../reference/graph/ # /docs/grafana/next/reference/graph/ + - ../../visualizations/ # /docs/grafana/next/visualizations/ + - ../../visualizations/graph-panel/ # /docs/grafana/next/visualizations/graph-panel/ labels: products: - cloud diff --git a/docs/sources/panels-visualizations/visualizations/alert-list/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/alert-list/index.md similarity index 91% rename from docs/sources/panels-visualizations/visualizations/alert-list/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/alert-list/index.md index 3e6550a8f5e..31ad53d0251 100644 --- a/docs/sources/panels-visualizations/visualizations/alert-list/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/alert-list/index.md @@ -1,9 +1,10 @@ --- aliases: - - ../../features/panels/alertlist/ - - ../../panels/visualizations/alert-list-panel/ - - ../../reference/alertlist/ - - ../../visualizations/alert-list-panel/ + - ../../../features/panels/alertlist/ # /docs/grafana/next/features/panels/alertlist/ + - ../../../panels-visualizations/visualizations/alert-list/ # /docs/grafana/next/panels-visualizations/visualizations/alert-list/ + - ../../../panels/visualizations/alert-list-panel/ # /docs/grafana/next/panels/visualizations/alert-list-panel/ + - ../../../reference/alertlist/ # /docs/grafana/next/reference/alertlist/ + - ../../../visualizations/alert-list-panel/ # /docs/grafana/next/visualizations/alert-list-panel/ keywords: - grafana - alert list diff --git a/docs/sources/panels-visualizations/visualizations/annotations/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/annotations/index.md similarity index 90% rename from docs/sources/panels-visualizations/visualizations/annotations/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/annotations/index.md index d69ea3d95de..ff53ee4e0f4 100644 --- a/docs/sources/panels-visualizations/visualizations/annotations/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/annotations/index.md @@ -1,8 +1,9 @@ --- aliases: - - ../../features/panels/annotations/ - - ../../panels/visualizations/annotations/ - - ../../visualizations/annotations/ + - ../../../features/panels/annotations/ # /docs/grafana/next/features/panels/annotations/ + - ../../../panels/visualizations/annotations/ # /docs/grafana/next/panels/visualizations/annotations/ + - ../../annotations/ # /docs/grafana/next/visualizations/annotations/ + - ../../../panels-visualizations/visualizations/annotations/ # /docs/grafana/next/panels-visualizations/visualizations/annotations/ description: Configure options for Grafana's annotations list visualization keywords: - grafana diff --git a/docs/sources/panels-visualizations/visualizations/bar-chart/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/bar-chart/index.md similarity index 97% rename from docs/sources/panels-visualizations/visualizations/bar-chart/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/bar-chart/index.md index 45a847aeac3..9e3f445e612 100644 --- a/docs/sources/panels-visualizations/visualizations/bar-chart/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/bar-chart/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../../panels/visualizations/bar-chart/ - - ../../visualizations/bar-chart/ + - ../../../panels/visualizations/bar-chart/ # /docs/grafana/next/panels/visualizations/bar-chart/ + - ../../bar-chart/ # /docs/grafana/next/visualizations/bar-chart/ + - ../../../panels-visualizations/visualizations/bar-chart/ # /docs/grafana/next/panels-visualizations/visualizations/bar-chart/ description: Configure options for Grafana's bar chart visualization keywords: - grafana diff --git a/docs/sources/panels-visualizations/visualizations/bar-gauge/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/bar-gauge/index.md similarity index 95% rename from docs/sources/panels-visualizations/visualizations/bar-gauge/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/bar-gauge/index.md index 72862007d31..90be816c461 100644 --- a/docs/sources/panels-visualizations/visualizations/bar-gauge/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/bar-gauge/index.md @@ -1,8 +1,9 @@ --- aliases: - - ../../features/panels/bar_gauge/ - - ../../panels/visualizations/bar-gauge-panel/ - - ../../visualizations/bar-gauge-panel/ + - ../../../features/panels/bar_gauge/ # /docs/grafana/next/features/panels/bar_gauge/ + - ../../../panels/visualizations/bar-gauge-panel/ # /docs/grafana/next/panels/visualizations/bar-gauge-panel/ + - ../../bar-gauge-panel/ # /docs/grafana/next/visualizations/bar-gauge-panel/ + - ../../../panels-visualizations/visualizations/bar-gauge/ # /docs/grafana/next/panels-visualizations/visualizations/bar-gauge/ description: Configure options for Grafana's bar gauge visualization keywords: - grafana diff --git a/docs/sources/panels-visualizations/visualizations/candlestick/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/candlestick/index.md similarity index 98% rename from docs/sources/panels-visualizations/visualizations/candlestick/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/candlestick/index.md index dc0df1d1e9f..bc07d805000 100644 --- a/docs/sources/panels-visualizations/visualizations/candlestick/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/candlestick/index.md @@ -1,8 +1,9 @@ --- aliases: - - ../../features/panels/candlestick/ - - ../../panels/visualizations/candlestick/ - - ../../visualizations/candlestick/ + - ../../../features/panels/candlestick/ # /docs/grafana/next/features/panels/candlestick/ + - ../../../panels/visualizations/candlestick/ # /docs/grafana/next/panels/visualizations/candlestick/ + - ../../candlestick/ # /docs/grafana/next/visualizations/candlestick/ + - ../../../panels-visualizations/visualizations/candlestick/ # /docs/grafana/next/panels-visualizations/visualizations/candlestick/ description: Configure options for Grafana's candlestick visualization keywords: - grafana diff --git a/docs/sources/panels-visualizations/visualizations/canvas/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/canvas/index.md similarity index 99% rename from docs/sources/panels-visualizations/visualizations/canvas/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/canvas/index.md index 76a18031449..821d547d7d3 100644 --- a/docs/sources/panels-visualizations/visualizations/canvas/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/canvas/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../../features/panels/canvas/ - - ../../visualizations/canvas/ + - ../../../features/panels/canvas/ # /docs/grafana/next/features/panels/canvas/ + - ../../canvas/ # /docs/grafana/next/visualizations/canvas/ + - ../../../panels-visualizations/visualizations/canvas/ # /docs/grafana/next/panels-visualizations/visualizations/canvas/ description: Configure options for Grafana's canvas visualization keywords: - grafana diff --git a/docs/sources/panels-visualizations/visualizations/dashboard-list/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/dashboard-list/index.md similarity index 90% rename from docs/sources/panels-visualizations/visualizations/dashboard-list/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/dashboard-list/index.md index 92e12996630..5c6b4aa8d4a 100644 --- a/docs/sources/panels-visualizations/visualizations/dashboard-list/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/dashboard-list/index.md @@ -1,9 +1,10 @@ --- aliases: - - ../../features/panels/dashlist/ - - ../../panels/visualizations/dashboard-list-panel/ - - ../../reference/dashlist/ - - ../../visualizations/dashboard-list-panel/ + - ../../../features/panels/dashlist/ # /docs/grafana/next/features/panels/dashlist/ + - ../../../panels/visualizations/dashboard-list-panel/ # /docs/grafana/next/panels/visualizations/dashboard-list-panel/ + - ../../../reference/dashlist/ # /docs/grafana/next/reference/dashlist/ + - ../../dashboard-list-panel/ # /docs/grafana/next/visualizations/dashboard-list-panel/ + - ../../../panels-visualizations/visualizations/dashboard-list/ # /docs/grafana/next/panels-visualizations/visualizations/dashboard-list/ keywords: - grafana - dashboard list diff --git a/docs/sources/panels-visualizations/visualizations/datagrid/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/datagrid/index.md similarity index 94% rename from docs/sources/panels-visualizations/visualizations/datagrid/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/datagrid/index.md index 60d9aab5201..b54326968a6 100644 --- a/docs/sources/panels-visualizations/visualizations/datagrid/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/datagrid/index.md @@ -1,8 +1,9 @@ --- aliases: - - ../../features/panels/datagrid_panel/ - - ../../reference/datagrid/ - - ../../visualizations/datagrid/ + - ../../../features/panels/datagrid_panel/ # /docs/grafana/next/features/panels/datagrid_panel/ + - ../../../reference/datagrid/ # /docs/grafana/next/reference/datagrid/ + - ../../datagrid/ # /docs/grafana/next/visualizations/datagrid/ + - ../../../panels-visualizations/visualizations/datagrid/ # /docs/grafana/next/panels-visualizations/visualizations/datagrid/ description: Configure options for Grafana's datagrid visualization keywords: - grafana diff --git a/docs/sources/panels-visualizations/visualizations/flame-graph/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/flame-graph/index.md similarity index 98% rename from docs/sources/panels-visualizations/visualizations/flame-graph/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/flame-graph/index.md index 362acb1384a..be79dcbb317 100644 --- a/docs/sources/panels-visualizations/visualizations/flame-graph/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/flame-graph/index.md @@ -1,6 +1,7 @@ --- aliases: - - ../../visualizations/flame-graph/ + - ../../flame-graph/ # /docs/grafana/next/visualizations/flame-graph/ + - ../../../panels-visualizations/visualizations/flame-graph/ # /docs/grafana/next/panels-visualizations/visualizations/flame-graph/ keywords: - grafana - dashboard diff --git a/docs/sources/panels-visualizations/visualizations/gauge/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/gauge/index.md similarity index 96% rename from docs/sources/panels-visualizations/visualizations/gauge/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/gauge/index.md index fbb1cb922ae..496abc455f4 100644 --- a/docs/sources/panels-visualizations/visualizations/gauge/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/gauge/index.md @@ -1,8 +1,9 @@ --- aliases: - - ../../features/panels/gauge/ - - ../../panels/visualizations/gauge-panel/ - - ../../visualizations/gauge-panel/ + - ../../../features/panels/gauge/ # /docs/grafana/next/features/panels/gauge/ + - ../../../panels/visualizations/gauge-panel/ # /docs/grafana/next/panels/visualizations/gauge-panel/ + - ../../gauge-panel/ # /docs/grafana/next/visualizations/gauge-panel/ + - ../../../panels-visualizations/visualizations/gauge/ # /docs/grafana/next/panels-visualizations/visualizations/gauge/ description: Configure options for Grafana's gauge visualization keywords: - grafana diff --git a/docs/sources/panels-visualizations/visualizations/geomap/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/geomap/index.md similarity index 94% rename from docs/sources/panels-visualizations/visualizations/geomap/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/geomap/index.md index 030b002760b..241622708db 100644 --- a/docs/sources/panels-visualizations/visualizations/geomap/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/geomap/index.md @@ -1,26 +1,27 @@ --- aliases: - - ../../features/panels/geomap/ - - ../../features/panels/geomap/arcgis/ - - ../../features/panels/geomap/carto/ - - ../../features/panels/geomap/controls/ - - ../../features/panels/geomap/daynight/ - - ../../features/panels/geomap/geojson/ - - ../../features/panels/geomap/heatmap/ - - ../../features/panels/geomap/markers/ - - ../../features/panels/geomap/osm/ - - ../../features/panels/geomap/zyx/ - - ../../panels/visualizations/geomap/ - - ../../panels/visualizations/geomap/arcgis/ - - ../../panels/visualizations/geomap/carto/ - - ../../panels/visualizations/geomap/controls/ - - ../../panels/visualizations/geomap/daynight/ - - ../../panels/visualizations/geomap/geojson/ - - ../../panels/visualizations/geomap/heatmap/ - - ../../panels/visualizations/geomap/markers/ - - ../../panels/visualizations/geomap/osm/ - - ../../panels/visualizations/geomap/zyx/ - - ../../visualizations/geomap/ + - ../../../features/panels/geomap/ # /docs/grafana/next/features/panels/geomap/ + - ../../../features/panels/geomap/arcgis/ # /docs/grafana/next/features/panels/geomap/arcgis/ + - ../../../features/panels/geomap/carto/ # /docs/grafana/next/features/panels/geomap/carto/ + - ../../../features/panels/geomap/controls/ # /docs/grafana/next/features/panels/geomap/controls/ + - ../../../features/panels/geomap/daynight/ # /docs/grafana/next/features/panels/geomap/daynight/ + - ../../../features/panels/geomap/geojson/ # /docs/grafana/next/features/panels/geomap/geojson/ + - ../../../features/panels/geomap/heatmap/ # /docs/grafana/next/features/panels/geomap/heatmap/ + - ../../../features/panels/geomap/markers/ # /docs/grafana/next/features/panels/geomap/markers/ + - ../../../features/panels/geomap/osm/ # /docs/grafana/next/features/panels/geomap/osm/ + - ../../../features/panels/geomap/zyx/ # /docs/grafana/next/features/panels/geomap/zyx/ + - ../../../panels/visualizations/geomap/ # /docs/grafana/next/panels/visualizations/geomap/ + - ../../../panels/visualizations/geomap/arcgis/ # /docs/grafana/next/panels/visualizations/geomap/arcgis/ + - ../../../panels/visualizations/geomap/carto/ # /docs/grafana/next/panels/visualizations/geomap/carto/ + - ../../../panels/visualizations/geomap/controls/ # /docs/grafana/next/panels/visualizations/geomap/controls/ + - ../../../panels/visualizations/geomap/daynight/ # /docs/grafana/next/panels/visualizations/geomap/daynight/ + - ../../../panels/visualizations/geomap/geojson/ # /docs/grafana/next/panels/visualizations/geomap/geojson/ + - ../../../panels/visualizations/geomap/heatmap/ # /docs/grafana/next/panels/visualizations/geomap/heatmap/ + - ../../../panels/visualizations/geomap/markers/ # /docs/grafana/next/panels/visualizations/geomap/markers/ + - ../../../panels/visualizations/geomap/osm/ # /docs/grafana/next/panels/visualizations/geomap/osm/ + - ../../../panels/visualizations/geomap/zyx/ # /docs/grafana/next/panels/visualizations/geomap/zyx/ + - ../../../visualizations/geomap/ # /docs/grafana/visualizations/geomap/ + - ../../../panels-visualizations/visualizations/geomap/ # /docs/grafana/next/panels-visualizations/visualizations/geomap/ description: Configure options for Grafana's geomap visualization keywords: - grafana diff --git a/docs/sources/panels-visualizations/visualizations/heatmap/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/heatmap/index.md similarity index 97% rename from docs/sources/panels-visualizations/visualizations/heatmap/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/heatmap/index.md index a51479e4e7a..31ffb8295dc 100644 --- a/docs/sources/panels-visualizations/visualizations/heatmap/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/heatmap/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../../features/panels/heatmap/ - - ../../visualizations/heatmap/ + - ../../../features/panels/heatmap/ # /docs/grafana/next/features/panels/heatmap/ + - ../../heatmap/ # /docs/grafana/next/visualizations/heatmap/ + - ../../../panels-visualizations/visualizations/heatmap/ # /docs/grafana/next/panels-visualizations/visualizations/heatmap/ description: Configure options for Grafana's heatmap visualization keywords: - grafana diff --git a/docs/sources/panels-visualizations/visualizations/histogram/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/histogram/index.md similarity index 94% rename from docs/sources/panels-visualizations/visualizations/histogram/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/histogram/index.md index c96747809dc..c1df19215f7 100644 --- a/docs/sources/panels-visualizations/visualizations/histogram/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/histogram/index.md @@ -1,8 +1,9 @@ --- aliases: - - ../../features/panels/histogram/ - - ../../panels/visualizations/histogram/ - - ../../visualizations/histogram/ + - ../../../features/panels/histogram/ # /docs/grafana/next/features/panels/histogram/ + - ../../../panels/visualizations/histogram/ # /docs/grafana/next/panels/visualizations/histogram/ + - ../../../visualizations/histogram/ # /docs/grafana/next/visualizations/histogram/ + - ../../../panels-visualizations/visualizations/histogram/ # /docs/grafana/next/panels-visualizations/visualizations/histogram/ description: Configure options for Grafana's histogram visualization keywords: - grafana diff --git a/docs/sources/panels-visualizations/visualizations/logs/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/logs/index.md similarity index 92% rename from docs/sources/panels-visualizations/visualizations/logs/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/logs/index.md index 00f0163f55f..91f179e9979 100644 --- a/docs/sources/panels-visualizations/visualizations/logs/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/logs/index.md @@ -1,9 +1,10 @@ --- aliases: - - ../../features/panels/logs/ - - ../../panels/visualizations/logs-panel/ - - ../../reference/logs/ - - ../../visualizations/logs-panel/ + - ../../../features/panels/logs/ # /docs/grafana/next/features/panels/logs/ + - ../../../panels/visualizations/logs-panel/ # /docs/grafana/next/panels/visualizations/logs-panel/ + - ../../../reference/logs/ # /docs/grafana/next/reference/logs/ + - ../../logs-panel/ # /docs/grafana/next/visualizations/logs-panel/ + - ../../../panels-visualizations/visualizations/logs/ # /docs/grafana/next/panels-visualizations/visualizations/logs/ keywords: - grafana - dashboard diff --git a/docs/sources/panels-visualizations/visualizations/news/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/news/index.md similarity index 90% rename from docs/sources/panels-visualizations/visualizations/news/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/news/index.md index 1797116334f..134a90b245f 100644 --- a/docs/sources/panels-visualizations/visualizations/news/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/news/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../../panels/visualizations/news-graph/ - - ../../visualizations/news-panel/ + - ../../../panels/visualizations/news-graph/ # /docs/grafana/next/panels/visualizations/news-graph/ + - ../../news-panel/ # /docs/grafana/next/visualizations/news-panel/ + - ../../../panels-visualizations/visualizations/news/ # /docs/grafana/next/panels-visualizations/visualizations/news/ keywords: - grafana - news diff --git a/docs/sources/panels-visualizations/visualizations/node-graph/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/node-graph/index.md similarity index 98% rename from docs/sources/panels-visualizations/visualizations/node-graph/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/node-graph/index.md index a18b7349310..ba0eeb73233 100644 --- a/docs/sources/panels-visualizations/visualizations/node-graph/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/node-graph/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../../panels/visualizations/node-graph/ - - ../../visualizations/node-graph/ + - ../../../panels-visualizations/visualizations/node-graph/ # /docs/grafana/next/panels-visualizations/visualizations/node-graph/ + - ../../../panels/visualizations/node-graph/ # /docs/grafana/next/panels/visualizations/node-graph/ + - ../../../visualizations/node-graph/ # /docs/grafana/next/visualizations/node-graph/ keywords: - grafana - dashboard diff --git a/docs/sources/panels-visualizations/visualizations/pie-chart/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/pie-chart/index.md similarity index 96% rename from docs/sources/panels-visualizations/visualizations/pie-chart/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/pie-chart/index.md index 0c46b734d1d..c29e80febdb 100644 --- a/docs/sources/panels-visualizations/visualizations/pie-chart/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/pie-chart/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../../panels/visualizations/pie-chart-pane/ - - ../../visualizations/pie-chart-panel/ + - ../../../panels/visualizations/pie-chart-pane/ # /docs/grafana/next/panels/visualizations/pie-chart-pane/ + - ../../pie-chart-panel/ # /docs/grafana/next/visualizations/pie-chart-panel/ + - ../../../panels-visualizations/visualizations/pie-chart/ # /docs/grafana/next/panels-visualizations/visualizations/pie-chart/ keywords: - grafana - pie chart diff --git a/docs/sources/panels-visualizations/visualizations/stat/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/stat/index.md similarity index 95% rename from docs/sources/panels-visualizations/visualizations/stat/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/stat/index.md index e1ad7fada4a..383322d6d27 100644 --- a/docs/sources/panels-visualizations/visualizations/stat/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/stat/index.md @@ -1,10 +1,11 @@ --- aliases: - - ../../features/panels/singlestat/ - - ../../features/panels/stat/ - - ../../panels/visualizations/stat-panel/ - - ../../reference/singlestat/ - - ../../visualizations/stat-panel/ + - ../../../features/panels/singlestat/ # /docs/grafana/next/features/panels/singlestat/ + - ../../../features/panels/stat/ # /docs/grafana/next/features/panels/stat/ + - ../../../panels/visualizations/stat-panel/ # /docs/grafana/next/panels/visualizations/stat-panel/ + - ../../../reference/singlestat/ # /docs/grafana/next/reference/singlestat/ + - ../../stat-panel/ # /docs/grafana/next/visualizations/stat-panel/ + - ../../../panels-visualizations/visualizations/stat/ # /docs/grafana/next/panels-visualizations/visualizations/stat/ description: Configure options for Grafana's stat visualization keywords: - grafana diff --git a/docs/sources/panels-visualizations/visualizations/state-timeline/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/state-timeline/index.md similarity index 96% rename from docs/sources/panels-visualizations/visualizations/state-timeline/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/state-timeline/index.md index 2bf81512885..c5840be810d 100644 --- a/docs/sources/panels-visualizations/visualizations/state-timeline/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/state-timeline/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../../panels/visualizations/state-timeline/ - - ../../visualizations/state-timeline/ + - ../../../panels/visualizations/state-timeline/ # /docs/grafana/next/panels/visualizations/state-timeline/ + - ../../state-timeline/ # /docs/grafana/next/visualizations/state-timeline/ + - ../../../panels-visualizations/visualizations/state-timeline/ # /docs/grafana/next/panels-visualizations/visualizations/state-timeline/ description: Configure options for Grafana's state timeline visualization keywords: - grafana diff --git a/docs/sources/panels-visualizations/visualizations/status-history/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/status-history/index.md similarity index 95% rename from docs/sources/panels-visualizations/visualizations/status-history/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/status-history/index.md index 6c7fdb4fd5e..4b30df76171 100644 --- a/docs/sources/panels-visualizations/visualizations/status-history/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/status-history/index.md @@ -1,7 +1,8 @@ --- aliases: - - ../../panels/visualizations/status-history/ - - ../../visualizations/status-history/ + - ../../../panels/visualizations/status-history/ # /docs/grafana/next/panels/visualizations/status-history/ + - ../../status-history/ # /docs/grafana/next/visualizations/status-history/ + - ../../../panels-visualizations/visualizations/status-history/ # /docs/grafana/next/panels-visualizations/visualizations/status-history/ description: Configure options for Grafana's status history visualization keywords: - grafana diff --git a/docs/sources/panels-visualizations/visualizations/table/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/table/index.md similarity index 97% rename from docs/sources/panels-visualizations/visualizations/table/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/table/index.md index 24185ffc378..84015fa7357 100644 --- a/docs/sources/panels-visualizations/visualizations/table/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/table/index.md @@ -1,11 +1,12 @@ --- aliases: - - ../../features/panels/table_panel/ - - ../../panels/visualizations/table/filter-table-columns/ - - ../../reference/table/ - - ../../visualizations/table/ - - ../../visualizations/table/filter-table-columns/ - - /docs/grafana/next/panels/visualizations/table/table-field-options/ + - ../../../features/panels/table_panel/ # /docs/grafana/next/features/panels/table_panel/ + - ../../../panels/visualizations/table/filter-table-columns/ # /docs/grafana/next/panels/visualizations/table/filter-table-columns/ + - ../../../reference/table/ # /docs/grafana/next/reference/table/ + - ../../table/ # /docs/grafana/next/visualizations/table/ + - ../../table/filter-table-columns/ # /docs/grafana/next/visualizations/table/filter-table-columns/ + - ../../../panels/visualizations/table/table-field-options/ # /docs/grafana/next/panels/visualizations/table/table-field-options/ + - ../../../panels-visualizations/visualizations/table/ # /docs/grafana/next/panels-visualizations/visualizations/table/ description: Configure options for Grafana's table visualization keywords: - grafana diff --git a/docs/sources/panels-visualizations/visualizations/text/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/text/index.md similarity index 87% rename from docs/sources/panels-visualizations/visualizations/text/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/text/index.md index fefcc32d251..5647fcff04b 100644 --- a/docs/sources/panels-visualizations/visualizations/text/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/text/index.md @@ -1,9 +1,10 @@ --- aliases: - - ../../features/panels/text/ - - ../../panels/visualizations/text-panel/ - - ../../reference/alertlist/ - - ../../visualizations/text-panel/ + - ../../../features/panels/text/ # /docs/grafana/next/features/panels/text/ + - ../../../panels-visualizations/visualizations/text/ # /docs/grafana/next/panels-visualizations/visualizations/text/ + - ../../../panels/visualizations/text-panel/ # /docs/grafana/next/panels/visualizations/text-panel/ + - ../../../reference/alertlist/ # /docs/grafana/next/reference/alertlist/ + - ../../../visualizations/text-panel/ # /docs/grafana/next/visualizations/text-panel/ keywords: - grafana - text diff --git a/docs/sources/panels-visualizations/visualizations/time-series/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/time-series/index.md similarity index 79% rename from docs/sources/panels-visualizations/visualizations/time-series/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/time-series/index.md index ad1b84f8a27..e7c51fb74cf 100644 --- a/docs/sources/panels-visualizations/visualizations/time-series/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/time-series/index.md @@ -1,22 +1,23 @@ --- aliases: - - ../../features/panels/histogram/ - - ../../panels/visualizations/time-series/ - - ../../panels/visualizations/time-series/annotate-time-series/ - - ../../panels/visualizations/time-series/change-axis-display/ - - ../../panels/visualizations/time-series/graph-color-scheme/ - - ../../panels/visualizations/time-series/graph-time-series-as-bars/ - - ../../panels/visualizations/time-series/graph-time-series-as-lines/ - - ../../panels/visualizations/time-series/graph-time-series-as-points/ - - ../../panels/visualizations/time-series/graph-time-series-stacking/ - - ../../visualizations/time-series/ - - ../../visualizations/time-series/annotate-time-series/ - - ../../visualizations/time-series/change-axis-display/ - - ../../visualizations/time-series/graph-color-scheme/ - - ../../visualizations/time-series/graph-time-series-as-bars/ - - ../../visualizations/time-series/graph-time-series-as-lines/ - - ../../visualizations/time-series/graph-time-series-as-points/ - - ../../visualizations/time-series/graph-time-series-stacking/ + - ../../../features/panels/histogram/ # /docs/grafana/next/features/panels/histogram/ + - ../../../panels/visualizations/time-series/ # /docs/grafana/next/panels/visualizations/time-series/ + - ../../../panels/visualizations/time-series/annotate-time-series/ # /docs/grafana/next/panels/visualizations/time-series/annotate-time-series/ + - ../../../panels/visualizations/time-series/change-axis-display/ # /docs/grafana/next/panels/visualizations/time-series/change-axis-display/ + - ../../../panels/visualizations/time-series/graph-color-scheme/ # /docs/grafana/next/panels/visualizations/time-series/graph-color-scheme/ + - ../../../panels/visualizations/time-series/graph-time-series-as-bars/ # /docs/grafana/next/panels/visualizations/time-series/graph-time-series-as-bars/ + - ../../../panels/visualizations/time-series/graph-time-series-as-lines/ # /docs/grafana/next/panels/visualizations/time-series/graph-time-series-as-lines/ + - ../../../panels/visualizations/time-series/graph-time-series-as-points/ # /docs/grafana/next/panels/visualizations/time-series/graph-time-series-as-points/ + - ../../../panels/visualizations/time-series/graph-time-series-stacking/ # /docs/grafana/next/panels/visualizations/time-series/graph-time-series-stacking/ + - ../../time-series/ # /docs/grafana/next/visualizations/time-series/ + - ../../time-series/annotate-time-series/ # /docs/grafana/next/visualizations/time-series/annotate-time-series/ + - ../../time-series/change-axis-display/ # /docs/grafana/next/visualizations/time-series/change-axis-display/ + - ../../time-series/graph-color-scheme/ # /docs/grafana/next/visualizations/time-series/graph-color-scheme/ + - ../../time-series/graph-time-series-as-bars/ # /docs/grafana/next/visualizations/time-series/graph-time-series-as-bars/ + - ../../time-series/graph-time-series-as-lines/ # /docs/grafana/next/visualizations/time-series/graph-time-series-as-lines/ + - ../../time-series/graph-time-series-as-points/ # /docs/grafana/next/visualizations/time-series/graph-time-series-as-points/ + - ../../time-series/graph-time-series-stacking/ # /docs/grafana/next/visualizations/time-series/graph-time-series-stacking/ + - ../../../panels-visualizations/visualizations/time-series/ # /docs/grafana/next/panels-visualizations/visualizations/time-series/ keywords: - grafana - graph panel diff --git a/docs/sources/panels-visualizations/visualizations/traces/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/traces/index.md similarity index 98% rename from docs/sources/panels-visualizations/visualizations/traces/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/traces/index.md index abf7fc1ddc3..f9e2a74d16d 100644 --- a/docs/sources/panels-visualizations/visualizations/traces/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/traces/index.md @@ -1,6 +1,7 @@ --- aliases: - - ../../visualizations/traces/ + - ../../traces/ # /docs/grafana/next/visualizations/traces/ + - ../../../panels-visualizations/visualizations/traces/ # /docs/grafana/next/panels-visualizations/visualizations/traces/ keywords: - grafana - dashboard diff --git a/docs/sources/panels-visualizations/visualizations/trend/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/trend/index.md similarity index 96% rename from docs/sources/panels-visualizations/visualizations/trend/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/trend/index.md index 21b58fd1b0f..c685bc15d48 100644 --- a/docs/sources/panels-visualizations/visualizations/trend/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/trend/index.md @@ -21,6 +21,8 @@ refs: destination: /docs/grafana//panels-visualizations/visualizations/time-series/ - pattern: /docs/grafana-cloud/ destination: /docs/grafana-cloud/visualizations/panels-visualizations/visualizations/time-series/ +aliases: + - ../../../panels-visualizations/visualizations/trend/ # /docs/grafana/next/panels-visualizations/visualizations/trend/ --- # Trend diff --git a/docs/sources/panels-visualizations/visualizations/xy-chart/index.md b/docs/sources/visualizations/panels-visualizations/visualizations/xy-chart/index.md similarity index 98% rename from docs/sources/panels-visualizations/visualizations/xy-chart/index.md rename to docs/sources/visualizations/panels-visualizations/visualizations/xy-chart/index.md index 72d59e961cc..c8eab88c838 100644 --- a/docs/sources/panels-visualizations/visualizations/xy-chart/index.md +++ b/docs/sources/visualizations/panels-visualizations/visualizations/xy-chart/index.md @@ -31,6 +31,8 @@ refs: destination: /docs/grafana//panels-visualizations/configure-overrides/ - pattern: /docs/grafana-cloud/ destination: /docs/grafana-cloud/visualizations/panels-visualizations/configure-overrides/ +aliases: + - ../../../panels-visualizations/visualizations/xy-chart/ # /docs/grafana/next/panels-visualizations/visualizations/xy-chart/ --- # XY chart diff --git a/docs/sources/explore/simplified-exploration/_index.md b/docs/sources/visualizations/simplified-exploration/_index.md similarity index 92% rename from docs/sources/explore/simplified-exploration/_index.md rename to docs/sources/visualizations/simplified-exploration/_index.md index 360b37aee5a..f812dd1d4c5 100644 --- a/docs/sources/explore/simplified-exploration/_index.md +++ b/docs/sources/visualizations/simplified-exploration/_index.md @@ -4,8 +4,9 @@ keywords: - Simplified exploration - queryless - Explore apps -title: Simplified exploration -menuTitle: Simplified exploration + - Drilldown apps +title: Drilldown +menuTitle: Drilldown weight: 100 hero: title: Simplified exploration with the Drilldown apps @@ -32,9 +33,11 @@ cards: href: ./profiles/ description: View and analyze high-level service performance, identify problem processes for optimization, and diagnose issues to determine root causes. height: 24 +aliases: + - ../explore/simplified-exploration/ # /docs/grafana/next/explore/simplified-exploration/ --- -# Simplified exploration +# Drilldown The Grafana Drilldown apps are designed for effortless data exploration through intuitive, queryless interactions. diff --git a/docs/sources/whatsnew/whats-new-in-v12-2.md b/docs/sources/whatsnew/whats-new-in-v12-2.md index bc8314d56be..64951665275 100644 --- a/docs/sources/whatsnew/whats-new-in-v12-2.md +++ b/docs/sources/whatsnew/whats-new-in-v12-2.md @@ -51,6 +51,9 @@ posts: - title: Authentication and authorization items: - whats-new/2025-09-10-scim-configuration-ui.md + - title: Auditing + items: + - whats-new/2025-10-09-auditing-options-for-recording-data-sources-queries.md whats_new_grafana_version: 12.2 weight: -51 --- diff --git a/e2e-playwright/dashboard-new-layouts/dashboard-group-panels.spec.ts b/e2e-playwright/dashboard-new-layouts/dashboard-group-panels.spec.ts index a5b996713b7..c2bde611cdf 100644 --- a/e2e-playwright/dashboard-new-layouts/dashboard-group-panels.spec.ts +++ b/e2e-playwright/dashboard-new-layouts/dashboard-group-panels.spec.ts @@ -92,8 +92,8 @@ test.describe( await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); - // Ungroup - await ungroupPanels(dashboardPage, selectors); + // Ungroup using the new ungroup rows button + await dashboardPage.getByGrafanaSelector(selectors.components.CanvasGridAddActions.ungroupRows).click(); // Verify Row title is gone await expect(dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row'))).toBeHidden(); @@ -112,7 +112,7 @@ test.describe( ).toHaveCount(3); }); - test('can add and remove several rows', async ({ dashboardPage, selectors, page }) => { + test('can add multiple rows and ungroup them all at once', async ({ dashboardPage, selectors, page }) => { await importTestDashboard(page, selectors, 'Add and remove rows'); await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); @@ -171,6 +171,7 @@ test.describe( await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + // First test individual row deletion await dashboardPage .getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1')) .locator('..') @@ -178,29 +179,38 @@ test.describe( await dashboardPage.getByGrafanaSelector(selectors.components.EditPaneHeader.deleteButton).click(); await dashboardPage.getByGrafanaSelector(selectors.pages.ConfirmModal.delete).click(); - await dashboardPage - .getByGrafanaSelector(selectors.components.DashboardRow.title('New row 2')) - .locator('..') - .click(); - await dashboardPage.getByGrafanaSelector(selectors.components.EditPaneHeader.deleteButton).click(); - await dashboardPage.getByGrafanaSelector(selectors.pages.ConfirmModal.delete).click(); - + // Verify one row is deleted await expect(firstRow).toBeVisible(); await expect(secondRow).toBeHidden(); + await expect(thirdRow).toBeVisible(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) + ).toHaveCount(4); // 3 from first row + 1 from third row + + // Now test ungrouping all remaining rows at once + await dashboardPage.getByGrafanaSelector(selectors.components.CanvasGridAddActions.ungroupRows).click(); + + // Handle the ConvertMixedGridsModal that appears when there are mixed grid types + // The modal asks which grid type to convert to - we'll choose "Custom" (GridLayout) + await page.getByRole('button', { name: 'Convert to Custom' }).click(); + + // Verify all remaining rows are gone and all panels are now in a single grid + await expect(firstRow).toBeHidden(); await expect(thirdRow).toBeHidden(); await expect( dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) - ).toHaveCount(3); + ).toHaveCount(4); // All 4 panels should be visible in the single grid await saveDashboard(dashboardPage, selectors); await page.reload(); - await expect(firstRow).toBeVisible(); + // Verify all rows are still gone after reload + await expect(firstRow).toBeHidden(); await expect(secondRow).toBeHidden(); await expect(thirdRow).toBeHidden(); await expect( dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) - ).toHaveCount(3); + ).toHaveCount(4); }); test('can paste a copied row', async ({ dashboardPage, selectors, page }) => { @@ -473,7 +483,7 @@ test.describe( // Ungroup await ungroupPanels(dashboardPage, selectors); // ungroup tabs - await ungroupPanels(dashboardPage, selectors); // ungroup rows + await dashboardPage.getByGrafanaSelector(selectors.components.CanvasGridAddActions.ungroupRows).click(); // ungroup rows // Verify tab and row titles is gone await expect(dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row'))).toBeHidden(); @@ -804,7 +814,7 @@ test.describe( await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); // Ungroup - await ungroupPanels(dashboardPage, selectors); // ungroup rows + await dashboardPage.getByGrafanaSelector(selectors.components.CanvasGridAddActions.ungroupRows).click(); // ungroup rows await ungroupPanels(dashboardPage, selectors); // ungroup tabs // Verify tab and row titles is gone diff --git a/e2e-playwright/dashboard-new-layouts/dashboards-edit-custom-variables.spec.ts b/e2e-playwright/dashboard-new-layouts/dashboards-edit-custom-variables.spec.ts new file mode 100644 index 00000000000..ce5465c1e33 --- /dev/null +++ b/e2e-playwright/dashboard-new-layouts/dashboards-edit-custom-variables.spec.ts @@ -0,0 +1,212 @@ +import { Locator } from '@playwright/test'; + +import { test, expect, DashboardPage, E2ESelectorGroups } from '@grafana/plugin-e2e'; + +import { flows } from './utils'; + +test.use({ + featureToggles: { + kubernetesDashboards: true, + dashboardNewLayouts: true, + dashboardUndoRedo: true, + groupByVariable: true, + }, +}); + +test.use({ + viewport: { width: 1920, height: 1080 }, +}); + +const PAGE_UNDER_TEST = 'kVi2Gex7z/test-variable-output'; +const DASHBOARD_NAME = 'Test variable output'; + +test.describe( + 'Dashboard edit - Custom variable', + { + tag: ['@dashboards'], + }, + () => { + let addButton: Locator | undefined; + let rows: Locator | undefined; + let valueInputs: Locator | undefined; + let labelInputs: Locator | undefined; + let deleteButtons: Locator | undefined; + + const getAddButton = async (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => { + addButton = dashboardPage.getByGrafanaSelector( + selectors.pages.Dashboard.Settings.Variables.Edit.StaticOptionsEditor.addButton + ); + await expect(addButton).toBeVisible(); + }; + + const refetchItems = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => { + rows = dashboardPage.getByGrafanaSelector( + selectors.pages.Dashboard.Settings.Variables.Edit.StaticOptionsEditor.row + ); + + valueInputs = dashboardPage.getByGrafanaSelector( + selectors.pages.Dashboard.Settings.Variables.Edit.StaticOptionsEditor.valueInput + ); + + labelInputs = dashboardPage.getByGrafanaSelector( + selectors.pages.Dashboard.Settings.Variables.Edit.StaticOptionsEditor.labelInput + ); + + deleteButtons = dashboardPage.getByGrafanaSelector( + selectors.pages.Dashboard.Settings.Variables.Edit.StaticOptionsEditor.deleteButton + ); + }; + + const checkRows = async (length: number) => { + expect(await rows!.all()).toHaveLength(length); + }; + + const fillValue = async (text: string, index: number) => { + await valueInputs!.nth(index).fill(text); + }; + + const fillLabel = async (text: string, index: number) => { + await labelInputs!.nth(index).fill(text); + }; + + const fillLabelValue = async (value: string, label: string, index: number) => { + await fillValue(value, index); + await fillLabel(label, index); + }; + + const openModal = async (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => { + await dashboardPage + .getByGrafanaSelector(selectors.pages.Dashboard.Settings.Variables.Edit.CustomVariable.optionsOpenButton) + .click(); + + await getAddButton(dashboardPage, selectors); + + refetchItems(dashboardPage, selectors); + }; + + const closeModal = async (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => { + await dashboardPage + .getByGrafanaSelector(selectors.pages.Dashboard.Settings.Variables.Edit.CustomVariable.closeButton) + .click(); + }; + + const checkItems = async (items: Array<[string, string?]>) => { + for (let i = 0; i < items.length; i++) { + const [value, label] = items[i]; + await expect(valueInputs!.nth(i)).toHaveValue(value); + await expect(labelInputs!.nth(i)).toHaveValue(label ?? ''); + } + }; + + const checkPreview = async (dashboardPage: DashboardPage, selectors: E2ESelectorGroups, labels: string[]) => { + const previewOptions = dashboardPage.getByGrafanaSelector( + selectors.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption + ); + + for (let i = 0; i < labels.length; i++) { + expect(await previewOptions.nth(i).textContent()).toBe(labels[i]); + } + }; + + const addItem = async (dashboardPage: DashboardPage, selectors: E2ESelectorGroups, value = '', label = '') => { + await addButton!.click(); + refetchItems(dashboardPage, selectors); + await fillLabelValue(value ?? '', label ?? '', (await rows!.all()).length - 1); + }; + + const removeItem = async (dashboardPage: DashboardPage, selectors: E2ESelectorGroups, index: number) => { + await deleteButtons!.nth(index).click(); + refetchItems(dashboardPage, selectors); + }; + + test.beforeEach(() => { + valueInputs = undefined; + labelInputs = undefined; + deleteButtons = undefined; + }); + + test('can add a new custom variable', async ({ gotoDashboardPage, selectors, page }) => { + const dashboardPage = await gotoDashboardPage({ uid: PAGE_UNDER_TEST }); + await expect(page.getByText(DASHBOARD_NAME)).toBeVisible(); + + // common steps to add a new variable + await flows.newEditPaneVariableClick(dashboardPage, selectors); + await flows.newEditPanelCommonVariableInputs(dashboardPage, selectors, { + type: 'custom', + name: 'foo', + label: 'Foo', + value: '', + }); + + await openModal(dashboardPage, selectors); + await checkRows(1); + await addItem(dashboardPage, selectors); + await checkRows(2); + await fillValue('first value', 0); + await fillLabelValue('second value', 'second label', 1); + await addItem(dashboardPage, selectors, 'third value', 'third label'); + await addItem(dashboardPage, selectors, 'fourth value', 'fourth value'); + await removeItem(dashboardPage, selectors, 2); + await checkRows(3); + await checkPreview(dashboardPage, selectors, ['first value', 'second label', 'fourth value']); + await closeModal(dashboardPage, selectors); + + // assert variable is visible and has the correct values + const variableLabel = dashboardPage.getByGrafanaSelector( + selectors.pages.Dashboard.SubMenu.submenuItemLabels('Foo') + ); + await expect(variableLabel).toBeVisible(); + await expect(variableLabel).toContainText('Foo'); + await expect( + dashboardPage.getByGrafanaSelector( + selectors.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('first value') + ) + ).toBeVisible(); + + // check that variable deletion works + await dashboardPage.getByGrafanaSelector(selectors.components.EditPaneHeader.deleteButton).click(); + await expect(variableLabel).toBeHidden(); + }); + + test('can edit a custom variable', async ({ gotoDashboardPage, selectors, page }) => { + const dashboardPage = await gotoDashboardPage({ + uid: PAGE_UNDER_TEST, + queryParams: new URLSearchParams({ orgId: '1', editview: 'variables' }), + }); + await expect(page.getByText(DASHBOARD_NAME)).toBeVisible(); + + // Create a custom variable in the dashboard settings page + await dashboardPage.getByGrafanaSelector(selectors.components.CallToActionCard.buttonV2('Add variable')).click(); + const typeSelect = dashboardPage + .getByGrafanaSelector(selectors.pages.Dashboard.Settings.Variables.Edit.General.generalTypeSelectV2) + .locator('input'); + await typeSelect.fill('Custom'); + await typeSelect.press('Enter'); + await dashboardPage + .getByGrafanaSelector(selectors.pages.Dashboard.Settings.Variables.Edit.General.generalNameInputV2) + .fill('foo'); + await dashboardPage + .getByGrafanaSelector(selectors.pages.Dashboard.Settings.Variables.Edit.General.generalLabelInputV2) + .fill('Foo'); + await dashboardPage + .getByGrafanaSelector(selectors.pages.Dashboard.Settings.Variables.Edit.CustomVariable.customValueInput) + .fill('first value, second label : second value, fourth value : fourth value'); + await dashboardPage + .getByGrafanaSelector(selectors.pages.Dashboard.Settings.Variables.Edit.General.applyButton) + .click(); + await dashboardPage + .getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.backToDashboardButton) + .click(); + + // Open the modal editor in the side pane + await dashboardPage.getByGrafanaSelector(selectors.components.PanelEditor.Outline.section).click(); + await dashboardPage.getByGrafanaSelector(selectors.components.PanelEditor.Outline.node('Variables')).click(); + await dashboardPage.getByGrafanaSelector(selectors.components.PanelEditor.Outline.item('foo')).click(); + await openModal(dashboardPage, selectors); + + // Check the items + await checkItems([['first value'], ['second value', 'second label'], ['fourth value']]); + await checkPreview(dashboardPage, selectors, ['first value', 'second label', 'fourth value']); + }); + } +); diff --git a/e2e-playwright/dashboard-new-layouts/dashboards-edit-variables.spec.ts b/e2e-playwright/dashboard-new-layouts/dashboards-edit-variables.spec.ts index 54991dfd623..4b5ea9574f8 100644 --- a/e2e-playwright/dashboard-new-layouts/dashboards-edit-variables.spec.ts +++ b/e2e-playwright/dashboard-new-layouts/dashboards-edit-variables.spec.ts @@ -20,46 +20,6 @@ test.describe( tag: ['@dashboards'], }, () => { - test('can add a new custom variable', async ({ gotoDashboardPage, selectors, page }) => { - const dashboardPage = await gotoDashboardPage({ uid: PAGE_UNDER_TEST }); - await expect(page.getByText(DASHBOARD_NAME)).toBeVisible(); - - const variable: Variable = { - type: 'custom', - name: 'foo', - label: 'Foo', - value: 'one,two,three', - }; - - // common steps to add a new variable - await flows.newEditPaneVariableClick(dashboardPage, selectors); - await flows.newEditPanelCommonVariableInputs(dashboardPage, selectors, variable); - - // set the custom variable value - const customValueInput = dashboardPage.getByGrafanaSelector( - selectors.pages.Dashboard.Settings.Variables.Edit.CustomVariable.customValueInput - ); - await customValueInput.fill(variable.value); - await customValueInput.blur(); - - // assert the dropdown for the variable is visible and has the correct values - const variableLabel = dashboardPage.getByGrafanaSelector( - selectors.pages.Dashboard.SubMenu.submenuItemLabels(variable.label!) - ); - await expect(variableLabel).toBeVisible(); - await expect(variableLabel).toContainText(variable.label!); - - const values = variable.value.split(','); - const firstValueLink = dashboardPage.getByGrafanaSelector( - selectors.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts(values[0]) - ); - await expect(firstValueLink).toBeVisible(); - - // check that variable deletion works - await dashboardPage.getByGrafanaSelector(selectors.components.EditPaneHeader.deleteButton).click(); - await expect(variableLabel).toBeHidden(); - }); - test('can add a new constant variable', async ({ gotoDashboardPage, selectors, page }) => { const dashboardPage = await gotoDashboardPage({ uid: PAGE_UNDER_TEST }); await expect(page.getByText(DASHBOARD_NAME)).toBeVisible(); diff --git a/e2e-playwright/dashboard-new-layouts/dashboards-repeats-custom-grid.spec.ts b/e2e-playwright/dashboard-new-layouts/dashboards-repeats-custom-grid.spec.ts index 0a349df5728..2d235571f97 100644 --- a/e2e-playwright/dashboard-new-layouts/dashboards-repeats-custom-grid.spec.ts +++ b/e2e-playwright/dashboard-new-layouts/dashboards-repeats-custom-grid.spec.ts @@ -1,6 +1,5 @@ import { test, expect } from '@grafana/plugin-e2e'; -import testV2Dashboard from '../dashboards/TestV2Dashboard.json'; import testV2DashWithRepeats from '../dashboards/V2DashWithRepeats.json'; import { diff --git a/e2e-playwright/dashboard-new-layouts/dashboards-repeats-tabs-layout.spec.ts b/e2e-playwright/dashboard-new-layouts/dashboards-repeats-tabs-layout.spec.ts new file mode 100644 index 00000000000..100ec864b0d --- /dev/null +++ b/e2e-playwright/dashboard-new-layouts/dashboards-repeats-tabs-layout.spec.ts @@ -0,0 +1,487 @@ +import { test, expect } from '@grafana/plugin-e2e'; + +import V2DashWithTabRepeats from '../dashboards/V2DashWithTabRepeats.json'; + +import { + verifyChanges, + saveDashboard, + importTestDashboard, + goToEmbeddedPanel, + checkRepeatedTabTitles, + groupIntoTab, + moveTab, + getTabPosition, +} from './utils'; + +const repeatTitleBase = 'Tab - '; +const newTitleBase = 'edited tab rep - '; +const repeatOptions = [1, 2, 3, 4]; + +test.use({ + featureToggles: { + kubernetesDashboards: true, + dashboardNewLayouts: true, + groupByVariable: true, + }, +}); + +test.use({ + viewport: { width: 1920, height: 1080 }, +}); + +test.describe( + 'Repeats - Dashboard tabs layout', + { + tag: ['@dashboards'], + }, + () => { + test('can enable tab repeats', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard(page, selectors, 'Tabs layout repeats - add repeats'); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + + await groupIntoTab(page, dashboardPage, selectors); + + await dashboardPage + .getByGrafanaSelector(selectors.components.PanelEditor.ElementEditPane.TabsLayout.titleInput) + .fill(`${repeatTitleBase}$c1`); + + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.join(' + ')}`) + ) + ).toBeVisible(); + + const repeatOptionsGroup = dashboardPage.getByGrafanaSelector( + selectors.components.OptionsGroup.group('repeat-options') + ); + // expand repeat options dropdown + await repeatOptionsGroup.getByRole('button').first().click(); + // find repeat variable dropdown + await repeatOptionsGroup.getByRole('combobox').click(); + await page.getByRole('option', { name: 'c1' }).click(); + + await checkRepeatedTabTitles(dashboardPage, selectors, repeatTitleBase, repeatOptions); + + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + await checkRepeatedTabTitles(dashboardPage, selectors, repeatTitleBase, repeatOptions); + }); + + test('can update tab repeats with variable change', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Tabs layout repeats - update on variable change', + JSON.stringify(V2DashWithTabRepeats) + ); + + const c1Var = dashboardPage.getByGrafanaSelector(selectors.pages.Dashboard.SubMenu.submenuItemLabels('c1')); + await c1Var + .locator('..') + .getByTestId(selectors.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts(repeatOptions.join(','))) + .click(); + // deselect last variable option + await dashboardPage + .getByGrafanaSelector( + selectors.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts(`${repeatOptions.at(-1)}`) + ) + .click(); + await page.locator('body').click({ position: { x: 0, y: 0 } }); // blur select + + // verify that repeats are present for first 3 values + await checkRepeatedTabTitles(dashboardPage, selectors, repeatTitleBase, repeatOptions.slice(0, -1)); + // verify there is no repeat with last value + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(-1)}`)) + ).toBeHidden(); + }); + test('can update repeats in edit pane', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Tabs layout repeats - update through edit pane', + JSON.stringify(V2DashWithTabRepeats) + ); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + // select first/original repeat tab to activate edit pane + await dashboardPage + .getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(0)}`)) + .click(); + + const titleInput = dashboardPage.getByGrafanaSelector( + selectors.components.PanelEditor.ElementEditPane.TabsLayout.titleInput + ); + await titleInput.fill(`${newTitleBase}$c1`); + await titleInput.blur(); + + await checkRepeatedTabTitles(dashboardPage, selectors, newTitleBase, repeatOptions); + + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + await checkRepeatedTabTitles(dashboardPage, selectors, newTitleBase, repeatOptions); + }); + + test('can update repeats after panel change', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Tabs layout repeats - update repeats after panel change', + JSON.stringify(V2DashWithTabRepeats) + ); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + + await dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')).first().click(); + + const panelTitleInput = dashboardPage.getByGrafanaSelector( + selectors.components.PanelEditor.OptionsPane.fieldInput('Title') + ); + await panelTitleInput.fill('New edited panel'); + await panelTitleInput.blur(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(1)}`)) + .click(); + + // intermediate step to verify tab switch happened + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Tab 2 - Row 1 - Panel repeat 1')) + ).toBeVisible(); + + // verify edited panel title updated in repeated tab + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New edited panel')) + ).toBeVisible(); + + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New edited panel')) + ).toBeVisible(); + }); + + test('can update repeats after panel change in editor', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Tabs layout repeats - update repeats after panel change in editor', + JSON.stringify(V2DashWithTabRepeats) + ); + + const panel = dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')).first(); + await panel.hover(); + await page.keyboard.press('e'); + + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.DashboardEditPaneSplitter.primaryBody) + ).toBeHidden(); // verifying that panel editor loaded + + const panelTitleInput = dashboardPage.getByGrafanaSelector( + selectors.components.PanelEditor.OptionsPane.fieldInput('Title') + ); + await panelTitleInput.fill('New edited panel'); + await panelTitleInput.blur(); + + // playwright too fast, verifying JSON diff that changes landed + await verifyChanges(dashboardPage, page, selectors, 'New edited panel'); + + // verify panel title change in panel editor UI + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title(`New edited panel`)) + ).toBeVisible(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.backToDashboardButton) + .click(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.DashboardEditPaneSplitter.primaryBody) + ).toBeVisible(); // verifying that dashboard loaded + + await dashboardPage + .getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(1)}`)) + .click(); + + // intermediate step to verify tab switch happened + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Tab 2 - Row 1 - Panel repeat 1')) + ).toBeVisible(); + + // verify edited panel title updated in repeated tab + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New edited panel')) + ).toBeVisible(); + + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + // verify edited panel title updated in repeated tab + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New edited panel')) + ).toBeVisible(); + }); + + test('can hide canvas grid add row action in repeats', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Tabs layout repeats - hide canvas add action in repeats', + JSON.stringify(V2DashWithTabRepeats) + ); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + + await expect(dashboardPage.getByGrafanaSelector(selectors.components.CanvasGridAddActions.addRow)).toBeVisible(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(1)}`)) + .click(); + + await expect(dashboardPage.getByGrafanaSelector(selectors.components.CanvasGridAddActions.addRow)).toBeHidden(); + }); + + test('can move repeated tabs', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Tabs layout repeats - move repeated tabs', + JSON.stringify(V2DashWithTabRepeats) + ); + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + await moveTab(dashboardPage, page, selectors, `${repeatTitleBase}${repeatOptions.at(0)}`, 'New tab'); + + // playwright too fast - adding intermediate step so that UI has time to update + await dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('New tab')).click(); + + // verify move by tab position + const repeatedTab = await getTabPosition(dashboardPage, selectors, `${repeatTitleBase}${repeatOptions.at(0)}`); + const normalTab = await getTabPosition(dashboardPage, selectors, 'New tab'); + expect(normalTab?.x).toBeLessThan(repeatedTab?.x || 0); + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + const repeatedTab2 = await getTabPosition(dashboardPage, selectors, `${repeatTitleBase}${repeatOptions.at(0)}`); + const normalTab2 = await getTabPosition(dashboardPage, selectors, 'New tab'); + expect(normalTab2?.x).toBeLessThan(repeatedTab2?.x || 0); + }); + + test('can load into repeated tab', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Tabs layout repeats - can load into repeated tab', + JSON.stringify(V2DashWithTabRepeats) + ); + + await dashboardPage + .getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(2)}`)) + .click(); + + await page.reload(); + + await expect(page.locator('[data-testid="uplot-main-div"]').first()).toBeVisible(); + + expect( + await dashboardPage + .getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(2)}`)) + .getAttribute('aria-selected') + ).toBe('true'); + }); + + test('can view panels in repeated tab', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Tabs layout repeats - view panels in repeated tabs', + JSON.stringify(V2DashWithTabRepeats) + ); + + // non repeated panel in repeated tab + await dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')).first().hover(); + await page.keyboard.press('v'); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Tab 1 - Row 1 - Panel repeat 1')) + ).toBeHidden(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) + ).toBeVisible(); + + await page.reload(); + + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) + ).toBeVisible(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.backToDashboardButton) + .click(); + + // repeated panel in original tab repeat + await dashboardPage + .getByGrafanaSelector(selectors.components.DashboardRow.title('Row 2')) + .scrollIntoViewIfNeeded(); + await dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Tab 1 - Row 2 - Panel repeat 2')) + .hover(); + await page.keyboard.press('v'); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Tab 1 - Row 1 - Panel repeat 1')) + ).toBeHidden(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Tab 1 - Row 2 - Panel repeat 2')) + ).toBeVisible(); + + await page.reload(); + + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Tab 1 - Row 2 - Panel repeat 2')) + ).toBeVisible(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.backToDashboardButton) + .click(); + + // repeated panel in repeated tab + await dashboardPage + .getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(2)}`)) + .click(); + await dashboardPage + .getByGrafanaSelector(selectors.components.DashboardRow.title('Row 2')) + .scrollIntoViewIfNeeded(); + await dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Tab 3 - Row 2 - Panel repeat 2')) + .hover(); + await page.keyboard.press('v'); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Tab 3 - Row 1 - Panel repeat 1')) + ).toBeHidden(); + + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Tab 3 - Row 2 - Panel repeat 2')) + ).toBeVisible(); + + await page.reload(); + + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Tab 3 - Row 2 - Panel repeat 2')) + ).toBeVisible(); + }); + + test('can view embedded panels in repeated tab', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Tabs layout repeats - view embedded panels in repeated tabs', + JSON.stringify(V2DashWithTabRepeats) + ); + + const dashUrl = page.url(); + + // non repeated panel in repeated tab + await dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')).first().hover(); + await page.keyboard.press('p+e'); + await goToEmbeddedPanel(page); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) + ).toBeVisible(); + await page.goto(dashUrl); + + // repeated panel in original tab repeat + await dashboardPage + .getByGrafanaSelector(selectors.components.DashboardRow.title('Row 2')) + .scrollIntoViewIfNeeded(); + await dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Tab 1 - Row 2 - Panel repeat 2')) + .hover(); + await page.keyboard.press('p+e'); + await goToEmbeddedPanel(page); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Tab 1 - Row 2 - Panel repeat 2')) + ).toBeVisible(); + await page.goto(dashUrl); + + // repeated panel in repeated tab + await dashboardPage + .getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(2)}`)) + .click(); + await dashboardPage + .getByGrafanaSelector(selectors.components.DashboardRow.title('Row 2')) + .scrollIntoViewIfNeeded(); + await dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Tab 3 - Row 2 - Panel repeat 2')) + .hover(); + await page.keyboard.press('p+e'); + await goToEmbeddedPanel(page); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Tab 3 - Row 2 - Panel repeat 2')) + ).toBeVisible(); + }); + + test('can remove repeats', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Tabs layout repeats - remove repeats', + JSON.stringify(V2DashWithTabRepeats) + ); + + // verify 5 tabs are present (4 repeats and 1 normal) + await checkRepeatedTabTitles(dashboardPage, selectors, repeatTitleBase, repeatOptions); + await expect(dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('New tab'))).toBeVisible(); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(0)}`)) + .click(); + + const repeatOptionsGroup = dashboardPage.getByGrafanaSelector( + selectors.components.OptionsGroup.group('repeat-options') + ); + // expand repeat options dropdown + await repeatOptionsGroup.getByRole('button').first().click(); + // find repeat variable dropdown + await repeatOptionsGroup.getByRole('combobox').click(); + await page.getByRole('option', { name: 'Disable repeating' }).click(); + + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.join(' + ')}`) + ) + ).toBeVisible(); + await expect(dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('New tab'))).toBeVisible(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(1)}`)) + ).toBeHidden(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(2)}`)) + ).toBeHidden(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(3)}`)) + ).toBeHidden(); + + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.join(' + ')}`) + ) + ).toBeVisible(); + await expect(dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('New tab'))).toBeVisible(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(1)}`)) + ).toBeHidden(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(2)}`)) + ).toBeHidden(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Tab.title(`${repeatTitleBase}${repeatOptions.at(3)}`)) + ).toBeHidden(); + }); + } +); diff --git a/e2e-playwright/dashboard-new-layouts/utils.ts b/e2e-playwright/dashboard-new-layouts/utils.ts index 2d279b0545a..c59f782b37a 100644 --- a/e2e-playwright/dashboard-new-layouts/utils.ts +++ b/e2e-playwright/dashboard-new-layouts/utils.ts @@ -185,5 +185,50 @@ export async function goToEmbeddedPanel(page: Page) { const baseUrl = currentUrl.match(baseUrlRegex)?.[0]; soloPanelUrl = soloPanelUrl!.replace(baseUrlRegex, baseUrl!); - page.goto(soloPanelUrl!); + await page.goto(soloPanelUrl!); +} + +export async function moveTab( + dashboardPage: DashboardPage, + page: Page, + selectors: E2ESelectorGroups, + sourceTab: string, + targetTab: string +) { + // Get target panel position + const targetTabElement = dashboardPage.getByGrafanaSelector(selectors.components.Tab.title(targetTab)).first(); + + // Get source panel element + const sourceTabElement = dashboardPage.getByGrafanaSelector(selectors.components.Tab.title(sourceTab)).first(); + + const targetBox = await targetTabElement.boundingBox(); + + // Perform drag and drop (dragTo() did not work in this case) + await sourceTabElement.hover(); + await page.mouse.down(); + // move to adjusted target position (relative to top left) + await page.mouse.move((targetBox?.x || 0) + (targetBox?.width || 0), targetBox?.y || 0, { steps: 5 }); + await page.mouse.up(); +} + +export async function groupIntoTab(page: Page, dashboardPage: DashboardPage, selectors: E2ESelectorGroups) { + await dashboardPage.getByGrafanaSelector(selectors.components.CanvasGridAddActions.groupPanels).click(); + await page.getByText('Group into tab').click(); +} + +export async function checkRepeatedTabTitles( + dashboardPage: DashboardPage, + selectors: E2ESelectorGroups, + title: string, + options: Array +) { + for (const option of options) { + await expect(dashboardPage.getByGrafanaSelector(selectors.components.Tab.title(`${title}${option}`))).toBeVisible(); + } +} + +export async function getTabPosition(dashboardPage: DashboardPage, selectors: E2ESelectorGroups, tabTitle: string) { + const tab = dashboardPage.getByGrafanaSelector(selectors.components.Tab.title(tabTitle)).first(); + const boundingBox = await tab.boundingBox(); + return boundingBox; } diff --git a/e2e-playwright/dashboards/V2DashWithTabRepeats.json b/e2e-playwright/dashboards/V2DashWithTabRepeats.json new file mode 100644 index 00000000000..99cabae8d94 --- /dev/null +++ b/e2e-playwright/dashboards/V2DashWithTabRepeats.json @@ -0,0 +1,837 @@ +{ + "apiVersion": "dashboard.grafana.app/v2beta1", + "kind": "Dashboard", + "metadata": { + "name": "addwm76", + "namespace": "default", + "uid": "TOro1wyxnlZJEWBZN3MF2MuXtdBb1GOnG6zynaCifi4X", + "resourceVersion": "3", + "generation": 4, + "creationTimestamp": "2025-09-18T08:03:45Z", + "labels": {}, + "annotations": {} + }, + "spec": { + "annotations": [], + "cursorSync": "Off", + "description": "", + "editable": true, + "elements": { + "panel-1": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "PD8C576611E62080A" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 1, + "links": [], + "title": "Tab $c1 - Row $c2 - Panel repeat $c3", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.3.0-pre" + } + } + }, + "panel-2": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "PD8C576611E62080A" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "scenarioId": "random_walk", + "seriesCount": 1 + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 2, + "links": [], + "title": "New panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.3.0-pre" + } + } + }, + "panel-3": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "PD8C576611E62080A" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 3, + "links": [], + "title": "New panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.3.0-pre" + } + } + }, + "panel-4": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "PD8C576611E62080A" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 4, + "links": [], + "title": "New panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.3.0-pre" + } + } + }, + "panel-5": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "PD8C576611E62080A" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 5, + "links": [], + "title": "New panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.3.0-pre" + } + } + } + }, + "layout": { + "kind": "TabsLayout", + "spec": { + "tabs": [ + { + "kind": "TabsLayoutTab", + "spec": { + "layout": { + "kind": "RowsLayout", + "spec": { + "rows": [ + { + "kind": "RowsLayoutRow", + "spec": { + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-5" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "New row" + } + }, + { + "kind": "RowsLayoutRow", + "spec": { + "collapse": false, + "layout": { + "kind": "GridLayout", + "spec": { + "items": [ + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-1" + }, + "height": 8, + "repeat": { + "direction": "h", + "mode": "variable", + "value": "c3" + }, + "width": 24, + "x": 0, + "y": 0 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-2" + }, + "height": 8, + "width": 12, + "x": 0, + "y": 8 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-3" + }, + "height": 8, + "width": 12, + "x": 12, + "y": 8 + } + } + ] + } + }, + "repeat": { + "mode": "variable", + "value": "c2" + }, + "title": "Row $c2" + } + } + ] + } + }, + "repeat": { + "mode": "variable", + "value": "c1" + }, + "title": "Tab - $c1" + } + }, + { + "kind": "TabsLayoutTab", + "spec": { + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-4" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "New tab" + } + } + ] + } + }, + "links": [], + "liveNow": false, + "preload": false, + "tags": [], + "timeSettings": { + "autoRefresh": "", + "autoRefreshIntervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"], + "fiscalYearStartMonth": 0, + "from": "now-6h", + "hideTimepicker": false, + "timezone": "browser", + "to": "now" + }, + "title": "tab repeats", + "variables": [ + { + "kind": "CustomVariable", + "spec": { + "allowCustomValue": true, + "current": { + "text": ["1", "2", "3", "4"], + "value": ["1", "2", "3", "4"] + }, + "hide": "dontHide", + "includeAll": true, + "multi": true, + "name": "c1", + "options": [ + { + "selected": true, + "text": "1", + "value": "1" + }, + { + "selected": true, + "text": "2", + "value": "2" + }, + { + "selected": true, + "text": "3", + "value": "3" + }, + { + "selected": true, + "text": "4", + "value": "4" + } + ], + "query": "1,2,3,4", + "skipUrlSync": false + } + }, + { + "kind": "CustomVariable", + "spec": { + "allowCustomValue": true, + "current": { + "text": ["1", "2", "3", "4"], + "value": ["1", "2", "3", "4"] + }, + "hide": "dontHide", + "includeAll": true, + "multi": true, + "name": "c2", + "options": [ + { + "selected": true, + "text": "1", + "value": "1" + }, + { + "selected": true, + "text": "2", + "value": "2" + }, + { + "selected": true, + "text": "3", + "value": "3" + }, + { + "selected": true, + "text": "4", + "value": "4" + } + ], + "query": "1,2,3,4", + "skipUrlSync": false + } + }, + { + "kind": "CustomVariable", + "spec": { + "allowCustomValue": true, + "current": { + "text": ["1", "2", "3", "4"], + "value": ["1", "2", "3", "4"] + }, + "hide": "dontHide", + "includeAll": false, + "multi": true, + "name": "c3", + "options": [ + { + "selected": true, + "text": "1", + "value": "1" + }, + { + "selected": true, + "text": "2", + "value": "2" + }, + { + "selected": true, + "text": "3", + "value": "3" + }, + { + "selected": true, + "text": "4", + "value": "4" + } + ], + "query": "1,2,3,4", + "skipUrlSync": false + } + } + ] + }, + "status": {} +} diff --git a/e2e/internal/cmd/cypress/cmd.go b/e2e/internal/cmd/cypress/cmd.go index ec4d836cd15..24b347c115c 100644 --- a/e2e/internal/cmd/cypress/cmd.go +++ b/e2e/internal/cmd/cypress/cmd.go @@ -109,10 +109,15 @@ func NewCmd() *cli.Command { }, &cli.BoolFlag{ Name: "image-renderer", - Usage: "Install the image renderer plugin (requires --start-grafana)", + Usage: "Start the image renderer Docker container (requires --start-grafana)", + Category: "Grafana Server", + }, + &cli.StringFlag{ + Name: "image-renderer-version", + Usage: "When enabling the image renderer, which version to use", + Value: "latest", Category: "Grafana Server", }, - &cli.StringFlag{ Name: "suite", Usage: "Path to the suite to run (e.g. './e2e/dashboards-suite')", @@ -194,7 +199,10 @@ func runAction(ctx context.Context, c *cli.Command) error { cmd.Env = os.Environ() cmd.Env = append(cmd.Env, fmt.Sprintf("TZ=%s", c.String("timezone"))) if c.Bool("image-renderer") { - cmd.Env = append(cmd.Env, "INSTALL_IMAGE_RENDERER=true") + cmd.Env = append(cmd.Env, "START_IMAGE_RENDERER=true") + } + if c.String("image-renderer-version") != "" { + cmd.Env = append(cmd.Env, fmt.Sprintf("IMAGE_RENDERER_VERSION=%s", c.String("image-renderer-version"))) } cmd.Stdout = prefixGrafana(os.Stdout) cmd.Stderr = prefixGrafana(os.Stderr) diff --git a/e2e/old-arch/dashboards-suite/templating-dashboard-links-and-variables.spec.ts b/e2e/old-arch/dashboards-suite/templating-dashboard-links-and-variables.spec.ts index 06e13002db4..a612d23b50d 100644 --- a/e2e/old-arch/dashboards-suite/templating-dashboard-links-and-variables.spec.ts +++ b/e2e/old-arch/dashboards-suite/templating-dashboard-links-and-variables.spec.ts @@ -8,11 +8,19 @@ describe('Templating', () => { it('Tests dashboard links and variables in links', () => { cy.intercept({ method: 'GET', - url: '/api/search?tag=templating&limit=100', + pathname: /search/, + query: { + tag: 'templating', + limit: '100', + }, }).as('tagsTemplatingSearch'); cy.intercept({ method: 'GET', - url: '/api/search?tag=demo&limit=100', + pathname: /search/, + query: { + tag: 'demo', + limit: '100', + }, }).as('tagsDemoSearch'); e2e.flows.openDashboard({ uid: 'yBCC3aKGk' }); diff --git a/eslint-suppressions.json b/eslint-suppressions.json index c69363ff210..0de835bc1d9 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -420,11 +420,6 @@ "count": 1 } }, - "packages/grafana-prometheus/src/querybuilder/QueryPattern.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "packages/grafana-prometheus/src/querybuilder/components/LabelFilterItem.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 4 @@ -470,6 +465,11 @@ "count": 1 } }, + "packages/grafana-runtime/src/components/DataSourcePicker.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "packages/grafana-runtime/src/config.ts": { "@typescript-eslint/consistent-type-assertions": { "count": 5 @@ -539,6 +539,11 @@ "count": 2 } }, + "packages/grafana-sql/src/components/ErrorBoundary.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "packages/grafana-sql/src/components/configuration/ConnectionLimits.tsx": { "no-restricted-syntax": { "count": 2 @@ -564,9 +569,32 @@ "count": 1 } }, + "packages/grafana-ui/src/components/BarGauge/BarGauge.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "packages/grafana-ui/src/components/Cascader/Cascader.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "packages/grafana-ui/src/components/Cascader/styles.ts": { + "@grafana/no-unreduced-motion": { + "count": 17 + } + }, "packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx": { "@typescript-eslint/no-explicit-any": { "count": 2 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "packages/grafana-ui/src/components/Combobox/Combobox.story.tsx": { @@ -613,6 +641,9 @@ }, "no-restricted-syntax": { "count": 3 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "packages/grafana-ui/src/components/DataSourceSettings/SecureSocksProxySettings.tsx": { @@ -635,6 +666,11 @@ "count": 3 } }, + "packages/grafana-ui/src/components/ErrorBoundary/ErrorBoundary.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "packages/grafana-ui/src/components/FileDropzone/FileDropzone.story.tsx": { "no-restricted-syntax": { "count": 1 @@ -650,11 +686,6 @@ "count": 3 } }, - "packages/grafana-ui/src/components/Forms/Checkbox.story.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "packages/grafana-ui/src/components/Forms/Form.story.tsx": { "react-hooks/rules-of-hooks": { "count": 9 @@ -674,6 +705,9 @@ }, "no-restricted-syntax": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "packages/grafana-ui/src/components/Forms/Legacy/Select/NoOptionsMessage.tsx": { @@ -687,6 +721,9 @@ }, "no-restricted-syntax": { "count": 6 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 3 } }, "packages/grafana-ui/src/components/Forms/Legacy/Select/SelectOption.tsx": { @@ -700,11 +737,22 @@ "packages/grafana-ui/src/components/Forms/Legacy/Select/SelectOptionGroup.tsx": { "@typescript-eslint/no-explicit-any": { "count": 3 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "packages/grafana-ui/src/components/Forms/Legacy/Switch/Switch.tsx": { "no-restricted-syntax": { "count": 3 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "packages/grafana-ui/src/components/Gauge/Gauge.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "packages/grafana-ui/src/components/Icon/Icon.story.tsx": { @@ -717,16 +765,16 @@ "count": 3 } }, + "packages/grafana-ui/src/components/JSONFormatter/JSONFormatter.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "packages/grafana-ui/src/components/JSONFormatter/json_explorer/json_explorer.ts": { "@typescript-eslint/no-explicit-any": { "count": 2 } }, - "packages/grafana-ui/src/components/Layout/Stack/Stack.story.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "packages/grafana-ui/src/components/MatchersUI/FieldValueMatcher.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 1 @@ -742,14 +790,17 @@ "count": 1 } }, - "packages/grafana-ui/src/components/Modal/Modal.story.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "packages/grafana-ui/src/components/Modal/ModalsContext.tsx": { "@typescript-eslint/no-explicit-any": { "count": 4 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "packages/grafana-ui/src/components/Monaco/CodeEditor.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "packages/grafana-ui/src/components/PageLayout/PageToolbar.story.tsx": { @@ -777,6 +828,16 @@ "count": 1 } }, + "packages/grafana-ui/src/components/QueryField/QueryField.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "packages/grafana-ui/src/components/SecretFormField/SecretFormField.tsx": { "no-restricted-syntax": { "count": 2 @@ -815,6 +876,11 @@ "count": 4 } }, + "packages/grafana-ui/src/components/Select/ValueContainer.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "packages/grafana-ui/src/components/Select/resetSelectStyles.ts": { "@typescript-eslint/no-explicit-any": { "count": 4 @@ -825,6 +891,11 @@ "count": 6 } }, + "packages/grafana-ui/src/components/SetInterval/SetInterval.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.ts": { "@typescript-eslint/consistent-type-assertions": { "count": 3 @@ -833,6 +904,21 @@ "count": 13 } }, + "packages/grafana-ui/src/components/Sparkline/Sparkline.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "packages/grafana-ui/src/components/StatsPicker/StatsPicker.story.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "packages/grafana-ui/src/components/StatsPicker/StatsPicker.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "packages/grafana-ui/src/components/Table/Cells/TableCell.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 3 @@ -913,11 +999,31 @@ "count": 1 } }, + "packages/grafana-ui/src/components/TableInputCSV/TableInputCSV.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "packages/grafana-ui/src/components/Tags/Tag.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 1 } }, + "packages/grafana-ui/src/components/Tooltip/PopoverController.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "packages/grafana-ui/src/components/Typeahead/Typeahead.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 2 + } + }, + "packages/grafana-ui/src/components/UnitPicker/UnitPicker.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "packages/grafana-ui/src/components/ValuePicker/ValuePicker.tsx": { "@grafana/no-aria-label-selectors": { "count": 1 @@ -936,6 +1042,9 @@ "packages/grafana-ui/src/components/VizRepeater/VizRepeater.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 2 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "packages/grafana-ui/src/components/VizTooltip/VizTooltip.tsx": { @@ -951,6 +1060,9 @@ "packages/grafana-ui/src/components/uPlot/Plot.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 2 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts": { @@ -1062,6 +1174,11 @@ "count": 1 } }, + "public/app/AppWrapper.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/core/TableModel.ts": { "@typescript-eslint/no-explicit-any": { "count": 2 @@ -1082,16 +1199,6 @@ "count": 1 } }, - "public/app/core/components/AppChrome/History/HistoryWrapper.tsx": { - "no-restricted-syntax": { - "count": 2 - } - }, - "public/app/core/components/AppNotifications/StoredNotificationItem.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "public/app/core/components/DynamicImports/SafeDynamicImport.tsx": { "@typescript-eslint/no-explicit-any": { "count": 1 @@ -1113,6 +1220,14 @@ }, "@typescript-eslint/no-explicit-any": { "count": 2 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/core/components/Login/LoginCtrl.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/core/components/Login/LoginForm.tsx": { @@ -1130,14 +1245,12 @@ "count": 1 } }, - "public/app/core/components/NavLandingPage/NavLandingPageCard.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "public/app/core/components/OptionsUI/NumberInput.tsx": { "no-restricted-syntax": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/core/components/OptionsUI/fieldColor.tsx": { @@ -1145,6 +1258,21 @@ "count": 1 } }, + "public/app/core/components/OptionsUI/multiSelect.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/core/components/OptionsUI/select.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/core/components/OptionsUI/strings.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/core/components/Page/EditableTitle.tsx": { "no-restricted-syntax": { "count": 1 @@ -1165,10 +1293,28 @@ "count": 1 } }, + "public/app/core/components/Select/ServiceAccountPicker.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/core/components/Select/TeamPicker.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/core/components/Select/UserPicker.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/core/components/SharedPreferences/SharedPreferences.tsx": { "no-restricted-syntax": { "count": 8 }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + }, "react/no-unescaped-entities": { "count": 1 } @@ -1183,6 +1329,11 @@ "count": 1 } }, + "public/app/core/components/SplitPaneWrapper/SplitPaneWrapper.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/core/components/TagFilter/TagFilter.tsx": { "@typescript-eslint/no-explicit-any": { "count": 1 @@ -1193,6 +1344,11 @@ "count": 1 } }, + "public/app/core/components/TimeSeries/TimeSeries.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/core/components/TimeSeries/utils.ts": { "@typescript-eslint/consistent-type-assertions": { "count": 1 @@ -1201,6 +1357,11 @@ "count": 2 } }, + "public/app/core/components/TimelineChart/TimelineChart.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/core/config.ts": { "no-barrel-files/no-barrel-files": { "count": 2 @@ -1334,11 +1495,6 @@ "count": 1 } }, - "public/app/features/admin/ServerStatsCard.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "public/app/features/admin/UserCreatePage.tsx": { "no-restricted-syntax": { "count": 4 @@ -1347,11 +1503,27 @@ "public/app/features/admin/UserLdapSyncInfo.tsx": { "no-restricted-syntax": { "count": 3 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/admin/UserOrgs.tsx": { "no-restricted-syntax": { "count": 2 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 3 + } + }, + "public/app/features/admin/UserProfile.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/admin/UserSessions.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/admin/ldap/LdapDrawer.tsx": { @@ -1402,16 +1574,6 @@ "count": 2 } }, - "public/app/features/alerting/unified/AlertsFolderView.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, - "public/app/features/alerting/unified/RedirectToRuleViewer.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "public/app/features/alerting/unified/components/AlertLabelDropdown.tsx": { "no-restricted-syntax": { "count": 1 @@ -1523,11 +1685,6 @@ "count": 1 } }, - "public/app/features/alerting/unified/components/receivers/form/GenerateAlertDataModal.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "public/app/features/alerting/unified/components/receivers/form/GrafanaCommonChannelSettings.tsx": { "no-restricted-syntax": { "count": 1 @@ -1614,7 +1771,7 @@ "@typescript-eslint/consistent-type-assertions": { "count": 1 }, - "no-restricted-syntax": { + "react-prefer-function-component/react-prefer-function-component": { "count": 1 } }, @@ -1658,11 +1815,6 @@ "count": 1 } }, - "public/app/features/alerting/unified/components/rule-editor/rule-types/RuleType.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "public/app/features/alerting/unified/components/rules/Filter/RulesFilter.v1.tsx": { "no-restricted-syntax": { "count": 4 @@ -1688,11 +1840,6 @@ "count": 1 } }, - "public/app/features/alerting/unified/components/settings/AlertmanagerCard.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "public/app/features/alerting/unified/components/silences/MatchersField.tsx": { "no-restricted-syntax": { "count": 5 @@ -1759,11 +1906,6 @@ "count": 6 } }, - "public/app/features/alerting/unified/rule-list/FilterViewStatus.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "public/app/features/alerting/unified/types/alerting.ts": { "@typescript-eslint/no-explicit-any": { "count": 5 @@ -1813,6 +1955,16 @@ "count": 1 } }, + "public/app/features/annotations/components/AnnotationResultMapper.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/annotations/components/StandardAnnotationQueryEditor.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/annotations/events_processing.ts": { "@typescript-eslint/no-explicit-any": { "count": 1 @@ -1856,6 +2008,26 @@ "count": 1 } }, + "public/app/features/canvas/runtime/element.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/canvas/runtime/frame.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/canvas/runtime/root.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/canvas/runtime/scene.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/commandPalette/actions/scopeActions.tsx": { "react-hooks/rules-of-hooks": { "count": 4 @@ -1871,11 +2043,6 @@ "count": 1 } }, - "public/app/features/connections/tabs/ConnectData/CardGrid/CardGrid.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "public/app/features/connections/tabs/ConnectData/CardGrid/index.tsx": { "no-barrel-files/no-barrel-files": { "count": 1 @@ -1922,11 +2089,6 @@ "count": 2 } }, - "public/app/features/correlations/Forms/ConfigureCorrelationSourceForm.tsx": { - "no-restricted-syntax": { - "count": 3 - } - }, "public/app/features/correlations/Forms/ConfigureCorrelationTargetForm.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 2 @@ -1945,11 +2107,6 @@ "count": 4 } }, - "public/app/features/correlations/components/EmptyCorrelationsCTA.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "public/app/features/correlations/types.ts": { "@typescript-eslint/no-explicit-any": { "count": 2 @@ -1960,6 +2117,21 @@ "count": 2 } }, + "public/app/features/dashboard-scene/conditional-rendering/conditions/ConditionalRenderingData.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/dashboard-scene/conditional-rendering/conditions/ConditionalRenderingTimeRangeSize.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/dashboard-scene/conditional-rendering/conditions/ConditionalRenderingVariable.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/dashboard-scene/edit-pane/DashboardEditPaneRenderer.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 1 @@ -2146,11 +2318,6 @@ "count": 4 } }, - "public/app/features/dashboard-scene/settings/variables/VariableSetEditableElement.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "public/app/features/dashboard-scene/settings/variables/components/AdHocVariableForm.tsx": { "no-restricted-syntax": { "count": 1 @@ -2189,19 +2356,6 @@ "count": 1 } }, - "public/app/features/dashboard-scene/settings/variables/editors/QueryVariableEditor.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, - "public/app/features/dashboard-scene/settings/variables/utils.ts": { - "@typescript-eslint/consistent-type-assertions": { - "count": 1 - }, - "@typescript-eslint/no-explicit-any": { - "count": 1 - } - }, "public/app/features/dashboard-scene/sharing/ShareButton/share-externally/EmailShare/ConfigEmailSharing/ConfigEmailSharing.tsx": { "no-restricted-syntax": { "count": 1 @@ -2299,6 +2453,11 @@ "count": 1 } }, + "public/app/features/dashboard/components/DashNav/DashNavTimeControls.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/dashboard/components/DashNav/index.ts": { "no-barrel-files/no-barrel-files": { "count": 1 @@ -2322,6 +2481,11 @@ "count": 1 } }, + "public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/dashboard/components/DashboardRow/index.ts": { "no-barrel-files/no-barrel-files": { "count": 1 @@ -2340,6 +2504,14 @@ "public/app/features/dashboard/components/DashboardSettings/TimePickerSettings.tsx": { "no-restricted-syntax": { "count": 5 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/dashboard/components/DashboardSettings/VersionsSettings.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/dashboard/components/DashboardSettings/index.ts": { @@ -2362,6 +2534,11 @@ "count": 1 } }, + "public/app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor.tsx": { "@grafana/no-aria-label-selectors": { "count": 1 @@ -2371,11 +2548,32 @@ }, "no-restricted-syntax": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/dashboard/components/PanelEditor/OptionsPaneOptions.test.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/dashboard/components/PanelEditor/PanelEditorQueries.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/dashboard/components/PanelEditor/PanelHeaderCorner.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/dashboard/components/PanelEditor/VisualizationSelectPane.tsx": { @@ -2435,11 +2633,22 @@ }, "no-restricted-syntax": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/dashboard/components/ShareModal/ShareLink.tsx": { "no-restricted-syntax": { "count": 3 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/dashboard/components/ShareModal/ShareModal.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/dashboard/components/ShareModal/SharePublicDashboard/ConfigPublicDashboard/ConfigPublicDashboard.tsx": { @@ -2455,6 +2664,9 @@ "public/app/features/dashboard/components/ShareModal/ShareSnapshot.tsx": { "no-restricted-syntax": { "count": 4 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/dashboard/components/ShareModal/ThemePicker.tsx": { @@ -2475,6 +2687,11 @@ "count": 1 } }, + "public/app/features/dashboard/components/SubMenu/SubMenu.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/dashboard/components/SubMenu/SubMenuItems.tsx": { "no-restricted-syntax": { "count": 1 @@ -2485,14 +2702,12 @@ "count": 1 } }, - "public/app/features/dashboard/components/TransformationsEditor/TransformationPicker.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "public/app/features/dashboard/components/TransformationsEditor/TransformationsEditor.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 2 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/dashboard/components/VersionHistory/useDashboardRestore.tsx": { @@ -2512,6 +2727,9 @@ }, "@typescript-eslint/no-explicit-any": { "count": 2 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/dashboard/containers/DashboardPageProxy.tsx": { @@ -2524,6 +2742,21 @@ "count": 1 } }, + "public/app/features/dashboard/dashgrid/DashboardGrid.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/dashboard/dashgrid/DashboardPanel.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/dashboard/dashgrid/PanelStateWrapper.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/dashboard/dashgrid/SeriesVisibilityConfigFactory.ts": { "@typescript-eslint/consistent-type-assertions": { "count": 1 @@ -2541,10 +2774,10 @@ }, "public/app/features/dashboard/state/DashboardMigrator.ts": { "@typescript-eslint/consistent-type-assertions": { - "count": 4 + "count": 2 }, "@typescript-eslint/no-explicit-any": { - "count": 24 + "count": 16 } }, "public/app/features/dashboard/state/DashboardModel.repeat.test.ts": { @@ -2619,11 +2852,6 @@ "count": 2 } }, - "public/app/features/datasources/components/BasicSettings.tsx": { - "no-restricted-syntax": { - "count": 3 - } - }, "public/app/features/datasources/components/ButtonRow.tsx": { "no-restricted-syntax": { "count": 1 @@ -2634,6 +2862,11 @@ "count": 1 } }, + "public/app/features/datasources/components/DataSourcePluginSettings.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/datasources/components/DataSourcePluginState.tsx": { "no-restricted-syntax": { "count": 3 @@ -2647,19 +2880,6 @@ "public/app/features/datasources/components/DataSourceTypeCard.tsx": { "@grafana/no-aria-label-selectors": { "count": 1 - }, - "no-restricted-syntax": { - "count": 1 - } - }, - "public/app/features/datasources/components/DataSourcesListCard.tsx": { - "no-restricted-syntax": { - "count": 2 - } - }, - "public/app/features/datasources/components/picker/DataSourceCard.tsx": { - "no-restricted-syntax": { - "count": 1 } }, "public/app/features/datasources/state/actions.test.ts": { @@ -2722,6 +2942,9 @@ "public/app/features/dimensions/editors/ThresholdsEditor/ThresholdsEditor.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/dimensions/editors/URLPickerTab.tsx": { @@ -2746,7 +2969,7 @@ }, "public/app/features/explore/CorrelationHelper.tsx": { "no-restricted-syntax": { - "count": 3 + "count": 2 } }, "public/app/features/explore/CorrelationTransformationAddModal.tsx": { @@ -2754,21 +2977,61 @@ "count": 4 } }, + "public/app/features/explore/Explore.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/explore/ExploreTimeControls.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/explore/Logs/LiveLogs.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/explore/Logs/LogsColumnSearch.tsx": { "no-restricted-syntax": { "count": 1 } }, + "public/app/features/explore/Logs/LogsContainer.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/explore/RawPrometheus/RawPrometheusContainer.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/explore/RichHistory/RichHistorySettingsTab.tsx": { "no-restricted-syntax": { "count": 1 } }, + "public/app/features/explore/Table/TableContainer.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/explore/TraceView/TraceView.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 2 } }, + "public/app/features/explore/TraceView/components/TracePageHeader/SpanGraph/CanvasSpanGraph.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/explore/TraceView/components/TracePageHeader/SpanGraph/ViewingLayer.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/explore/TraceView/components/TracePageHeader/TracePageHeader.tsx": { "react-hooks/rules-of-hooks": { "count": 1 @@ -2779,26 +3042,71 @@ "count": 1 } }, + "public/app/features/explore/TraceView/components/TraceTimelineViewer/ListView/index.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanBarRow.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/SpanDetailLinkButtons.tsx": { "react-hooks/rules-of-hooks": { "count": 1 } }, + "public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetailRow.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanLinks.tsx": { "no-restricted-syntax": { "count": 1 } }, + "public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanTreeOffset.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/explore/TraceView/components/TraceTimelineViewer/TimelineHeaderRow/TimelineColumnResizer.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/explore/TraceView/components/TraceTimelineViewer/TimelineHeaderRow/TimelineViewingLayer.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/explore/TraceView/components/TraceTimelineViewer/TimelineHeaderRow/index.tsx": { "no-barrel-files/no-barrel-files": { "count": 1 } }, + "public/app/features/explore/TraceView/components/TraceTimelineViewer/VirtualizedTraceView.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/explore/TraceView/components/TraceTimelineViewer/index.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/explore/TraceView/components/TraceTimelineViewer/utils.tsx": { "no-barrel-files/no-barrel-files": { "count": 1 } }, + "public/app/features/explore/TraceView/components/common/SearchBarInput.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/explore/TraceView/components/demo/trace-generators.ts": { "@typescript-eslint/consistent-type-assertions": { "count": 1 @@ -2822,6 +3130,21 @@ "count": 1 } }, + "public/app/features/explore/TraceView/components/utils/DraggableManager/demo/DividerDemo.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/explore/TraceView/components/utils/DraggableManager/demo/DraggableManagerDemo.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/explore/TraceView/components/utils/DraggableManager/demo/RegionDemo.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/explore/TraceView/components/utils/DraggableManager/demo/index.tsx": { "no-barrel-files/no-barrel-files": { "count": 1 @@ -2865,11 +3188,6 @@ "count": 2 } }, - "public/app/features/expressions/ExpressionQueryEditor.tsx": { - "react/no-unescaped-entities": { - "count": 4 - } - }, "public/app/features/expressions/guards.ts": { "@typescript-eslint/consistent-type-assertions": { "count": 1 @@ -2899,6 +3217,9 @@ "public/app/features/inspector/InspectDataTab.tsx": { "@grafana/no-aria-label-selectors": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/inspector/InspectJSONTab.tsx": { @@ -2917,6 +3238,9 @@ }, "@typescript-eslint/no-explicit-any": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/invites/SignupInvited.tsx": { @@ -2929,6 +3253,11 @@ "count": 2 } }, + "public/app/features/live/LiveConnectionWarning.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/live/centrifuge/LiveDataStream.ts": { "@typescript-eslint/consistent-type-assertions": { "count": 1 @@ -2939,6 +3268,21 @@ "count": 1 } }, + "public/app/features/logs/components/LogDetails.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/logs/components/LogDetailsRow.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/logs/components/LogMessageAnsi.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/logs/logsFrame.ts": { "@typescript-eslint/consistent-type-assertions": { "count": 1 @@ -2955,6 +3299,9 @@ "public/app/features/manage-dashboards/DashboardImportPage.tsx": { "no-restricted-syntax": { "count": 2 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/manage-dashboards/components/ImportDashboardForm.tsx": { @@ -2970,8 +3317,8 @@ "count": 1 } }, - "public/app/features/manage-dashboards/components/PublicDashboardListTable/PublicDashboardListTable.tsx": { - "no-restricted-syntax": { + "public/app/features/manage-dashboards/components/ImportDashboardOverview.tsx": { + "react-prefer-function-component/react-prefer-function-component": { "count": 1 } }, @@ -3026,6 +3373,11 @@ "count": 1 } }, + "public/app/features/org/OrgDetailsPage.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/org/OrgProfile.tsx": { "no-restricted-syntax": { "count": 1 @@ -3051,11 +3403,6 @@ "count": 1 } }, - "public/app/features/playlist/PlaylistCard.tsx": { - "no-restricted-syntax": { - "count": 2 - } - }, "public/app/features/playlist/PlaylistForm.tsx": { "@grafana/no-aria-label-selectors": { "count": 2 @@ -3089,6 +3436,11 @@ "count": 1 } }, + "public/app/features/plugins/admin/components/PluginDashboards.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/plugins/admin/components/PluginDetailsPage.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 1 @@ -3117,6 +3469,11 @@ "count": 1 } }, + "public/app/features/plugins/components/AppRootPage.test.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/plugins/datasource_srv.test.ts": { "@typescript-eslint/no-explicit-any": { "count": 3 @@ -3170,11 +3527,6 @@ "count": 2 } }, - "public/app/features/provisioning/File/FileHistoryPage.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "public/app/features/provisioning/File/FileStatusPage.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 2 @@ -3202,6 +3554,9 @@ }, "react-hooks/rules-of-hooks": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/query/components/QueryEditorRowHeader.tsx": { @@ -3209,9 +3564,17 @@ "count": 1 } }, + "public/app/features/query/components/QueryEditorRows.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/query/components/QueryGroup.tsx": { "@grafana/no-aria-label-selectors": { "count": 2 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/query/state/DashboardQueryRunner/AnnotationsQueryRunner.ts": { @@ -3300,6 +3663,11 @@ "count": 2 } }, + "public/app/features/teams/TeamGroupSync.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/teams/TeamSettings.tsx": { "no-restricted-syntax": { "count": 4 @@ -3373,11 +3741,21 @@ "count": 1 } }, + "public/app/features/transformers/editors/ConcatenateTransformerEditor.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/transformers/editors/ConvertFieldTypeTransformerEditor.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 1 } }, + "public/app/features/transformers/editors/FilterByNameTransformerEditor.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/transformers/editors/GroupToNestedTableTransformerEditor.tsx": { "no-restricted-syntax": { "count": 1 @@ -3388,6 +3766,11 @@ "count": 1 } }, + "public/app/features/transformers/editors/RenameByRegexTransformer.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/transformers/editors/SortByTransformerEditor.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 1 @@ -3442,9 +3825,17 @@ "count": 3 } }, + "public/app/features/variables/adhoc/AdHocVariableEditor.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/variables/adhoc/picker/AdHocFilter.tsx": { "no-restricted-syntax": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/variables/adhoc/picker/AdHocFilterKey.tsx": { @@ -3462,24 +3853,52 @@ "count": 1 } }, + "public/app/features/variables/adhoc/picker/AdHocPicker.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/variables/adhoc/picker/ConditionSegment.tsx": { "no-restricted-syntax": { "count": 2 } }, + "public/app/features/variables/constant/ConstantVariableEditor.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/variables/constant/reducer.ts": { "@typescript-eslint/consistent-type-assertions": { "count": 1 } }, + "public/app/features/variables/custom/CustomVariableEditor.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/variables/custom/reducer.ts": { "@typescript-eslint/consistent-type-assertions": { "count": 1 } }, + "public/app/features/variables/datasource/DataSourceVariableEditor.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/variables/editor/VariableEditorContainer.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 2 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/features/variables/editor/VariableEditorEditor.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/variables/editor/VariableEditorList.tsx": { @@ -3510,6 +3929,11 @@ "count": 4 } }, + "public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/features/variables/pickers/OptionsPicker/actions.ts": { "@typescript-eslint/no-explicit-any": { "count": 2 @@ -3531,16 +3955,25 @@ "public/app/features/variables/pickers/shared/VariableInput.tsx": { "no-restricted-syntax": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/variables/pickers/shared/VariableOptions.tsx": { "@grafana/no-aria-label-selectors": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/variables/query/QueryVariableEditor.tsx": { "@typescript-eslint/no-explicit-any": { "count": 2 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/features/variables/query/QueryVariableRefreshSelect.tsx": { @@ -3671,6 +4104,11 @@ "count": 1 } }, + "public/app/plugins/datasource/azuremonitor/components/ConfigEditor/ConfigEditor.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/plugins/datasource/azuremonitor/components/ConfigEditor/CurrentUserFallbackCredentials.tsx": { "no-restricted-syntax": { "count": 2 @@ -3683,7 +4121,7 @@ }, "public/app/plugins/datasource/azuremonitor/components/LogsQueryEditor/AzureCheatSheet.tsx": { "no-restricted-syntax": { - "count": 2 + "count": 1 } }, "public/app/plugins/datasource/azuremonitor/components/LogsQueryEditor/index.tsx": { @@ -3764,6 +4202,11 @@ "count": 1 } }, + "public/app/plugins/datasource/cloud-monitoring/components/ConfigEditor/ConfigEditor.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/plugins/datasource/cloud-monitoring/components/Fields.tsx": { "no-restricted-syntax": { "count": 1 @@ -3772,6 +4215,9 @@ "public/app/plugins/datasource/cloud-monitoring/components/VariableQueryEditor.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/plugins/datasource/cloud-monitoring/datasource.ts": { @@ -3969,6 +4415,11 @@ "count": 1 } }, + "public/app/plugins/datasource/grafana-testdata-datasource/components/CSVWaveEditor.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/plugins/datasource/grafana-testdata-datasource/components/RandomWalkEditor.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 2 @@ -4003,6 +4454,9 @@ "public/app/plugins/datasource/grafana/components/QueryEditor.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 2 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/plugins/datasource/grafana/components/TimeRegionEditor.tsx": { @@ -4018,9 +4472,17 @@ "count": 1 } }, + "public/app/plugins/datasource/graphite/components/MetricTankMetaInspector.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/plugins/datasource/graphite/configuration/ConfigEditor.tsx": { "no-restricted-syntax": { "count": 3 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/plugins/datasource/graphite/datasource.ts": { @@ -4098,6 +4560,9 @@ }, "no-restricted-syntax": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/plugins/datasource/influxdb/components/editor/config/InfluxSQLConfig.tsx": { @@ -4113,6 +4578,14 @@ "public/app/plugins/datasource/influxdb/components/editor/query/flux/FluxQueryEditor.tsx": { "no-restricted-syntax": { "count": 3 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/plugins/datasource/influxdb/components/editor/query/fsql/FSQLEditor.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/plugins/datasource/influxdb/components/editor/query/influxql/visual/PartListSection.tsx": { @@ -4163,11 +4636,21 @@ "count": 2 } }, + "public/app/plugins/datasource/loki/components/LokiCheatSheet.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/plugins/datasource/loki/components/LokiContextUi.tsx": { "no-restricted-syntax": { "count": 7 } }, + "public/app/plugins/datasource/loki/components/LokiLabelBrowser.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx": { "no-restricted-syntax": { "count": 2 @@ -4176,6 +4659,9 @@ "public/app/plugins/datasource/loki/components/LokiQueryField.tsx": { "no-restricted-syntax": { "count": 2 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/plugins/datasource/loki/configuration/DerivedField.tsx": { @@ -4198,11 +4684,6 @@ "count": 1 } }, - "public/app/plugins/datasource/loki/querybuilder/components/QueryPattern.tsx": { - "no-restricted-syntax": { - "count": 1 - } - }, "public/app/plugins/datasource/loki/querybuilder/state.ts": { "no-restricted-syntax": { "count": 2 @@ -4283,6 +4764,11 @@ "count": 15 } }, + "public/app/plugins/datasource/tempo/QueryField.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/plugins/datasource/tempo/ServiceGraphSection.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 1 @@ -4291,6 +4777,9 @@ "public/app/plugins/datasource/tempo/_importedDependencies/components/AdHocFilter/AdHocFilter.tsx": { "no-restricted-syntax": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/plugins/datasource/tempo/_importedDependencies/components/AdHocFilter/AdHocFilterKey.tsx": { @@ -4363,8 +4852,8 @@ "count": 1 } }, - "public/app/plugins/panel/annolist/AnnotationListItem.tsx": { - "no-restricted-syntax": { + "public/app/plugins/panel/annolist/AnnoListPanel.tsx": { + "react-prefer-function-component/react-prefer-function-component": { "count": 1 } }, @@ -4378,6 +4867,11 @@ "count": 1 } }, + "public/app/plugins/panel/bargauge/BarGaugePanel.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/plugins/panel/candlestick/CandlestickPanel.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 1 @@ -4391,6 +4885,21 @@ "count": 8 } }, + "public/app/plugins/panel/canvas/CanvasPanel.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/plugins/panel/canvas/components/connections/Connections.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/plugins/panel/canvas/components/connections/Connections2.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/plugins/panel/canvas/editor/LineStyleEditor.tsx": { "no-restricted-syntax": { "count": 1 @@ -4417,11 +4926,22 @@ }, "@typescript-eslint/no-explicit-any": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/plugins/panel/debug/EventBusLogger.tsx": { "@typescript-eslint/no-explicit-any": { "count": 2 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/plugins/panel/debug/RenderInfoViewer.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/plugins/panel/debug/StateView.tsx": { @@ -4434,9 +4954,22 @@ "count": 1 } }, + "public/app/plugins/panel/gauge/GaugePanel.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, + "public/app/plugins/panel/geomap/GeomapPanel.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/plugins/panel/geomap/components/DebugOverlay.tsx": { "@grafana/no-aria-label-selectors": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/plugins/panel/geomap/components/MarkersLegend.tsx": { @@ -4447,6 +4980,11 @@ "count": 1 } }, + "public/app/plugins/panel/geomap/components/ObservablePropsWrapper.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/plugins/panel/geomap/editor/GeomapStyleRulesEditor.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 1 @@ -4495,6 +5033,11 @@ "count": 2 } }, + "public/app/plugins/panel/gettingstarted/GettingStarted.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/plugins/panel/heatmap/HeatmapPanel.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 1 @@ -4529,6 +5072,11 @@ "count": 17 } }, + "public/app/plugins/panel/histogram/Histogram.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/plugins/panel/live/LiveChannelEditor.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 2 @@ -4540,6 +5088,9 @@ "public/app/plugins/panel/live/LivePanel.tsx": { "@typescript-eslint/consistent-type-assertions": { "count": 1 + }, + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 } }, "public/app/plugins/panel/nodeGraph/Edge.tsx": { @@ -4582,6 +5133,11 @@ "count": 1 } }, + "public/app/plugins/panel/stat/StatPanel.tsx": { + "react-prefer-function-component/react-prefer-function-component": { + "count": 1 + } + }, "public/app/plugins/panel/state-timeline/migrations.ts": { "@typescript-eslint/no-explicit-any": { "count": 2 diff --git a/eslint.config.js b/eslint.config.js index a0245a55b48..f01463559aa 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -8,6 +8,7 @@ const jsxA11yPlugin = require('eslint-plugin-jsx-a11y'); const lodashPlugin = require('eslint-plugin-lodash'); const barrelPlugin = require('eslint-plugin-no-barrel-files'); const reactPlugin = require('eslint-plugin-react'); +const reactPreferFunctionComponentPlugin = require('eslint-plugin-react-prefer-function-component'); const testingLibraryPlugin = require('eslint-plugin-testing-library'); const unicornPlugin = require('eslint-plugin-unicorn'); @@ -100,6 +101,7 @@ module.exports = [ '**/build/', '**/compiled/', '**/dist/', + 'coverage/', 'data/', 'deployment_tools_config.json', 'devenv', @@ -139,6 +141,7 @@ module.exports = [ 'no-barrel-files': barrelPlugin, '@grafana': grafanaPlugin, unicorn: unicornPlugin, + 'react-prefer-function-component': reactPreferFunctionComponentPlugin, }, settings: { @@ -155,6 +158,7 @@ module.exports = [ '@grafana/no-border-radius-literal': 'error', '@grafana/no-unreduced-motion': 'error', '@grafana/no-restricted-img-srcs': 'error', + 'react-prefer-function-component/react-prefer-function-component': ['error', { allowJsxUtilityClass: true }], 'react/prop-types': 'off', // need to ignore emotion's `css` prop, see https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-unknown-property.md#rule-options 'react/no-unknown-property': ['error', { ignore: ['css'] }], @@ -271,10 +275,11 @@ module.exports = [ { // No NPM package should import from @grafana/*/internal because it does not exist // outside of this repo - they're not published to NPM. - name: 'grafana/packages-overrides', + name: 'grafana/packages', files: ['packages/**/*.{ts,tsx}'], ignores: [], rules: { + 'import/no-extraneous-dependencies': ['error', { includeInternal: true }], 'no-restricted-imports': [ 'error', withBaseRestrictedImportsConfig({ diff --git a/go.mod b/go.mod index 5010002e3a8..705bbafcd56 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/grafana/grafana -go 1.24.6 +go 1.25.3 require ( buf.build/gen/go/parca-dev/parca/connectrpc/go v1.18.1-20250703125925-3f0fcf4bff96.1 // @grafana/observability-traces-and-profiling @@ -13,8 +13,8 @@ require ( filippo.io/age v1.2.1 // @grafana/identity-access-team github.com/1NCE-GmbH/grpc-go-pool v0.0.0-20231117122434-2a5bb974daa2 // @grafana/grafana-search-and-storage github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // @grafana/partner-datasources - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1 // @grafana/identity-access-team - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 // @grafana/grafana-backend-group + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 // @grafana/identity-access-team + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.12.0 // @grafana/grafana-backend-group github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // @grafana/grafana-backend-group github.com/Azure/azure-storage-blob-go v0.15.0 // @grafana/grafana-backend-group github.com/Azure/go-autorest/autorest v0.11.29 // @grafana/grafana-backend-group @@ -38,7 +38,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/ec2 v1.225.2 // @grafana/aws-datasources github.com/aws/aws-sdk-go-v2/service/oam v1.18.3 // @grafana/aws-datasources github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.26.6 // @grafana/aws-datasources - github.com/aws/smithy-go v1.22.5 // @grafana/aws-datasources + github.com/aws/smithy-go v1.23.1 // @grafana/aws-datasources github.com/beevik/etree v1.4.1 // @grafana/grafana-backend-group github.com/benbjohnson/clock v1.3.5 // @grafana/alerting-backend github.com/blang/semver/v4 v4.0.0 // indirect; @grafana/grafana-developer-enablement-squad @@ -67,7 +67,7 @@ require ( github.com/go-openapi/loads v0.22.0 // @grafana/alerting-backend github.com/go-openapi/runtime v0.28.0 // @grafana/alerting-backend github.com/go-openapi/strfmt v0.23.0 // @grafana/alerting-backend - github.com/go-redis/redis/v8 v8.11.5 // @grafana/grafana-backend-group + github.com/go-redis/redis/v8 v8.11.5 // indirect; @grafana/grafana-backend-group github.com/go-sourcemap/sourcemap v2.1.4+incompatible // @grafana/grafana-backend-group github.com/go-sql-driver/mysql v1.9.3 // @grafana/grafana-search-and-storage github.com/go-stack/stack v1.8.1 // @grafana/grafana-backend-group @@ -86,7 +86,7 @@ require ( github.com/googleapis/gax-go/v2 v2.14.2 // @grafana/grafana-backend-group github.com/gorilla/mux v1.8.1 // @grafana/grafana-backend-group github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // @grafana/grafana-app-platform-squad - github.com/grafana/alerting v0.0.0-20251007160934-e642236ea9eb // @grafana/alerting-backend + github.com/grafana/alerting v0.0.0-20251009192429-9427c24835ae // @grafana/alerting-backend github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f // @grafana/identity-access-team github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 // @grafana/identity-access-team github.com/grafana/dataplane/examples v0.0.1 // @grafana/observability-metrics @@ -96,10 +96,10 @@ require ( github.com/grafana/gofpdf v0.0.0-20250307124105-3b9c5d35577f // @grafana/sharing-squad github.com/grafana/gomemcache v0.0.0-20250318131618-74242eea118d // @grafana/grafana-operator-experience-squad github.com/grafana/grafana-api-golang-client v0.27.0 // @grafana/alerting-backend - github.com/grafana/grafana-app-sdk v0.46.0 // @grafana/grafana-app-platform-squad - github.com/grafana/grafana-app-sdk/logging v0.45.0 // @grafana/grafana-app-platform-squad + github.com/grafana/grafana-app-sdk v0.47.0 // @grafana/grafana-app-platform-squad + github.com/grafana/grafana-app-sdk/logging v0.46.0 // @grafana/grafana-app-platform-squad github.com/grafana/grafana-aws-sdk v1.2.0 // @grafana/aws-datasources - github.com/grafana/grafana-azure-sdk-go/v2 v2.2.0 // @grafana/partner-datasources + github.com/grafana/grafana-azure-sdk-go/v2 v2.3.1 // @grafana/partner-datasources github.com/grafana/grafana-cloud-migration-snapshot v1.9.0 // @grafana/grafana-operator-experience-squad github.com/grafana/grafana-google-sdk-go v0.4.2 // @grafana/partner-datasources github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79 // @grafana/grafana-backend-group @@ -107,7 +107,7 @@ require ( github.com/grafana/loki/v3 v3.2.1 // @grafana/observability-logs github.com/grafana/nanogit v0.0.0-20250723104447-68f58f5ecec0 // indirect; @grafana/grafana-git-ui-sync-team github.com/grafana/otel-profiling-go v0.5.1 // @grafana/grafana-backend-group - github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // @grafana/observability-traces-and-profiling + github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // @grafana/observability-traces-and-profiling github.com/grafana/pyroscope/api v1.2.1-0.20250415190842-3ff7247547ae // @grafana/observability-traces-and-profiling github.com/grafana/tempo v1.5.1-0.20250529124718-87c2dc380cec // @grafana/observability-traces-and-profiling github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // @grafana/grafana-search-and-storage @@ -132,20 +132,20 @@ require ( github.com/json-iterator/go v1.1.12 // @grafana/grafana-backend-group github.com/lib/pq v1.10.9 // @grafana/grafana-backend-group github.com/m3db/prometheus_remote_client_golang v0.4.4 // @grafana/grafana-backend-group - github.com/madflojo/testcerts v1.1.1 // @grafana/alerting-backend + github.com/madflojo/testcerts v1.4.0 // @grafana/alerting-backend github.com/mattn/go-isatty v0.0.20 // @grafana/grafana-backend-group - github.com/mattn/go-sqlite3 v1.14.22 // @grafana/grafana-backend-group + github.com/mattn/go-sqlite3 v1.14.32 // @grafana/grafana-backend-group github.com/matttproud/golang_protobuf_extensions v1.0.4 // @grafana/alerting-backend github.com/microsoft/go-mssqldb v1.9.2 // @grafana/partner-datasources github.com/migueleliasweb/go-github-mock v1.1.0 // @grafana/grafana-git-ui-sync-team github.com/mitchellh/copystructure v1.2.0 // @grafana/grafana-operator-experience-squad github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c //@grafana/identity-access-team - github.com/mocktools/go-smtp-mock/v2 v2.3.1 // @grafana/grafana-backend-group + github.com/mocktools/go-smtp-mock/v2 v2.5.1 // @grafana/grafana-backend-group github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // @grafana/alerting-backend github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // @grafana/grafana-operator-experience-squad github.com/olekukonko/tablewriter v0.0.5 // @grafana/grafana-backend-group - github.com/open-feature/go-sdk v1.14.1 // @grafana/grafana-backend-group - github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.3 // @grafana/grafana-backend-group + github.com/open-feature/go-sdk v1.16.0 // @grafana/grafana-backend-group + github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.6 // @grafana/grafana-backend-group github.com/openfga/api/proto v0.0.0-20250909172242-b4b2a12f5c67 // @grafana/identity-access-team github.com/openfga/language/pkg/go v0.2.0-beta.2.0.20250428093642-7aeebe78bbfe // @grafana/identity-access-team github.com/openfga/openfga v1.10.0 // @grafana/identity-access-team @@ -161,7 +161,7 @@ require ( github.com/prometheus/prometheus v0.303.1 // @grafana/alerting-backend github.com/prometheus/sigv4 v0.1.2 // @grafana/alerting-backend github.com/puzpuzpuz/xsync/v4 v4.2.0 // @grafana/grafana-backend-group - github.com/redis/go-redis/v9 v9.8.0 // @grafana/alerting-backend + github.com/redis/go-redis/v9 v9.14.0 // @grafana/alerting-backend github.com/robfig/cron/v3 v3.0.1 // @grafana/grafana-backend-group github.com/rs/cors v1.11.1 // @grafana/identity-access-team github.com/russellhaering/goxmldsig v1.4.0 // @grafana/grafana-backend-group @@ -175,18 +175,18 @@ require ( github.com/ua-parser/uap-go v0.0.0-20250213224047-9c035f085b90 // @grafana/grafana-backend-group github.com/urfave/cli v1.22.17 // indirect; @grafana/grafana-backend-group github.com/urfave/cli/v2 v2.27.7 // @grafana/grafana-backend-group - github.com/urfave/cli/v3 v3.3.3 // @grafana/grafana-backend-group + github.com/urfave/cli/v3 v3.4.1 // @grafana/grafana-backend-group github.com/wk8/go-ordered-map v1.0.0 // @grafana/grafana-backend-group github.com/xlab/treeprint v1.2.0 // @grafana/observability-traces-and-profiling github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // @grafana/grafana-operator-experience-squad github.com/yudai/gojsondiff v1.0.0 // @grafana/grafana-backend-group go.opencensus.io v0.24.0 // @grafana/grafana-backend-group - go.opentelemetry.io/collector/pdata v1.30.0 // @grafana/grafana-backend-group + go.opentelemetry.io/collector/pdata v1.43.0 // @grafana/grafana-backend-group go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // @grafana/plugins-platform-backend - go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.62.0 // @grafana/grafana-operator-experience-squad + go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.63.0 // @grafana/grafana-operator-experience-squad go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // @grafana/sharing-squad - go.opentelemetry.io/contrib/propagators/jaeger v1.37.0 // @grafana/grafana-backend-group - go.opentelemetry.io/contrib/samplers/jaegerremote v0.31.0 // @grafana/grafana-backend-group + go.opentelemetry.io/contrib/propagators/jaeger v1.38.0 // @grafana/grafana-backend-group + go.opentelemetry.io/contrib/samplers/jaegerremote v0.32.0 // @grafana/grafana-backend-group go.opentelemetry.io/otel v1.38.0 // @grafana/grafana-backend-group go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // @grafana/grafana-backend-group go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // @grafana/grafana-backend-group @@ -202,16 +202,16 @@ require ( golang.org/x/crypto v0.42.0 // @grafana/grafana-backend-group golang.org/x/exp v0.0.0-20250911091902-df9299821621 // @grafana/alerting-backend golang.org/x/mod v0.28.0 // indirect; @grafana/grafana-backend-group - golang.org/x/net v0.44.0 // @grafana/oss-big-tent @grafana/partner-datasources - golang.org/x/oauth2 v0.30.0 // @grafana/identity-access-team + golang.org/x/net v0.45.0 // @grafana/oss-big-tent @grafana/partner-datasources + golang.org/x/oauth2 v0.31.0 // @grafana/identity-access-team golang.org/x/sync v0.17.0 // @grafana/alerting-backend - golang.org/x/text v0.29.0 // @grafana/grafana-backend-group + golang.org/x/text v0.30.0 // @grafana/grafana-backend-group golang.org/x/time v0.13.0 // @grafana/grafana-backend-group golang.org/x/tools v0.37.0 // indirect; @grafana/grafana-as-code gonum.org/v1/gonum v0.16.0 // @grafana/oss-big-tent google.golang.org/api v0.235.0 // @grafana/grafana-backend-group - google.golang.org/grpc v1.75.1 // @grafana/plugins-platform-backend - google.golang.org/protobuf v1.36.9 // @grafana/plugins-platform-backend + google.golang.org/grpc v1.76.0 // @grafana/plugins-platform-backend + google.golang.org/protobuf v1.36.10 // @grafana/plugins-platform-backend gopkg.in/ini.v1 v1.67.0 // @grafana/alerting-backend gopkg.in/mail.v2 v2.3.1 // @grafana/grafana-backend-group gopkg.in/yaml.v2 v2.4.0 // @grafana/alerting-backend @@ -225,7 +225,7 @@ require ( k8s.io/kube-aggregator v0.34.1 // @grafana/grafana-app-platform-squad k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // @grafana/grafana-app-platform-squad k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // @grafana/partner-datasources - modernc.org/sqlite v1.38.2 // @grafana/grafana-backend-group + modernc.org/sqlite v1.39.1 // @grafana/grafana-backend-group pgregory.net/rapid v1.2.0 // @grafana/grafana-operator-experience-squad sigs.k8s.io/randfill v1.0.0 // @grafana/grafana-app-platform-squad sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // @grafana/grafana-app-platform-squad @@ -242,6 +242,7 @@ require ( github.com/grafana/grafana/apps/folder v0.0.0 // @grafana/grafana-search-and-storage github.com/grafana/grafana/apps/iam v0.0.0 // @grafana/identity-access-team github.com/grafana/grafana/apps/investigations v0.0.0 // @fcjack @matryer + github.com/grafana/grafana/apps/logsdrilldown v0.0.0 // @grafana/observability-logs github.com/grafana/grafana/apps/playlist v0.0.0 // @grafana/grafana-app-platform-squad github.com/grafana/grafana/apps/plugins v0.0.0 // @grafana/plugins-platform-backend github.com/grafana/grafana/apps/preferences v0.0.0 // @grafana/grafana-app-platform-squad @@ -271,6 +272,7 @@ replace ( github.com/grafana/grafana/apps/folder => ./apps/folder github.com/grafana/grafana/apps/iam => ./apps/iam github.com/grafana/grafana/apps/investigations => ./apps/investigations + github.com/grafana/grafana/apps/logsdrilldown => ./apps/logsdrilldown github.com/grafana/grafana/apps/playlist => ./apps/playlist github.com/grafana/grafana/apps/plugins => ./apps/plugins github.com/grafana/grafana/apps/preferences => ./apps/preferences @@ -296,7 +298,7 @@ require ( cloud.google.com/go/monitoring v1.24.2 // indirect cuelabs.dev/go/oci/ociregistry v0.0.0-20240906074133-82eb438dd565 // indirect github.com/Azure/azure-pipeline-go v0.2.3 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect @@ -306,7 +308,7 @@ require ( github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0 // indirect github.com/FZambia/eagle v0.2.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 // indirect @@ -324,6 +326,7 @@ require ( github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/apache/thrift v0.22.0 // indirect github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/at-wat/mqtt-go v0.19.4 // indirect @@ -534,7 +537,7 @@ require ( github.com/oklog/run v1.1.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/oklog/ulid/v2 v2.1.1 // indirect - github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5 // indirect + github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.6 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.124.1 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/pkg/core/xidutils v0.124.1 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger v0.124.1 // indirect @@ -605,6 +608,7 @@ require ( go.etcd.io/etcd/client/v3 v3.6.4 // indirect go.mongodb.org/mongo-driver v1.17.3 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/collector/featuregate v1.43.0 // indirect go.opentelemetry.io/collector/semconv v0.124.0 // indirect go.opentelemetry.io/contrib/bridges/prometheus v0.61.0 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.36.0 // indirect @@ -645,7 +649,7 @@ require ( gopkg.in/telebot.v3 v3.3.8 // indirect k8s.io/apiextensions-apiserver v0.34.1 // indirect k8s.io/kms v0.34.1 // indirect - modernc.org/libc v1.66.3 // indirect + modernc.org/libc v1.66.10 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.11.0 // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect @@ -653,8 +657,6 @@ require ( sigs.k8s.io/yaml v1.6.0 // indirect ) -require github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect - // Use fork of crewjam/saml with fixes for some issues until changes get merged into upstream replace github.com/crewjam/saml => github.com/grafana/saml v0.4.15-0.20240917091248-ae3bbdad8a56 diff --git a/go.sum b/go.sum index a752393996b..ccf464203f2 100644 --- a/go.sum +++ b/go.sum @@ -648,14 +648,14 @@ github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl github.com/Azure/azure-sdk-for-go v23.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1 h1:Wc1ml6QlJs2BHQ/9Bqu1jiyggbsSjramq2oUmp5WeIo= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 h1:5YTBM8QDVIBN3sxBil89WfdAAqDZbyJTgh688DSxX5w= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1/go.mod h1:YD5h/ldMsG0XiIw7PdyNhLxaM317eFh5yNLccNfGdyw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.12.0 h1:wL5IEG5zb7BVv1Kv0Xm92orq+5hB5Nipn3B5tn4Rqfk= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.12.0/go.mod h1:J7MUC/wtRpfGVbQ5sIItY5/FuVWmvzlY21WAOfQnq/I= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI= github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 h1:m/sWOGCREuSBqg2htVQTBY8nOZpyajYztF0vUvSZTuM= github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0/go.mod h1:Pu5Zksi2KrU7LPbZbNINx6fuVrUp/ffvpxdDj+i8LeE= github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 h1:FbH3BbSb4bvGluTesZZ+ttN/MDsnMmQP36OSnDuSXqw= @@ -703,8 +703,8 @@ github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e h1:NeAW1fUYUEWhft github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= -github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= -github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0 h1:XkkQbfMyuH2jTSjQjSoihryI8GINRcs4xp8lNawg0FI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= github.com/Bose/minisentinel v0.0.0-20200130220412-917c5a9223bb h1:ZVN4Iat3runWOFLaBCDVU5a9X/XikSRBosye++6gojw= github.com/Bose/minisentinel v0.0.0-20200130220412-917c5a9223bb/go.mod h1:WsAABbY4HQBgd3mGuG4KMNTbHJCPvx9IVBHzysbknss= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -890,8 +890,8 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.2 h1:pd9G9HQaM6UZAZh19pYOkpKS github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.2/go.mod h1:eknndR9rU8UpE/OmFpqU78V1EcXPKFTTm5l/buZYgvM= github.com/aws/aws-sdk-go-v2/service/sts v1.38.0 h1:iV1Ko4Em/lkJIsoKyGfc0nQySi+v0Udxr6Igq+y9JZc= github.com/aws/aws-sdk-go-v2/service/sts v1.38.0/go.mod h1:bEPcjW7IbolPfK67G1nilqWyoxYMSPrDiIQ3RdIdKgo= -github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw= -github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= +github.com/aws/smithy-go v1.23.1 h1:sLvcH6dfAFwGkHLZ7dGiYF7aK6mg4CgKA/iDKjLDt9M= +github.com/aws/smithy-go v1.23.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= github.com/axiomhq/hyperloglog v0.0.0-20191112132149-a4c4c47bc57f/go.mod h1:2stgcRjl6QmW+gU2h5E7BQXg4HU0gzxKWDuT5HviN9s= github.com/axiomhq/hyperloglog v0.0.0-20240507144631-af9851f82b27 h1:60m4tnanN1ctzIu4V3bfCNJ39BiOPSm1gHFlFjTkRE0= github.com/axiomhq/hyperloglog v0.0.0-20240507144631-af9851f82b27/go.mod h1:k08r+Yj1PRAmuayFiRK6MYuR5Ve4IuZtTfxErMIh0+c= @@ -1585,8 +1585,8 @@ github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7Fsg github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= -github.com/grafana/alerting v0.0.0-20251007160934-e642236ea9eb h1:ejpL3pI9t1ebEFtxaP7TMDKZagCu1nSq1O8op+sO4DY= -github.com/grafana/alerting v0.0.0-20251007160934-e642236ea9eb/go.mod h1:VGjS5gDwWEADPP6pF/drqLxEImgeuHlEW5u8E5EfIrM= +github.com/grafana/alerting v0.0.0-20251009192429-9427c24835ae h1:NLPwY3tIP0lg0g9wTRiMcypm6VRXW6W+MOLBsq8JSVA= +github.com/grafana/alerting v0.0.0-20251009192429-9427c24835ae/go.mod h1:VGjS5gDwWEADPP6pF/drqLxEImgeuHlEW5u8E5EfIrM= github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f h1:Cbm6OKkOcJ+7CSZsGsEJzktC/SIa5bxVeYKQLuYK86o= github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f/go.mod h1:axY0cdOg3q0TZHwpHnIz5x16xZ8ZBxJHShsSHHXcHQg= github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 h1:qEwZ+7MbPjzRvTi31iT9w7NBhKIpKwZrFbYmOZLqkwA= @@ -1605,14 +1605,14 @@ github.com/grafana/gomemcache v0.0.0-20250318131618-74242eea118d h1:oXRJlb9UjVsl github.com/grafana/gomemcache v0.0.0-20250318131618-74242eea118d/go.mod h1:j/s0jkda4UXTemDs7Pgw/vMT06alWc42CHisvYac0qw= github.com/grafana/grafana-api-golang-client v0.27.0 h1:zIwMXcbCB4n588i3O2N6HfNcQogCNTd/vPkEXTr7zX8= github.com/grafana/grafana-api-golang-client v0.27.0/go.mod h1:uNLZEmgKtTjHBtCQMwNn3qsx2mpMb8zU+7T4Xv3NR9Y= -github.com/grafana/grafana-app-sdk v0.46.0 h1:gvzQvCQgZJ/73BfAcbDt/6TAMhnVikVPxZt/UwDl+oc= -github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= -github.com/grafana/grafana-app-sdk/logging v0.45.0 h1:0SH6nYZpiLBZRwUq4J6+1vo8xuHKJjnO95/2pGOoA8w= -github.com/grafana/grafana-app-sdk/logging v0.45.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grafana/grafana-app-sdk v0.47.0 h1:zTKV+p6zM9y+In+dAcaHczbJJsQj9WKglSBcQXMOA+8= +github.com/grafana/grafana-app-sdk v0.47.0/go.mod h1:kywXmkppq0oReUMzkjTW8Fq2EBzyN7v914jttTWnWxA= +github.com/grafana/grafana-app-sdk/logging v0.46.0 h1:JhQ+ZK5orcmM+dZ3YZdT9uCizJEFU2I6JBNUSFWvCC8= +github.com/grafana/grafana-app-sdk/logging v0.46.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= github.com/grafana/grafana-aws-sdk v1.2.0 h1:LLR4/g91WBuCRwm2cbWfCREq565+GxIFe08nqqIcIuw= github.com/grafana/grafana-aws-sdk v1.2.0/go.mod h1:bBo7qOmM3f61vO+2JxTolNUph1l2TmtzmWcU9/Im+8A= -github.com/grafana/grafana-azure-sdk-go/v2 v2.2.0 h1:0TYrkzAc3u0HX+9GK86cGrLTUAcmQfl3/LEB3tL+SOA= -github.com/grafana/grafana-azure-sdk-go/v2 v2.2.0/go.mod h1:H9sVh9A4yg5egMGZeh0mifxT1Q/uqwKe1LBjBJU6pN8= +github.com/grafana/grafana-azure-sdk-go/v2 v2.3.1 h1:FFcEA01tW+SmuJIuDbHOdgUBL+d7DPrZ2N4zwzPhfGk= +github.com/grafana/grafana-azure-sdk-go/v2 v2.3.1/go.mod h1:Oi4anANlCuTCc66jCyqIzfVbgLXFll8Wja+Y4vfANlc= github.com/grafana/grafana-cloud-migration-snapshot v1.9.0 h1:JOzchPgptwJdruYoed7x28lFDwhzs7kssResYsnC0iI= github.com/grafana/grafana-cloud-migration-snapshot v1.9.0/go.mod h1:nOHgq4Oa829qmBKA5KIXw5Ipo3rhLs0d6A8UI9Nw8Zk= github.com/grafana/grafana-google-sdk-go v0.4.2 h1:F44hQF1y6UVJhlJPi+Mz+GCJsioVgezEgPMMEQbUZRo= @@ -1637,8 +1637,8 @@ github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls= github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604 h1:aXfUhVN/Ewfpbko2CCtL65cIiGgwStOo4lWH2b6gw2U= github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604/go.mod h1:O/QP1BCm0HHIzbKvgMzqb5sSyH88rzkFk84F4TfJjBU= -github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= -github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= +github.com/grafana/pyroscope-go/godeltaprof v0.1.9 h1:c1Us8i6eSmkW+Ez05d3co8kasnuOY813tbMN8i/a3Og= +github.com/grafana/pyroscope-go/godeltaprof v0.1.9/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= github.com/grafana/pyroscope/api v1.2.1-0.20250415190842-3ff7247547ae h1:35W3Wjp9KWnSoV/DuymmyIj5aHE0CYlDQ5m2KeXUPAc= github.com/grafana/pyroscope/api v1.2.1-0.20250415190842-3ff7247547ae/go.mod h1:6CJ1uXmLZ13ufpO9xE4pST+DyaBt0uszzrV0YnoaVLQ= github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248= @@ -1928,8 +1928,8 @@ github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuz github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= github.com/m3db/prometheus_remote_client_golang v0.4.4 h1:DsAIjVKoCp7Ym35tAOFL1OuMLIdIikAEHeNPHY+yyM8= github.com/m3db/prometheus_remote_client_golang v0.4.4/go.mod h1:wHfVbA3eAK6dQvKjCkHhusWYegCk3bDGkA15zymSHdc= -github.com/madflojo/testcerts v1.1.1 h1:YsSHWV79nMNZK0mJtwXjKoYHjJEbLPFefR8TxmmWupY= -github.com/madflojo/testcerts v1.1.1/go.mod h1:MW8sh39gLnkKh4K0Nc55AyHEDl9l/FBLDUsQhpmkuo0= +github.com/madflojo/testcerts v1.4.0 h1:I09gN0C1ly9IgeVNcAqKk8RAKIJTe3QnFrrPBDyvzN4= +github.com/madflojo/testcerts v1.4.0/go.mod h1:MW8sh39gLnkKh4K0Nc55AyHEDl9l/FBLDUsQhpmkuo0= github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg= github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -1977,8 +1977,8 @@ github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh 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.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= -github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs= +github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= 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= @@ -2054,8 +2054,8 @@ github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5 github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= -github.com/mocktools/go-smtp-mock/v2 v2.3.1 h1:wq75NDSsOy5oHo/gEQQT0fRRaYKRqr1IdkjhIPXxagM= -github.com/mocktools/go-smtp-mock/v2 v2.3.1/go.mod h1:h9AOf/IXLSU2m/1u4zsjtOM/WddPwdOUBz56dV9f81M= +github.com/mocktools/go-smtp-mock/v2 v2.5.1 h1:QcMJMChSgG1olVj4o6xxQFdrWzRjYNrcq660HAjd0wA= +github.com/mocktools/go-smtp-mock/v2 v2.5.1/go.mod h1:Rr8M2njlxx//l5INl2+uESnsL2lDsL24teEykCrGfmE= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -2119,12 +2119,12 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= -github.com/open-feature/go-sdk v1.14.1 h1:jcxjCIG5Up3XkgYwWN5Y/WWfc6XobOhqrIwjyDBsoQo= -github.com/open-feature/go-sdk v1.14.1/go.mod h1:t337k0VB/t/YxJ9S0prT30ISUHwYmUd/jhUZgFcOvGg= -github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.3 h1:6jpO63NCEZv4xunJj+aNlDuFVuRkVBPMcIuxvFPYRWQ= -github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.3/go.mod h1:dPUHjAIFzg+ci/wt6XxlNiiMkOh5Yw4SGyeRY0AFT0g= -github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5 h1:ZdqlGnNwhWf3luhBQlIpbglvcCzjkcuEgOEhYhr5Emc= -github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5/go.mod h1:jrD4UG3ZCzuwImKHlyuIN2iWeYjlOX5+zJ/sX45efuE= +github.com/open-feature/go-sdk v1.16.0 h1:5NCHYv5slvNBIZhYXAzAufo0OI59OACZ5tczVqSE+Tg= +github.com/open-feature/go-sdk v1.16.0/go.mod h1:EIF40QcoYT1VbQkMPy2ZJH4kvZeY+qGUXAorzSWgKSo= +github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.6 h1:megzzlQGjsRVWDX8oJnLaa5eEcsAHekiL4Uvl3jSAcY= +github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.6/go.mod h1:K1gDKvt76CGFLSUMHUydd5ba2V5Cv69gQZsdbnXhAm8= +github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.6 h1:WinefYxeVx5rV0uQmuWbxQf8iACu/JiRubo5w0saToc= +github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.6/go.mod h1:Dwcaoma6lZVqYwyfVlY7eB6RXbG+Ju3b9cnpTlUN+Hc= github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.124.1 h1:NrjsoVPxI6lmV8jPImDcMeqYh+97Y71f/HB5Sfpfe3I= github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.124.1/go.mod h1:AFMryJmht7dZxcAwc2sx/r4gxbriElWw49ugxKp2mcA= github.com/open-telemetry/opentelemetry-collector-contrib/pkg/core/xidutils v0.124.1 h1:E1e96GTHmiAfIfeYfA5ZVnOxud3+vbisGp0gE1tfd4s= @@ -2285,8 +2285,8 @@ github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2z github.com/puzpuzpuz/xsync/v4 v4.2.0 h1:dlxm77dZj2c3rxq0/XNvvUKISAmovoXF4a4qM6Wvkr0= github.com/puzpuzpuz/xsync/v4 v4.2.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= -github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/redis/go-redis/v9 v9.14.0 h1:u4tNCjXOyzfgeLN+vAZaW1xUooqWDqVEsZN0U01jfAE= +github.com/redis/go-redis/v9 v9.14.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/redis/rueidis v1.0.64 h1:XqgbueDuNV3qFdVdQwAHJl1uNt90zUuAJuzqjH4cw6Y= github.com/redis/rueidis v1.0.64/go.mod h1:Lkhr2QTgcoYBhxARU7kJRO8SyVlgUuEkcJO1Y8MCluA= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= @@ -2479,8 +2479,8 @@ github.com/urfave/cli v1.22.17 h1:SYzXoiPfQjHBbkYxbew5prZHS1TOLT3ierW8SYLqtVQ= github.com/urfave/cli v1.22.17/go.mod h1:b0ht0aqgH/6pBYzzxURyrM4xXNgsoT/n2ZzwQiEhNVo= github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU= github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4= -github.com/urfave/cli/v3 v3.3.3 h1:byCBaVdIXuLPIDm5CYZRVG6NvT7tv1ECqdU4YzlEa3I= -github.com/urfave/cli/v3 v3.3.3/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= +github.com/urfave/cli/v3 v3.4.1 h1:1M9UOCy5bLmGnuu1yn3t3CB4rG79Rtoxuv1sPhnm6qM= +github.com/urfave/cli/v3 v3.4.1/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= 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/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= @@ -2578,8 +2578,10 @@ go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/collector v0.124.0 h1:g/dfdGFhBcQI0ggGxTmGlJnJ6Yl6T2gVxQoIj4UfXCc= -go.opentelemetry.io/collector/pdata v1.30.0 h1:j3jyq9um436r6WzWySzexP2nLnFdmL5uVBYAlyr9nDM= -go.opentelemetry.io/collector/pdata v1.30.0/go.mod h1:0Bxu1ktuj4wE7PIASNSvd0SdBscQ1PLtYasymJ13/Cs= +go.opentelemetry.io/collector/featuregate v1.43.0 h1:Aq8UR5qv1zNlbbkTyqv8kLJtnoQMq/sG1/jS9o1cCJI= +go.opentelemetry.io/collector/featuregate v1.43.0/go.mod h1:d0tiRzVYrytB6LkcYgz2ESFTv7OktRPQe0QEQcPt1L4= +go.opentelemetry.io/collector/pdata v1.43.0 h1:zVkj2hcjiMLwX+QDDNwb7iTh3LBjNXKv2qPSgj1Rzb4= +go.opentelemetry.io/collector/pdata v1.43.0/go.mod h1:KsJzdDG9e5BaHlmYr0sqdSEKeEiSfKzoF+rdWU7J//w= go.opentelemetry.io/collector/pdata/pprofile v0.124.0 h1:ZjL9wKqzP4BHj0/F1jfGxs1Va8B7xmYayipZeNVoWJE= go.opentelemetry.io/collector/pdata/pprofile v0.124.0/go.mod h1:1EN3Gw5LSI4fSVma/Yfv/6nqeuYgRTm1/kmG5nE5Oyo= go.opentelemetry.io/collector/semconv v0.124.0 h1:YTdo3UFwNyDQCh9DiSm2rbzAgBuwn/9dNZ0rv454goA= @@ -2593,15 +2595,15 @@ go.opentelemetry.io/contrib/exporters/autoexport v0.61.0/go.mod h1:N6otC+qXTD5bA go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.55.0/go.mod h1:rsg1EO8LXSs2po50PB5CeY/MSVlhghuKBgXlKnqm6ks= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.62.0 h1:wCeciVlAfb5DC8MQl/DlmAv/FVPNpQgFvI/71+hatuc= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.62.0/go.mod h1:WfEApdZDMlLUAev/0QQpr8EJ/z0VWDKYZ5tF5RH5T1U= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.63.0 h1:2pn7OzMewmYRiNtv1doZnLo3gONcnMHlFnmOR8Vgt+8= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.63.0/go.mod h1:rjbQTDEPQymPE0YnRQp9/NuPwwtL0sesz/fnqRW/v84= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= -go.opentelemetry.io/contrib/propagators/jaeger v1.37.0 h1:pW+qDVo0jB0rLsNeaP85xLuz20cvsECUcN7TE+D8YTM= -go.opentelemetry.io/contrib/propagators/jaeger v1.37.0/go.mod h1:x7bd+t034hxLTve1hF9Yn9qQJlO/pP8H5pWIt7+gsFM= -go.opentelemetry.io/contrib/samplers/jaegerremote v0.31.0 h1:l8XCsDh7L6Z7PB+vlw1s4ufNab+ayT2RMNdvDE/UyPc= -go.opentelemetry.io/contrib/samplers/jaegerremote v0.31.0/go.mod h1:XAOSk4bqj5vtoiY08bexeiafzxdXeLlxKFnwscvn8Fc= +go.opentelemetry.io/contrib/propagators/jaeger v1.38.0 h1:nXGeLvT1QtCAhkASkP/ksjkTKZALIaQBIW+JSIw1KIc= +go.opentelemetry.io/contrib/propagators/jaeger v1.38.0/go.mod h1:oMvOXk78ZR3KEuPMBgp/ThAMDy9ku/eyUVztr+3G6Wo= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.32.0 h1:oPW/SRFyHgIgxrvNhSBzqvZER2N5kRlci3/rGTOuyWo= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.32.0/go.mod h1:B9Oka5QVD0bnmZNO6gBbBta6nohD/1Z+f9waH2oXyBs= go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= @@ -2658,6 +2660,12 @@ go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= +go.opentelemetry.io/proto/slim/otlp v1.8.0 h1:afcLwp2XOeCbGrjufT1qWyruFt+6C9g5SOuymrSPUXQ= +go.opentelemetry.io/proto/slim/otlp v1.8.0/go.mod h1:Yaa5fjYm1SMCq0hG0x/87wV1MP9H5xDuG/1+AhvBcsI= +go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.1.0 h1:Uc+elixz922LHx5colXGi1ORbsW8DTIGM+gg+D9V7HE= +go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.1.0/go.mod h1:VyU6dTWBWv6h9w/+DYgSZAPMabWbPTFTuxp25sM8+s0= +go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.1.0 h1:i8YpvWGm/Uq1koL//bnbJ/26eV3OrKWm09+rDYo7keU= +go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.1.0/go.mod h1:pQ70xHY/ZVxNUBPn+qUWPl8nwai87eWdqL3M37lNi9A= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= @@ -2875,8 +2883,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2914,8 +2922,8 @@ golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -3119,8 +3127,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 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= @@ -3510,8 +3518,8 @@ google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5v google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -3534,8 +3542,8 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= @@ -3633,19 +3641,19 @@ lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v4 v4.26.2 h1:991HMkLjJzYBIfha6ECZdjrIYz2/1ayr+FL8GN+CNzM= -modernc.org/cc/v4 v4.26.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= +modernc.org/cc/v4 v4.26.5 h1:xM3bX7Mve6G8K8b+T11ReenJOT+BmVqQj0FY5T4+5Y4= +modernc.org/cc/v4 v4.26.5/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= -modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU= -modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE= +modernc.org/ccgo/v4 v4.28.1 h1:wPKYn5EC/mYTqBO373jKjvX2n+3+aK7+sICCv4Fjy1A= +modernc.org/ccgo/v4 v4.28.1/go.mod h1:uD+4RnfrVgE6ec9NGguUNdhqzNIeeomeXf6CL0GTE5Q= modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= -modernc.org/fileutil v1.3.8 h1:qtzNm7ED75pd1C7WgAGcK4edm4fvhtBsEiI/0NQ54YM= -modernc.org/fileutil v1.3.8/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= +modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA= +modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= @@ -3658,8 +3666,8 @@ modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= -modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ= -modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8= +modernc.org/libc v1.66.10 h1:yZkb3YeLx4oynyR+iUsXsybsX4Ubx7MQlSYEw4yj59A= +modernc.org/libc v1.66.10/go.mod h1:8vGSEwvoUoltr4dlywvHqjtAqHBaw0j1jI7iFBTAr2I= modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= @@ -3677,8 +3685,8 @@ modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= -modernc.org/sqlite v1.38.2 h1:Aclu7+tgjgcQVShZqim41Bbw9Cho0y/7WzYptXqkEek= -modernc.org/sqlite v1.38.2/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E= +modernc.org/sqlite v1.39.1 h1:H+/wGFzuSCIEVCvXYVHX5RQglwhMOvtHSv+VtidL2r4= +modernc.org/sqlite v1.39.1/go.mod h1:9fjQZ0mB1LLP0GYrp39oOJXx/I2sxEnZtzCmEQIKvGE= modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= diff --git a/go.work b/go.work index efba709a41b..1b60b90eae9 100644 --- a/go.work +++ b/go.work @@ -1,4 +1,4 @@ -go 1.24.6 +go 1.25.3 // The `skip:golangci-lint` comment tag is used to exclude the package from the `golangci-lint` GitHub Action. // The module at the root of the repo (`.`) is excluded because ./pkg/... is included manually in the `golangci-lint` configuration. @@ -14,6 +14,7 @@ use ( ./apps/folder ./apps/iam ./apps/investigations + ./apps/logsdrilldown ./apps/playlist ./apps/plugins ./apps/preferences diff --git a/go.work.sum b/go.work.sum index 00ee74f2be3..8fbb5a5b0bf 100644 --- a/go.work.sum +++ b/go.work.sum @@ -680,6 +680,8 @@ github.com/aws/aws-sdk-go-v2/service/ssm v1.52.4 h1:hgSBvRT7JEWx2+vEGI9/Ld5rZtl7 github.com/aws/aws-sdk-go-v2/service/ssm v1.52.4/go.mod h1:v7NIzEFIHBiicOMaMTuEmbnzGnqW0d+6ulNALul6fYE= github.com/aws/aws-sdk-go-v2/service/ssm v1.58.0 h1:zQz6Q5uaC8s9734DV9UDAm2q1TEEfOvEejDBSulOapI= github.com/aws/aws-sdk-go-v2/service/ssm v1.58.0/go.mod h1:PUWUl5MDiYNQkUHN9Pyd9kgtA/YhbxnSnHP+yQqzrM8= +github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw= +github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/awslabs/aws-lambda-go-api-proxy v0.16.2 h1:CJyGEyO1CIwOnXTU40urf0mchf6t3voxpvUDikOU9LY= github.com/awslabs/aws-lambda-go-api-proxy v0.16.2/go.mod h1:vxxjwBHe/KbgFeNlAP/Tvp4SsVRL3WQamcWRxqVh0z0= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= @@ -783,6 +785,7 @@ github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GK github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= @@ -799,8 +802,12 @@ github.com/cucumber/gherkin/go/v26 v26.2.0 h1:EgIjePLWiPeslwIWmNQ3XHcypPsWAHoMCz github.com/cucumber/gherkin/go/v26 v26.2.0/go.mod h1:t2GAPnB8maCT4lkHL99BDCVNzCh1d7dBhCLt150Nr/0= github.com/cucumber/godog v0.15.0 h1:51AL8lBXF3f0cyA5CV4TnJFCTHpgiy+1x1Hb3TtZUmo= github.com/cucumber/godog v0.15.0/go.mod h1:FX3rzIDybWABU4kuIXLZ/qtqEe1Ac5RdXmqvACJOces= +github.com/cucumber/godog v0.15.1 h1:rb/6oHDdvVZKS66hrhpjFQFHjthFSrQBCOI1LwshNTI= +github.com/cucumber/godog v0.15.1/go.mod h1:qju+SQDewOljHuq9NSM66s0xEhogx0q30flfxL4WUk8= github.com/cucumber/messages/go/v21 v21.0.1 h1:wzA0LxwjlWQYZd32VTlAVDTkW6inOFmSM+RuOwHZiMI= github.com/cucumber/messages/go/v21 v21.0.1/go.mod h1:zheH/2HS9JLVFukdrsPWoPdmUtmYQAQPLk7w5vWsk5s= +github.com/cucumber/messages/go/v22 v22.0.0 h1:hk3ITpEWQ+KWDe619zYcqtaLOfcu9jgClSeps3DlNWI= +github.com/cucumber/messages/go/v22 v22.0.0/go.mod h1:aZipXTKc0JnjCsXrJnuZpWhtay93k7Rn3Dee7iyPJjs= github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07 h1:UHFGPvSxX4C4YBApSPvmUfL8tTvWLj2ryqvT9K4Jcuk= github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f h1:7uSNgsgcarNk4oiN/nNkO0J7KAjlsF5Yv5Gf/tFdHas= github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4 h1:CVAqftqbj+exlab+8KJQrE+kNIVlQfJt58j4GxCMF1s= @@ -977,6 +984,8 @@ github.com/gocraft/dbr/v2 v2.7.2/go.mod h1:5bCqyIXO5fYn3jEp/L06QF4K1siFdhxChMjdN github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= @@ -988,7 +997,6 @@ github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9 github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/cel-go v0.23.2/go.mod h1:52Pb6QsDbC5kvgxvZhiL9QX1oZEkcUF/ZqaPx1J5Wwo= github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= -github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-jsonnet v0.18.0 h1:/6pTy6g+Jh1a1I2UMoAODkqELFiVIdOxbNwv0DDzoOg= github.com/google/go-jsonnet v0.18.0/go.mod h1:C3fTzyVJDslXdiTqw/bTFk7vSGyCtH3MGRbDfvEwGd0= github.com/google/go-pkcs11 v0.3.0 h1:PVRnTgtArZ3QQqTGtbtjtnIkzl2iY2kt24yqbrf7td8= @@ -1064,10 +1072,10 @@ github.com/grafana/dskit v0.0.0-20250818234656-8ff9c6532e85/go.mod h1:kImsvJ1xnm github.com/grafana/go-gelf/v2 v2.0.1 h1:BOChP0h/jLeD+7F9mL7tq10xVkDG15he3T1zHuQaWak= github.com/grafana/go-gelf/v2 v2.0.1/go.mod h1:lexHie0xzYGwCgiRGcvZ723bSNyNI8ZRD4s0CLobh90= github.com/grafana/gomemcache v0.0.0-20250228145437-da7b95fd2ac1/go.mod h1:j/s0jkda4UXTemDs7Pgw/vMT06alWc42CHisvYac0qw= -github.com/grafana/gomemcache v0.0.0-20250828162811-a96f6acee2fe/go.mod h1:j/s0jkda4UXTemDs7Pgw/vMT06alWc42CHisvYac0qw= github.com/grafana/grafana-app-sdk v0.40.1/go.mod h1:4P8h7VB6KcDjX9bAoBQc6IP8iNylxe6bSXLR9gA39gM= github.com/grafana/grafana-app-sdk v0.41.0 h1:SYHN3U7B1myRKY3UZZDkFsue9TDmAOap0UrQVTqtYBU= github.com/grafana/grafana-app-sdk v0.41.0/go.mod h1:Wg/3vEZfok1hhIWiHaaJm+FwkosfO98o8KbeLFEnZpY= +github.com/grafana/grafana-app-sdk v0.46.0/go.mod h1:LCTrqR1SwBS13XGVYveBmM7giJDDjzuXK+M9VzPuPWc= github.com/grafana/grafana-app-sdk/logging v0.38.0/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk= github.com/grafana/grafana-app-sdk/logging v0.39.0 h1:3GgN5+dUZYqq74Q+GT9/ET+yo+V54zWQk/Q2/JsJQB4= github.com/grafana/grafana-app-sdk/logging v0.39.0/go.mod h1:WhDENSnaGHtyVVwZGVnAR7YLvh2xlLDYR3D7E6h7XVk= @@ -1076,6 +1084,7 @@ github.com/grafana/grafana-app-sdk/logging v0.40.0/go.mod h1:otUD9XpJD7A5sCLb8mc github.com/grafana/grafana-app-sdk/logging v0.43.0/go.mod h1:0xrjKSGY5z+NLGuGsXQpxiCHR4Smu79i/CbAfdkaB1M= github.com/grafana/grafana-app-sdk/logging v0.43.1/go.mod h1:0xrjKSGY5z+NLGuGsXQpxiCHR4Smu79i/CbAfdkaB1M= github.com/grafana/grafana-app-sdk/logging v0.43.2/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= +github.com/grafana/grafana-app-sdk/logging v0.45.0/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA= github.com/grafana/grafana-app-sdk/plugin v0.41.0 h1:ShUvGpAVzM3UxcsfwS6l/lwW4ytDeTbCQXf8w2P8Yp8= github.com/grafana/grafana-app-sdk/plugin v0.41.0/go.mod h1:YIhimVfAqtOp3kdhxOanaSZjypVKh/bYxf9wfFfhDm0= github.com/grafana/grafana-aws-sdk v0.38.2 h1:TzQD0OpWsNjtldi5G5TLDlBRk8OyDf+B5ujcoAu4Dp0= @@ -1225,10 +1234,13 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kevinmbeaulieu/eq-go v1.0.0 h1:AQgYHURDOmnVJ62jnEk0W/7yFKEn+Lv8RHN6t7mB0Zo= github.com/kevinmbeaulieu/eq-go v1.0.0/go.mod h1:G3S8ajA56gKBZm4UB9AOyoOS37JO3roToPzKNM8dtdM= +github.com/keybase/dbus v0.0.0-20220506165403-5aa21ea2c23a h1:K0EAzgzEQHW4Y5lxrmvPMltmlRDzlhLfGmots9EHUTI= +github.com/keybase/dbus v0.0.0-20220506165403-5aa21ea2c23a/go.mod h1:YPNKjjE7Ubp9dTbnWvsP3HT+hYnY6TfXzubYTBeUxc8= github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46 h1:veS9QfglfvqAw2e+eeNT/SbGySq8ajECXJ9e4fPoLhY= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s= github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= @@ -1289,6 +1301,8 @@ github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dt github.com/lyft/protoc-gen-star v0.6.1 h1:erE0rdztuaDq3bpGifD95wfoPrSZc95nGA6tbiNYh6M= github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4 h1:sIXJOMrYnQZJu7OB7ANSF4MYri2fTEGIsRLz6LwI4xE= github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= +github.com/madflojo/testcerts v1.1.1 h1:YsSHWV79nMNZK0mJtwXjKoYHjJEbLPFefR8TxmmWupY= +github.com/madflojo/testcerts v1.1.1/go.mod h1:MW8sh39gLnkKh4K0Nc55AyHEDl9l/FBLDUsQhpmkuo0= github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= @@ -1337,6 +1351,7 @@ github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= +github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/mostynb/go-grpc-compression v1.2.3 h1:42/BKWMy0KEJGSdWvzqIyOZ95YcR9mLPqKctH7Uo//I= @@ -1363,6 +1378,13 @@ github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C github.com/onsi/ginkgo/v2 v2.22.1/go.mod h1:S6aTpoRsSq2cZOd+pssHAlKW/Q/jZt6cPrPlnj4a1xM= github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/open-feature/go-sdk v1.15.1/go.mod h1:2WAFYzt8rLYavcubpCoiym3iSCXiHdPB6DxtMkv2wyo= +github.com/open-feature/go-sdk v1.16.0 h1:5NCHYv5slvNBIZhYXAzAufo0OI59OACZ5tczVqSE+Tg= +github.com/open-feature/go-sdk v1.16.0/go.mod h1:EIF40QcoYT1VbQkMPy2ZJH4kvZeY+qGUXAorzSWgKSo= +github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.6 h1:megzzlQGjsRVWDX8oJnLaa5eEcsAHekiL4Uvl3jSAcY= +github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.6/go.mod h1:K1gDKvt76CGFLSUMHUydd5ba2V5Cv69gQZsdbnXhAm8= +github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.6 h1:WinefYxeVx5rV0uQmuWbxQf8iACu/JiRubo5w0saToc= +github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.6/go.mod h1:Dwcaoma6lZVqYwyfVlY7eB6RXbG+Ju3b9cnpTlUN+Hc= github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector v0.121.0 h1:gX7HGoRE0OTMS8ZVh/zPeQe+ZEASKxAo6Wn9dIcsgRE= github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector v0.121.0/go.mod h1:y6UqtUREKcyDzLPQC5wSPbOlZR2HLUrNp/2ITZalVKA= github.com/open-telemetry/opentelemetry-collector-contrib/exporter/kafkaexporter v0.121.0 h1:1J3XbT944dDqif4TINht6SBz1l+HXpOeyZglaUfdY+0= @@ -1454,6 +1476,7 @@ github.com/phpdave11/gofpdf v1.4.2 h1:KPKiIbfwbvC/wOncwhrpRdXVj2CZTCFlw4wnoyjtHf github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs= github.com/pkg/sftp v1.13.7 h1:uv+I3nNJvlKZIQGSr8JVQLNHFU9YhhNpvC14Y6KgmSM= @@ -1549,6 +1572,7 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -1630,6 +1654,7 @@ github.com/uber-go/atomic v1.4.0/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex github.com/uber/jaeger-client-go v2.28.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= +github.com/urfave/cli/v3 v3.3.3/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= 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/vertica/vertica-sql-go v1.3.3 h1:fL+FKEAEy5ONmsvya2WH5T8bhkvY27y/Ik3ReR2T+Qw= @@ -1803,6 +1828,8 @@ go.opentelemetry.io/collector/internal/telemetry v0.124.0 h1:kzd1/ZYhLj4bt2pDB52 go.opentelemetry.io/collector/internal/telemetry v0.124.0/go.mod h1:ZjXjqV0dJ+6D4XGhTOxg/WHjnhdmXsmwmUSgALea66Y= go.opentelemetry.io/collector/otelcol v0.124.0 h1:q/+ebTZgEZX+yFbvO7FeqpEtvtRPJ+YzZzHsVzqA71s= go.opentelemetry.io/collector/otelcol v0.124.0/go.mod h1:mFGJZn5YuffdMVO/lPBavbW+R64Dgd3jOMgw2WAmJEM= +go.opentelemetry.io/collector/pdata v1.30.0 h1:j3jyq9um436r6WzWySzexP2nLnFdmL5uVBYAlyr9nDM= +go.opentelemetry.io/collector/pdata v1.30.0/go.mod h1:0Bxu1ktuj4wE7PIASNSvd0SdBscQ1PLtYasymJ13/Cs= go.opentelemetry.io/collector/pdata/testdata v0.124.0 h1:vY+pWG7CQfzzGSB5+zGYHQOltRQr59Ek9QiPe+rI+NY= go.opentelemetry.io/collector/pdata/testdata v0.124.0/go.mod h1:lNH48lGhGv4CYk27fJecpsR1zYHmZjKgNrAprwjym0o= go.opentelemetry.io/collector/pipeline v0.124.0 h1:hKvhDyH2GPnNO8LGL34ugf36sY7EOXPjBvlrvBhsOdw= @@ -1853,6 +1880,7 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.5 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0/go.mod h1:HDBUsEjOuRC0EzKZ1bSaRGZWUBAzo+MhAcUUORSr4D0= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0/go.mod h1:CosX/aS4eHnG9D7nESYpV753l4j9q5j3SL/PUYd2lR8= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.62.0/go.mod h1:WfEApdZDMlLUAev/0QQpr8EJ/z0VWDKYZ5tF5RH5T1U= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= @@ -1866,6 +1894,8 @@ go.opentelemetry.io/contrib/otelconf v0.15.0/go.mod h1:OPH1seO5z9dp1P26gnLtoM9ht go.opentelemetry.io/contrib/propagators/b3 v1.35.0 h1:DpwKW04LkdFRFCIgM3sqwTJA/QREHMeMHYPWP1WeaPQ= go.opentelemetry.io/contrib/propagators/b3 v1.35.0/go.mod h1:9+SNxwqvCWo1qQwUpACBY5YKNVxFJn5mlbXg/4+uKBg= go.opentelemetry.io/contrib/propagators/jaeger v1.35.0/go.mod h1:0ciyFyYZxE6JqRAQvIgGRabKWDUmNdW3GAQb6y/RlFU= +go.opentelemetry.io/contrib/propagators/jaeger v1.37.0/go.mod h1:x7bd+t034hxLTve1hF9Yn9qQJlO/pP8H5pWIt7+gsFM= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.31.0/go.mod h1:XAOSk4bqj5vtoiY08bexeiafzxdXeLlxKFnwscvn8Fc= go.opentelemetry.io/contrib/zpages v0.60.0 h1:wOM9ie1Hz4H88L9KE6GrGbKJhfm+8F1NfW/Y3q9Xt+8= go.opentelemetry.io/contrib/zpages v0.60.0/go.mod h1:xqfToSRGh2MYUsfyErNz8jnNDPlnpZqWM/y6Z2Cx7xw= go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= @@ -1923,6 +1953,7 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= @@ -1983,6 +2014,7 @@ golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -1995,6 +2027,7 @@ golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2031,6 +2064,7 @@ golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= @@ -2100,6 +2134,7 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go. google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw= google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA= google.golang.org/genproto/googleapis/api v0.0.0-20250728155136-f173205681a0/go.mod h1:8ytArBbtOy2xfht+y2fqKd5DRDJRUQhqbyEnQ4bDChs= +google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:oDOGiMSXHL4sDTJvFvIB9nRQCGdLP1o/iVaqQK8zB+M= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA= google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE= google.golang.org/genproto/googleapis/bytestream v0.0.0-20250505200425-f936aa4a68b2 h1:DbpkGFGRkd4GORg+IWQW2EhxUaa/My/PM8d1CGyTDMY= @@ -2134,6 +2169,7 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250811230008-5f3141c8851a/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo= google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo= google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc= @@ -2157,6 +2193,7 @@ google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3i google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= google.golang.org/grpc v1.74.0/go.mod h1:NZUaK8dAMUfzhK6uxZ+9511LtOrk73UGWOFoNvz7z+s= google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE= google.golang.org/grpc/examples v0.0.0-20230224211313-3775f633ce20 h1:MLBCGN1O7GzIx+cBiwfYPwtmZ41U3Mn/cotLJciaArI= google.golang.org/grpc/examples v0.0.0-20230224211313-3775f633ce20/go.mod h1:Nr5H8+MlGWr5+xX/STzdoEqJrO+YteqFbMyCsrb6mH0= @@ -2170,6 +2207,7 @@ google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojt google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= @@ -2224,12 +2262,17 @@ lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= modernc.org/cc/v3 v3.36.3 h1:uISP3F66UlixxWEcKuIWERa4TwrZENHSL8tWxZz8bHg= modernc.org/cc/v3 v3.41.0 h1:QoR1Sn3YWlmA1T4vLaKZfawdVtSiGx8H+cEojbC7v1Q= modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y= +modernc.org/cc/v4 v4.26.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= modernc.org/ccgo/v3 v3.16.9 h1:AXquSwg7GuMk11pIdw7fmO1Y/ybgazVkMhsZWCV0mHM= modernc.org/ccgo/v3 v3.17.0 h1:o3OmOqx4/OFnl4Vm3G8Bgmqxnvxnh0nbxeT5p/dWChA= modernc.org/ccgo/v3 v3.17.0/go.mod h1:Sg3fwVpmLvCUTaqEUjiBDAvshIaKDB0RXaf+zgqFu8I= +modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE= modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= modernc.org/ccorpus2 v1.5.2 h1:Ui+4tc58mf/W+2arcYCJR903y3zl3ecsI7Fpaaqozyw= modernc.org/ccorpus2 v1.5.2/go.mod h1:Wifvo4Q/qS/h1aRoC2TffcHsnxwTikmi1AuLANuucJQ= +modernc.org/ccorpus2 v1.5.4 h1:k9A52f3NsUQzHStOav5ukvkdKz63CW5po4gaC5VH4Qc= +modernc.org/ccorpus2 v1.5.4/go.mod h1:Wifvo4Q/qS/h1aRoC2TffcHsnxwTikmi1AuLANuucJQ= +modernc.org/fileutil v1.3.8/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= @@ -2238,12 +2281,16 @@ modernc.org/lex v1.1.1/go.mod h1:6r8o8DLJkAnOsQaGi8fMoi+Vt6LTbDaCrkUK729D8xM= modernc.org/lexer v1.0.4 h1:hU7xVbZsqwPphyzChc7nMSGrsuaD2PDNOmzrzkS5AlE= modernc.org/lexer v1.0.4/go.mod h1:tOajb8S4sdfOYitzCgXDFmbVJ/LE0v1fNJ7annTw36U= modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY= +modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ= +modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= modernc.org/scannertest v1.0.2 h1:JPtfxcVdbRvzmRf2YUvsDibJsQRw8vKA/3jb31y7cy0= modernc.org/scannertest v1.0.2/go.mod h1:RzTm5RwglF/6shsKoEivo8N91nQIoWtcWI7ns+zPyGA= modernc.org/sqlite v1.29.6/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U= modernc.org/sqlite v1.38.0/go.mod h1:1Bj+yES4SVvBZ4cBOpVZ6QgesMCKpJZDq0nxYzOpmNE= +modernc.org/sqlite v1.38.2 h1:Aclu7+tgjgcQVShZqim41Bbw9Cho0y/7WzYptXqkEek= +modernc.org/sqlite v1.38.2/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/tcl v1.13.1 h1:npxzTwFTZYM8ghWicVIX1cRWzj7Nd8i6AqqX2p+IYao= modernc.org/z v1.5.1 h1:RTNHdsrOpeoSeOF4FbzTo8gBYByaJ5xT7NgZ9ZqRiJM= diff --git a/hack/go.mod b/hack/go.mod index ba694313e1f..6234b45073e 100644 --- a/hack/go.mod +++ b/hack/go.mod @@ -1,16 +1,16 @@ module github.com/grafana/grafana/hack -go 1.24.6 +go 1.25.3 require k8s.io/code-generator v0.34.1 require ( github.com/go-logr/logr v1.4.2 // indirect github.com/spf13/pflag v1.0.6 // indirect - golang.org/x/mod v0.24.0 // indirect - golang.org/x/sync v0.14.0 // indirect - golang.org/x/text v0.25.0 // indirect - golang.org/x/tools v0.33.0 // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/text v0.29.0 // indirect + golang.org/x/tools v0.36.0 // indirect k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f // indirect k8s.io/klog/v2 v2.130.1 // indirect ) diff --git a/hack/go.sum b/hack/go.sum index 60d1ab0595e..b370b15f40f 100644 --- a/hack/go.sum +++ b/hack/go.sum @@ -4,14 +4,14 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= -golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= -golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= -golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= k8s.io/code-generator v0.34.1 h1:WpphT26E+j7tEgIUfFr5WfbJrktCGzB3JoJH9149xYc= k8s.io/code-generator v0.34.1/go.mod h1:DeWjekbDnJWRwpw3s0Jat87c+e0TgkxoR4ar608yqvg= k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f h1:SLb+kxmzfA87x4E4brQzB33VBbT2+x7Zq9ROIHmGn9Q= diff --git a/jest.config.codeowner.js b/jest.config.codeowner.js new file mode 100644 index 00000000000..d94df3cfa3e --- /dev/null +++ b/jest.config.codeowner.js @@ -0,0 +1,117 @@ +const fs = require('fs'); +const path = require('path'); + +const baseConfig = require('./jest.config.js'); + +const CODEOWNERS_MANIFEST_FILENAMES_BY_TEAM_PATH = 'codeowners-manifest/filenames-by-team.json'; + +const teamName = process.env.TEAM_NAME; +if (!teamName) { + console.error('ERROR: TEAM_NAME environment variable is required'); + process.exit(1); +} + +const outputDir = `./coverage/by-team/${createOwnerDirectory(teamName)}`; + +const codeownersFilePath = path.join(__dirname, CODEOWNERS_MANIFEST_FILENAMES_BY_TEAM_PATH); + +if (!fs.existsSync(codeownersFilePath)) { + console.error(`Codeowners file not found at ${codeownersFilePath} ...`); + console.error('Please run: yarn codeowners-manifest first to generate the mapping file'); + process.exit(1); +} + +const codeownersData = JSON.parse(fs.readFileSync(codeownersFilePath, 'utf8')); +const teamFiles = codeownersData[teamName] || []; + +if (teamFiles.length === 0) { + console.error(`ERROR: No files found for team "${teamName}"`); + console.error('Available teams:', Object.keys(codeownersData).join(', ')); + process.exit(1); +} + +const sourceFiles = teamFiles.filter((file) => { + const ext = path.extname(file); + return ( + ['.ts', '.tsx', '.js', '.jsx'].includes(ext) && + !file.includes('.test.') && + !file.includes('.spec.') && + !file.includes('.story.') && + !file.includes('.gen.ts') && + !file.includes('.d.ts') && + !file.endsWith('/types.ts') + ); +}); + +const testFiles = teamFiles.filter((file) => { + const ext = path.extname(file); + return ['.ts', '.tsx', '.js', '.jsx'].includes(ext) && (file.includes('.test.') || file.includes('.spec.')); +}); + +if (testFiles.length === 0) { + console.log(`No test files found for team ${teamName}`); + process.exit(0); +} + +console.log( + `๐Ÿงช Collecting coverage for ${sourceFiles.length} testable files and running ${testFiles.length} test files of ${teamFiles.length} files owned by ${teamName}.` +); + +module.exports = { + ...baseConfig, + + collectCoverage: true, + collectCoverageFrom: sourceFiles.map((file) => `/${file}`), + coverageReporters: ['none'], + coverageDirectory: '/tmp/jest-coverage-ignore', + + coverageProvider: 'v8', + reporters: [ + 'default', + [ + 'jest-monocart-coverage', + { + name: `Coverage Report - ${teamName} owned files`, + outputDir: outputDir, + reports: ['console-summary', 'v8', 'json', 'lcov'], + sourceFilter: (coveredFile) => sourceFiles.includes(coveredFile), + all: { + dir: ['./packages', './public'], + filter: (filePath) => { + const relativePath = filePath.replace(process.cwd() + '/', ''); + return sourceFiles.includes(relativePath); + }, + }, + cleanCache: true, + onEnd: (coverageResults) => { + console.log(`๐Ÿ“„ Coverage report saved to file://${path.resolve(outputDir)}/index.html`); + // TODO: Emit coverage metrics https://github.com/grafana/grafana/issues/111208 + }, + }, + ], + ], + + testRegex: undefined, + + testMatch: testFiles.map((file) => `/${file}`), +}; + +/** + * Create a filesystem-safe directory structure for different owner types + * @param {string} owner - CODEOWNERS owner (username, team, or email) + * @returns {string} Directory path relative to coverage/by-team/ + */ +function createOwnerDirectory(owner) { + if (owner.includes('@') && owner.includes('/')) { + // Example: @grafana/dataviz-squad + const [org, team] = owner.substring(1).split('/'); + return `teams/${org}/${team}`; + } else if (owner.startsWith('@')) { + // Example: @jesdavpet + return `users/${owner.substring(1)}`; + } else { + // Example: user@domain.tld + const [user, domain] = owner.split('@'); + return `emails/${user}-at-${domain}`; + } +} diff --git a/kinds/dashboard/dashboard_kind.cue b/kinds/dashboard/dashboard_kind.cue index 20571c8211a..13c2b4f25f6 100644 --- a/kinds/dashboard/dashboard_kind.cue +++ b/kinds/dashboard/dashboard_kind.cue @@ -360,8 +360,9 @@ lineage: schemas: [{ // `textbox`: Display a free text input field with an optional default value. // `custom`: Define the variable options manually using a comma-separated list. // `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables + // `switch`: Boolean variables rendered as a switch #VariableType: "query" | "adhoc" | "groupby" | "constant" | "datasource" | "interval" | "textbox" | "custom" | - "system" | "snapshot" @cuetsy(kind="type") @grafanamaturity(NeedsExpertReview) + "system" | "snapshot" | "switch" @cuetsy(kind="type") @grafanamaturity(NeedsExpertReview) // Color mode for a field. You can specify a single color, or select a continuous (gradient) color schemes, based on a value. // Continuous color interpolates a color using the percentage of a value relative to min and max. diff --git a/kinds/librarypanel/librarypanel_kind.cue b/kinds/librarypanel/librarypanel_kind.cue deleted file mode 100644 index b87ceccb6fc..00000000000 --- a/kinds/librarypanel/librarypanel_kind.cue +++ /dev/null @@ -1,63 +0,0 @@ -package kind - -import ( - "strings" - "time" -) - -name: "LibraryPanel" -maturity: "experimental" -description: "A standalone panel" - -lineage: schemas: [{ - version: [0, 0] - schema: { - spec: { - // Folder UID - folderUid?: string @grafanamaturity(ToMetadata="sys") - - // Library element UID - uid: string - - // Panel name (also saved in the model) - name: string & strings.MinRunes(1) - - // Panel description - description?: string - - // The panel type (from inside the model) - type: string & strings.MinRunes(1) - - // Dashboard version when this was saved (zero if unknown) - schemaVersion?: uint16 - - // panel version, incremented each time the dashboard is updated. - version: int64 @grafanamaturity(NeedsExpertReview) - - // TODO: should be the same panel schema defined in dashboard - // Typescript: Omit; - model: {...} - - // Object storage metadata - meta?: #LibraryElementDTOMeta @grafanamaturity(ToMetadata="sys") - } @cuetsy(kind="interface") @grafana(TSVeneer="type") - - #LibraryElementDTOMetaUser: { - id: int64 - name: string - avatarUrl: string - } @cuetsy(kind="interface") @grafanamaturity(NeedsExpertReview) - - #LibraryElementDTOMeta: { - folderName: string - folderUid: string @grafanamaturity(ToMetadata="sys") - connectedDashboards: int64 - - created: string & time.Time - updated: string & time.Time - - createdBy: #LibraryElementDTOMetaUser @grafanamaturity(ToMetadata="sys") - updatedBy: #LibraryElementDTOMetaUser @grafanamaturity(ToMetadata="sys") - } @cuetsy(kind="interface") @grafanamaturity(NeedsExpertReview) - } -}] diff --git a/package.json b/package.json index 64006c8d73c..d045ebb590a 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,11 @@ "build": "NODE_ENV=production nx exec --verbose -- webpack --config scripts/webpack/webpack.prod.js", "build:nominify": "yarn run build -- --env noMinify=1", "build:stats": "NODE_ENV=production webpack --progress --config scripts/webpack/webpack.stats.js", + "codeowners-manifest": "node ./scripts/codeowners-manifest/index.js", + "codeowners-manifest:clean": "rm -rf codeowners-manifest && mkdir -p codeowners-manifest", + "codeowners-manifest:generate": "node ./scripts/codeowners-manifest/generate.js", + "codeowners-manifest:metadata": "node ./scripts/codeowners-manifest/metadata.js", + "codeowners-manifest:raw": "node ./scripts/codeowners-manifest/raw.js", "dev": "NODE_ENV=dev nx exec -- webpack --config scripts/webpack/webpack.dev.js", "e2e": "./e2e/start-and-run-suite", "e2e:old-arch": "./e2e/start-and-run-suite old-arch", @@ -30,6 +35,7 @@ "e2e:plugin:build:dev": "nx run-many -t dev --projects='@test-plugins/*' --maxParallel=100", "test": "jest --notify --watch", "test:coverage": "jest --coverage", + "test:coverage:by-codeowner": "yarn codeowners-manifest && node scripts/test-coverage-by-codeowner.js", "test:storybook": "yarn workspace @grafana/ui storybook:test", "test:coverage:changes": "jest --coverage --changedSince=origin/main", "test:accessibility-report": "./scripts/generate-a11y-report.sh", @@ -56,7 +62,8 @@ "stats": "webpack --mode production --config scripts/webpack/webpack.prod.js --profile --json > compilation-stats.json", "storybook": "yarn workspace @grafana/ui storybook --ci", "storybook:build": "yarn workspace @grafana/ui storybook:build", - "themes-generate": "esbuild --target=es6 ./scripts/cli/generateSassVariableFiles.ts --bundle --platform=node --tsconfig=./scripts/cli/tsconfig.json | node", + "themes-schema": "typescript-json-schema ./tsconfig.json NewThemeOptions --include 'packages/grafana-data/src/themes/createTheme.ts' --out public/app/features/theme-playground/schema.generated.json", + "themes-generate": "yarn themes-schema && esbuild --target=es6 ./scripts/cli/generateSassVariableFiles.ts --bundle --platform=node --tsconfig=./scripts/cli/tsconfig.json | node", "themes:usage": "eslint . --ignore-pattern '*.test.ts*' --ignore-pattern '*.spec.ts*' --cache --plugin '@grafana' --rule '{ @grafana/theme-token-usage: \"error\" }'", "typecheck": "tsc --noEmit && yarn run packages:typecheck", "plugins:build-bundled": "echo 'bundled plugins are no longer supported'", @@ -148,13 +155,12 @@ "@types/react-window": "1.8.8", "@types/react-window-infinite-loader": "^1", "@types/redux-mock-store": "1.5.0", - "@types/semver": "7.7.0", + "@types/semver": "7.7.1", "@types/slate": "0.47.11", "@types/slate-plain-serializer": "0.7.5", "@types/slate-react": "0.22.9", "@types/swagger-ui-react": "5.18.0", "@types/systemjs": "6.15.3", - "@types/tinycolor2": "1.4.6", "@types/uuid": "10.0.0", "@types/webpack-assets-manifest": "^5", "@types/webpack-env": "^1.18.4", @@ -191,6 +197,7 @@ "eslint-plugin-no-barrel-files": "^1.1.1", "eslint-plugin-react": "7.37.5", "eslint-plugin-react-hooks": "5.2.0", + "eslint-plugin-react-prefer-function-component": "4.0.1", "eslint-plugin-testing-library": "^7.0.0", "eslint-plugin-unicorn": "^56.0.0", "eslint-scope": "^8.1.0", @@ -198,6 +205,7 @@ "expose-loader": "5.0.1", "fishery": "^2.2.2", "fork-ts-checker-webpack-plugin": "9.1.0", + "github-codeowners": "^0.2.1", "glob": "11.0.3", "html-loader": "5.1.0", "html-webpack-plugin": "5.6.3", @@ -211,6 +219,7 @@ "jest-fail-on-console": "3.3.1", "jest-junit": "16.0.0", "jest-matcher-utils": "29.7.0", + "jest-monocart-coverage": "^1.1.1", "jest-watch-typeahead": "^2.2.2", "jimp": "^1.6.0", "jsdom-testing-mocks": "^1.13.1", @@ -241,12 +250,12 @@ "style-loader": "4.0.0", "stylelint": "16.23.0", "stylelint-config-sass-guidelines": "12.1.0", - "terser-webpack-plugin": "5.3.14", "testing-library-selector": "0.3.1", "tracelib": "1.0.1", "ts-jest": "29.4.0", "ts-node": "10.9.2", "typescript": "5.9.2", + "typescript-json-schema": "^0.65.1", "webpack": "5.101.0", "webpack-assets-manifest": "^5.1.0", "webpack-cli": "6.0.1", @@ -268,7 +277,7 @@ "@formatjs/intl-durationformat": "^0.7.0", "@glideapps/glide-data-grid": "^6.0.0", "@grafana/alerting": "workspace:*", - "@grafana/assistant": "0.0.18", + "@grafana/assistant": "0.1.0", "@grafana/aws-sdk": "0.7.1", "@grafana/azure-sdk": "0.0.7", "@grafana/data": "workspace:*", @@ -279,15 +288,15 @@ "@grafana/flamegraph": "workspace:*", "@grafana/google-sdk": "0.3.5", "@grafana/i18n": "workspace:*", - "@grafana/lezer-logql": "0.2.8", + "@grafana/lezer-logql": "0.2.9", "@grafana/llm": "0.22.1", "@grafana/monaco-logql": "^0.0.8", "@grafana/o11y-ds-frontend": "workspace:*", "@grafana/plugin-ui": "^0.10.10", "@grafana/prometheus": "workspace:*", "@grafana/runtime": "workspace:*", - "@grafana/scenes": "6.38.0", - "@grafana/scenes-react": "6.38.0", + "@grafana/scenes": "^6.39.8", + "@grafana/scenes-react": "^6.39.8", "@grafana/schema": "workspace:*", "@grafana/sql": "workspace:*", "@grafana/ui": "workspace:*", @@ -302,15 +311,16 @@ "@locker/near-membrane-shared-dom": "0.14.0", "@msagl/core": "^1.1.19", "@msagl/parser": "^1.1.19", + "@openfeature/ofrep-web-provider": "^0.3.3", "@openfeature/web-sdk": "^1.6.1", "@opentelemetry/api": "1.9.0", "@opentelemetry/exporter-collector": "0.25.0", "@opentelemetry/semantic-conventions": "1.37.0", "@popperjs/core": "2.11.8", - "@react-aria/dialog": "3.5.30", - "@react-aria/focus": "3.21.1", - "@react-aria/overlays": "3.29.1", - "@react-aria/utils": "3.30.1", + "@react-aria/dialog": "3.5.31", + "@react-aria/focus": "3.21.2", + "@react-aria/overlays": "3.30.0", + "@react-aria/utils": "3.31.0", "@react-awesome-query-builder/ui": "6.6.15", "@reduxjs/toolkit": "2.9.0", "@visx/event": "3.12.0", @@ -343,7 +353,7 @@ "i18next-browser-languagedetector": "^8.0.0", "i18next-pseudo": "^2.2.1", "immer": "10.1.3", - "immutable": "5.1.3", + "immutable": "5.1.4", "infinite-viewer": "^0.29.1", "ix": "^7.0.0", "jquery": "3.7.1", @@ -356,7 +366,7 @@ "lodash": "4.17.21", "logfmt": "^1.3.2", "lossless-json": "^4.1.1", - "lru-cache": "11.2.1", + "lru-cache": "11.2.2", "lru-memoize": "^1.1.0", "lucene": "^2.1.1", "marked": "16.3.0", @@ -411,21 +421,20 @@ "reselect": "5.1.1", "rxjs": "7.8.2", "selecto": "1.26.3", - "semver": "7.7.2", + "semver": "7.7.3", "slate": "0.47.9", "slate-plain-serializer": "0.7.13", "slate-react": "0.22.10", "swagger-ui-react": "5.28.1", "symbol-observable": "4.0.0", "systemjs": "6.15.1", - "tinycolor2": "1.6.0", "tslib": "2.8.1", "tween-functions": "^1.2.0", "type-fest": "^4.18.2", "uplot": "1.6.32", "uuid": "11.1.0", "vis-data": "^8.0.0", - "vis-network": "10.0.1", + "vis-network": "10.0.2", "whatwg-fetch": "3.6.20" }, "resolutions": { @@ -442,7 +451,7 @@ "@grafana/plugin-e2e/@grafana/e2e-selectors": "workspace:*", "@grafana/scenes/@grafana/e2e-selectors": "workspace:*", "@grafana/scenes-react/@grafana/e2e-selectors": "workspace:*", - "swagger-ui-react/dompurify": "3.2.6", + "swagger-ui-react/dompurify": "3.3.0", "refractor/prismjs": "^1.27.0", "@mapbox/jsonlint-lines-primitives": "github:mapbox/jsonlint#commit=e31b7289baedf3e1000d7ae7edd42268212c9954", "get-document": "github:webmodules/get-document#commit=a04ccb499d6e0433a368c3bb150b4899b698461f", diff --git a/packages/grafana-alerting/package.json b/packages/grafana-alerting/package.json index f162791a6bf..167358447d0 100644 --- a/packages/grafana-alerting/package.json +++ b/packages/grafana-alerting/package.json @@ -70,6 +70,7 @@ "@types/lodash": "^4", "@types/react": "18.3.18", "@types/react-dom": "18.3.5", + "@types/tinycolor2": "^1", "i18next": "^25.5.2", "react": "18.3.1", "react-dom": "18.3.1", @@ -85,7 +86,6 @@ "@grafana/data": ">=11.6 <= 12.x", "@grafana/runtime": ">=11.6 <= 12.x", "@grafana/ui": ">=11.6 <= 12.x", - "@reduxjs/toolkit": "^2.8.0", "msw": "^2.0.0", "react": "^18.0.0", "react-dom": "^18.0.0" @@ -94,7 +94,9 @@ "@emotion/css": "11.13.5", "@faker-js/faker": "^9.8.0", "@grafana/i18n": "12.3.0-pre", + "@reduxjs/toolkit": "^2.9.0", "fishery": "^2.3.1", - "lodash": "^4.17.21" + "lodash": "^4.17.21", + "tinycolor2": "^1.6.0" } } diff --git a/packages/grafana-alerting/scripts/README.md b/packages/grafana-alerting/scripts/README.md index c27d22246a8..32730a22a13 100644 --- a/packages/grafana-alerting/scripts/README.md +++ b/packages/grafana-alerting/scripts/README.md @@ -1,4 +1,23 @@ -These files are built using the `yarn run codegen` command. +# Re-generate the clients + +โš ๏ธ This guide assumes the Backend definitions have been updated in `apps/alerting`. + +## Re-create OpenAPI specification + +Start with re-generating the OpenAPI snapshots by running the test in `pkg/tests/apis/openapi_test.go`. + +This will output the OpenAPI JSON spec file(s) in `pkg/tests/apis/openapi_snapshots`. + +## Process OpenAPI specifications + +Next up run the post-processing of the snapshots with `yarn run process-specs`, this will copy processed specifications to `./data/openapi/`. + +## Generate RTKQ files + +These files are built using the `yarn run codegen` command, make sure to run that in the Grafana Alerting package working directory. + +`yarn --cwd ./packages/grafana-alerting run codegen`. + API clients will be written to `src/grafana/api//api.gen.ts`. Make sure to create a versioned API client for each API version โ€“ see `src/grafana/api/v0alpha1/api.ts` as an example. diff --git a/packages/grafana-alerting/scripts/codegen.ts b/packages/grafana-alerting/scripts/codegen.ts index 53ec8976a85..59c9a7e5cb8 100644 --- a/packages/grafana-alerting/scripts/codegen.ts +++ b/packages/grafana-alerting/scripts/codegen.ts @@ -7,35 +7,42 @@ */ import type { ConfigFile } from '@rtk-query/codegen-openapi'; -// โ„น๏ธ append versions here to generate additional API clients -const VERSIONS = ['v0alpha1'] as const; -const GROUP = 'notifications.alerting.grafana.app' as const; +// โ„น๏ธ append API groups and versions here to generate additional API clients +const SPECS = [ + ['notifications.alerting.grafana.app', ['v0alpha1']], + ['rules.alerting.grafana.app', ['v0alpha1']], + // keep this in Grafana Enterprise + // ['alertenrichment.grafana.app', ['v1beta1']], +] as const; type OutputFile = Omit; type OutputFiles = Record; -const outputFiles = VERSIONS.reduce((acc, version) => { - // we append the version here so we export versioned API clients from this package without having to re-export with an alias - const exportName = 'alertingAPI'; +const outputFiles = SPECS.reduce((groupAcc, [group, versions]) => { + return versions.reduce((versionAcc, version) => { + // Create a unique export name based on the group + const groupName = group.split('.')[0]; // e.g., 'notifications', 'rules', 'alertenrichment' + const exportName = `${groupName}API`; - // โ„น๏ธ these snapshots are generated by running "go test pkg/tests/apis/openapi_test.go" and "scripts/process-specs.ts", - // see the README in the "openapi_snapshots" directory - const schemaFile = `../../../data/openapi/${GROUP}-${version}.json`; + // โ„น๏ธ these snapshots are generated by running "go test pkg/tests/apis/openapi_test.go" and "scripts/process-specs.ts", + // see the README in the "openapi_snapshots" directory + const schemaFile = `../../../data/openapi/${group}-${version}.json`; - // โ„น๏ธ make sure there is a API file in each versioned directory - const apiFile = `../src/grafana/api/${version}/api.ts`; + // โ„น๏ธ make sure there is a API file in each versioned directory + const apiFile = `../src/grafana/api/${groupName}/${version}/api.ts`; - // output each api client into a versioned directory - const outputPath = `../src/grafana/api/${version}/api.gen.ts`; + // output each api client into a versioned directory with group-specific naming + const outputPath = `../src/grafana/api/${groupName}/${version}/${groupName}.api.gen.ts`; - acc[outputPath] = { - exportName, - schemaFile, - apiFile, - tag: true, // generate tags for cache invalidation - } satisfies OutputFile; + versionAcc[outputPath] = { + exportName, + schemaFile, + apiFile, + tag: true, // generate tags for cache invalidation + } satisfies OutputFile; - return acc; + return versionAcc; + }, groupAcc); }, {}); export default { diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/api.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/api.ts similarity index 89% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/api.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/api.ts index 6d22d1df2c2..5b45157954f 100644 --- a/packages/grafana-alerting/src/grafana/api/v0alpha1/api.ts +++ b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/api.ts @@ -1,6 +1,6 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; -import { getAPIBaseURL, getAPIReducerPath } from '../util'; +import { getAPIBaseURL, getAPIReducerPath } from '../../util'; import { GROUP, VERSION } from './const'; diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/const.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/const.ts similarity index 100% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/const.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/const.ts diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/fakes/Receivers.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/fakes/Receivers.ts similarity index 93% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/fakes/Receivers.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/fakes/Receivers.ts index 9bc5189e964..fbd88a5972d 100644 --- a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/fakes/Receivers.ts +++ b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/fakes/Receivers.ts @@ -1,7 +1,7 @@ import { faker } from '@faker-js/faker'; import { Factory } from 'fishery'; -import { DEFAULT_NAMESPACE, generateResourceVersion, generateTitle, generateUID } from '../../../../mocks/util'; +import { DEFAULT_NAMESPACE, generateResourceVersion, generateTitle, generateUID } from '../../../../../mocks/util'; import { GROUP, VERSION } from '../../const'; import { ContactPoint, @@ -47,16 +47,17 @@ export const ContactPointSpecFactory = Factory.define(() = export const GenericIntegrationFactory = Factory.define(() => ({ type: 'generic', + version: '1', disableResolveMessage: false, settings: { foo: 'bar', }, - version: 'v1', })); export const EmailIntegrationFactory = Factory.define(() => ({ type: 'email', - version: 'v1', + version: '1', + secureFields: {}, settings: { addresses: faker.internet.email(), }, @@ -64,7 +65,8 @@ export const EmailIntegrationFactory = Factory.define(() => ({ export const SlackIntegrationFactory = Factory.define(() => ({ type: 'slack', - version: 'v1', + version: '1', + secureFields: { token: true }, settings: { mentionChannel: '#alerts', }, diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/fakes/Routes.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/fakes/Routes.ts similarity index 91% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/fakes/Routes.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/fakes/Routes.ts index ba9a1b4b8f0..66a6ea1ffce 100644 --- a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/fakes/Routes.ts +++ b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/fakes/Routes.ts @@ -1,8 +1,8 @@ import { faker } from '@faker-js/faker'; import { Factory } from 'fishery'; -import { LabelMatcher } from '../../../../matchers/types'; -import { Route } from '../../../../notificationPolicies/types'; +import { LabelMatcher } from '../../../../../matchers/types'; +import { Route } from '../../../../../notificationPolicies/types'; export const LabelMatcherFactory = Factory.define(() => { const operators: Array = ['=', '!=', '=~', '!~']; diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/fakes/common.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/fakes/common.ts similarity index 100% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/fakes/common.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/fakes/common.ts diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/createReceiverHandler.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/createReceiverHandler.ts similarity index 74% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/createReceiverHandler.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/createReceiverHandler.ts index 6ca0ba803c4..2c21893b6d3 100644 --- a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/createReceiverHandler.ts +++ b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/createReceiverHandler.ts @@ -1,7 +1,7 @@ import { HttpResponse, http } from 'msw'; -import { getAPIBaseURLForMocks } from '../../../../../mocks/util'; -import { CreateReceiverApiResponse } from '../../../api.gen'; +import { getAPIBaseURLForMocks } from '../../../../../../mocks/util'; +import { CreateReceiverApiResponse } from '../../../../v0alpha1/notifications.api.gen'; import { GROUP, VERSION } from '../../../const'; export function createReceiverHandler( diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/deleteReceiverHandler.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/deleteReceiverHandler.ts similarity index 74% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/deleteReceiverHandler.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/deleteReceiverHandler.ts index 13d47dda277..d3ff5c660f8 100644 --- a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/deleteReceiverHandler.ts +++ b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/deleteReceiverHandler.ts @@ -1,7 +1,7 @@ import { HttpResponse, http } from 'msw'; -import { getAPIBaseURLForMocks } from '../../../../../mocks/util'; -import { DeleteReceiverApiResponse } from '../../../api.gen'; +import { getAPIBaseURLForMocks } from '../../../../../../mocks/util'; +import { DeleteReceiverApiResponse } from '../../../../v0alpha1/notifications.api.gen'; import { GROUP, VERSION } from '../../../const'; export function deleteReceiverHandler( diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/deletecollectionReceiverHandler.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/deletecollectionReceiverHandler.ts similarity index 73% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/deletecollectionReceiverHandler.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/deletecollectionReceiverHandler.ts index 8d1141df76f..f3871112e66 100644 --- a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/deletecollectionReceiverHandler.ts +++ b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/deletecollectionReceiverHandler.ts @@ -1,7 +1,7 @@ import { HttpResponse, http } from 'msw'; -import { getAPIBaseURLForMocks } from '../../../../../mocks/util'; -import { DeletecollectionReceiverApiResponse } from '../../../api.gen'; +import { getAPIBaseURLForMocks } from '../../../../../../mocks/util'; +import { DeletecollectionReceiverApiResponse } from '../../../../v0alpha1/notifications.api.gen'; import { GROUP, VERSION } from '../../../const'; export function deletecollectionReceiverHandler( diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/getReceiverHandler.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/getReceiverHandler.ts similarity index 74% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/getReceiverHandler.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/getReceiverHandler.ts index bc82c667dd0..d90d1fbecba 100644 --- a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/getReceiverHandler.ts +++ b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/getReceiverHandler.ts @@ -1,7 +1,7 @@ import { HttpResponse, http } from 'msw'; -import { getAPIBaseURLForMocks } from '../../../../../mocks/util'; -import { GetReceiverApiResponse } from '../../../api.gen'; +import { getAPIBaseURLForMocks } from '../../../../../../mocks/util'; +import { GetReceiverApiResponse } from '../../../../v0alpha1/notifications.api.gen'; import { GROUP, VERSION } from '../../../const'; export function getReceiverHandler( diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/index.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/index.ts similarity index 100% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/index.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/index.ts diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/listReceiverHandler.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/listReceiverHandler.ts similarity index 88% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/listReceiverHandler.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/listReceiverHandler.ts index 6040ffe4d8a..fde49565388 100644 --- a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/listReceiverHandler.ts +++ b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/listReceiverHandler.ts @@ -1,6 +1,6 @@ import { HttpResponse, http } from 'msw'; -import { getAPIBaseURLForMocks } from '../../../../../mocks/util'; +import { getAPIBaseURLForMocks } from '../../../../../../mocks/util'; import { GROUP, VERSION } from '../../../const'; import { EnhancedListReceiverApiResponse } from '../../../types'; diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/replaceReceiverHandler.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/replaceReceiverHandler.ts similarity index 74% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/replaceReceiverHandler.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/replaceReceiverHandler.ts index 85ab132925e..c054de71882 100644 --- a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/replaceReceiverHandler.ts +++ b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/replaceReceiverHandler.ts @@ -1,7 +1,7 @@ import { HttpResponse, http } from 'msw'; -import { getAPIBaseURLForMocks } from '../../../../../mocks/util'; -import { ReplaceReceiverApiResponse } from '../../../api.gen'; +import { getAPIBaseURLForMocks } from '../../../../../../mocks/util'; +import { ReplaceReceiverApiResponse } from '../../../../v0alpha1/notifications.api.gen'; import { GROUP, VERSION } from '../../../const'; export function replaceReceiverHandler( diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/updateReceiverHandler.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/updateReceiverHandler.ts similarity index 74% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/updateReceiverHandler.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/updateReceiverHandler.ts index 645a8774364..ce8498331cd 100644 --- a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/ReceiverHandlers/updateReceiverHandler.ts +++ b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/updateReceiverHandler.ts @@ -1,7 +1,7 @@ import { HttpResponse, http } from 'msw'; -import { getAPIBaseURLForMocks } from '../../../../../mocks/util'; -import { UpdateReceiverApiResponse } from '../../../api.gen'; +import { getAPIBaseURLForMocks } from '../../../../../../mocks/util'; +import { UpdateReceiverApiResponse } from '../../../../v0alpha1/notifications.api.gen'; import { GROUP, VERSION } from '../../../const'; export function updateReceiverHandler( diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/index.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/index.ts similarity index 100% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/mocks/handlers/index.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/mocks/handlers/index.ts diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/api.gen.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/notifications.api.gen.ts similarity index 99% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/api.gen.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/notifications.api.gen.ts index d36b068dccb..66b145753a6 100644 --- a/packages/grafana-alerting/src/grafana/api/v0alpha1/api.gen.ts +++ b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/notifications.api.gen.ts @@ -613,7 +613,7 @@ const injectedRtkApi = api }), overrideExisting: false, }); -export { injectedRtkApi as alertingAPI }; +export { injectedRtkApi as notificationsAPI }; export type GetApiResourcesApiResponse = /** status 200 OK */ ApiResourceList; export type GetApiResourcesApiArg = void; export type ListReceiverApiResponse = /** status 200 OK */ ReceiverList; @@ -623,7 +623,7 @@ export type ListReceiverApiArg = { /** allowWatchBookmarks requests watch events with type "BOOKMARK". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored. */ allowWatchBookmarks?: boolean; /** The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key". - + This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications. */ continue?: string; /** A selector to restrict the list of returned objects by their fields. Defaults to everything. */ @@ -631,19 +631,19 @@ export type ListReceiverApiArg = { /** A selector to restrict the list of returned objects by their labels. Defaults to everything. */ labelSelector?: string; /** limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. - + The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned. */ limit?: number; /** resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersion?: string; /** resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersionMatch?: string; /** `sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic "Bookmark" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `"k8s.io/initial-events-end": "true"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched. - + When `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan is interpreted as "data at least as new as the provided `resourceVersion`" and the bookmark event is send when the state is synced @@ -653,7 +653,7 @@ export type ListReceiverApiArg = { when request started being processed. - `resourceVersionMatch` set to any other value or unset Invalid error is returned. - + Defaults to true if `resourceVersion=""` or `resourceVersion="0"` (for backward compatibility reasons) and to false otherwise. */ sendInitialEvents?: boolean; /** Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity. */ @@ -681,7 +681,7 @@ export type DeletecollectionReceiverApiArg = { /** If 'true', then the output is pretty printed. Defaults to 'false' unless the user-agent indicates a browser or command-line HTTP tool (curl and wget). */ pretty?: string; /** The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key". - + This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications. */ continue?: string; /** When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed */ @@ -695,7 +695,7 @@ export type DeletecollectionReceiverApiArg = { /** A selector to restrict the list of returned objects by their labels. Defaults to everything. */ labelSelector?: string; /** limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. - + The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned. */ limit?: number; /** Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the "orphan" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both. */ @@ -703,15 +703,15 @@ export type DeletecollectionReceiverApiArg = { /** Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground. */ propagationPolicy?: string; /** resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersion?: string; /** resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersionMatch?: string; /** `sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic "Bookmark" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `"k8s.io/initial-events-end": "true"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched. - + When `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan is interpreted as "data at least as new as the provided `resourceVersion`" and the bookmark event is send when the state is synced @@ -721,7 +721,7 @@ export type DeletecollectionReceiverApiArg = { when request started being processed. - `resourceVersionMatch` set to any other value or unset Invalid error is returned. - + Defaults to true if `resourceVersion=""` or `resourceVersion="0"` (for backward compatibility reasons) and to false otherwise. */ sendInitialEvents?: boolean; /** Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity. */ @@ -825,7 +825,7 @@ export type ListRoutingTreeApiArg = { /** allowWatchBookmarks requests watch events with type "BOOKMARK". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored. */ allowWatchBookmarks?: boolean; /** The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key". - + This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications. */ continue?: string; /** A selector to restrict the list of returned objects by their fields. Defaults to everything. */ @@ -833,19 +833,19 @@ export type ListRoutingTreeApiArg = { /** A selector to restrict the list of returned objects by their labels. Defaults to everything. */ labelSelector?: string; /** limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. - + The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned. */ limit?: number; /** resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersion?: string; /** resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersionMatch?: string; /** `sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic "Bookmark" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `"k8s.io/initial-events-end": "true"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched. - + When `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan is interpreted as "data at least as new as the provided `resourceVersion`" and the bookmark event is send when the state is synced @@ -855,7 +855,7 @@ export type ListRoutingTreeApiArg = { when request started being processed. - `resourceVersionMatch` set to any other value or unset Invalid error is returned. - + Defaults to true if `resourceVersion=""` or `resourceVersion="0"` (for backward compatibility reasons) and to false otherwise. */ sendInitialEvents?: boolean; /** Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity. */ @@ -883,7 +883,7 @@ export type DeletecollectionRoutingTreeApiArg = { /** If 'true', then the output is pretty printed. Defaults to 'false' unless the user-agent indicates a browser or command-line HTTP tool (curl and wget). */ pretty?: string; /** The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key". - + This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications. */ continue?: string; /** When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed */ @@ -897,7 +897,7 @@ export type DeletecollectionRoutingTreeApiArg = { /** A selector to restrict the list of returned objects by their labels. Defaults to everything. */ labelSelector?: string; /** limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. - + The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned. */ limit?: number; /** Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the "orphan" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both. */ @@ -905,15 +905,15 @@ export type DeletecollectionRoutingTreeApiArg = { /** Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground. */ propagationPolicy?: string; /** resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersion?: string; /** resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersionMatch?: string; /** `sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic "Bookmark" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `"k8s.io/initial-events-end": "true"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched. - + When `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan is interpreted as "data at least as new as the provided `resourceVersion`" and the bookmark event is send when the state is synced @@ -923,7 +923,7 @@ export type DeletecollectionRoutingTreeApiArg = { when request started being processed. - `resourceVersionMatch` set to any other value or unset Invalid error is returned. - + Defaults to true if `resourceVersion=""` or `resourceVersion="0"` (for backward compatibility reasons) and to false otherwise. */ sendInitialEvents?: boolean; /** Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity. */ @@ -1031,7 +1031,7 @@ export type ListTemplateGroupApiArg = { /** allowWatchBookmarks requests watch events with type "BOOKMARK". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored. */ allowWatchBookmarks?: boolean; /** The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key". - + This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications. */ continue?: string; /** A selector to restrict the list of returned objects by their fields. Defaults to everything. */ @@ -1039,19 +1039,19 @@ export type ListTemplateGroupApiArg = { /** A selector to restrict the list of returned objects by their labels. Defaults to everything. */ labelSelector?: string; /** limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. - + The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned. */ limit?: number; /** resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersion?: string; /** resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersionMatch?: string; /** `sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic "Bookmark" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `"k8s.io/initial-events-end": "true"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched. - + When `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan is interpreted as "data at least as new as the provided `resourceVersion`" and the bookmark event is send when the state is synced @@ -1061,7 +1061,7 @@ export type ListTemplateGroupApiArg = { when request started being processed. - `resourceVersionMatch` set to any other value or unset Invalid error is returned. - + Defaults to true if `resourceVersion=""` or `resourceVersion="0"` (for backward compatibility reasons) and to false otherwise. */ sendInitialEvents?: boolean; /** Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity. */ @@ -1089,7 +1089,7 @@ export type DeletecollectionTemplateGroupApiArg = { /** If 'true', then the output is pretty printed. Defaults to 'false' unless the user-agent indicates a browser or command-line HTTP tool (curl and wget). */ pretty?: string; /** The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key". - + This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications. */ continue?: string; /** When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed */ @@ -1103,7 +1103,7 @@ export type DeletecollectionTemplateGroupApiArg = { /** A selector to restrict the list of returned objects by their labels. Defaults to everything. */ labelSelector?: string; /** limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. - + The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned. */ limit?: number; /** Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the "orphan" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both. */ @@ -1111,15 +1111,15 @@ export type DeletecollectionTemplateGroupApiArg = { /** Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground. */ propagationPolicy?: string; /** resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersion?: string; /** resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersionMatch?: string; /** `sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic "Bookmark" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `"k8s.io/initial-events-end": "true"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched. - + When `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan is interpreted as "data at least as new as the provided `resourceVersion`" and the bookmark event is send when the state is synced @@ -1129,7 +1129,7 @@ export type DeletecollectionTemplateGroupApiArg = { when request started being processed. - `resourceVersionMatch` set to any other value or unset Invalid error is returned. - + Defaults to true if `resourceVersion=""` or `resourceVersion="0"` (for backward compatibility reasons) and to false otherwise. */ sendInitialEvents?: boolean; /** Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity. */ @@ -1241,7 +1241,7 @@ export type ListTimeIntervalApiArg = { /** allowWatchBookmarks requests watch events with type "BOOKMARK". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored. */ allowWatchBookmarks?: boolean; /** The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key". - + This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications. */ continue?: string; /** A selector to restrict the list of returned objects by their fields. Defaults to everything. */ @@ -1249,19 +1249,19 @@ export type ListTimeIntervalApiArg = { /** A selector to restrict the list of returned objects by their labels. Defaults to everything. */ labelSelector?: string; /** limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. - + The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned. */ limit?: number; /** resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersion?: string; /** resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersionMatch?: string; /** `sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic "Bookmark" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `"k8s.io/initial-events-end": "true"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched. - + When `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan is interpreted as "data at least as new as the provided `resourceVersion`" and the bookmark event is send when the state is synced @@ -1271,7 +1271,7 @@ export type ListTimeIntervalApiArg = { when request started being processed. - `resourceVersionMatch` set to any other value or unset Invalid error is returned. - + Defaults to true if `resourceVersion=""` or `resourceVersion="0"` (for backward compatibility reasons) and to false otherwise. */ sendInitialEvents?: boolean; /** Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity. */ @@ -1299,7 +1299,7 @@ export type DeletecollectionTimeIntervalApiArg = { /** If 'true', then the output is pretty printed. Defaults to 'false' unless the user-agent indicates a browser or command-line HTTP tool (curl and wget). */ pretty?: string; /** The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key". - + This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications. */ continue?: string; /** When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed */ @@ -1313,7 +1313,7 @@ export type DeletecollectionTimeIntervalApiArg = { /** A selector to restrict the list of returned objects by their labels. Defaults to everything. */ labelSelector?: string; /** limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. - + The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned. */ limit?: number; /** Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the "orphan" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both. */ @@ -1321,15 +1321,15 @@ export type DeletecollectionTimeIntervalApiArg = { /** Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground. */ propagationPolicy?: string; /** resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersion?: string; /** resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. - + Defaults to unset */ resourceVersionMatch?: string; /** `sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic "Bookmark" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `"k8s.io/initial-events-end": "true"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched. - + When `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan is interpreted as "data at least as new as the provided `resourceVersion`" and the bookmark event is send when the state is synced @@ -1339,7 +1339,7 @@ export type DeletecollectionTimeIntervalApiArg = { when request started being processed. - `resourceVersionMatch` set to any other value or unset Invalid error is returned. - + Defaults to true if `resourceVersion=""` or `resourceVersion="0"` (for backward compatibility reasons) and to false otherwise. */ sendInitialEvents?: boolean; /** Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity. */ @@ -1510,21 +1510,21 @@ export type ObjectMeta = { [key: string]: string; }; /** CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - + Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata */ creationTimestamp?: Time; /** Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only. */ deletionGracePeriodSeconds?: number; /** DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field, once the finalizers list is empty. As long as the finalizers list contains items, deletion is blocked. Once the deletionTimestamp is set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested. - + Populated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata */ deletionTimestamp?: Time; /** Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed. Finalizers may be processed and removed in any order. Order is NOT enforced because it introduces significant risk of stuck finalizers. finalizers is a shared field, any actor with permission can reorder it. If the finalizer list is processed in order, then this can lead to a situation in which the component responsible for the first finalizer in the list is waiting for a signal (field value, external system, or other) produced by a component responsible for a finalizer later in the list, resulting in a deadlock. Without enforced ordering finalizers are free to order amongst themselves and are not vulnerable to ordering changes in the list. */ finalizers?: string[]; /** GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server. - + If this field is specified and the generated name exists, the server will return a 409. - + Applied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#idempotency */ generateName?: string; /** A sequence number representing a specific generation of the desired state. Populated by the system. Read-only. */ @@ -1538,19 +1538,19 @@ export type ObjectMeta = { /** Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names */ name?: string; /** Namespace defines the space within which each name must be unique. An empty namespace is equivalent to the "default" namespace, but "default" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty. - + Must be a DNS_LABEL. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces */ namespace?: string; /** List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller. */ ownerReferences?: OwnerReference[]; /** An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources. - + Populated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency */ resourceVersion?: string; /** Deprecated: selfLink is a legacy read-only field that is no longer populated by the system. */ selfLink?: string; /** UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations. - + Populated by the system. Read-only. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids */ uid?: string; }; @@ -1602,7 +1602,7 @@ export type ReceiverStatus = { }; export type Receiver = { /** APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources */ - apiVersion?: string; + apiVersion: string; /** Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds */ kind: string; metadata: ObjectMeta; @@ -1629,7 +1629,7 @@ export type ReceiverList = { }; export type StatusCause = { /** The field of the resource that has caused this error, as named by its JSON serialization. May include dot and postfix notation for nested attributes. Arrays are zero-indexed. Fields may appear more than once in an array of causes due to fields having multiple errors. Optional. - + Examples: "name" - the field "name" on the current resource "items[0].name" - the field "name" on the first array entry in "items" */ @@ -1730,7 +1730,7 @@ export type RoutingTreeStatus = { }; export type RoutingTree = { /** APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources */ - apiVersion?: string; + apiVersion: string; /** Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds */ kind: string; metadata: ObjectMeta; @@ -1779,7 +1779,7 @@ export type TemplateGroupStatus = { }; export type TemplateGroup = { /** APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources */ - apiVersion?: string; + apiVersion: string; /** Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds */ kind: string; metadata: ObjectMeta; @@ -1840,7 +1840,7 @@ export type TimeIntervalStatus = { }; export type TimeInterval = { /** APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources */ - apiVersion?: string; + apiVersion: string; /** Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds */ kind: string; metadata: ObjectMeta; diff --git a/packages/grafana-alerting/src/grafana/api/v0alpha1/types.ts b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/types.ts similarity index 98% rename from packages/grafana-alerting/src/grafana/api/v0alpha1/types.ts rename to packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/types.ts index f31b2d442ba..1212fc74b92 100644 --- a/packages/grafana-alerting/src/grafana/api/v0alpha1/types.ts +++ b/packages/grafana-alerting/src/grafana/api/notifications/v0alpha1/types.ts @@ -3,7 +3,7 @@ */ import { MergeDeep, MergeExclusive, OverrideProperties } from 'type-fest'; -import type { ListReceiverApiResponse, Receiver, ReceiverIntegration } from './api.gen'; +import type { ListReceiverApiResponse, Receiver, ReceiverIntegration } from './notifications.api.gen'; type GenericIntegration = OverrideProperties< ReceiverIntegration, diff --git a/packages/grafana-alerting/src/grafana/api/rules/v0alpha1/api.ts b/packages/grafana-alerting/src/grafana/api/rules/v0alpha1/api.ts new file mode 100644 index 00000000000..5b45157954f --- /dev/null +++ b/packages/grafana-alerting/src/grafana/api/rules/v0alpha1/api.ts @@ -0,0 +1,18 @@ +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; + +import { getAPIBaseURL, getAPIReducerPath } from '../../util'; + +import { GROUP, VERSION } from './const'; + +const baseUrl = getAPIBaseURL(GROUP, VERSION); +const reducerPath = getAPIReducerPath(GROUP, VERSION); + +export const api = createApi({ + reducerPath, + baseQuery: fetchBaseQuery({ + // Set URL correctly so MSW can intercept requests + // https://mswjs.io/docs/runbook#rtk-query-requests-are-not-intercepted + baseUrl: new URL(baseUrl, globalThis.location.origin).href, + }), + endpoints: () => ({}), +}); diff --git a/packages/grafana-alerting/src/grafana/api/rules/v0alpha1/const.ts b/packages/grafana-alerting/src/grafana/api/rules/v0alpha1/const.ts new file mode 100644 index 00000000000..823560db3fb --- /dev/null +++ b/packages/grafana-alerting/src/grafana/api/rules/v0alpha1/const.ts @@ -0,0 +1,2 @@ +export const VERSION = 'v0alpha1' as const; +export const GROUP = 'rules.alerting.grafana.app' as const; diff --git a/public/app/api/clients/rules/v0alpha1/endpoints.gen.ts b/packages/grafana-alerting/src/grafana/api/rules/v0alpha1/rules.api.gen.ts similarity index 99% rename from public/app/api/clients/rules/v0alpha1/endpoints.gen.ts rename to packages/grafana-alerting/src/grafana/api/rules/v0alpha1/rules.api.gen.ts index 6537a5061fc..361362d5699 100644 --- a/public/app/api/clients/rules/v0alpha1/endpoints.gen.ts +++ b/packages/grafana-alerting/src/grafana/api/rules/v0alpha1/rules.api.gen.ts @@ -1,4 +1,4 @@ -import { api } from './baseAPI'; +import { api } from './api'; export const addTagTypes = ['API Discovery', 'AlertRule', 'RecordingRule'] as const; const injectedRtkApi = api .enhanceEndpoints({ @@ -313,7 +313,7 @@ const injectedRtkApi = api }), overrideExisting: false, }); -export { injectedRtkApi as generatedAPI }; +export { injectedRtkApi as rulesAPI }; export type GetApiResourcesApiResponse = /** status 200 OK */ ApiResourceList; export type GetApiResourcesApiArg = void; export type ListAlertRuleApiResponse = /** status 200 OK */ AlertRuleList; diff --git a/packages/grafana-alerting/src/grafana/contactPoints/components/ContactPointSelector/ContactPointSelector.test.scenario.ts b/packages/grafana-alerting/src/grafana/contactPoints/components/ContactPointSelector/ContactPointSelector.test.scenario.ts index 026a0cf7221..9812d5c5d28 100644 --- a/packages/grafana-alerting/src/grafana/contactPoints/components/ContactPointSelector/ContactPointSelector.test.scenario.ts +++ b/packages/grafana-alerting/src/grafana/contactPoints/components/ContactPointSelector/ContactPointSelector.test.scenario.ts @@ -5,8 +5,8 @@ import { EmailIntegrationFactory, ListReceiverApiResponseFactory, SlackIntegrationFactory, -} from '../../../api/v0alpha1/mocks/fakes/Receivers'; -import { listReceiverHandler } from '../../../api/v0alpha1/mocks/handlers/ReceiverHandlers'; +} from '../../../api/notifications/v0alpha1/mocks/fakes/Receivers'; +import { listReceiverHandler } from '../../../api/notifications/v0alpha1/mocks/handlers/ReceiverHandlers/listReceiverHandler'; export const simpleContactPointsList = ListReceiverApiResponseFactory.build({ items: [ diff --git a/packages/grafana-alerting/src/grafana/contactPoints/components/ContactPointSelector/ContactPointSelector.tsx b/packages/grafana-alerting/src/grafana/contactPoints/components/ContactPointSelector/ContactPointSelector.tsx index 674dbc76dd3..e6e8702b57e 100644 --- a/packages/grafana-alerting/src/grafana/contactPoints/components/ContactPointSelector/ContactPointSelector.tsx +++ b/packages/grafana-alerting/src/grafana/contactPoints/components/ContactPointSelector/ContactPointSelector.tsx @@ -2,7 +2,7 @@ import { chain } from 'lodash'; import { Combobox, ComboboxOption } from '@grafana/ui'; -import type { ContactPoint } from '../../../api/v0alpha1/types'; +import type { ContactPoint } from '../../../api/notifications/v0alpha1/types'; import { useListContactPoints } from '../../hooks/v0alpha1/useContactPoints'; import { getContactPointDescription } from '../../utils'; diff --git a/packages/grafana-alerting/src/grafana/contactPoints/hooks/v0alpha1/useContactPoints.tsx b/packages/grafana-alerting/src/grafana/contactPoints/hooks/v0alpha1/useContactPoints.tsx index e72577e91d0..7b6ec11f2b2 100644 --- a/packages/grafana-alerting/src/grafana/contactPoints/hooks/v0alpha1/useContactPoints.tsx +++ b/packages/grafana-alerting/src/grafana/contactPoints/hooks/v0alpha1/useContactPoints.tsx @@ -5,8 +5,12 @@ import { } from '@reduxjs/toolkit/query/react'; import { OverrideProperties } from 'type-fest'; -import { CreateReceiverApiArg, type ListReceiverApiArg, alertingAPI } from '../../../api/v0alpha1/api.gen'; -import type { ContactPoint, EnhancedListReceiverApiResponse } from '../../../api/v0alpha1/types'; +import { + CreateReceiverApiArg, + type ListReceiverApiArg, + notificationsAPI, +} from '../../../api/notifications/v0alpha1/notifications.api.gen'; +import type { ContactPoint, EnhancedListReceiverApiResponse } from '../../../api/notifications/v0alpha1/types'; // this is a workaround for the fact that the generated types are not narrow enough type ListContactPointsHookResult = TypedUseQueryHookResult< @@ -18,17 +22,17 @@ type ListContactPointsHookResult = TypedUseQueryHookResult< // Type for the options that can be passed to the hook // Based on the pattern used for mutation options in this file type ListContactPointsQueryArgs = Parameters< - typeof alertingAPI.endpoints.listReceiver.useQuery + typeof notificationsAPI.endpoints.listReceiver.useQuery >[0]; type ListContactPointsQueryOptions = Parameters< - typeof alertingAPI.endpoints.listReceiver.useQuery + typeof notificationsAPI.endpoints.listReceiver.useQuery >[1]; /** * useListContactPoints is a hook that fetches a list of contact points * - * This function wraps the alertingAPI.useListReceiverQuery with proper typing + * This function wraps the notificationsAPI.useListReceiverQuery with proper typing * to ensure that the returned ContactPoints are correctly typed in the data.items array. * * It automatically uses the configured namespace for the query. @@ -40,7 +44,7 @@ export function useListContactPoints( queryArgs: ListContactPointsQueryArgs = {}, queryOptions: ListContactPointsQueryOptions = {} ) { - return alertingAPI.useListReceiverQuery(queryArgs, queryOptions); + return notificationsAPI.useListReceiverQuery(queryArgs, queryOptions); } // type narrowing mutations requires us to define a few helper types @@ -56,17 +60,17 @@ type CreateContactPointMutation = TypedUseMutationResult< >; type UseCreateContactPointOptions = Parameters< - typeof alertingAPI.endpoints.createReceiver.useMutation + typeof notificationsAPI.endpoints.createReceiver.useMutation >[0]; /** * useCreateContactPoint is a hook that creates a new contact point with one or more integrations * - * This function wraps the alertingAPI.useCreateReceiverMutation with proper typing + * This function wraps the notificationsAPI.useCreateReceiverMutation with proper typing * to ensure that the payload supports type narrowing. */ export function useCreateContactPoint(options?: UseCreateContactPointOptions) { - const [updateFn, result] = alertingAPI.endpoints.createReceiver.useMutation(options); + const [updateFn, result] = notificationsAPI.endpoints.createReceiver.useMutation(options); const typedUpdateFn = (args: CreateContactPointArgs) => { // @ts-expect-error this one is just impossible for me to figure out diff --git a/packages/grafana-alerting/src/grafana/contactPoints/utils.test.ts b/packages/grafana-alerting/src/grafana/contactPoints/utils.test.ts index 1aa816c1ab1..547c63398f7 100644 --- a/packages/grafana-alerting/src/grafana/contactPoints/utils.test.ts +++ b/packages/grafana-alerting/src/grafana/contactPoints/utils.test.ts @@ -3,7 +3,7 @@ import { EmailIntegrationFactory, GenericIntegrationFactory, SlackIntegrationFactory, -} from '../api/v0alpha1/mocks/fakes/Receivers'; +} from '../api/notifications/v0alpha1/mocks/fakes/Receivers'; import { getContactPointDescription } from './utils'; diff --git a/packages/grafana-alerting/src/grafana/contactPoints/utils.ts b/packages/grafana-alerting/src/grafana/contactPoints/utils.ts index 390c09d3887..ac4242bd1b1 100644 --- a/packages/grafana-alerting/src/grafana/contactPoints/utils.ts +++ b/packages/grafana-alerting/src/grafana/contactPoints/utils.ts @@ -1,7 +1,7 @@ import { countBy, isEmpty } from 'lodash'; -import { Receiver } from '../api/v0alpha1/api.gen'; -import { ContactPoint } from '../api/v0alpha1/types'; +import { Receiver } from '../api/notifications/v0alpha1/notifications.api.gen'; +import { ContactPoint } from '../api/notifications/v0alpha1/types'; /** * Generates a human-readable description of a ContactPoint by summarizing its integrations. diff --git a/packages/grafana-alerting/src/grafana/matchers/types.ts b/packages/grafana-alerting/src/grafana/matchers/types.ts index 8b6da9530c4..3cf3103fd1c 100644 --- a/packages/grafana-alerting/src/grafana/matchers/types.ts +++ b/packages/grafana-alerting/src/grafana/matchers/types.ts @@ -1,4 +1,4 @@ -import { RoutingTreeMatcher } from '../api/v0alpha1/api.gen'; +import { RoutingTreeMatcher } from '../api/notifications/v0alpha1/notifications.api.gen'; export type Label = [string, string]; diff --git a/packages/grafana-alerting/src/grafana/notificationPolicies/hooks/useMatchPolicies.test.ts b/packages/grafana-alerting/src/grafana/notificationPolicies/hooks/useMatchPolicies.test.ts index 9bf6cd1c7b1..dc650db546b 100644 --- a/packages/grafana-alerting/src/grafana/notificationPolicies/hooks/useMatchPolicies.test.ts +++ b/packages/grafana-alerting/src/grafana/notificationPolicies/hooks/useMatchPolicies.test.ts @@ -1,5 +1,6 @@ -import { RoutingTree } from '../../api/v0alpha1/api.gen'; -import { LabelMatcherFactory, RouteFactory } from '../../api/v0alpha1/mocks/fakes/Routes'; +import { VERSION } from '../../api/notifications/v0alpha1/const'; +import { LabelMatcherFactory, RouteFactory } from '../../api/notifications/v0alpha1/mocks/fakes/Routes'; +import { RoutingTree } from '../../api/notifications/v0alpha1/notifications.api.gen'; import { Label } from '../../matchers/types'; import { matchInstancesToRouteTrees } from './useMatchPolicies'; @@ -15,6 +16,7 @@ describe('matchInstancesToRouteTrees', () => { const trees: RoutingTree[] = [ { kind: 'RoutingTree', + apiVersion: VERSION, metadata: { name: treeName }, spec: { defaults: { @@ -49,6 +51,7 @@ describe('matchInstancesToRouteTrees', () => { const trees: RoutingTree[] = [ { kind: 'RoutingTree', + apiVersion: VERSION, metadata: { name: treeName }, spec: { defaults: { diff --git a/packages/grafana-alerting/src/grafana/notificationPolicies/hooks/useMatchPolicies.ts b/packages/grafana-alerting/src/grafana/notificationPolicies/hooks/useMatchPolicies.ts index 1e830830701..d23efaae967 100644 --- a/packages/grafana-alerting/src/grafana/notificationPolicies/hooks/useMatchPolicies.ts +++ b/packages/grafana-alerting/src/grafana/notificationPolicies/hooks/useMatchPolicies.ts @@ -1,6 +1,6 @@ import { useCallback } from 'react'; -import { RoutingTree, alertingAPI } from '../../api/v0alpha1/api.gen'; +import { RoutingTree, notificationsAPI } from '../../api/notifications/v0alpha1/notifications.api.gen'; import { Label } from '../../matchers/types'; import { USER_DEFINED_TREE_NAME } from '../consts'; import { Route, RouteWithID } from '../types'; @@ -36,7 +36,7 @@ export type InstanceMatchResult = { * and returns an array of InstanceMatchResult objects, each containing the matched routes and matching details */ export function useMatchInstancesToRouteTrees() { - const { data, ...rest } = alertingAPI.endpoints.listRoutingTree.useQuery( + const { data, ...rest } = notificationsAPI.endpoints.listRoutingTree.useQuery( {}, { refetchOnFocus: true, diff --git a/packages/grafana-alerting/src/grafana/notificationPolicies/types.ts b/packages/grafana-alerting/src/grafana/notificationPolicies/types.ts index 04bdc4f96c5..56465daf613 100644 --- a/packages/grafana-alerting/src/grafana/notificationPolicies/types.ts +++ b/packages/grafana-alerting/src/grafana/notificationPolicies/types.ts @@ -1,6 +1,6 @@ import { OverrideProperties } from 'type-fest'; -import { RoutingTreeRoute } from '../api/v0alpha1/api.gen'; +import { RoutingTreeRoute } from '../api/notifications/v0alpha1/notifications.api.gen'; import { LabelMatcher } from '../matchers/types'; // type-narrow the route tree diff --git a/packages/grafana-alerting/src/grafana/notificationPolicies/utils.old.test.ts b/packages/grafana-alerting/src/grafana/notificationPolicies/utils.old.test.ts index 0107ac4878f..e18bd6f0038 100644 --- a/packages/grafana-alerting/src/grafana/notificationPolicies/utils.old.test.ts +++ b/packages/grafana-alerting/src/grafana/notificationPolicies/utils.old.test.ts @@ -1,7 +1,7 @@ /** * These tests were moved from Grafana core, we're keepign them around to prevent uncaught regressions */ -import { LabelMatcherFactory, RouteFactory } from '../api/v0alpha1/mocks/fakes/Routes'; +import { LabelMatcherFactory, RouteFactory } from '../api/notifications/v0alpha1/mocks/fakes/Routes'; import { Route } from './types'; import { findMatchingRoutes } from './utils'; diff --git a/packages/grafana-alerting/src/grafana/notificationPolicies/utils.test.ts b/packages/grafana-alerting/src/grafana/notificationPolicies/utils.test.ts index 2c23b899a64..e3432f26f56 100644 --- a/packages/grafana-alerting/src/grafana/notificationPolicies/utils.test.ts +++ b/packages/grafana-alerting/src/grafana/notificationPolicies/utils.test.ts @@ -1,6 +1,6 @@ import { omit } from 'lodash'; -import { LabelMatcherFactory, RouteFactory } from '../api/v0alpha1/mocks/fakes/Routes'; +import { LabelMatcherFactory, RouteFactory } from '../api/notifications/v0alpha1/mocks/fakes/Routes'; import { Label } from '../matchers/types'; import { LabelMatchDetails, matchLabels } from '../matchers/utils'; diff --git a/packages/grafana-alerting/src/grafana/notificationPolicies/utils.ts b/packages/grafana-alerting/src/grafana/notificationPolicies/utils.ts index 444244fe5fe..1fc7608a76f 100644 --- a/packages/grafana-alerting/src/grafana/notificationPolicies/utils.ts +++ b/packages/grafana-alerting/src/grafana/notificationPolicies/utils.ts @@ -1,6 +1,6 @@ import { groupBy, isArray, pick, reduce, uniqueId } from 'lodash'; -import { RoutingTree, RoutingTreeRoute } from '../api/v0alpha1/api.gen'; +import { RoutingTree, RoutingTreeRoute } from '../api/notifications/v0alpha1/notifications.api.gen'; import { Label } from '../matchers/types'; import { LabelMatchDetails, matchLabels } from '../matchers/utils'; diff --git a/packages/grafana-alerting/src/testing.ts b/packages/grafana-alerting/src/testing.ts index f9c6426fe9c..e8743403c3e 100644 --- a/packages/grafana-alerting/src/testing.ts +++ b/packages/grafana-alerting/src/testing.ts @@ -1,10 +1,10 @@ // export MSW handlers for testing -export * from './grafana/api/v0alpha1/mocks/handlers'; +export * from './grafana/api/notifications/v0alpha1/mocks/handlers'; // export mocks and factories -export * from './grafana/api/v0alpha1/mocks/fakes/common'; -export * from './grafana/api/v0alpha1/mocks/fakes/Receivers'; -export * from './grafana/api/v0alpha1/mocks/fakes/Routes'; +export * from './grafana/api/notifications/v0alpha1/mocks/fakes/common'; +export * from './grafana/api/notifications/v0alpha1/mocks/fakes/Receivers'; +export * from './grafana/api/notifications/v0alpha1/mocks/fakes/Routes'; // scenarios export * from './grafana/contactPoints/components/ContactPointSelector/ContactPointSelector.test.scenario'; diff --git a/packages/grafana-alerting/src/unstable.ts b/packages/grafana-alerting/src/unstable.ts index 1b5fd591ee4..1aa47bae5d5 100644 --- a/packages/grafana-alerting/src/unstable.ts +++ b/packages/grafana-alerting/src/unstable.ts @@ -3,7 +3,7 @@ */ // Contact Points -export * from './grafana/api/v0alpha1/types'; +export * from './grafana/api/notifications/v0alpha1/types'; export { useListContactPoints } from './grafana/contactPoints/hooks/v0alpha1/useContactPoints'; export { ContactPointSelector } from './grafana/contactPoints/components/ContactPointSelector/ContactPointSelector'; export { getContactPointDescription } from './grafana/contactPoints/utils'; @@ -36,5 +36,6 @@ export { AlertLabels, type AlertLabelsProps } from './grafana/rules/components/l export { type LabelMatcher, type Label } from './grafana/matchers/types'; export { matchLabelsSet, matchLabels, isLabelMatch, type LabelMatchDetails } from './grafana/matchers/utils'; -// Low-level API hooks -export { alertingAPI } from './grafana/api/v0alpha1/api.gen'; +// API endpoints +export { notificationsAPI as notificationsAPIv0alpha1 } from './grafana/api/notifications/v0alpha1/notifications.api.gen'; +export { rulesAPI as rulesAPIv0alpha1 } from './grafana/api/rules/v0alpha1/rules.api.gen'; diff --git a/packages/grafana-alerting/tests/provider.tsx b/packages/grafana-alerting/tests/provider.tsx index 4331f7e6b8a..b3caa8679b2 100644 --- a/packages/grafana-alerting/tests/provider.tsx +++ b/packages/grafana-alerting/tests/provider.tsx @@ -2,13 +2,13 @@ import { configureStore } from '@reduxjs/toolkit'; import { useEffect } from 'react'; import { Provider } from 'react-redux'; -import { alertingAPI } from '../src/unstable'; +import { notificationsAPIv0alpha1 } from '../src/unstable'; // create an empty store export const store = configureStore({ - middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(alertingAPI.middleware), + middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(notificationsAPIv0alpha1.middleware), reducer: { - [alertingAPI.reducerPath]: alertingAPI.reducer, + [notificationsAPIv0alpha1.reducerPath]: notificationsAPIv0alpha1.reducer, }, }); @@ -35,7 +35,7 @@ export const getDefaultWrapper = () => { function useResetQueryCacheAfterUnmount() { useEffect(() => { return () => { - store.dispatch(alertingAPI.util.resetApiState()); + store.dispatch(notificationsAPIv0alpha1.util.resetApiState()); }; }, []); } diff --git a/packages/grafana-data/package.json b/packages/grafana-data/package.json index 0f96258a426..950d5122932 100644 --- a/packages/grafana-data/package.json +++ b/packages/grafana-data/package.json @@ -64,7 +64,7 @@ "@types/systemjs": "6.15.3", "d3-interpolate": "3.0.1", "date-fns": "4.1.0", - "dompurify": "3.2.6", + "dompurify": "3.3.0", "eventemitter3": "5.0.1", "fast_array_intersect": "1.1.0", "history": "4.10.1", @@ -84,7 +84,9 @@ "xss": "^1.0.14" }, "devDependencies": { + "@grafana/scenes": "6.38.0", "@rollup/plugin-node-resolve": "16.0.1", + "@testing-library/react": "16.3.0", "@types/history": "4.7.11", "@types/lodash": "4.17.20", "@types/node": "22.17.0", diff --git a/packages/grafana-data/src/dataframe/processDataFrame.test.ts b/packages/grafana-data/src/dataframe/processDataFrame.test.ts index 72b3041d87c..5c7593e91c0 100644 --- a/packages/grafana-data/src/dataframe/processDataFrame.test.ts +++ b/packages/grafana-data/src/dataframe/processDataFrame.test.ts @@ -365,6 +365,7 @@ describe('sorted DataFrame', () => { { name: 'fourth', type: FieldType.time, values: [1, 2, 3], nanos: [10, 20, 30] }, ], }); + it('Should sort numbers', () => { const sorted = sortDataFrame(frame, 0, true); expect(sorted.length).toEqual(3); @@ -386,6 +387,17 @@ describe('sorted DataFrame', () => { expect(sorted.fields[3].values).toEqual([3, 2, 1]); expect(sorted.fields[3].nanos).toEqual([30, 20, 10]); }); + + it('Should handle arrays with empty values correctly', () => { + // Create a sparse array with empty slots (undefined values) + const values = ['502', '502', , '500', '500', '200', '404']; // Note the empty slot at index 2 + const frame = toDataFrame({ + fields: [{ name: 'status', type: FieldType.string, values }], + }); + const sorted = sortDataFrame(frame, 0, false); + + expect(sorted.fields[0].values).toEqual(['200', '404', '500', '500', '502', '502', undefined]); + }); }); describe('sorted DataFrame by nanos', () => { diff --git a/packages/grafana-data/src/dataframe/processDataFrame.ts b/packages/grafana-data/src/dataframe/processDataFrame.ts index 4a028b6b4fd..14621547725 100644 --- a/packages/grafana-data/src/dataframe/processDataFrame.ts +++ b/packages/grafana-data/src/dataframe/processDataFrame.ts @@ -429,18 +429,20 @@ export function sortDataFrame(data: DataFrame, sortIndex?: number, reverse = fal return { ...data, - fields: data.fields.map((f) => { - const newF = { - ...f, - values: f.values.map((v, i) => f.values[index[i]]), + fields: data.fields.map((field) => { + const newValues = Array.from({ length: field.values.length }, (_, i) => field.values[index[i]]); + + const newField = { + ...field, + values: newValues, }; // only add .nanos if it exists - const { nanos } = f; + const { nanos } = field; if (nanos !== undefined) { - newF.nanos = nanos.map((n, i) => nanos[index[i]]); + newField.nanos = Array.from({ length: nanos.length }, (_, i) => nanos[index[i]]); } - return newF; + return newField; }), }; } diff --git a/packages/grafana-data/src/field/displayProcessor.test.ts b/packages/grafana-data/src/field/displayProcessor.test.ts index 2cd13b48b58..b47ca53b17e 100644 --- a/packages/grafana-data/src/field/displayProcessor.test.ts +++ b/packages/grafana-data/src/field/displayProcessor.test.ts @@ -423,6 +423,11 @@ describe('Format value', () => { const processor = getDisplayProcessorFromConfig({ decimals: 5 }, FieldType.number); expect(processor(35, 2).text).toEqual('35.00000'); }); + + it('does not attempt to coerce non-numeric strings back to numbers', () => { + const processor = getDisplayProcessorFromConfig({ unit: 'dthms' }, FieldType.number); + expect(processor(35, 2).text).toEqual('00:00:35'); // we're checking that this isn't NaN. + }); }); }); diff --git a/packages/grafana-data/src/field/displayProcessor.ts b/packages/grafana-data/src/field/displayProcessor.ts index a9f0a7c2927..28c17bb604d 100644 --- a/packages/grafana-data/src/field/displayProcessor.ts +++ b/packages/grafana-data/src/field/displayProcessor.ts @@ -49,7 +49,7 @@ export function getDisplayProcessor(options?: DisplayProcessorOptions): DisplayP const { palette } = options.theme.visualization; let unit = config.unit; - let hasDateUnit = unit && (timeFormats[unit] || unit.startsWith('time:')); + let hasDateUnit = Boolean(unit && (timeFormats[unit] || unit.startsWith('time:'))); let showMs = false; if (field.type === FieldType.time && !hasDateUnit) { @@ -152,7 +152,11 @@ export function getDisplayProcessor(options?: DisplayProcessorOptions): DisplayP // this is needed because we may have determined the minimum determined `adjacentDecimals` for y tick increments based on // e.g. 'seconds' field unit (0.15s, 0.20s, 0.25s), but then formatFunc decided to return milli or nanos (150, 200, 250) // so we end up with excess precision: 150.00, 200.00, 250.00 - v.text = +v.text + ''; + // #73795 - some units, like duration formats, return text which cannot be coerced back into a number safely at this point. + const asNum = +v.text; + if (!Number.isNaN(asNum)) { + v.text = asNum + ''; + } } else { v = formatFunc(numeric, config.decimals, null, options.timeZone, showMs); } diff --git a/packages/grafana-data/src/field/fieldColor.test.ts b/packages/grafana-data/src/field/fieldColor.test.ts index bcfa9648df4..3463549c3c4 100644 --- a/packages/grafana-data/src/field/fieldColor.test.ts +++ b/packages/grafana-data/src/field/fieldColor.test.ts @@ -47,7 +47,7 @@ describe('fieldColorModeRegistry', () => { it('Palette classic with series index 1', () => { const calcFn = getCalculator({ mode: FieldColorModeId.PaletteClassic, seriesIndex: 1, name: 'series2' }); - expect(calcFn(70, 0, undefined)).toEqual('#FADE2A'); + expect(calcFn(70, 0, undefined)).toEqual('#F2CC0C'); }); it('Palette uses name', () => { diff --git a/packages/grafana-data/src/field/fieldDisplay.test.ts b/packages/grafana-data/src/field/fieldDisplay.test.ts index d4419310bad..718c0e54430 100644 --- a/packages/grafana-data/src/field/fieldDisplay.test.ts +++ b/packages/grafana-data/src/field/fieldDisplay.test.ts @@ -388,7 +388,7 @@ describe('FieldDisplay', () => { const result = getFieldDisplayValues(options); expect(result[0].display.color).toEqual('#73BF69'); - expect(result[1].display.color).toEqual('#FADE2A'); + expect(result[1].display.color).toEqual('#F2CC0C'); }); it('When showing all values lookup color via an override', () => { @@ -435,7 +435,7 @@ describe('FieldDisplay', () => { const result = getFieldDisplayValues(options); expect(result[0].display.color).toEqual('#AAA'); - expect(result[1].display.color).toEqual('#FADE2A'); + expect(result[1].display.color).toEqual('#F2CC0C'); }); it('Multiple other string fields', () => { diff --git a/packages/grafana-data/src/field/fieldOverrides.ts b/packages/grafana-data/src/field/fieldOverrides.ts index c3a64d496ae..2aac477cd2b 100644 --- a/packages/grafana-data/src/field/fieldOverrides.ts +++ b/packages/grafana-data/src/field/fieldOverrides.ts @@ -257,6 +257,12 @@ function calculateRange( globalRange: NumericRange | undefined, data: DataFrame[] ): { range?: { min?: number | null; max?: number | null; delta: number }; newGlobalRange: NumericRange | undefined } { + // If range is defined with min/max, use it + if (isNumber(config.min) && isNumber(config.max)) { + const range = { min: config.min, max: config.max, delta: config.max - config.min }; + return { range, newGlobalRange: globalRange ?? range }; + } + // Only calculate ranges when the field is a number and one of min/max is set to auto. if (field.type !== FieldType.number || (isNumber(config.min) && isNumber(config.max))) { return { newGlobalRange: globalRange }; diff --git a/packages/grafana-data/src/index.ts b/packages/grafana-data/src/index.ts index 269dba30b62..e058612a3c7 100644 --- a/packages/grafana-data/src/index.ts +++ b/packages/grafana-data/src/index.ts @@ -533,6 +533,7 @@ export { type QueryVariableModel, type TextBoxVariableModel, type ConstantVariableModel, + type SwitchVariableModel, type VariableWithMultiSupport, type VariableWithOptions, type DashboardProps, diff --git a/packages/grafana-data/src/internal/index.ts b/packages/grafana-data/src/internal/index.ts index 8fcb8da4e0d..e2dab753baa 100644 --- a/packages/grafana-data/src/internal/index.ts +++ b/packages/grafana-data/src/internal/index.ts @@ -93,6 +93,7 @@ export { DataTransformerID } from '../transformations/transformers/ids'; export { mergeTransformer } from '../transformations/transformers/merge'; export { getThemeById } from '../themes/registry'; +export * as experimentalThemeDefinitions from '../themes/themeDefinitions'; export { GrafanaEdition } from '../types/config'; export { SIPrefix } from '../valueFormats/symbolFormatters'; diff --git a/packages/grafana-data/src/panel/getPanelOptionsWithDefaults.test.ts b/packages/grafana-data/src/panel/getPanelOptionsWithDefaults.test.ts index f155696053d..7c182b53837 100644 --- a/packages/grafana-data/src/panel/getPanelOptionsWithDefaults.test.ts +++ b/packages/grafana-data/src/panel/getPanelOptionsWithDefaults.test.ts @@ -1,18 +1,11 @@ -import { - ConfigOverrideRule, - FieldColorModeId, - FieldConfig, - FieldConfigProperty, - FieldConfigSource, - PanelPlugin, - standardEditorsRegistry, - standardFieldConfigEditorRegistry, - StandardOptionConfig, - ThresholdsMode, -} from '@grafana/data'; - import { getPanelPlugin, mockStandardFieldConfigOptions } from '../../test'; +import { standardEditorsRegistry, standardFieldConfigEditorRegistry } from '../field/standardFieldConfigEditorRegistry'; +import { FieldConfig } from '../types/dataFrame'; +import { FieldColorModeId } from '../types/fieldColor'; +import { ConfigOverrideRule, FieldConfigProperty, FieldConfigSource } from '../types/fieldOverrides'; +import { ThresholdsMode } from '../types/thresholds'; +import { PanelPlugin, StandardOptionConfig } from './PanelPlugin'; import { getPanelOptionsWithDefaults, restoreCustomOverrideRules } from './getPanelOptionsWithDefaults'; standardFieldConfigEditorRegistry.setInit(() => mockStandardFieldConfigOptions()); diff --git a/packages/grafana-data/src/themes/createVisualizationColors.ts b/packages/grafana-data/src/themes/createVisualizationColors.ts index 80238d2a655..fca963c9c07 100644 --- a/packages/grafana-data/src/themes/createVisualizationColors.ts +++ b/packages/grafana-data/src/themes/createVisualizationColors.ts @@ -261,7 +261,7 @@ function getClassicPalette() { return [ 'green', - 'yellow', + 'semi-dark-yellow', 'blue', 'orange', 'red', diff --git a/packages/grafana-data/src/types/config.ts b/packages/grafana-data/src/types/config.ts index 29079be8bd8..92991080976 100644 --- a/packages/grafana-data/src/types/config.ts +++ b/packages/grafana-data/src/types/config.ts @@ -1,3 +1,5 @@ +import type { InternalLoggerLevel } from '@grafana/faro-core'; + import { SystemDateFormatSettings } from '../datetime/formats'; import { MapLayerOptions } from '../geo/layer'; @@ -93,11 +95,14 @@ export interface LicenseInfo { export interface GrafanaJavascriptAgentConfig { enabled: boolean; customEndpoint: string; - errorInstrumentalizationEnabled: boolean; - consoleInstrumentalizationEnabled: boolean; - webVitalsInstrumentalizationEnabled: boolean; - tracingInstrumentalizationEnabled: boolean; apiKey: string; + internalLoggerLevel: InternalLoggerLevel; + + consoleInstrumentalizationEnabled: boolean; + performanceInstrumentalizationEnabled: boolean; + cspInstrumentalizationEnabled: boolean; + tracingInstrumentalizationEnabled: boolean; + webVitalsAttribution: boolean; } export interface UnifiedAlertingStateHistoryConfig { @@ -316,6 +321,7 @@ export interface GrafanaConfig { quickRanges?: TimeOption[]; pluginRestrictedAPIsAllowList?: Record; pluginRestrictedAPIsBlockList?: Record; + openFeatureContext: Record; // The namespace to use for kubernetes apiserver requests namespace: string; diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index 632a507db07..9a21f7b4cbf 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -299,6 +299,14 @@ export interface FeatureToggles { */ kubernetesCorrelations?: boolean; /** + * Adds support for Kubernetes logs drilldown + */ + kubernetesLogsDrilldown?: boolean; + /** + * Adds support for Kubernetes querycaching + */ + kubernetesQueryCaching?: boolean; + /** * Disable schema validation for dashboards/v1 */ dashboardDisableSchemaValidationV1?: boolean; @@ -396,6 +404,10 @@ export interface FeatureToggles { */ dashboardUndoRedo?: boolean; /** + * Enables unlimited dashboard panel grouping + */ + unlimitedLayoutsNesting?: boolean; + /** * Enables use of the `systemPanelFilterVar` variable to filter panels in a dashboard */ panelFilterVariable?: boolean; @@ -488,11 +500,6 @@ export interface FeatureToggles { */ useMultipleScopeNodesEndpoint?: boolean; /** - * In-development feature that will allow injection of labels into prometheus queries. - * @default true - */ - promQLScope?: boolean; - /** * In-development feature that will allow injection of labels into loki queries. * @default false */ @@ -614,6 +621,10 @@ export interface FeatureToggles { */ zanzana?: boolean; /** + * Use openFGA as main authorization engine and disable legacy RBAC clietn. + */ + zanzanaNoLegacyClient?: boolean; + /** * Enables reload of dashboards on scopes, time range and variables changes */ reloadDashboardsOnParamsChange?: boolean; @@ -1031,6 +1042,10 @@ export interface FeatureToggles { */ kubernetesAuthzResourcePermissionApis?: boolean; /** + * Enable sync of Zanzana authorization store on AuthZ CRD mutations + */ + kubernetesAuthzZanzanaSync?: boolean; + /** * Enables create, delete, and update mutations for resources owned by IAM identity */ kubernetesAuthnMutation?: boolean; @@ -1094,6 +1109,11 @@ export interface FeatureToggles { */ enableAppChromeExtensions?: boolean; /** + * Set this to true to enable all dashboard empty state extensions registered by plugins. + * @default false + */ + enableDashboardEmptyExtensions?: boolean; + /** * Enables use of app platform API for folders * @default false */ @@ -1113,11 +1133,6 @@ export interface FeatureToggles { */ alertingNotificationHistory?: boolean; /** - * Allows decoupled core plugins to load from the Grafana CDN - * @default false - */ - pluginAssetProvider?: boolean; - /** * Enable dual reader for unified storage search */ unifiedStorageSearchDualReaderEnabled?: boolean; @@ -1163,6 +1178,10 @@ export interface FeatureToggles { */ teamFolders?: boolean; /** + * Enables Pathfinder app + */ + grafanaPathfinder?: boolean; + /** * Enables the alerting triage feature * @default false */ @@ -1193,11 +1212,6 @@ export interface FeatureToggles { */ tempoSearchBackendMigration?: boolean; /** - * Filter out bots from collecting data for Frontend Observability - * @default false - */ - filterOutBotsFromFrontendLogs?: boolean; - /** * Prioritize loading plugins from the CDN before other sources * @default false */ @@ -1207,4 +1221,24 @@ export interface FeatureToggles { * @default false */ cdnPluginsUrls?: boolean; + /** + * Enable new gauge visualization + * @default false + */ + newGauge?: boolean; + /** + * Restrict PanelChrome contents with overflow: hidden; + * @default true + */ + preventPanelChromeOverflow?: boolean; + /** + * Load plugins during store service startup instead of wire provider + * @default false + */ + pluginStoreServiceLoading?: boolean; + /** + * When storing dashboard and folder resource permissions, only store action sets and not the full list of underlying permission + * @default true + */ + onlyStoreActionSets?: boolean; } diff --git a/packages/grafana-data/src/types/icon.ts b/packages/grafana-data/src/types/icon.ts index b59fdeca75a..57e086c1ba2 100644 --- a/packages/grafana-data/src/types/icon.ts +++ b/packages/grafana-data/src/types/icon.ts @@ -28,6 +28,7 @@ export const availableIconsIndex = { apps: true, 'archive-alt': true, arrow: true, + 'arrow-circle-right': true, 'arrow-down': true, 'arrow-from-right': true, 'arrow-left': true, @@ -69,7 +70,10 @@ export const availableIconsIndex = { 'clipboard-alt': true, 'clock-nine': true, cloud: true, + 'cloud-database-tree': true, 'cloud-download': true, + 'cloud-exclamation': true, + 'cloud-info': true, 'cloud-provider': true, 'cloud-upload': true, 'code-branch': true, @@ -177,6 +181,7 @@ export const availableIconsIndex = { 'key-skeleton-alt': true, keyboard: true, kubernetes: true, + 'laptop-cloud': true, 'layer-group': true, 'layers-alt': true, layers: true, @@ -280,6 +285,7 @@ export const availableIconsIndex = { 'ai-sparkle': true, bitbucket: true, git: true, + 'tachometer-fast': true, }; export type IconName = keyof typeof availableIconsIndex; diff --git a/packages/grafana-data/src/types/pluginExtensions.ts b/packages/grafana-data/src/types/pluginExtensions.ts index 4707c9123dd..47e130afcce 100644 --- a/packages/grafana-data/src/types/pluginExtensions.ts +++ b/packages/grafana-data/src/types/pluginExtensions.ts @@ -181,6 +181,15 @@ export type PluginExtensionEventHelpers = { * Closes the extension sidebar. */ closeSidebar: () => void; + /** + * @internal + * Toggles the extension sidebar with the registered component. + * If the sidebar is open with the same component, it will be closed. + * If the sidebar is closed or open with a different component, it will be opened with the specified component. + * @param componentTitle The title of the component to be toggled in the sidebar. + * @param props The props to be passed to the component. + */ + toggleSidebar: (componentTitle: string, props?: Record) => void; }; // Extension Points & Contexts @@ -195,6 +204,7 @@ export enum PluginExtensionPoints { AlertingRuleQueryEditor = 'grafana/alerting/alertingrule/queryeditor', CommandPalette = 'grafana/commandpalette/action', DashboardPanelMenu = 'grafana/dashboard/panel/menu', + DashboardEmpty = 'grafana/dashboard/empty', DataSourceConfig = 'grafana/datasources/config', DataSourceConfigActions = 'grafana/datasources/config/actions', DataSourceConfigErrorStatus = 'grafana/datasources/config/error-status', diff --git a/packages/grafana-data/src/types/templateVars.ts b/packages/grafana-data/src/types/templateVars.ts index 347b01b10d1..e6feea4dd3f 100644 --- a/packages/grafana-data/src/types/templateVars.ts +++ b/packages/grafana-data/src/types/templateVars.ts @@ -23,7 +23,8 @@ export type TypedVariableModel = | UserVariableModel | OrgVariableModel | DashboardVariableModel - | SnapshotVariableModel; + | SnapshotVariableModel + | SwitchVariableModel; export enum VariableRefresh { never, // removed from the UI @@ -130,6 +131,10 @@ export interface ConstantVariableModel extends VariableWithOptions { type: 'constant'; } +export interface SwitchVariableModel extends VariableWithOptions { + type: 'switch'; +} + export interface VariableWithMultiSupport extends VariableWithOptions { multi: boolean; includeAll: boolean; diff --git a/packages/grafana-data/src/utils/throwIfAngular.test.ts b/packages/grafana-data/src/utils/throwIfAngular.test.ts index 6e3bf3c0f83..8cdbae71cd9 100644 --- a/packages/grafana-data/src/utils/throwIfAngular.test.ts +++ b/packages/grafana-data/src/utils/throwIfAngular.test.ts @@ -1,4 +1,5 @@ -import { PanelPlugin, PluginMeta, PluginType } from '@grafana/data'; +import { PanelPlugin } from '../panel/PanelPlugin'; +import { PluginMeta, PluginType } from '../types/plugin'; import { throwIfAngular } from './throwIfAngular'; diff --git a/packages/grafana-e2e-selectors/package.json b/packages/grafana-e2e-selectors/package.json index 1b6dde9a254..008f555cc3b 100644 --- a/packages/grafana-e2e-selectors/package.json +++ b/packages/grafana-e2e-selectors/package.json @@ -41,7 +41,7 @@ "devDependencies": { "@rollup/plugin-node-resolve": "16.0.1", "@types/node": "22.17.0", - "@types/semver": "7.7.0", + "@types/semver": "7.7.1", "esbuild": "0.25.8", "rimraf": "6.0.1", "rollup": "^4.22.4", diff --git a/packages/grafana-e2e-selectors/src/selectors/components.ts b/packages/grafana-e2e-selectors/src/selectors/components.ts index 05b0f553578..3ee3b293200 100644 --- a/packages/grafana-e2e-selectors/src/selectors/components.ts +++ b/packages/grafana-e2e-selectors/src/selectors/components.ts @@ -33,6 +33,9 @@ export const versionedComponents = { ungroup: { '12.1.0': 'data-testid CanvasGridAddActions ungroup', }, + ungroupRows: { + '12.1.0': 'data-testid CanvasGridAddActions ungroup-rows', + }, addRow: { '12.1.0': 'data-testid CanvasGridAddActions add-row', }, @@ -670,6 +673,11 @@ export const versionedComponents = { '12.1.0': 'data-testid fill screen switch', }, }, + TabsLayout: { + titleInput: { + '12.2.0': 'data-testid tab title input', + }, + }, }, }, PanelInspector: { diff --git a/packages/grafana-e2e-selectors/src/selectors/pages.ts b/packages/grafana-e2e-selectors/src/selectors/pages.ts index 581a8294d10..7716ccc1436 100644 --- a/packages/grafana-e2e-selectors/src/selectors/pages.ts +++ b/packages/grafana-e2e-selectors/src/selectors/pages.ts @@ -500,24 +500,9 @@ export const versionedPages = { queryOptionsQueryInput: { '10.4.0': 'data-testid Variable editor Form Default Variable Query Editor textarea', }, - queryOptionsStaticOptionsRow: { - [MIN_GRAFANA_VERSION]: 'Variable editor Form Query Static Options row', - }, queryOptionsStaticOptionsToggle: { [MIN_GRAFANA_VERSION]: 'Variable editor Form Query Static Options toggle', }, - queryOptionsStaticOptionsLabelInput: { - [MIN_GRAFANA_VERSION]: 'Variable editor Form Query Static Options Label input', - }, - queryOptionsStaticOptionsValueInput: { - [MIN_GRAFANA_VERSION]: 'Variable editor Form Query Static Options Value input', - }, - queryOptionsStaticOptionsDeleteButton: { - [MIN_GRAFANA_VERSION]: 'Variable editor Form Query Static Options Delete button', - }, - queryOptionsStaticOptionsAddButton: { - [MIN_GRAFANA_VERSION]: 'Variable editor Form Query Static Options Add button', - }, queryOptionsStaticOptionsOrderDropdown: { [MIN_GRAFANA_VERSION]: 'Variable editor Form Query Static Options Order dropdown', }, @@ -559,6 +544,12 @@ export const versionedPages = { customValueInput: { [MIN_GRAFANA_VERSION]: 'data-testid custom-variable-input', }, + optionsOpenButton: { + [MIN_GRAFANA_VERSION]: 'data-testid custom-variable-options-open-button', + }, + closeButton: { + [MIN_GRAFANA_VERSION]: 'data-testid custom-variable-close-button', + }, }, IntervalVariable: { intervalsValueInput: { @@ -596,6 +587,37 @@ export const versionedPages = { '11.0.0': 'data-testid ad-hoc filters variable mode toggle', }, }, + SwitchVariable: { + valuePairTypeSelect: { + ['12.3.0']: 'data-testid switch variable value pair type select', + }, + enabledValueInput: { + ['12.3.0']: 'data-testid switch variable enabled value input', + }, + disabledValueInput: { + ['12.3.0']: 'data-testid switch variable disabled value input', + }, + }, + StaticOptionsEditor: { + addButton: { + [MIN_GRAFANA_VERSION]: 'data-testid Variable editor Form Static Options Add button', + }, + labelInput: { + [MIN_GRAFANA_VERSION]: 'data-testid Variable editor Form Static Options Label input', + }, + valueInput: { + [MIN_GRAFANA_VERSION]: 'data-testid Variable editor Form Static Options Value input', + }, + moveButton: { + [MIN_GRAFANA_VERSION]: 'data-testid Variable editor Form Static Options Move button', + }, + deleteButton: { + [MIN_GRAFANA_VERSION]: 'data-testid Variable editor Form Static Options Delete button', + }, + row: { + [MIN_GRAFANA_VERSION]: 'data-testid Variable editor Form Static Options Row', + }, + }, }, }, }, diff --git a/packages/grafana-eslint-rules/rules/no-unreduced-motion.cjs b/packages/grafana-eslint-rules/rules/no-unreduced-motion.cjs index a8a691c9ed7..821b31e13d3 100644 --- a/packages/grafana-eslint-rules/rules/no-unreduced-motion.cjs +++ b/packages/grafana-eslint-rules/rules/no-unreduced-motion.cjs @@ -1,4 +1,5 @@ // @ts-check +/** @typedef {import('@typescript-eslint/utils/ts-eslint').RuleContext} RuleContext */ const { ESLintUtils, AST_NODE_TYPES } = require('@typescript-eslint/utils'); const createRule = ESLintUtils.RuleCreator( @@ -6,9 +7,38 @@ const createRule = ESLintUtils.RuleCreator( ); const restrictedProperties = ['animation', 'transition']; +const excludedProperties = ['transitionProperty']; const isRestrictedProperty = (/** @type string */ propertyName) => { - return restrictedProperties.some((prop) => propertyName.startsWith(prop)); + return ( + !excludedProperties.includes(propertyName) && restrictedProperties.some((prop) => propertyName.startsWith(prop)) + ); +}; + +/** + * @param {import('@typescript-eslint/utils').TSESTree.ObjectExpression} obj + * @param {import('@typescript-eslint/utils/ts-eslint').RuleContext} context + */ +const checkProperties = (obj, context) => { + for (const property of obj.properties) { + if (property.type !== AST_NODE_TYPES.Property) { + continue; + } + + if ( + property.value.type === AST_NODE_TYPES.ObjectExpression && + property.key.type !== AST_NODE_TYPES.CallExpression + ) { + checkProperties(property.value, context); + } + + if (property.key.type === AST_NODE_TYPES.Identifier && isRestrictedProperty(property.key.name)) { + context.report({ + node: property, + messageId: 'noUnreducedMotion', + }); + } + } }; const rule = createRule({ @@ -29,18 +59,7 @@ const rule = createRule({ for (const cssObject of cssObjects) { if (cssObject?.type === AST_NODE_TYPES.ObjectExpression) { - for (const property of cssObject.properties) { - if ( - property.type === AST_NODE_TYPES.Property && - property.key.type === AST_NODE_TYPES.Identifier && - isRestrictedProperty(property.key.name) - ) { - context.report({ - node: property, - messageId: 'noUnreducedMotion', - }); - } - } + checkProperties(cssObject, context); } } } diff --git a/packages/grafana-eslint-rules/tests/no-unreduced-motion.test.js b/packages/grafana-eslint-rules/tests/no-unreduced-motion.test.js new file mode 100644 index 00000000000..2e4244c0ad4 --- /dev/null +++ b/packages/grafana-eslint-rules/tests/no-unreduced-motion.test.js @@ -0,0 +1,65 @@ +import { RuleTester } from 'eslint'; + +import noUnreducedMotion from '../rules/no-unreduced-motion.cjs'; + +RuleTester.setDefaultConfig({ + languageOptions: { + ecmaVersion: 2018, + sourceType: 'module', + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, + }, +}); + +const ruleTester = new RuleTester(); + +ruleTester.run('eslint no-unreduced-motion', noUnreducedMotion, { + valid: [ + { + name: 'basic case with handled preference', + code: ` +css({ + [theme.transitions.handleMotion('no-preference')]: { + transition: 'opacity 0.5s ease-in-out', + }, +}) +`, + }, + { + name: 'basic case ignored property', + code: ` +css({ + transitionProperty: 'opacity', +}) +`, + }, + ], + invalid: [ + { + name: 'basic case', + code: ` +css({ + transition: 'opacity 0.5s ease-in-out', +}) +`, + errors: 1, + }, + { + name: 'invalid usage in nested property or pseudo element', + code: ` +css({ + foo: { + transition: 'opacity 0.5s ease-in-out', + }, + '&:before': { + transition: 'opacity 0.5s ease-in-out', + }, +}) + `, + errors: 2, + }, + ], +}); diff --git a/packages/grafana-flamegraph/package.json b/packages/grafana-flamegraph/package.json index b7279e5244b..3185d65d5c1 100644 --- a/packages/grafana-flamegraph/package.json +++ b/packages/grafana-flamegraph/package.json @@ -83,7 +83,7 @@ "typescript": "5.9.2" }, "peerDependencies": { - "@grafana/assistant": "^0.0.17 || ^0.0.18", + "@grafana/assistant": "^0.1.0", "react": "^18.0.0", "react-dom": "^18.0.0" } diff --git a/packages/grafana-flamegraph/src/FlameGraphContainer.test.tsx b/packages/grafana-flamegraph/src/FlameGraphContainer.test.tsx index e8786e42466..10e2eeb8d03 100644 --- a/packages/grafana-flamegraph/src/FlameGraphContainer.test.tsx +++ b/packages/grafana-flamegraph/src/FlameGraphContainer.test.tsx @@ -10,7 +10,10 @@ import FlameGraphContainer, { labelSearch } from './FlameGraphContainer'; import { MIN_WIDTH_TO_SHOW_BOTH_TOPTABLE_AND_FLAMEGRAPH } from './constants'; jest.mock('@grafana/assistant', () => ({ - useAssistant: jest.fn(() => [false, null]), // [isAvailable, openAssistant] + useAssistant: jest.fn().mockReturnValue({ + isAvailable: false, + openAssistant: undefined, + }), createAssistantContextItem: jest.fn(), OpenAssistantButton: () =>
OpenAssistantButton
, })); diff --git a/packages/grafana-flamegraph/src/FlameGraphHeader.test.tsx b/packages/grafana-flamegraph/src/FlameGraphHeader.test.tsx index 59be0ed931e..ce00964a8d5 100644 --- a/packages/grafana-flamegraph/src/FlameGraphHeader.test.tsx +++ b/packages/grafana-flamegraph/src/FlameGraphHeader.test.tsx @@ -8,7 +8,10 @@ import FlameGraphHeader from './FlameGraphHeader'; import { ColorScheme, SelectedView } from './types'; jest.mock('@grafana/assistant', () => ({ - useAssistant: jest.fn(() => [false, null]), // [isAvailable, openAssistant] + useAssistant: jest.fn().mockReturnValue({ + isAvailable: false, + openAssistant: undefined, + }), createAssistantContextItem: jest.fn(), OpenAssistantButton: () =>
OpenAssistantButton
, })); diff --git a/packages/grafana-i18n/package.json b/packages/grafana-i18n/package.json index 365211e2faa..ba8d2311acf 100644 --- a/packages/grafana-i18n/package.json +++ b/packages/grafana-i18n/package.json @@ -28,6 +28,7 @@ "require": "./src/internal/index.ts" }, "./eslint-plugin": { + "types": "./src/eslint/index.d.ts", "import": "./src/eslint/index.cjs", "require": "./src/eslint/index.cjs" } diff --git a/packages/grafana-i18n/src/eslint/index.d.ts b/packages/grafana-i18n/src/eslint/index.d.ts new file mode 100644 index 00000000000..d9ce3ca877c --- /dev/null +++ b/packages/grafana-i18n/src/eslint/index.d.ts @@ -0,0 +1,6 @@ +// Stub type definition for the eslint plugin to pass our package validation. +// Will revisit this when we fix our package building and packaging process. + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +declare const plugin: any; +export = plugin; diff --git a/packages/grafana-plugin-configs/package.json b/packages/grafana-plugin-configs/package.json index 7c4b0d8b191..d18f5f00a96 100644 --- a/packages/grafana-plugin-configs/package.json +++ b/packages/grafana-plugin-configs/package.json @@ -4,6 +4,8 @@ "private": true, "version": "12.3.0-pre", "dependencies": { + "react": "18.3.1", + "terser-webpack-plugin": "5.3.14", "tslib": "2.8.1" }, "type": "module", @@ -13,6 +15,7 @@ "@swc/helpers": "^0.5.0", "@swc/jest": "^0.2.26", "@types/eslint": "9.6.1", + "@types/react": "18.3.18", "@types/webpack-bundle-analyzer": "^4.7.0", "copy-webpack-plugin": "13.0.0", "eslint": "9.32.0", diff --git a/packages/grafana-prometheus/package.json b/packages/grafana-prometheus/package.json index f06dec8c0eb..772df81b58f 100644 --- a/packages/grafana-prometheus/package.json +++ b/packages/grafana-prometheus/package.json @@ -61,12 +61,13 @@ "@types/react-dom": "18.3.5", "@types/react-highlight-words": "0.20.0", "@types/react-window": "1.8.8", - "@types/semver": "7.7.0", + "@types/semver": "7.7.1", "@types/uuid": "10.0.0", "debounce-promise": "3.1.2", "lodash": "4.17.21", "moment": "2.30.1", "moment-timezone": "0.5.47", + "monaco-editor": "0.34.1", "monaco-promql": "1.8.0", "pluralize": "8.0.0", "prismjs": "1.30.0", @@ -74,7 +75,7 @@ "react-use": "17.6.0", "react-window": "1.8.11", "rxjs": "7.8.2", - "semver": "7.7.2", + "semver": "7.7.3", "uuid": "11.1.0" }, "devDependencies": { diff --git a/packages/grafana-prometheus/src/components/monaco-query-field/promql.ts b/packages/grafana-prometheus/src/components/monaco-query-field/promql.ts index 4a850789c72..d144b130208 100644 --- a/packages/grafana-prometheus/src/components/monaco-query-field/promql.ts +++ b/packages/grafana-prometheus/src/components/monaco-query-field/promql.ts @@ -74,6 +74,7 @@ const functions = [ 'absent', 'ceil', 'changes', + 'clamp', 'clamp_max', 'clamp_min', 'day_of_month', diff --git a/packages/grafana-prometheus/src/datasource.test.ts b/packages/grafana-prometheus/src/datasource.test.ts index bc30a4befff..ac5e2f59623 100644 --- a/packages/grafana-prometheus/src/datasource.test.ts +++ b/packages/grafana-prometheus/src/datasource.test.ts @@ -664,10 +664,6 @@ describe('PrometheusDatasource', () => { }); describe('interpolateVariablesInQueries', () => { - afterEach(() => { - config.featureToggles.promQLScope = undefined; - }); - it('should call replace function 3 times', () => { const query: PromQuery = { expr: 'test{job="testjob"}', @@ -695,17 +691,32 @@ describe('PrometheusDatasource', () => { expect(ds.enhanceExprWithAdHocFilters).toHaveBeenCalled(); }); - it('should not apply adhoc filters when promQLScope is enabled', () => { - config.featureToggles.promQLScope = true; + it('should not apply adhoc filters when scopes with filters are present', () => { ds.enhanceExprWithAdHocFilters = jest.fn(); ds.generateScopeFilters = jest.fn(); - const queries = [ + // Fix: Use correct types for scopes and filters + const typedScopes = [ + { + name: 'test-scope', + title: 'Test Scope', + type: 'test', + filters: [ + { + key: 'bar', + operator: 'equals' as const, + value: 'baz', + }, + ], + }, + ]; + const typedQueries: PromQuery[] = [ { refId: 'A', expr: 'rate({bar="baz", job="foo"} [5m]', + scopes: typedScopes, }, ]; - ds.interpolateVariablesInQueries(queries, {}); + ds.interpolateVariablesInQueries(typedQueries, {}); expect(ds.enhanceExprWithAdHocFilters).not.toHaveBeenCalled(); expect(ds.generateScopeFilters).toHaveBeenCalled(); }); @@ -716,10 +727,6 @@ describe('PrometheusDatasource', () => { replaceMock.mockImplementation((a: string, ...rest: unknown[]) => a); }); - afterEach(() => { - config.featureToggles.promQLScope = false; - }); - it('should call replace function for legendFormat', () => { const query = { expr: 'test{job="bar"}', @@ -783,7 +790,21 @@ describe('PrometheusDatasource', () => { }); it('should generate scope filters and **not** apply ad-hoc filters to expr', () => { - config.featureToggles.promQLScope = true; + const scopes = [ + { + name: 'test-scope', + title: 'Test Scope', + type: 'test', + filters: [ + { + key: 'bar', + operator: 'equals' as const, + value: 'baz', + }, + ], + }, + ]; + replaceMock.mockImplementation((a: string) => a); const filters = [ { @@ -801,17 +822,18 @@ describe('PrometheusDatasource', () => { const query = { expr: 'test{job="bar"}', refId: 'A', + scopes: scopes, }; const expectedScopeFilters: ScopeSpecFilter[] = [ { key: 'k1', - operator: 'equals', + operator: 'equals' as const, value: 'v1', }, { key: 'k2', - operator: 'not-equals', + operator: 'not-equals' as const, value: 'v2', }, ]; @@ -891,13 +913,27 @@ describe('PrometheusDatasource', () => { }); it('should replace variables in adhoc filters on backend when promQLScope is enabled', () => { - config.featureToggles.promQLScope = true; + const scopes = [ + { + name: 'test-scope', + title: 'Test Scope', + type: 'test', + filters: [ + { + key: 'bar', + operator: 'equals' as const, + value: 'baz', + }, + ], + }, + ]; const searchPattern = /\$A/g; replaceMock.mockImplementation((a: string) => a?.replace(searchPattern, '99') ?? a); const query = { expr: 'test', refId: 'A', + scopes: scopes, }; const filters = [ { @@ -906,6 +942,7 @@ describe('PrometheusDatasource', () => { value: '$A', }, ]; + const result = ds.applyTemplateVariables(query, {}, filters); expect(result).toMatchObject({ expr: 'test', diff --git a/packages/grafana-prometheus/src/datasource.ts b/packages/grafana-prometheus/src/datasource.ts index 9755325ff78..4f2beb195d1 100644 --- a/packages/grafana-prometheus/src/datasource.ts +++ b/packages/grafana-prometheus/src/datasource.ts @@ -430,7 +430,7 @@ export class PrometheusDatasource utcOffsetSec: utcOffset * 60, }; - if (config.featureToggles.promQLScope) { + if (request.scopes) { processedTarget.scopes = (request.scopes ?? []).map((scope) => ({ name: scope.metadata.name, ...scope.spec, @@ -543,7 +543,7 @@ export class PrometheusDatasource options.timeRange = getDefaultTimeRange(); } - if (config.featureToggles.promQLScope && (options?.scopes?.length ?? 0) > 0) { + if ((options?.scopes?.length ?? 0) > 0) { const suggestions = await this.languageProvider.fetchSuggestions( options.timeRange, options.queries, @@ -574,7 +574,7 @@ export class PrometheusDatasource } const requestId = `[${this.uid}][${options.key}]`; - if (config.featureToggles.promQLScope && (options?.scopes?.length ?? 0) > 0) { + if ((options?.scopes?.length ?? 0) > 0) { return ( await this.languageProvider.fetchSuggestions( options.timeRange, @@ -609,7 +609,7 @@ export class PrometheusDatasource scopedVars, this.interpolateExploreMetrics(query.fromExploreMetrics) ); - const replacedInterpolatedQuery = config.featureToggles.promQLScope + const replacedInterpolatedQuery = targetHasScopes(query) ? interpolatedQuery : this.templateSrv.replace( this.enhanceExprWithAdHocFilters(filters, interpolatedQuery), @@ -619,7 +619,7 @@ export class PrometheusDatasource const expandedQuery = { ...query, - ...(config.featureToggles.promQLScope ? { adhocFilters: this.generateScopeFilters(filters) } : {}), + ...(query.scopes && query.scopes.length > 0 ? { adhocFilters: this.generateScopeFilters(filters) } : {}), datasource: this.getRef(), expr: replacedInterpolatedQuery, interval: this.templateSrv.replace(query.interval, scopedVars), @@ -791,13 +791,13 @@ export class PrometheusDatasource // Apply ad-hoc filters // When ad-hoc filters are applied, we replace again the variables in case the ad-hoc filters also reference a variable - const exprWithAdhoc = config.featureToggles.promQLScope + const exprWithAdhoc = targetHasScopes(target) ? expr : this.templateSrv.replace(this.enhanceExprWithAdHocFilters(filters, expr), variables, this.interpolateQueryExpr); return { ...target, - ...(config.featureToggles.promQLScope ? { adhocFilters: this.generateScopeFilters(filters) } : {}), + ...(targetHasScopes(target) ? { adhocFilters: this.generateScopeFilters(filters) } : {}), expr: exprWithAdhoc, interval: this.templateSrv.replace(target.interval, variables), legendFormat: this.templateSrv.replace(target.legendFormat, variables), @@ -862,6 +862,10 @@ export class PrometheusDatasource } } +function targetHasScopes(target: PromQuery): boolean { + return !!(target.scopes && target.scopes.length > 0); +} + export function extractRuleMappingFromGroups(groups: RawRecordingRules[]): RuleQueryMapping { return groups.reduce( (mapping, group) => diff --git a/packages/grafana-prometheus/src/locales/cs-CZ/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/cs-CZ/grafana-prometheus.json index 095fdb99b4a..7afae00fd13 100644 --- a/packages/grafana-prometheus/src/locales/cs-CZ/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/cs-CZ/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "Ve zdroji dat nebyly nalezeny ลพรกdnรฉ metriky.", "name": "Nรกzev", "type": "Typ" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "Analรฝza dotazu je nejednoznaฤnรก." - } } } } diff --git a/packages/grafana-prometheus/src/locales/de-DE/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/de-DE/grafana-prometheus.json index 2f872d72e6c..5b95ca6bdf4 100644 --- a/packages/grafana-prometheus/src/locales/de-DE/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/de-DE/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "Es wurden keine Metriken in der Datenquelle gefunden.", "name": "Name", "type": "Typ" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "Das Abfrage-Parsing ist unklar." - } } } } diff --git a/packages/grafana-prometheus/src/locales/en-US/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/en-US/grafana-prometheus.json index 34fb4482a0d..58c601d9514 100644 --- a/packages/grafana-prometheus/src/locales/en-US/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/en-US/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "There are no metrics found in the data source.", "name": "Name", "type": "Type" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "Query parsing is ambiguous." - } } } } diff --git a/packages/grafana-prometheus/src/locales/es-ES/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/es-ES/grafana-prometheus.json index 940880addf9..8b0b9d4c5d1 100644 --- a/packages/grafana-prometheus/src/locales/es-ES/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/es-ES/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "No se han encontrado mรฉtricas en la fuente de datos.", "name": "Nombre", "type": "Tipo" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "El anรกlisis de la consulta es ambiguo." - } } } } diff --git a/packages/grafana-prometheus/src/locales/fr-FR/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/fr-FR/grafana-prometheus.json index f6c73691099..2ad85dcac95 100644 --- a/packages/grafana-prometheus/src/locales/fr-FR/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/fr-FR/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "Aucune mรฉtrique trouvรฉe dans la source de donnรฉes.", "name": "Nom", "type": "Type" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "Lโ€™analyse de la requรชte est ambiguรซ." - } } } } diff --git a/packages/grafana-prometheus/src/locales/hu-HU/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/hu-HU/grafana-prometheus.json index ef0f4990ee2..5a8d1906a38 100644 --- a/packages/grafana-prometheus/src/locales/hu-HU/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/hu-HU/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "Nem talรกlhatรณ metrika az adatforrรกsban.", "name": "Nรฉv", "type": "Tรญpus" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "A lekรฉrdezรฉs elemzรฉse nem egyรฉrtelmลฑ." - } } } } diff --git a/packages/grafana-prometheus/src/locales/id-ID/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/id-ID/grafana-prometheus.json index c69be5dfd39..cf37adca5c0 100644 --- a/packages/grafana-prometheus/src/locales/id-ID/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/id-ID/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "Tidak ada metrik yang ditemukan di sumber data.", "name": "Nama", "type": "Jenis" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "Penguraian kueri mengalami masalah ketidakjelasan." - } } } } diff --git a/packages/grafana-prometheus/src/locales/it-IT/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/it-IT/grafana-prometheus.json index 0d852e162e3..314ac50298e 100644 --- a/packages/grafana-prometheus/src/locales/it-IT/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/it-IT/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "Non sono state trovate metriche nell'origine dati.", "name": "Nome", "type": "Tipo" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "L'analisi della query รจ ambigua." - } } } } diff --git a/packages/grafana-prometheus/src/locales/ja-JP/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/ja-JP/grafana-prometheus.json index 4f81b62c665..9efa150bca3 100644 --- a/packages/grafana-prometheus/src/locales/ja-JP/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/ja-JP/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "ใƒ‡ใƒผใ‚ฟใ‚ฝใƒผใ‚นๅ†…ใซใƒกใƒˆใƒชใƒƒใ‚ฏใŒ่ฆ‹ใคใ‹ใ‚Šใพใ›ใ‚“ใ€‚", "name": "ๅๅ‰", "type": "็จฎ้กž" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "ใ‚ฏใ‚จใƒช่งฃๆžใŒๆ›–ๆ˜งใงใ™ใ€‚" - } } } } diff --git a/packages/grafana-prometheus/src/locales/ko-KR/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/ko-KR/grafana-prometheus.json index 299e57788c0..857372ed06e 100644 --- a/packages/grafana-prometheus/src/locales/ko-KR/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/ko-KR/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "๋ฐ์ดํ„ฐ ์†Œ์Šค์—์„œ ๋ฉ”ํŠธ๋ฆญ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", "name": "์ด๋ฆ„", "type": "์œ ํ˜•" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "์ฟผ๋ฆฌ ๊ตฌ๋ฌธ ๋ถ„์„์ด ๋ชจํ˜ธํ•ฉ๋‹ˆ๋‹ค." - } } } } diff --git a/packages/grafana-prometheus/src/locales/nl-NL/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/nl-NL/grafana-prometheus.json index ff2f4cca925..991614b0524 100644 --- a/packages/grafana-prometheus/src/locales/nl-NL/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/nl-NL/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "Er zijn geen statistieken gevonden in de gegevensbron.", "name": "Naam", "type": "Type" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "Query-parsing is dubbelzinnig." - } } } } diff --git a/packages/grafana-prometheus/src/locales/pl-PL/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/pl-PL/grafana-prometheus.json index 9c48c09d005..3c949a12c2f 100644 --- a/packages/grafana-prometheus/src/locales/pl-PL/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/pl-PL/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "Wย ลบrรณdle danych nie znaleziono ลผadnych metryk.", "name": "Imiฤ™", "type": "Typ" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "Analiza zapytania jest niejednoznaczna." - } } } } diff --git a/packages/grafana-prometheus/src/locales/pt-BR/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/pt-BR/grafana-prometheus.json index 75f2e20ec65..74d47a5342b 100644 --- a/packages/grafana-prometheus/src/locales/pt-BR/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/pt-BR/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "Nรฃo hรก mรฉtricas encontradas na fonte de dados.", "name": "Nome", "type": "Tipo" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "A anรกlise da consulta รฉ ambรญgua." - } } } } diff --git a/packages/grafana-prometheus/src/locales/pt-PT/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/pt-PT/grafana-prometheus.json index 2a84aa41ced..0c56b656f66 100644 --- a/packages/grafana-prometheus/src/locales/pt-PT/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/pt-PT/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "Nรฃo foram encontradas mรฉtricas na origem de dados.", "name": "Nome", "type": "Tipo" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "A anรกlise da consulta รฉ ambรญgua." - } } } } diff --git a/packages/grafana-prometheus/src/locales/ru-RU/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/ru-RU/grafana-prometheus.json index c1608d71796..da73342e2e9 100644 --- a/packages/grafana-prometheus/src/locales/ru-RU/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/ru-RU/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "ะ’ ะธัั‚ะพั‡ะฝะธะบะต ะดะฐะฝะฝั‹ั… ะฝะตั‚ ะผะตั‚ั€ะธะบ.", "name": "ะ˜ะผั", "type": "ะขะธะฟ" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "ะะตะพะดะฝะพะทะฝะฐั‡ะฝั‹ะต ั€ะตะทัƒะปัŒั‚ะฐั‚ั‹ ะฐะฝะฐะปะธะทะฐ ะทะฐะฟั€ะพัะฐ." - } } } } diff --git a/packages/grafana-prometheus/src/locales/sv-SE/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/sv-SE/grafana-prometheus.json index 63d795e2359..e41b22075dd 100644 --- a/packages/grafana-prometheus/src/locales/sv-SE/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/sv-SE/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "Inga mรคtvรคrden hittades i datakรคllan.", "name": "Namn", "type": "Typ" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "Tolkningen av frรฅgan รคr tvetydig." - } } } } diff --git a/packages/grafana-prometheus/src/locales/tr-TR/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/tr-TR/grafana-prometheus.json index e394fae0607..af4dea95932 100644 --- a/packages/grafana-prometheus/src/locales/tr-TR/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/tr-TR/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "Veri kaynaฤŸฤฑnda metrik bulunamadฤฑ.", "name": "Ad", "type": "Tรผr" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "Sorgu ayrฤฑลŸtฤฑrma belirsiz." - } } } } diff --git a/packages/grafana-prometheus/src/locales/zh-Hans/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/zh-Hans/grafana-prometheus.json index 57a1f49d2ae..890add6aa2f 100644 --- a/packages/grafana-prometheus/src/locales/zh-Hans/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/zh-Hans/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "ๆ•ฐๆฎๆบไธญๆœชๆ‰พๅˆฐๆŒ‡ๆ ‡ใ€‚", "name": "ๅ็งฐ", "type": "็ฑปๅž‹" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "ๆŸฅ่ฏข่งฃๆžไธๆ˜Ž็กฎใ€‚" - } } } } diff --git a/packages/grafana-prometheus/src/locales/zh-Hant/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/zh-Hant/grafana-prometheus.json index 8001cdafa8d..0f4fd89eaa2 100644 --- a/packages/grafana-prometheus/src/locales/zh-Hant/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/zh-Hant/grafana-prometheus.json @@ -486,11 +486,6 @@ "message-no-metrics-found": "ๅœจ่ณ‡ๆ–™ไพ†ๆบไธญๆœชๆ‰พๅˆฐไปปไฝ•ๆŒ‡ๆจ™ใ€‚", "name": "ๅ็จฑ๏ผˆๅๅญ—๏ผ‰", "type": "้กžๅž‹" - }, - "update-function-args": { - "text": { - "query-parsing-is-ambiguous": "ๆŸฅ่ฉขๅ‰–ๆžไธๆ˜Ž็ขบใ€‚" - } } } } diff --git a/packages/grafana-prometheus/src/querybuilder/QueryPattern.tsx b/packages/grafana-prometheus/src/querybuilder/QueryPattern.tsx index b61f64ec58d..5d8a74f787a 100644 --- a/packages/grafana-prometheus/src/querybuilder/QueryPattern.tsx +++ b/packages/grafana-prometheus/src/querybuilder/QueryPattern.tsx @@ -28,7 +28,7 @@ export const QueryPattern = (props: Props) => { const lang = { grammar: promqlGrammar, name: 'promql' }; return ( - + {pattern.name}
{ ); }} > -
+ {promQueryModeller .getQueryPatterns() .filter((pattern) => pattern.type === patternType) @@ -140,7 +140,7 @@ export const QueryPatternsModal = (props: Props) => { setSelectedPatternName={setSelectedPatternName} /> ))} -
+ ); })} @@ -160,12 +160,6 @@ export const QueryPatternsModal = (props: Props) => { const getStyles = (theme: GrafanaTheme2) => { return { - cardsContainer: css({ - display: 'flex', - flexDirection: 'row', - flexWrap: 'wrap', - justifyContent: 'space-between', - }), spacing: css({ marginBottom: theme.spacing(1), }), diff --git a/packages/grafana-prometheus/src/querybuilder/parsing.test.ts b/packages/grafana-prometheus/src/querybuilder/parsing.test.ts index 53db5b12b95..b3da120e8f0 100644 --- a/packages/grafana-prometheus/src/querybuilder/parsing.test.ts +++ b/packages/grafana-prometheus/src/querybuilder/parsing.test.ts @@ -200,49 +200,13 @@ describe('buildVisualQueryFromString', () => { }); describe('nested binary operation errors in visual query editor', () => { - // Visual query builder does not currently have support for nested binary operations, for now we should throw an error in the UI letting users know that their query will be misinterpreted - it('throws error when visual query parse is ambiguous', () => { + it('does not throw error when visual query contains binary ops in function argument', () => { expect( buildVisualQueryFromString('topk(5, node_arp_entries / node_arp_entries{cluster="dev-eu-west-2"})') ).toMatchObject({ - errors: [ - { - from: 8, - text: 'Query parsing is ambiguous.', - to: 68, - }, - ], + errors: [], }); }); - - it('throws error when visual query parse with aggregation is ambiguous (scalar)', () => { - expect(buildVisualQueryFromString('topk(5, 1 / 2)')).toMatchObject({ - errors: [ - { - from: 8, - text: 'Query parsing is ambiguous.', - to: 13, - }, - ], - }); - }); - - it('throws error when visual query parse with functionCall is ambiguous', () => { - expect( - buildVisualQueryFromString( - 'clamp_min(sum by(cluster)(rate(X{le="2.5"}[5m]))+sum by (cluster) (rate(X{le="5"}[5m])), 0.001)' - ) - ).toMatchObject({ - errors: [ - { - from: 10, - text: 'Query parsing is ambiguous.', - to: 87, - }, - ], - }); - }); - it('does not throw error when visual query parse is unambiguous', () => { expect( buildVisualQueryFromString('topk(5, node_arp_entries) / node_arp_entries{cluster="dev-eu-west-2"}') @@ -967,6 +931,29 @@ describe('buildVisualQueryFromString', () => { }) ); }); + + it('parses query with functions and binary operations', () => { + expect( + buildVisualQueryFromString( + 'clamp(sum(rate(loki_distributor_bytes_received_total{cluster="loki", tenant="kubernetes"}[5m])) / 1024 / 55, 5, 30)' + ) + ).toEqual( + noErrors({ + metric: 'loki_distributor_bytes_received_total', + labels: [ + { label: 'cluster', op: '=', value: 'loki' }, + { label: 'tenant', op: '=', value: 'kubernetes' }, + ], + operations: [ + { id: 'rate', params: ['5m'] }, + { id: 'sum', params: [] }, + { id: '__divide_by', params: [1024] }, + { id: '__divide_by', params: [55] }, + { id: 'clamp', params: [5, 30] }, + ], + }) + ); + }); }); function noErrors(query: PromVisualQuery) { diff --git a/packages/grafana-prometheus/src/querybuilder/parsing.ts b/packages/grafana-prometheus/src/querybuilder/parsing.ts index 9a517b53bd2..3b7c372a545 100644 --- a/packages/grafana-prometheus/src/querybuilder/parsing.ts +++ b/packages/grafana-prometheus/src/querybuilder/parsing.ts @@ -34,6 +34,7 @@ import { getAllByType, getLeftMostChild, getString, + isFunctionOrAggregation, makeBinOp, makeError, replaceBuiltInVariable, @@ -330,24 +331,6 @@ function updateFunctionArgs(expr: string, node: SyntaxNode | null, context: Cont let child = node.firstChild; while (child) { - let binaryExpressionWithinFunctionArgs: SyntaxNode | null; - if (child.type.id === BinaryExpr) { - binaryExpressionWithinFunctionArgs = child; - } else { - binaryExpressionWithinFunctionArgs = child.getChild(BinaryExpr); - } - - if (binaryExpressionWithinFunctionArgs) { - context.errors.push({ - text: t( - 'grafana-prometheus.querybuilder.update-function-args.text.query-parsing-is-ambiguous', - 'Query parsing is ambiguous.' - ), - from: binaryExpressionWithinFunctionArgs.from, - to: binaryExpressionWithinFunctionArgs.to, - }); - } - updateFunctionArgs(expr, child, context, op); child = child.nextSibling; } @@ -392,7 +375,7 @@ function updateFunctionArgs(expr: string, node: SyntaxNode | null, context: Cont * @param node * @param context */ -function handleBinary(expr: string, node: SyntaxNode, context: Context) { +function handleBinary(expr: string, node: SyntaxNode, context: Context, idx = 0) { const visQuery = context.query; const left = node.firstChild!; const op = getString(expr, left.nextSibling); @@ -407,6 +390,16 @@ function handleBinary(expr: string, node: SyntaxNode, context: Context) { const rightBinary = right.type.id === BinaryExpr; + // binary operations that are part of a function argument do not get processed and added to the query until the end, this index helps keep track + // of where to add the operation in the list rather than just appending it to the end. If the binary operation is just part of a nested binary exp, + // we append at the end + const parent = node.parent; + const child = node.firstChild; + const shouldOffsetTail = + parent && !parent.type.isTop && (isFunctionOrAggregation(parent) || (child && isFunctionOrAggregation(child))); + if (shouldOffsetTail) { + idx += 1; + } if (leftNumber) { // TODO: this should be already handled in case parent is binary expression as it has to be added to parent // if query starts with a number that isn't handled now. @@ -416,14 +409,18 @@ function handleBinary(expr: string, node: SyntaxNode, context: Context) { handleExpression(expr, left, context); } + // in the case we have an expression like func(...) / 2 or func(...) + 5, the binary expression will be at the top of the tree + // in which case, the idx will be 0. In this case it means that the binary operation must be added to the end of the array, and + + const newIdx = idx === 0 ? visQuery.operations.length : -idx; if (rightNumber) { - visQuery.operations.push(makeBinOp(opDef, expr, right, !!binModifier?.isBool)); + visQuery.operations.splice(newIdx, 0, makeBinOp(opDef, expr, right, !!binModifier?.isBool)); } else if (rightBinary) { // Due to the way binary ops are parsed we can get a binary operation on the right that starts with a number which // is a factor for a current binary operation. So we have to add it as an operation now. const leftMostChild = getLeftMostChild(right); if (leftMostChild?.type.id === NumberDurationLiteral) { - visQuery.operations.push(makeBinOp(opDef, expr, leftMostChild, !!binModifier?.isBool)); + visQuery.operations.splice(newIdx, 0, makeBinOp(opDef, expr, leftMostChild, !!binModifier?.isBool)); } // If we added the first number literal as operation here we still can continue and handle the rest as the first diff --git a/packages/grafana-prometheus/src/querybuilder/parsingUtils.test.ts b/packages/grafana-prometheus/src/querybuilder/parsingUtils.test.ts index c96a7877e8f..fa58edd28bc 100644 --- a/packages/grafana-prometheus/src/querybuilder/parsingUtils.test.ts +++ b/packages/grafana-prometheus/src/querybuilder/parsingUtils.test.ts @@ -4,6 +4,7 @@ import { parser } from '@prometheus-io/lezer-promql'; import { getLeftMostChild, getString, + isFunctionOrAggregation, replaceBuiltInVariable, replaceVariables, returnBuiltInVariable, @@ -123,4 +124,17 @@ describe('builtInTimeVariables', () => { expect(actual2).toBe(testCase.expr); }); }); + + describe('isFunctionOrAggregation', () => { + it('should identify function and aggregation nodes', () => { + const tree = parser.parse('clamp(sum(foo[5m]))'); + const root = tree.topNode; + const functionNode = root.firstChild!.lastChild; // clamp + const aggregationNode = root.firstChild!.lastChild!.firstChild; // sum + + expect(isFunctionOrAggregation(functionNode!)).toBe(true); + expect(isFunctionOrAggregation(aggregationNode!)).toBe(true); + expect(isFunctionOrAggregation(root)).toBe(false); + }); + }); }); diff --git a/packages/grafana-prometheus/src/querybuilder/parsingUtils.ts b/packages/grafana-prometheus/src/querybuilder/parsingUtils.ts index 3017bc33526..50d3a2ce725 100644 --- a/packages/grafana-prometheus/src/querybuilder/parsingUtils.ts +++ b/packages/grafana-prometheus/src/querybuilder/parsingUtils.ts @@ -1,5 +1,6 @@ // Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/querybuilder/parsingUtils.ts import { SyntaxNode, TreeCursor } from '@lezer/common'; +import { AggregateExpr, FunctionCallBody } from '@prometheus-io/lezer-promql'; import { QueryBuilderOperation, QueryBuilderOperationParamValue } from './shared/types'; @@ -194,3 +195,7 @@ export function replaceBuiltInVariable(expr: string): string { export function returnBuiltInVariable(expr: string): string { return expr.replace(builtInReplacementRegex, (match) => replacementToVariable[match]); } + +export function isFunctionOrAggregation(node: SyntaxNode): boolean { + return node.type.id === AggregateExpr || node.type.id === FunctionCallBody; +} diff --git a/packages/grafana-runtime/src/config.ts b/packages/grafana-runtime/src/config.ts index 2576de932b2..bf36333e107 100644 --- a/packages/grafana-runtime/src/config.ts +++ b/packages/grafana-runtime/src/config.ts @@ -153,13 +153,15 @@ export class GrafanaBootConfig { dateFormats?: SystemDateFormatSettings; grafanaJavascriptAgent = { enabled: false, - customEndpoint: '', apiKey: '', - allInstrumentationsEnabled: false, - errorInstrumentalizationEnabled: true, + customEndpoint: '', consoleInstrumentalizationEnabled: false, - webVitalsInstrumentalizationEnabled: false, + performanceInstrumentalizationEnabled: false, + cspInstrumentalizationEnabled: false, tracingInstrumentalizationEnabled: false, + webVitalsAttribution: false, + internalLoggerLevel: 0, + botFilterEnabled: false, }; pluginCatalogURL = 'https://grafana.com/grafana/plugins/'; pluginAdminEnabled = true; @@ -259,6 +261,8 @@ export class GrafanaBootConfig { listDashboardScopesEndpoint = ''; listScopesEndpoint = ''; + openFeatureContext: Record = {}; + constructor( options: BootData['settings'] & { bootData: BootData; diff --git a/packages/grafana-runtime/src/internal/openFeature/index.ts b/packages/grafana-runtime/src/internal/openFeature/index.ts index 891eefe7958..57e35516e30 100644 --- a/packages/grafana-runtime/src/internal/openFeature/index.ts +++ b/packages/grafana-runtime/src/internal/openFeature/index.ts @@ -24,7 +24,7 @@ export async function initOpenFeature() { await OpenFeature.setProviderAndWait(ofProvider, { targetingKey: config.namespace, - namespace: config.namespace, + ...config.openFeatureContext, }); } diff --git a/packages/grafana-runtime/src/services/index.ts b/packages/grafana-runtime/src/services/index.ts index e9d2eeac852..42ef1c3f655 100644 --- a/packages/grafana-runtime/src/services/index.ts +++ b/packages/grafana-runtime/src/services/index.ts @@ -30,6 +30,7 @@ export { type UsePluginFunctionsOptions, type UsePluginFunctionsResult, } from './pluginExtensions/usePluginFunctions'; +export { setHelpNavItemHook, useHelpNavItem, type UseHelpNavItem } from './navigation/useHelpNavItem'; export { getObservablePluginLinks } from './pluginExtensions/getObservablePluginLinks'; export { getObservablePluginComponents } from './pluginExtensions/getObservablePluginComponents'; export { diff --git a/packages/grafana-runtime/src/services/navigation/useHelpNavItem.ts b/packages/grafana-runtime/src/services/navigation/useHelpNavItem.ts new file mode 100644 index 00000000000..cb39aee2c0e --- /dev/null +++ b/packages/grafana-runtime/src/services/navigation/useHelpNavItem.ts @@ -0,0 +1,20 @@ +import { NavModelItem } from '@grafana/data'; + +export type UseHelpNavItem = () => NavModelItem | undefined; + +let singleton: UseHelpNavItem | undefined; + +export function setHelpNavItemHook(hook: UseHelpNavItem): void { + // We allow overriding the registry in tests + if (singleton && process.env.NODE_ENV !== 'test') { + throw new Error('setHelpNavItemHook() function should only be called once, when Grafana is starting.'); + } + singleton = hook; +} + +export function useHelpNavItem(): NavModelItem | undefined { + if (!singleton) { + throw new Error('useHelpNavItem() can only be used after the Grafana instance has started.'); + } + return singleton(); +} diff --git a/packages/grafana-runtime/src/services/pluginExtensions/utils.test.tsx b/packages/grafana-runtime/src/services/pluginExtensions/utils.test.tsx index 14f1a9082be..b57a795c3b5 100644 --- a/packages/grafana-runtime/src/services/pluginExtensions/utils.test.tsx +++ b/packages/grafana-runtime/src/services/pluginExtensions/utils.test.tsx @@ -108,11 +108,15 @@ describe('Plugin Extensions / Utils', () => { test('should work when using class components', () => { const props = {}; + // this specifically needs to be a class component + // eslint-disable-next-line react-prefer-function-component/react-prefer-function-component const Component1 = class extends React.Component<{}> { render() { return
Test 1
; } }; + // this specifically needs to be a class component + // eslint-disable-next-line react-prefer-function-component/react-prefer-function-component const Component2 = class extends React.Component<{}> { render() { return
Test 2
; diff --git a/packages/grafana-schema/package.json b/packages/grafana-schema/package.json index 773a4a663d2..feff0eb8ba3 100644 --- a/packages/grafana-schema/package.json +++ b/packages/grafana-schema/package.json @@ -41,6 +41,7 @@ "glob": "^11.0.0", "rimraf": "6.0.1", "rollup": "^4.22.4", + "rollup-plugin-copy": "3.5.0", "rollup-plugin-esbuild": "6.2.1", "rollup-plugin-node-externals": "^8.0.0", "typescript": "5.9.2" diff --git a/packages/grafana-schema/src/index.gen.ts b/packages/grafana-schema/src/index.gen.ts index 5646058691b..87f2a3fd960 100644 --- a/packages/grafana-schema/src/index.gen.ts +++ b/packages/grafana-schema/src/index.gen.ts @@ -104,20 +104,3 @@ export { defaultFieldConfig, defaultRowPanel } from './veneer/dashboard.types'; - -// Raw generated types from LibraryPanel kind. -export type { - LibraryElementDTOMetaUser, - LibraryElementDTOMeta -} from './raw/librarypanel/x/librarypanel_types.gen'; - -// The following exported declarations correspond to types in the librarypanel@0.0 kind's -// schema with attribute @grafana(TSVeneer="type"). -// -// The handwritten file for these type and default veneers is expected to be at -// packages/grafana-schema/src/veneer/librarypanel.types.ts. -// This re-export declaration enforces that the handwritten veneer file exists, -// and exports all the symbols in the list. -// -// TODO generate code such that tsc enforces type compatibility between raw and veneer decls -export type { LibraryPanel } from './veneer/librarypanel.types'; diff --git a/packages/grafana-schema/src/index.ts b/packages/grafana-schema/src/index.ts index 505aded6a29..e7588ef48a1 100644 --- a/packages/grafana-schema/src/index.ts +++ b/packages/grafana-schema/src/index.ts @@ -4,4 +4,5 @@ * @packageDocumentation */ export * from './veneer/common.types'; +export * from './veneer/librarypanel.types'; export * from './index.gen'; diff --git a/packages/grafana-schema/src/raw/composable/newgauge/panelcfg/x/NewGaugePanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/newgauge/panelcfg/x/NewGaugePanelCfg_types.gen.ts new file mode 100644 index 00000000000..045b217482f --- /dev/null +++ b/packages/grafana-schema/src/raw/composable/newgauge/panelcfg/x/NewGaugePanelCfg_types.gen.ts @@ -0,0 +1,51 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. +// +// Generated by: +// public/app/plugins/gen.go +// Using jennies: +// TSTypesJenny +// PluginTsTypesJenny +// +// Run 'make gen-cue' from repository root to regenerate. + +import * as common from '@grafana/schema'; + +export const pluginVersion = "12.3.0-pre"; + +export interface GaugePanelEffects { + barGlow?: boolean; + centerGlow?: boolean; + rounded?: boolean; + spotlight?: boolean; +} + +export const defaultGaugePanelEffects: Partial = { + barGlow: false, + centerGlow: false, + rounded: false, + spotlight: false, +}; + +export interface Options extends common.SingleStatBaseOptions { + barWidthFactor: number; + effects: GaugePanelEffects; + gradient: ('none' | 'auto'); + segmentCount: number; + segmentSpacing: number; + shape: ('circle' | 'gauge'); + showThresholdLabels: boolean; + showThresholdMarkers: boolean; + sparkline?: boolean; +} + +export const defaultOptions: Partial = { + barWidthFactor: 0.5, + effects: {}, + gradient: 'auto', + segmentCount: 1, + segmentSpacing: 0.3, + shape: 'gauge', + showThresholdLabels: false, + showThresholdMarkers: true, + sparkline: true, +}; diff --git a/packages/grafana-schema/src/raw/dashboard/x/dashboard_types.gen.ts b/packages/grafana-schema/src/raw/dashboard/x/dashboard_types.gen.ts index d158d884aa0..b370fc6206c 100644 --- a/packages/grafana-schema/src/raw/dashboard/x/dashboard_types.gen.ts +++ b/packages/grafana-schema/src/raw/dashboard/x/dashboard_types.gen.ts @@ -454,8 +454,9 @@ export const defaultAction: Partial = { * `textbox`: Display a free text input field with an optional default value. * `custom`: Define the variable options manually using a comma-separated list. * `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables + * `switch`: Boolean variables rendered as a switch */ -export type VariableType = ('query' | 'adhoc' | 'groupby' | 'constant' | 'datasource' | 'interval' | 'textbox' | 'custom' | 'system' | 'snapshot'); +export type VariableType = ('query' | 'adhoc' | 'groupby' | 'constant' | 'datasource' | 'interval' | 'textbox' | 'custom' | 'system' | 'snapshot' | 'switch'); /** * Color mode for a field. You can specify a single color, or select a continuous (gradient) color schemes, based on a value. diff --git a/packages/grafana-schema/src/raw/librarypanel/x/librarypanel_types.gen.ts b/packages/grafana-schema/src/raw/librarypanel/x/librarypanel_types.gen.ts deleted file mode 100644 index 97cba2a5c5e..00000000000 --- a/packages/grafana-schema/src/raw/librarypanel/x/librarypanel_types.gen.ts +++ /dev/null @@ -1,65 +0,0 @@ -// Code generated - EDITING IS FUTILE. DO NOT EDIT. -// -// Generated by: -// kinds/gen.go -// Using jennies: -// TSTypesJenny -// LatestMajorsOrXJenny -// -// Run 'make gen-cue' from repository root to regenerate. - -export interface LibraryElementDTOMetaUser { - avatarUrl: string; - id: number; - name: string; -} - -export interface LibraryElementDTOMeta { - connectedDashboards: number; - created: string; - createdBy: LibraryElementDTOMetaUser; - folderName: string; - folderUid: string; - updated: string; - updatedBy: LibraryElementDTOMetaUser; -} - -export interface LibraryPanel { - /** - * Panel description - */ - description?: string; - /** - * Folder UID - */ - folderUid?: string; - /** - * Object storage metadata - */ - meta?: LibraryElementDTOMeta; - /** - * TODO: should be the same panel schema defined in dashboard - * Typescript: Omit; - */ - model: Record; - /** - * Panel name (also saved in the model) - */ - name: string; - /** - * Dashboard version when this was saved (zero if unknown) - */ - schemaVersion?: number; - /** - * The panel type (from inside the model) - */ - type: string; - /** - * Library element UID - */ - uid: string; - /** - * panel version, incremented each time the dashboard is updated. - */ - version: number; -} diff --git a/packages/grafana-schema/src/schema/dashboard/v0alpha1/types.status.gen.ts b/packages/grafana-schema/src/schema/dashboard/v0alpha1/types.status.gen.ts index 91bf7909fd3..978b71f39b3 100644 --- a/packages/grafana-schema/src/schema/dashboard/v0alpha1/types.status.gen.ts +++ b/packages/grafana-schema/src/schema/dashboard/v0alpha1/types.status.gen.ts @@ -12,6 +12,8 @@ export interface ConversionStatus { // The version which was stored when the dashboard was created / updated. // Fetching this version should always succeed. storedVersion?: string; + // The original value map[string]any + source?: any; } export const defaultConversionStatus = (): ConversionStatus => ({ diff --git a/packages/grafana-schema/src/schema/dashboard/v1beta1/types.status.gen.ts b/packages/grafana-schema/src/schema/dashboard/v1beta1/types.status.gen.ts index 91bf7909fd3..978b71f39b3 100644 --- a/packages/grafana-schema/src/schema/dashboard/v1beta1/types.status.gen.ts +++ b/packages/grafana-schema/src/schema/dashboard/v1beta1/types.status.gen.ts @@ -12,6 +12,8 @@ export interface ConversionStatus { // The version which was stored when the dashboard was created / updated. // Fetching this version should always succeed. storedVersion?: string; + // The original value map[string]any + source?: any; } export const defaultConversionStatus = (): ConversionStatus => ({ diff --git a/packages/grafana-schema/src/schema/dashboard/v2alpha1/types.spec.gen.ts b/packages/grafana-schema/src/schema/dashboard/v2alpha1/types.spec.gen.ts index 8c6adae3078..6ecb17f191b 100644 --- a/packages/grafana-schema/src/schema/dashboard/v2alpha1/types.spec.gen.ts +++ b/packages/grafana-schema/src/schema/dashboard/v2alpha1/types.spec.gen.ts @@ -1415,6 +1415,7 @@ export const defaultAdHocFilterWithLabels = (): AdHocFilterWithLabels => ({ key: "", operator: "", value: "", + origin: FilterOrigin, }); // Determine the origin of the adhoc variable filter diff --git a/packages/grafana-schema/src/schema/dashboard/v2alpha1/types.status.gen.ts b/packages/grafana-schema/src/schema/dashboard/v2alpha1/types.status.gen.ts index 91bf7909fd3..978b71f39b3 100644 --- a/packages/grafana-schema/src/schema/dashboard/v2alpha1/types.status.gen.ts +++ b/packages/grafana-schema/src/schema/dashboard/v2alpha1/types.status.gen.ts @@ -12,6 +12,8 @@ export interface ConversionStatus { // The version which was stored when the dashboard was created / updated. // Fetching this version should always succeed. storedVersion?: string; + // The original value map[string]any + source?: any; } export const defaultConversionStatus = (): ConversionStatus => ({ diff --git a/packages/grafana-schema/src/schema/dashboard/v2beta1/types.spec.gen.ts b/packages/grafana-schema/src/schema/dashboard/v2beta1/types.spec.gen.ts index 40c2d212d31..19c324f1cd9 100644 --- a/packages/grafana-schema/src/schema/dashboard/v2beta1/types.spec.gen.ts +++ b/packages/grafana-schema/src/schema/dashboard/v2beta1/types.spec.gen.ts @@ -976,6 +976,7 @@ export const defaultDashboardLink = (): DashboardLink => ({ targetBlank: false, includeVars: false, keepTime: false, + placement: DashboardLinkPlacement, }); // Dashboard Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource) @@ -1052,7 +1053,7 @@ export const defaultTimeRangeOption = (): TimeRangeOption => ({ to: "now", }); -export type VariableKind = QueryVariableKind | TextVariableKind | ConstantVariableKind | DatasourceVariableKind | IntervalVariableKind | CustomVariableKind | GroupByVariableKind | AdhocVariableKind; +export type VariableKind = QueryVariableKind | TextVariableKind | ConstantVariableKind | DatasourceVariableKind | IntervalVariableKind | CustomVariableKind | GroupByVariableKind | AdhocVariableKind | SwitchVariableKind; export const defaultVariableKind = (): VariableKind => (defaultQueryVariableKind()); @@ -1427,6 +1428,7 @@ export const defaultAdHocFilterWithLabels = (): AdHocFilterWithLabels => ({ key: "", operator: "", value: "", + origin: FilterOrigin, }); // Determine the origin of the adhoc variable filter @@ -1444,6 +1446,36 @@ export const defaultMetricFindValue = (): MetricFindValue => ({ text: "", }); +export interface SwitchVariableKind { + kind: "SwitchVariable"; + spec: SwitchVariableSpec; +} + +export const defaultSwitchVariableKind = (): SwitchVariableKind => ({ + kind: "SwitchVariable", + spec: defaultSwitchVariableSpec(), +}); + +export interface SwitchVariableSpec { + name: string; + current: string; + enabledValue: string; + disabledValue: string; + label?: string; + hide: VariableHide; + skipUrlSync: boolean; + description?: string; +} + +export const defaultSwitchVariableSpec = (): SwitchVariableSpec => ({ + name: "", + current: "false", + enabledValue: "true", + disabledValue: "false", + hide: "dontHide", + skipUrlSync: false, +}); + export interface Spec { annotations: AnnotationQueryKind[]; // Configuration of dashboard cursor sync behavior. diff --git a/packages/grafana-schema/src/schema/dashboard/v2beta1/types.status.gen.ts b/packages/grafana-schema/src/schema/dashboard/v2beta1/types.status.gen.ts index 91bf7909fd3..978b71f39b3 100644 --- a/packages/grafana-schema/src/schema/dashboard/v2beta1/types.status.gen.ts +++ b/packages/grafana-schema/src/schema/dashboard/v2beta1/types.status.gen.ts @@ -12,6 +12,8 @@ export interface ConversionStatus { // The version which was stored when the dashboard was created / updated. // Fetching this version should always succeed. storedVersion?: string; + // The original value map[string]any + source?: any; } export const defaultConversionStatus = (): ConversionStatus => ({ diff --git a/packages/grafana-schema/src/veneer/librarypanel.types.ts b/packages/grafana-schema/src/veneer/librarypanel.types.ts index 007bb085742..0065ebe25e2 100644 --- a/packages/grafana-schema/src/veneer/librarypanel.types.ts +++ b/packages/grafana-schema/src/veneer/librarypanel.types.ts @@ -1,7 +1,55 @@ -import * as raw from '../raw/librarypanel/x/librarypanel_types.gen'; - import { Panel } from './dashboard.types'; -export interface LibraryPanel extends raw.LibraryPanel { +export interface LibraryElementDTOMetaUser { + avatarUrl: string; + id: number; + name: string; +} + +export interface LibraryElementDTOMeta { + connectedDashboards: number; + created: string; + createdBy: LibraryElementDTOMetaUser; + folderName: string; + folderUid: string; + updated: string; + updatedBy: LibraryElementDTOMetaUser; +} + +export interface LibraryPanel { + /** + * Panel description + */ + description?: string; + /** + * Folder UID + */ + folderUid?: string; + /** + * Object storage metadata + */ + meta?: LibraryElementDTOMeta; + + // The panel model: Omit; + /** + * Panel name (also saved in the model) + */ + name: string; + /** + * Dashboard version when this was saved (zero if unknown) + */ + schemaVersion?: number; + /** + * The panel type (from inside the model) + */ + type: string; + /** + * Library element UID + */ + uid: string; + /** + * panel version, incremented each time the dashboard is updated. + */ + version: number; } diff --git a/packages/grafana-sql/package.json b/packages/grafana-sql/package.json index a0206458ad3..4d97947a200 100644 --- a/packages/grafana-sql/package.json +++ b/packages/grafana-sql/package.json @@ -23,7 +23,7 @@ "@grafana/runtime": "12.3.0-pre", "@grafana/ui": "12.3.0-pre", "@react-awesome-query-builder/ui": "6.6.15", - "immutable": "5.1.3", + "immutable": "5.1.4", "lodash": "4.17.21", "react": "18.3.1", "react-dom": "18.3.1", diff --git a/packages/grafana-sql/src/components/ConfirmModal.tsx b/packages/grafana-sql/src/components/ConfirmModal.tsx index 62eba4bab5b..191c32a6835 100644 --- a/packages/grafana-sql/src/components/ConfirmModal.tsx +++ b/packages/grafana-sql/src/components/ConfirmModal.tsx @@ -2,7 +2,7 @@ import { css } from '@emotion/css'; import { useRef, useEffect } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { Trans } from '@grafana/i18n'; +import { t, Trans } from '@grafana/i18n'; import { Button, Icon, Modal, useStyles2 } from '@grafana/ui'; type ConfirmModalProps = { @@ -33,6 +33,7 @@ export function ConfirmModal({ isOpen, onCancel, onDiscard, onCopy }: ConfirmMod
} + ariaLabel={t('grafana-sql.components.confirm-modal.warning', 'Warning')} onDismiss={onCancel} isOpen={isOpen} > diff --git a/packages/grafana-test-utils/package.json b/packages/grafana-test-utils/package.json index 60e375d77cb..70bf836f843 100644 --- a/packages/grafana-test-utils/package.json +++ b/packages/grafana-test-utils/package.json @@ -53,12 +53,18 @@ "test:ci": "jest --maxWorkers 4" }, "dependencies": { - "msw": "2.10.4" + "chance": "^1.1.13", + "jest-matcher-utils": "29.7.0", + "lodash": "4.17.21", + "msw": "2.10.4", + "rxjs": "7.8.2" }, "devDependencies": { "@swc/core": "1.13.3", "@swc/jest": "^0.2.26", + "@types/chance": "^1.1.7", "@types/jest": "29.5.14", + "@types/lodash": "4.17.20", "@types/node": "22.17.0", "jest": "29.7.0", "typescript": "5.9.2" diff --git a/packages/grafana-test-utils/src/fixtures/index.ts b/packages/grafana-test-utils/src/fixtures/index.ts new file mode 100644 index 00000000000..0fc6300ba49 --- /dev/null +++ b/packages/grafana-test-utils/src/fixtures/index.ts @@ -0,0 +1,8 @@ +import { setupMockStarredDashboards } from './starred'; + +/** + * Reset any stateful fixtures that are used to drive mock handler endpoints + */ +export const resetFixtures = () => { + setupMockStarredDashboards(); +}; diff --git a/packages/grafana-test-utils/src/fixtures/starred.ts b/packages/grafana-test-utils/src/fixtures/starred.ts new file mode 100644 index 00000000000..77150e54c4a --- /dev/null +++ b/packages/grafana-test-utils/src/fixtures/starred.ts @@ -0,0 +1,14 @@ +import { wellFormedTree } from './folders'; + +const [_, { folderA_dashbdD, dashbdD }] = wellFormedTree(); + +const initialStarredDashboards = [dashbdD.item.uid, folderA_dashbdD.item.uid]; + +export const setupMockStarredDashboards = () => { + mockStarredDashboardsMap.clear(); + initialStarredDashboards.forEach((uid) => { + mockStarredDashboardsMap.set(uid, true); + }); +}; + +export const mockStarredDashboardsMap = new Map(); diff --git a/packages/grafana-test-utils/src/handlers/all-handlers.ts b/packages/grafana-test-utils/src/handlers/all-handlers.ts index b3b70fbd4cc..58e94fe83ac 100644 --- a/packages/grafana-test-utils/src/handlers/all-handlers.ts +++ b/packages/grafana-test-utils/src/handlers/all-handlers.ts @@ -1,24 +1,28 @@ import { HttpHandler } from 'msw'; import folderHandlers from './api/folders/handlers'; +import pluginsHandlers from './api/plugins/handlers'; import searchHandlers from './api/search/handlers'; import teamsHandlers from './api/teams/handlers'; import userHandlers from './api/user/handlers'; import appPlatformDashboardv0alpha1Handlers from './apis/dashboard.grafana.app/v0alpha1/handlers'; import appPlatformFolderv1beta1Handlers from './apis/folder.grafana.app/v1beta1/handlers'; import appPlatformIamv0alpha1Handlers from './apis/iam.grafana.app/v0alpha1/handlers'; +import appPlatformPreferencesv1alpha1Handlers from './apis/preferences.grafana.app/v1alpha1/handlers'; const allHandlers: HttpHandler[] = [ // Legacy handlers ...teamsHandlers, ...folderHandlers, ...searchHandlers, + ...pluginsHandlers, ...userHandlers, // App platform handlers ...appPlatformDashboardv0alpha1Handlers, ...appPlatformFolderv1beta1Handlers, ...appPlatformIamv0alpha1Handlers, + ...appPlatformPreferencesv1alpha1Handlers, ]; export default allHandlers; diff --git a/packages/grafana-test-utils/src/handlers/api/plugins/handlers.ts b/packages/grafana-test-utils/src/handlers/api/plugins/handlers.ts new file mode 100644 index 00000000000..0acf25b8bf1 --- /dev/null +++ b/packages/grafana-test-utils/src/handlers/api/plugins/handlers.ts @@ -0,0 +1,6 @@ +import { HttpResponse, http } from 'msw'; + +// TODO: Add more realistic mock plugins data +const getPluginsHandler = () => http.get('/api/plugins', () => HttpResponse.json([])); + +export default [getPluginsHandler()]; diff --git a/packages/grafana-test-utils/src/handlers/api/search/handlers.ts b/packages/grafana-test-utils/src/handlers/api/search/handlers.ts index 84cda34bb0c..2aebd03b174 100644 --- a/packages/grafana-test-utils/src/handlers/api/search/handlers.ts +++ b/packages/grafana-test-utils/src/handlers/api/search/handlers.ts @@ -2,7 +2,7 @@ import { Chance } from 'chance'; import { HttpResponse, http } from 'msw'; import { wellFormedTree } from '../../../fixtures/folders'; -import { mockStarredDashboards } from '../user/handlers'; +import { mockStarredDashboardsMap } from '../../../fixtures/starred'; import { SORT_OPTIONS } from './constants'; @@ -24,6 +24,7 @@ const getLegacySearchHandler = () => // Workaround for the fixture kind being 'dashboard' instead of 'dash-db' const mappedTypeFilter = typeFilter === 'dash-db' ? 'dashboard' : typeFilter; const starredFilter = new URL(request.url).searchParams.get('starred') || null; + const tagFilter = new URL(request.url).searchParams.getAll('tag') || null; const response = mockTree .filter((filterItem) => { @@ -32,8 +33,16 @@ const getLegacySearchHandler = () => ({ item }) => item.kind !== 'ui', ]; + if (tagFilter && tagFilter.length > 0) { + filters.push(({ item }) => + Boolean( + (item.kind === 'folder' || item.kind === 'dashboard') && item.tags?.some((tag) => tagFilter.includes(tag)) + ) + ); + } + if (starredFilter) { - filters.push(({ item }) => mockStarredDashboards.includes(item.uid)); + filters.push(({ item }) => mockStarredDashboardsMap.has(item.uid)); } if (folderFilter && folderFilter !== 'general') { diff --git a/packages/grafana-test-utils/src/handlers/api/user/handlers.ts b/packages/grafana-test-utils/src/handlers/api/user/handlers.ts index 90a7ebe049a..b426f6d0733 100644 --- a/packages/grafana-test-utils/src/handlers/api/user/handlers.ts +++ b/packages/grafana-test-utils/src/handlers/api/user/handlers.ts @@ -1,23 +1,23 @@ import { HttpResponse, http } from 'msw'; -import { wellFormedTree } from '../../../fixtures/folders'; - -const [_, { folderA_dashbdD, dashbdD }] = wellFormedTree(); - -export const mockStarredDashboards = [dashbdD.item.uid, folderA_dashbdD.item.uid]; +import { mockStarredDashboardsMap } from '../../../fixtures/starred'; const getStarsHandler = () => http.get('/api/user/stars', async () => { - return HttpResponse.json(mockStarredDashboards); + return HttpResponse.json(Array.from(mockStarredDashboardsMap.keys())); }); const deleteDashboardStarHandler = () => - http.delete('/api/user/stars/dashboard/uid/:uid', async () => { + http.delete<{ uid: string }>('/api/user/stars/dashboard/uid/:uid', async ({ params }) => { + const { uid } = params; + mockStarredDashboardsMap.delete(uid); return HttpResponse.json({ message: 'Dashboard unstarred' }); }); const addDashboardStarHandler = () => - http.post('/api/user/stars/dashboard/uid/:uid', async () => { + http.post<{ uid: string }>('/api/user/stars/dashboard/uid/:uid', async ({ params }) => { + const { uid } = params; + mockStarredDashboardsMap.set(uid, true); return HttpResponse.json({ message: 'Dashboard starred!' }); }); diff --git a/packages/grafana-test-utils/src/handlers/apis/dashboard.grafana.app/v0alpha1/handlers.ts b/packages/grafana-test-utils/src/handlers/apis/dashboard.grafana.app/v0alpha1/handlers.ts index f6d079755c5..6981201f81f 100644 --- a/packages/grafana-test-utils/src/handlers/apis/dashboard.grafana.app/v0alpha1/handlers.ts +++ b/packages/grafana-test-utils/src/handlers/apis/dashboard.grafana.app/v0alpha1/handlers.ts @@ -23,6 +23,7 @@ const getSearchHandler = () => const typeFilter = new URL(request.url).searchParams.get('type') || null; const nameFilter = new URL(request.url).searchParams.getAll('name'); const mappedTypeFilter = typeFilter ? typeFilterMap[typeFilter] || typeFilter : null; + const tagFilter = new URL(request.url).searchParams.getAll('tag') || null; const filtered = mockTree.filter((filterItem) => { const filters: FilterArray = [ @@ -39,6 +40,14 @@ const getSearchHandler = () => filters.push(({ item }) => item.kind === mappedTypeFilter); } + if (tagFilter && tagFilter.length > 0) { + filters.push(({ item }) => + Boolean( + (item.kind === 'folder' || item.kind === 'dashboard') && item.tags?.some((tag) => tagFilter.includes(tag)) + ) + ); + } + if (folderFilter && folderFilter !== 'general') { filters.push( ({ item }) => (item.kind === 'folder' || item.kind === 'dashboard') && item.parentUID === folderFilter diff --git a/packages/grafana-test-utils/src/handlers/apis/preferences.grafana.app/v1alpha1/handlers.ts b/packages/grafana-test-utils/src/handlers/apis/preferences.grafana.app/v1alpha1/handlers.ts new file mode 100644 index 00000000000..e5ad85df839 --- /dev/null +++ b/packages/grafana-test-utils/src/handlers/apis/preferences.grafana.app/v1alpha1/handlers.ts @@ -0,0 +1,69 @@ +import { HttpResponse, http } from 'msw'; + +import { mockStarredDashboardsMap } from '../../../../fixtures/starred'; + +const getStarsHandler = () => + http.get('/apis/preferences.grafana.app/v1alpha1/namespaces/:namespace/stars', () => { + const mockStarsResponse = { + kind: 'StarsList', + apiVersion: 'preferences.grafana.app/v1alpha1', + metadata: { + resourceVersion: '1758126936000', + }, + items: [ + { + metadata: { + name: 'user-u000000001', + namespace: 'default', + resourceVersion: '1758126936000', + creationTimestamp: '2025-05-14T14:02:10Z', + }, + spec: { + resource: [ + { + group: 'dashboard.grafana.app', + kind: 'Dashboard', + names: Array.from(mockStarredDashboardsMap.keys()), + }, + ], + }, + status: {}, + }, + ], + }; + return HttpResponse.json(mockStarsResponse); + }); + +const UPDATE_STARS_URL = + '/apis/preferences.grafana.app/v1alpha1/namespaces/:namespace/stars/:name/update/:group/:kind/:id'; + +type UpdateOrDeleteStarsParams = { + namespace: string; + name: string; + group: string; + kind: string; + id: string; +}; + +const successResponse = { + kind: 'Status', + apiVersion: 'v1', + metadata: {}, + code: 200, +}; + +const addStarHandler = () => + http.put(UPDATE_STARS_URL, ({ params }) => { + const { id } = params; + mockStarredDashboardsMap.set(id, true); + return HttpResponse.json(successResponse); + }); + +const removeStarHandler = () => + http.delete(UPDATE_STARS_URL, ({ params }) => { + const { id } = params; + mockStarredDashboardsMap.delete(id); + return HttpResponse.json(successResponse); + }); + +export default [getStarsHandler(), removeStarHandler(), addStarHandler()]; diff --git a/packages/grafana-test-utils/src/server/index.ts b/packages/grafana-test-utils/src/server/index.ts index 5b0ba7b0d83..71636cda7ac 100644 --- a/packages/grafana-test-utils/src/server/index.ts +++ b/packages/grafana-test-utils/src/server/index.ts @@ -1,6 +1,7 @@ import { HttpHandler } from 'msw'; import { setupServer } from 'msw/node'; +import { resetFixtures } from '../fixtures'; import allHandlers from '../handlers/all-handlers'; const server = setupServer(...allHandlers); @@ -20,6 +21,10 @@ export function setupMockServer( }); } + beforeEach(() => { + resetFixtures(); + }); + afterEach(() => { server.resetHandlers(); }); diff --git a/packages/grafana-ui/.storybook/preview.ts b/packages/grafana-ui/.storybook/preview.ts index 124981e1434..e245a46646a 100644 --- a/packages/grafana-ui/.storybook/preview.ts +++ b/packages/grafana-ui/.storybook/preview.ts @@ -64,7 +64,18 @@ const preview: Preview = { docs: { container: ThemedDocsContainer, }, - a11y: { test: 'error' }, + a11y: { + test: 'error', + config: { + rules: [ + { + id: 'scrollable-region-focusable', + selector: 'body', + enabled: false, + }, + ], + }, + }, knobs: { disable: true, }, diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index 68110536a26..91dc005eadc 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -75,10 +75,10 @@ "@hello-pangea/dnd": "18.0.1", "@monaco-editor/react": "4.7.0", "@popperjs/core": "2.11.8", - "@react-aria/dialog": "3.5.30", - "@react-aria/focus": "3.21.1", - "@react-aria/overlays": "3.29.1", - "@react-aria/utils": "3.30.1", + "@react-aria/dialog": "3.5.31", + "@react-aria/focus": "3.21.2", + "@react-aria/overlays": "3.30.0", + "@react-aria/utils": "3.31.0", "@tanstack/react-virtual": "^3.5.1", "@types/jquery": "3.5.33", "@types/lodash": "4.17.20", @@ -92,7 +92,7 @@ "hoist-non-react-statics": "3.3.2", "i18next": "^25.0.0", "i18next-browser-languagedetector": "^8.0.0", - "immutable": "5.1.3", + "immutable": "5.1.4", "is-hotkey": "0.2.0", "jquery": "3.7.1", "lodash": "4.17.21", diff --git a/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx b/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx index 271410e32ea..3392f059662 100644 --- a/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx +++ b/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx @@ -147,7 +147,6 @@ export class BarGauge extends PureComponent { lcdCellWidth, text, valueDisplayMode, - theme, isOverflow, } = this.props; const { valueHeight, valueWidth, maxBarHeight, maxBarWidth, wrapperWidth, wrapperHeight } = @@ -195,7 +194,7 @@ export class BarGauge extends PureComponent { const currentValue = minValue + (valueRange / cellCount) * i; const cellColor = getCellColor(currentValue, value, display); const cellStyles: CSSProperties = { - borderRadius: theme.shape.radius.default, + borderRadius: '2px', }; if (cellColor.isLit) { @@ -525,7 +524,7 @@ export function getBasicAndGradientStyles(props: Props): BasicAndGradientStyles }; const barStyles: CSSProperties = { - borderRadius: theme.shape.radius.default, + borderRadius: theme.shape.radius.sm, position: 'relative', }; @@ -533,7 +532,7 @@ export function getBasicAndGradientStyles(props: Props): BasicAndGradientStyles background: theme.colors.background.secondary, flexGrow: 1, display: 'flex', - borderRadius: theme.shape.radius.default, + borderRadius: theme.shape.radius.sm, position: 'relative', }; diff --git a/packages/grafana-ui/src/components/BigValue/BigValue.story.tsx b/packages/grafana-ui/src/components/BigValue/BigValue.story.tsx index 48c45f9843c..f112a86efd1 100644 --- a/packages/grafana-ui/src/components/BigValue/BigValue.story.tsx +++ b/packages/grafana-ui/src/components/BigValue/BigValue.story.tsx @@ -29,27 +29,36 @@ const meta: Meta = { width: { control: { type: 'range', min: 200, max: 800 } }, height: { control: { type: 'range', min: 200, max: 800 } }, colorMode: { - control: { type: 'select', options: [BigValueColorMode.Value, BigValueColorMode.Background] }, + control: { + type: 'select', + }, + options: [BigValueColorMode.Value, BigValueColorMode.Background], + }, + graphMode: { + control: { type: 'select' }, + options: [BigValueGraphMode.Area, BigValueGraphMode.None], + }, + justifyMode: { + control: { type: 'select' }, + options: [BigValueJustifyMode.Auto, BigValueJustifyMode.Center], }, - graphMode: { control: { type: 'select', options: [BigValueGraphMode.Area, BigValueGraphMode.None] } }, - justifyMode: { control: { type: 'select', options: [BigValueJustifyMode.Auto, BigValueJustifyMode.Center] } }, textMode: { control: { type: 'radio', - options: [ - BigValueTextMode.Auto, - BigValueTextMode.Name, - BigValueTextMode.ValueAndName, - BigValueTextMode.None, - BigValueTextMode.Value, - ], }, + options: [ + BigValueTextMode.Auto, + BigValueTextMode.Name, + BigValueTextMode.ValueAndName, + BigValueTextMode.None, + BigValueTextMode.Value, + ], }, color: { control: 'color' }, }, }; -interface StoryProps extends Partial { +interface StoryProps extends Props { numeric: number; title: string; color: string; diff --git a/packages/grafana-ui/src/components/BigValue/BigValue.tsx b/packages/grafana-ui/src/components/BigValue/BigValue.tsx index 6aceeb3660b..08bacf3e2af 100644 --- a/packages/grafana-ui/src/components/BigValue/BigValue.tsx +++ b/packages/grafana-ui/src/components/BigValue/BigValue.tsx @@ -1,6 +1,5 @@ import { cx } from '@emotion/css'; -import { PureComponent } from 'react'; -import * as React from 'react'; +import { memo, type MouseEventHandler } from 'react'; import { DisplayValue, DisplayValueAlignmentFactors, FieldSparkline } from '@grafana/data'; import { PercentChangeColorMode, VizTextDisplayOptions } from '@grafana/schema'; @@ -51,7 +50,7 @@ export interface Props extends Themeable2 { /** Sparkline values for showing a graph under/behind the value */ sparkline?: FieldSparkline; /** onClick handler for the value */ - onClick?: React.MouseEventHandler; + onClick?: MouseEventHandler; /** Custom styling */ className?: string; /** Color mode for coloring the value or the background */ @@ -83,58 +82,55 @@ export interface Props extends Themeable2 { disableWideLayout?: boolean; } -export class BigValue extends PureComponent { - static defaultProps: Partial = { - justifyMode: BigValueJustifyMode.Auto, - }; +export const BigValue = memo((props) => { + const { onClick, className, hasLinks, theme, justifyMode = BigValueJustifyMode.Auto } = props; - render() { - const { onClick, className, hasLinks, theme } = this.props; - const layout = buildLayout(this.props); - const panelStyles = layout.getPanelStyles(); - const valueAndTitleContainerStyles = layout.getValueAndTitleContainerStyles(); - const valueStyles = layout.getValueStyles(); - const titleStyles = layout.getTitleStyles(); - const textValues = layout.textValues; - const percentChange = this.props.value.percentChange; - const percentChangeColorMode = this.props.percentChangeColorMode; - const showPercentChange = percentChange != null && !Number.isNaN(percentChange); + const layout = buildLayout({ ...props, justifyMode }); + const panelStyles = layout.getPanelStyles(); + const valueAndTitleContainerStyles = layout.getValueAndTitleContainerStyles(); + const valueStyles = layout.getValueStyles(); + const titleStyles = layout.getTitleStyles(); + const textValues = layout.textValues; + const percentChange = props.value.percentChange; + const percentChangeColorMode = props.percentChangeColorMode; + const showPercentChange = percentChange != null && !Number.isNaN(percentChange); - // When there is an outer data link this tooltip will override the outer native tooltip - const tooltip = hasLinks ? undefined : textValues.tooltip; - - if (!onClick) { - return ( -
-
- {textValues.title &&
{textValues.title}
} - - {showPercentChange && ( - - )} -
- {layout.renderChart()} -
- ); - } + // When there is an outer data link this tooltip will override the outer native tooltip + const tooltip = hasLinks ? undefined : textValues.tooltip; + if (!onClick) { return ( - + ); } -} + + return ( + + ); +}); + +BigValue.displayName = 'BigValue'; diff --git a/packages/grafana-ui/src/components/BigValue/BigValueLayout.test.tsx b/packages/grafana-ui/src/components/BigValue/BigValueLayout.test.tsx index 8a2cf4aaf25..462e1f5e3dd 100644 --- a/packages/grafana-ui/src/components/BigValue/BigValueLayout.test.tsx +++ b/packages/grafana-ui/src/components/BigValue/BigValueLayout.test.tsx @@ -100,6 +100,28 @@ describe('BigValueLayout', () => { ); expect(layout).toBeInstanceOf(WideWithChartLayout); }); + + it.each([ + ['wide layout', {}], + ['non-wide layout', { disableWideLayout: true }], + ])('should shrink the value if percent change is shown for %s', (_, propsOverride) => { + const baseProps: Partial = { + width: 300, + height: 100, + sparkline: undefined, + alignmentFactors: { + text: '1000', + title: '12', + }, + ...propsOverride, + }; + const layout = buildLayout(getProps(baseProps)); + const layoutWithPercentChange = buildLayout( + getProps({ ...baseProps, value: { text: '25', numeric: 25, percentChange: 20 } }) + ); + + expect(layoutWithPercentChange.valueFontSize).toBeLessThan(layout.valueFontSize); + }); }); describe('percentChangeColor', () => { diff --git a/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx b/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx index a8914563f80..d13408d3271 100644 --- a/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx +++ b/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx @@ -171,7 +171,7 @@ export abstract class BigValueLayout { return { containerStyles, - iconSize: iconSize, + iconSize, }; } @@ -198,7 +198,6 @@ export abstract class BigValueLayout { width: `${width}px`, height: `${height}px`, padding: `${textMode === BigValueTextMode.None ? 2 : this.panelPadding}px`, - borderRadius: theme.shape.radius.default, position: 'relative', display: 'flex', }; @@ -295,11 +294,16 @@ export class WideNoChartLayout extends BigValueLayout { const valueWidthPercent = this.titleToAlignTo?.length ? 0.3 : 1.0; if (this.valueToAlignTo.length) { + let valueHeight = this.maxTextHeight; + if (props.value.percentChange != null) { + // percent change uses 40% of value height, so we want to scale the value font size accordingly + valueHeight = valueHeight * 0.75; + } // initial value size this.valueFontSize = calculateFontSize( this.valueToAlignTo, this.maxTextWidth * valueWidthPercent, - this.maxTextHeight, + valueHeight, LINE_HEIGHT, undefined, VALUE_FONT_WEIGHT @@ -480,10 +484,15 @@ export class StackedWithNoChartLayout extends BigValueLayout { } if (this.valueToAlignTo.length) { + let valueHeight = this.maxTextHeight - titleHeight; + if (props.value.percentChange != null) { + // percent change uses 40% of value height, so we want to scale the value font size accordingly + valueHeight = valueHeight * 0.75; + } this.valueFontSize = calculateFontSize( this.valueToAlignTo, this.maxTextWidth, - this.maxTextHeight - titleHeight, + valueHeight, LINE_HEIGHT, undefined, VALUE_FONT_WEIGHT diff --git a/packages/grafana-ui/src/components/Cascader/Cascader.tsx b/packages/grafana-ui/src/components/Cascader/Cascader.tsx index 9918a77d1b9..ed8c1af953d 100644 --- a/packages/grafana-ui/src/components/Cascader/Cascader.tsx +++ b/packages/grafana-ui/src/components/Cascader/Cascader.tsx @@ -211,11 +211,19 @@ class UnthemedCascader extends PureComponent { if (['ArrowDown', 'ArrowUp', 'Enter', 'ArrowLeft', 'ArrowRight'].includes(e.key)) { return; } - const { activeLabel } = this.state; + + const selectionStart = e.currentTarget.selectionStart; + const selectionEnd = e.currentTarget.selectionEnd; + let inputValue = e.currentTarget.value; + + if (selectionStart !== selectionEnd) { + inputValue = inputValue.substring(0, selectionStart ?? 0) + inputValue.substring(selectionEnd ?? 0); + } + this.setState({ focusCascade: false, isSearching: true, - inputValue: activeLabel, + inputValue: inputValue, }); }; @@ -280,6 +288,9 @@ class UnthemedCascader extends PureComponent { placeholder={placeholder} onBlur={this.onBlurCascade} value={activeLabel} + onFocus={(e) => { + e.currentTarget.select(); + }} onKeyDown={this.onInputKeyDown} onChange={() => {}} suffix={ diff --git a/packages/grafana-ui/src/components/Collapse/CollapsableSection.tsx b/packages/grafana-ui/src/components/Collapse/CollapsableSection.tsx index d6a844b1f18..12c00333dfd 100644 --- a/packages/grafana-ui/src/components/Collapse/CollapsableSection.tsx +++ b/packages/grafana-ui/src/components/Collapse/CollapsableSection.tsx @@ -122,7 +122,9 @@ const collapsableSectionStyles = (theme: GrafanaTheme2) => ({ '&:focus-visible': { outline: 'none', outlineOffset: 'unset', - transition: 'none', + [theme.transitions.handleMotion('no-preference', 'reduce')]: { + transition: 'none', + }, boxShadow: 'none', }, }), diff --git a/packages/grafana-ui/src/components/Collapse/Collapse.tsx b/packages/grafana-ui/src/components/Collapse/Collapse.tsx index 4089959a6ef..57aec7a3ed4 100644 --- a/packages/grafana-ui/src/components/Collapse/Collapse.tsx +++ b/packages/grafana-ui/src/components/Collapse/Collapse.tsx @@ -51,8 +51,14 @@ const getStyles = (theme: GrafanaTheme2) => ({ top: 0, height: '250%', position: 'absolute', - animation: 'loader 2s cubic-bezier(0.17, 0.67, 0.83, 0.67) 500ms', - animationIterationCount: 100, + [theme.transitions.handleMotion('no-preference', 'reduce')]: { + animation: 'loader 2s cubic-bezier(0.17, 0.67, 0.83, 0.67) 500ms', + animationIterationCount: 100, + }, + [theme.transitions.handleMotion('reduce')]: { + animationDuration: '10s', + animationIterationCount: 20, + }, left: '-25%', background: theme.colors.primary.main, }, diff --git a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx index ef916ecc76a..77cd0b63579 100644 --- a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx +++ b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx @@ -196,7 +196,9 @@ const getStyles = (theme: GrafanaTheme2) => { '&:hover': { '.thumb-vertical, .thumb-horizontal': { opacity: 1, - transition: 'opacity 0.3s ease-in-out', + [theme.transitions.handleMotion('no-preference', 'reduce')]: { + transition: 'opacity 0.3s ease-in-out', + }, }, }, }), diff --git a/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap b/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap index bfdedc58db4..9b2114e69f6 100644 --- a/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap +++ b/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap @@ -3,7 +3,7 @@ exports[`CustomScrollbar renders correctly 1`] = `
{ }), drawerMotion: css({ '&-appear': { - transform: 'translateX(100%)', - transition: 'none !important', - + [theme.transitions.handleMotion('no-preference')]: { + transform: 'translateX(100%)', + transition: 'none !important', + }, + [theme.transitions.handleMotion('reduce')]: { + opacity: 0, + }, '&-active': { - transition: `${theme.transitions.create('transform')} !important`, - transform: 'translateX(0)', + [theme.transitions.handleMotion('no-preference')]: { + transform: 'translateX(0)', + transition: `${theme.transitions.create('transform')} !important`, + }, + [theme.transitions.handleMotion('reduce')]: { + transition: `opacity 0.2s ease-in-out`, + opacity: 1, + }, }, }, }), @@ -308,7 +318,9 @@ const getStyles = (theme: GrafanaTheme2) => { '&-active': { opacity: 1, - transition: theme.transitions.create('opacity'), + [theme.transitions.handleMotion('no-preference', 'reduce')]: { + transition: theme.transitions.create('opacity'), + }, }, }, }), diff --git a/packages/grafana-ui/src/components/ErrorBoundary/ErrorBoundary.tsx b/packages/grafana-ui/src/components/ErrorBoundary/ErrorBoundary.tsx index a1bdc9a945f..63044d76d2f 100644 --- a/packages/grafana-ui/src/components/ErrorBoundary/ErrorBoundary.tsx +++ b/packages/grafana-ui/src/components/ErrorBoundary/ErrorBoundary.tsx @@ -44,8 +44,8 @@ export class ErrorBoundary extends PureComponent { this.props.errorLogger(error); } else { faro?.api?.pushError(error, { - type: 'boundary', context: { + type: 'boundary', source: this.props.boundaryName ?? 'unknown', }, }); diff --git a/packages/grafana-ui/src/components/Forms/Checkbox.story.tsx b/packages/grafana-ui/src/components/Forms/Checkbox.story.tsx index f79388911bd..f08f7a996af 100644 --- a/packages/grafana-ui/src/components/Forms/Checkbox.story.tsx +++ b/packages/grafana-ui/src/components/Forms/Checkbox.story.tsx @@ -18,8 +18,6 @@ const meta: Meta = { controls: { exclude: ['value', 'htmlValue'], }, - // TODO fix a11y issue in story and remove this - a11y: { test: 'off' }, }, }; @@ -94,7 +92,7 @@ export const AllStates: StoryFn = (args) => { - + diff --git a/packages/grafana-ui/src/components/Forms/Checkbox.tsx b/packages/grafana-ui/src/components/Forms/Checkbox.tsx index 29b8dc5e699..173f821e287 100644 --- a/packages/grafana-ui/src/components/Forms/Checkbox.tsx +++ b/packages/grafana-ui/src/components/Forms/Checkbox.tsx @@ -18,7 +18,7 @@ export interface CheckboxProps extends Omit, 'value' value?: boolean; /** htmlValue allows to specify the input "value" attribute */ htmlValue?: string | number; - /** Sets the checkbox into a "mixed" state. This is only a visual change and does not affect the value. */ + /** Sets the checkbox into a "mixed" state */ indeterminate?: boolean; /** Show an invalid state around the input */ invalid?: boolean; @@ -39,8 +39,6 @@ export const Checkbox = React.forwardRef( ); const styles = useStyles2(getCheckboxStyles, invalid); - const ariaChecked = indeterminate ? 'mixed' : undefined; - return (