From 75c4c5ca0fd2efa5305b3b8ae13faf86f1d0a7fb Mon Sep 17 00:00:00 2001 From: Matthew Jacobson Date: Wed, 19 Feb 2025 11:49:46 -0500 Subject: [PATCH 01/10] Alerting: Upgrade grafana/alerting to 92d5f29 (#100982) * Alerting: Upgrade grafana/alerting to 92d5f29 Includes: - Add more context to log in PipelineAndStateTimestampCoordinationStage (#277) - Update Alertmanager fork to latest commit (#279) - Copy http client from Grafana (#281) * Satisfy signature change from grafana/alerting #281 (http client) --- go.mod | 2 +- go.sum | 4 ++-- go.work.sum | 21 ++++++++++++++++++- pkg/services/ngalert/notifier/alertmanager.go | 5 ++--- pkg/storage/unified/apistore/go.mod | 2 +- pkg/storage/unified/apistore/go.sum | 4 ++-- pkg/storage/unified/resource/go.mod | 2 +- pkg/storage/unified/resource/go.sum | 4 ++-- 8 files changed, 31 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index 5bd76947b45..06cd809c8e6 100644 --- a/go.mod +++ b/go.mod @@ -71,7 +71,7 @@ require ( github.com/googleapis/gax-go/v2 v2.14.1 // @grafana/grafana-backend-group github.com/gorilla/mux v1.8.1 // @grafana/grafana-backend-group github.com/gorilla/websocket v1.5.3 // @grafana/grafana-app-platform-squad - github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038 // @grafana/alerting-backend + github.com/grafana/alerting v0.0.0-20250218192337-92d5f29b5664 // @grafana/alerting-backend github.com/grafana/authlib v0.0.0-20250219100139-6a3b1bbb50e7 // @grafana/identity-access-team github.com/grafana/authlib/types v0.0.0-20250219092154-21ce22b49f31 // @grafana/identity-access-team github.com/grafana/dataplane/examples v0.0.1 // @grafana/observability-metrics diff --git a/go.sum b/go.sum index 70182a7389d..d8fdfe5fe39 100644 --- a/go.sum +++ b/go.sum @@ -1511,8 +1511,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.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038 h1:dG/UKAjY/KlKp9fY8aEm+gSQHHRmPm5q+9cea3hRSu8= -github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU= +github.com/grafana/alerting v0.0.0-20250218192337-92d5f29b5664 h1:avtd90OVg2wMHz5pUsTWypu4rEt5bn5H0kOLXa7xgqc= +github.com/grafana/alerting v0.0.0-20250218192337-92d5f29b5664/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM= github.com/grafana/authlib v0.0.0-20250219100139-6a3b1bbb50e7 h1:NTMmow+74I3Jb033xhbRgWQS7A//5TDhiM4tl7bsVP4= github.com/grafana/authlib v0.0.0-20250219100139-6a3b1bbb50e7/go.mod h1:T3X4z0ejGfJOiOmZLFeKCRT/yxWJq/RtclAc/PHj/w4= github.com/grafana/authlib/types v0.0.0-20250219092154-21ce22b49f31 h1:EokLC5grHwLPs4tXW8T6E8187H1e5G9AP0QQ5B60HbA= diff --git a/go.work.sum b/go.work.sum index b532fdb1cde..45b22055290 100644 --- a/go.work.sum +++ b/go.work.sum @@ -509,6 +509,7 @@ github.com/elastic/go-sysinfo v1.11.2/go.mod h1:GKqR8bbMK/1ITnez9NIsIfXQr25aLhRJ github.com/elastic/go-windows v1.0.1 h1:AlYZOldA+UJ0/2nBuqWdo90GFCgG9xuyw9SYzGUtJm0= github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/fgprof v0.9.4 h1:ocDNwMFlnA0NU0zSB3I52xkO4sFXk80VK9lXjLClu88= @@ -545,6 +546,7 @@ github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= github.com/go-latex/latex v0.0.0-20231108140139-5c1ce85aa4ea h1:DfZQkvEbdmOe+JK2TMtBM+0I9GSdzE2y/L1/AmD8xKc= github.com/go-latex/latex v0.0.0-20231108140139-5c1ce85aa4ea/go.mod h1:Y7Vld91/HRbTBm7JwoI7HejdDB0u+e9AUBO9MB7yuZk= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= @@ -581,6 +583,7 @@ github.com/gomarkdown/markdown v0.0.0-20230716120725-531d2d74bc12/go.mod h1:JDGc github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws= github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/cel-go v0.22.0/go.mod h1:BuznPXXfQDpXKWQ9sPW3TzlAJN5zzFe+i9tIs0yC4s8= github.com/google/go-jsonnet v0.18.0 h1:/6pTy6g+Jh1a1I2UMoAODkqELFiVIdOxbNwv0DDzoOg= github.com/google/go-jsonnet v0.18.0/go.mod h1:C3fTzyVJDslXdiTqw/bTFk7vSGyCtH3MGRbDfvEwGd0= @@ -606,7 +609,6 @@ github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grafana/authlib/types v0.0.0-20250120144156-d6737a7dc8f5/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM= -github.com/grafana/authlib/types v0.0.0-20250219092154-21ce22b49f31 h1:EokLC5grHwLPs4tXW8T6E8187H1e5G9AP0QQ5B60HbA= github.com/grafana/cloudflare-go v0.0.0-20230110200409-c627cf6792f2 h1:qhugDMdQ4Vp68H0tp/0iN17DM2ehRo1rLEdOFe/gB8I= github.com/grafana/cloudflare-go v0.0.0-20230110200409-c627cf6792f2/go.mod h1:w/aiO1POVIeXUQyl0VQSZjl5OAGDTL5aX+4v0RA1tcw= github.com/grafana/cog v0.0.23 h1:/0CCJ24Z8XXM2DnboSd2FzoIswUroqIZzVr8oJWmMQs= @@ -735,6 +737,7 @@ github.com/mfridman/xflag v0.1.0 h1:TWZrZwG1QklFX5S4j1vxfF1sZbZeZSGofMwPMLAF29M= github.com/mfridman/xflag v0.1.0/go.mod h1:/483ywM5ZO5SuMVjrIGquYNE5CzLrj5Ux/LxWWnjRaE= github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg= github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE= +github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/mitchellh/cli v1.1.5 h1:OxRIeJXpAMztws/XHlN2vu6imG5Dpq+j61AzAX5fLng= @@ -953,6 +956,7 @@ go.einride.tech/aip v0.68.0 h1:4seM66oLzTpz50u4K1zlJyOXQ3tCzcJN7I22tKkjipw= go.einride.tech/aip v0.68.0/go.mod h1:7y9FF8VtPWqpxuAxl0KQWqaULxW4zFIesD6zF5RIHHg= go.etcd.io/gofail v0.1.0 h1:XItAMIhOojXFQMgrxjnd2EIIHun/d5qL0Pf7FzVTkFg= go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M= +go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opentelemetry.io/collector v0.102.1 h1:M/ciCcReQsSDYG9bJ2Qwqk7pQILDJ2bM/l0MdeCAvJE= go.opentelemetry.io/collector v0.102.1/go.mod h1:yF1lDRgL/Eksb4/LUnkMjvLvHHpi6wqBVlzp+dACnPM= go.opentelemetry.io/collector/component v0.102.1 h1:66z+LN5dVCXhvuVKD1b56/3cYLK+mtYSLIwlskYA9IQ= @@ -1029,6 +1033,7 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.5 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= go.opentelemetry.io/contrib/propagators/b3 v1.27.0 h1:IjgxbomVrV9za6bRi8fWCNXENs0co37SZedQilP2hm0= go.opentelemetry.io/contrib/propagators/b3 v1.27.0/go.mod h1:Dv9obQz25lCisDvvs4dy28UPh974CxkahRDUPsY7y9E= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= go.opentelemetry.io/otel/bridge/opencensus v1.27.0 h1:ao9aGGHd+G4YfjBpGs6vbkvt5hoC67STlJA9fCnOAcs= @@ -1049,10 +1054,13 @@ go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0 h1:BJee2iLkfRfl9l go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0/go.mod h1:DIzlHs3DRscCIBU3Y9YSzPfScwnYnzfnCd4g8zA7bZc= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 h1:EVSnY9JbEEW92bEkIYOVMw4q1WJxIAGoFTrtYOzWuRQ= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0/go.mod h1:Ea1N1QQryNXpCD0I1fdLibBAIpQuBkznMmkdKrapk1Y= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= @@ -1064,8 +1072,11 @@ go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc= golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= @@ -1079,9 +1090,12 @@ golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= @@ -1091,8 +1105,11 @@ golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbht golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -1100,9 +1117,11 @@ golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 h1:zf5N6UOrA487eEFacMe golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= diff --git a/pkg/services/ngalert/notifier/alertmanager.go b/pkg/services/ngalert/notifier/alertmanager.go index 63c05aaefdf..2250ae58417 100644 --- a/pkg/services/ngalert/notifier/alertmanager.go +++ b/pkg/services/ngalert/notifier/alertmanager.go @@ -9,6 +9,7 @@ import ( "strconv" "time" + alertingHttp "github.com/grafana/alerting/http" alertingNotify "github.com/grafana/alerting/notify" "github.com/grafana/alerting/notify/stages" "github.com/grafana/alerting/receivers" @@ -408,9 +409,7 @@ func (am *alertmanager) buildReceiverIntegrations(receiver *alertingNotify.APIRe tmpl, img, LoggerFactory, - func(n receivers.Metadata) (receivers.WebhookSender, error) { - return s, nil - }, + alertingHttp.DefaultClientConfiguration, func(n receivers.Metadata) (receivers.EmailSender, error) { return s, nil }, diff --git a/pkg/storage/unified/apistore/go.mod b/pkg/storage/unified/apistore/go.mod index 6733e336ea4..14c3d477026 100644 --- a/pkg/storage/unified/apistore/go.mod +++ b/pkg/storage/unified/apistore/go.mod @@ -192,7 +192,7 @@ require ( github.com/googleapis/gax-go/v2 v2.14.1 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038 // indirect + github.com/grafana/alerting v0.0.0-20250218192337-92d5f29b5664 // indirect github.com/grafana/authlib v0.0.0-20250219100139-6a3b1bbb50e7 // indirect github.com/grafana/dataplane/sdata v0.0.9 // indirect github.com/grafana/dskit v0.0.0-20241105154643-a6b453a88040 // indirect diff --git a/pkg/storage/unified/apistore/go.sum b/pkg/storage/unified/apistore/go.sum index 44e6bd2c091..42ff04a48e9 100644 --- a/pkg/storage/unified/apistore/go.sum +++ b/pkg/storage/unified/apistore/go.sum @@ -566,8 +566,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.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038 h1:dG/UKAjY/KlKp9fY8aEm+gSQHHRmPm5q+9cea3hRSu8= -github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU= +github.com/grafana/alerting v0.0.0-20250218192337-92d5f29b5664 h1:avtd90OVg2wMHz5pUsTWypu4rEt5bn5H0kOLXa7xgqc= +github.com/grafana/alerting v0.0.0-20250218192337-92d5f29b5664/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM= github.com/grafana/authlib v0.0.0-20250219100139-6a3b1bbb50e7 h1:NTMmow+74I3Jb033xhbRgWQS7A//5TDhiM4tl7bsVP4= github.com/grafana/authlib v0.0.0-20250219100139-6a3b1bbb50e7/go.mod h1:T3X4z0ejGfJOiOmZLFeKCRT/yxWJq/RtclAc/PHj/w4= github.com/grafana/authlib/types v0.0.0-20250219092154-21ce22b49f31 h1:EokLC5grHwLPs4tXW8T6E8187H1e5G9AP0QQ5B60HbA= diff --git a/pkg/storage/unified/resource/go.mod b/pkg/storage/unified/resource/go.mod index a4360087f06..82aff1d7974 100644 --- a/pkg/storage/unified/resource/go.mod +++ b/pkg/storage/unified/resource/go.mod @@ -116,7 +116,7 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect github.com/googleapis/gax-go/v2 v2.14.1 // indirect github.com/gorilla/mux v1.8.1 // indirect - github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038 // indirect + github.com/grafana/alerting v0.0.0-20250218192337-92d5f29b5664 // indirect github.com/grafana/dataplane/sdata v0.0.9 // indirect github.com/grafana/grafana-app-sdk/logging v0.30.0 // indirect github.com/grafana/grafana-aws-sdk v0.31.5 // indirect diff --git a/pkg/storage/unified/resource/go.sum b/pkg/storage/unified/resource/go.sum index ca5165f2a1f..666d232f374 100644 --- a/pkg/storage/unified/resource/go.sum +++ b/pkg/storage/unified/resource/go.sum @@ -397,8 +397,8 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038 h1:dG/UKAjY/KlKp9fY8aEm+gSQHHRmPm5q+9cea3hRSu8= -github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU= +github.com/grafana/alerting v0.0.0-20250218192337-92d5f29b5664 h1:avtd90OVg2wMHz5pUsTWypu4rEt5bn5H0kOLXa7xgqc= +github.com/grafana/alerting v0.0.0-20250218192337-92d5f29b5664/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM= github.com/grafana/authlib v0.0.0-20250219100139-6a3b1bbb50e7 h1:NTMmow+74I3Jb033xhbRgWQS7A//5TDhiM4tl7bsVP4= github.com/grafana/authlib v0.0.0-20250219100139-6a3b1bbb50e7/go.mod h1:T3X4z0ejGfJOiOmZLFeKCRT/yxWJq/RtclAc/PHj/w4= github.com/grafana/authlib/types v0.0.0-20250219092154-21ce22b49f31 h1:EokLC5grHwLPs4tXW8T6E8187H1e5G9AP0QQ5B60HbA= From 2d3de82ae990971f3f47e9528766287fdf951112 Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Wed, 19 Feb 2025 17:54:25 +0100 Subject: [PATCH 02/10] Frontend sandbox: Improve signature elegibility check to avoid extra requests (#100980) * Frontend sandbox: Improve signature elegibility check to avoid extra requests * remove caching element --- .../sandbox/sandbox_plugin_loader_registry.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/public/app/features/plugins/sandbox/sandbox_plugin_loader_registry.ts b/public/app/features/plugins/sandbox/sandbox_plugin_loader_registry.ts index 0d954d4ae75..2dbef3be1e1 100644 --- a/public/app/features/plugins/sandbox/sandbox_plugin_loader_registry.ts +++ b/public/app/features/plugins/sandbox/sandbox_plugin_loader_registry.ts @@ -62,21 +62,24 @@ export async function isPluginFrontendSandboxEligible({ return false; } - // don't run grafana-signed plugins in sandbox + // grafana signature and internal plugins are not allowed in the sandbox + return isPluginSignatureEligibleForSandbox({ pluginId }); +} + +async function isPluginSignatureEligibleForSandbox({ pluginId }: SandboxEligibilityCheckParams): Promise { try { - //this can fail if gcom is not accesible - const details = await getPluginDetails(pluginId); - return details.signatureType !== PluginSignatureType.grafana && details.signature !== 'internal'; + // this can fail if we are trying to fetch settings of a non-installed plugin + const pluginMeta = await getPluginSettings(pluginId, { showErrorAlert: false }); + return pluginMeta.signatureType !== PluginSignatureType.grafana && pluginMeta.signature !== 'internal'; } catch (e) { try { - // this can fail if we are trying to fetch settings of a non-installed plugin - const pluginMeta = await getPluginSettings(pluginId, { showErrorAlert: false }); - return pluginMeta.signatureType !== PluginSignatureType.grafana && pluginMeta.signature !== 'internal'; + //this can fail if gcom is not accesible + const details = await getPluginDetails(pluginId); + return details.signatureType !== PluginSignatureType.grafana && details.signature !== 'internal'; } catch (e) { return false; } } - return true; } /** From 8986df26a50351b79d14f05e20cb97cea3e8abe0 Mon Sep 17 00:00:00 2001 From: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Date: Wed, 19 Feb 2025 18:10:58 +0100 Subject: [PATCH 03/10] Azure Monitor: Set error source in http and user errors accordingly (#100873) --- pkg/tsdb/azuremonitor/azmoncredentials/builder.go | 4 +++- pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource.go | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pkg/tsdb/azuremonitor/azmoncredentials/builder.go b/pkg/tsdb/azuremonitor/azmoncredentials/builder.go index 30c98ec4915..69bb4582dab 100644 --- a/pkg/tsdb/azuremonitor/azmoncredentials/builder.go +++ b/pkg/tsdb/azuremonitor/azmoncredentials/builder.go @@ -1,10 +1,12 @@ package azmoncredentials import ( + "errors" "fmt" "github.com/grafana/grafana-azure-sdk-go/v2/azcredentials" "github.com/grafana/grafana-azure-sdk-go/v2/azsettings" + "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/data/utils/maputil" ) @@ -95,7 +97,7 @@ func getFromLegacy(data map[string]interface{}, secureData map[string]string) (a clientSecret := secureData["clientSecret"] if secureData["clientSecret"] == "" { - return nil, fmt.Errorf("unable to instantiate credentials, clientSecret must be set") + return nil, backend.DownstreamError(errors.New("unable to instantiate credentials, clientSecret must be set")) } credentials := &azcredentials.AzureClientSecretCredentials{ diff --git a/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource.go b/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource.go index 88e1c72db63..d8e2b99ce25 100644 --- a/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource.go +++ b/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource.go @@ -269,7 +269,11 @@ func (e *AzureMonitorDatasource) retrieveSubscriptionDetails(cli *http.Client, c res, err := cli.Do(req) if err != nil { - return "", fmt.Errorf("failed to request subscription details: %s", err) + err = fmt.Errorf("failed to request subscription details: %s", err) + if backend.IsDownstreamHTTPError(err) { + err = backend.DownstreamError(err) + } + return "", err } defer func() { From ff1b22297c7073178f47a48ecec4d8b452c6f74c Mon Sep 17 00:00:00 2001 From: Haris Rozajac <58232930+harisrozajac@users.noreply.github.com> Date: Wed, 19 Feb 2025 10:35:00 -0700 Subject: [PATCH 04/10] Dashboard Schema V2: Delete dashboard (#100929) * working version wip * add TODO * support alert success for k8s --- public/app/features/apiserver/client.ts | 6 ++-- public/app/features/apiserver/types.ts | 2 +- .../api/browseDashboardsAPI.ts | 29 ++++++++++++++----- public/app/features/dashboard/api/legacy.ts | 4 ++- public/app/features/dashboard/api/v0.ts | 2 +- public/app/features/dashboard/api/v2.ts | 6 +++- 6 files changed, 36 insertions(+), 13 deletions(-) diff --git a/public/app/features/apiserver/client.ts b/public/app/features/apiserver/client.ts index f631aca175a..cb53c57aa65 100644 --- a/public/app/features/apiserver/client.ts +++ b/public/app/features/apiserver/client.ts @@ -114,8 +114,10 @@ export class ScopedResourceClient implements return getBackendSrv().put>(`${this.url}/${obj.metadata.name}`, obj); } - public async delete(name: string): Promise { - return getBackendSrv().delete(`${this.url}/${name}`); + public async delete(name: string, showSuccessAlert: boolean): Promise { + return getBackendSrv().delete(`${this.url}/${name}`, undefined, { + showSuccessAlert, + }); } private parseListOptionsSelector = parseListOptionsSelector; diff --git a/public/app/features/apiserver/types.ts b/public/app/features/apiserver/types.ts index 5db483b3f28..89f15d33a80 100644 --- a/public/app/features/apiserver/types.ts +++ b/public/app/features/apiserver/types.ts @@ -209,7 +209,7 @@ export interface ResourceClient { subresource(name: string, path: string): Promise; list(opts?: ListOptions): Promise>; update(obj: ResourceForCreate): Promise>; - delete(name: string): Promise; + delete(name: string, showSuccessAlert?: boolean): Promise; } export interface K8sAPIGroup { diff --git a/public/app/features/browse-dashboards/api/browseDashboardsAPI.ts b/public/app/features/browse-dashboards/api/browseDashboardsAPI.ts index 93a0df6d8c4..fb411699d8a 100644 --- a/public/app/features/browse-dashboards/api/browseDashboardsAPI.ts +++ b/public/app/features/browse-dashboards/api/browseDashboardsAPI.ts @@ -300,17 +300,32 @@ export const browseDashboardsAPI = createApi({ // Delete all the dashboards sequentially // TODO error handling here for (const dashboardUID of selectedDashboards) { - const response = getDashboardAPI().deleteDashboard(dashboardUID, false); + const response = await getDashboardAPI().deleteDashboard(dashboardUID, true); - // @ts-expect-error - const name = response?.data?.title; + // handling success alerts for these feature toggles + // for legacy response, the success alert will be triggered by showSuccessAlert function in public/app/core/services/backend_srv.ts + if (config.featureToggles.dashboardRestore) { + const name = response?.title; - if (name) { + if (name) { + const payload = + config.featureToggles.useV2DashboardsAPI || config.featureToggles.kubernetesDashboards + ? ['Dashboard moved to Recently deleted'] + : [ + t('browse-dashboards.soft-delete.success', 'Dashboard {{name}} moved to Recently deleted', { + name, + }), + ]; + + appEvents.publish({ + type: AppEvents.alertSuccess.name, + payload, + }); + } + } else if (config.featureToggles.useV2DashboardsAPI || config.featureToggles.kubernetesDashboards) { appEvents.publish({ type: AppEvents.alertSuccess.name, - payload: [ - t('browse-dashboards.soft-delete.success', 'Dashboard {{name}} moved to Recently deleted', { name }), - ], + payload: ['Dashboard deleted'], }); } } diff --git a/public/app/features/dashboard/api/legacy.ts b/public/app/features/dashboard/api/legacy.ts index 1a4ff247307..64ae8975db0 100644 --- a/public/app/features/dashboard/api/legacy.ts +++ b/public/app/features/dashboard/api/legacy.ts @@ -25,7 +25,9 @@ export class LegacyDashboardAPI implements DashboardAPI } deleteDashboard(uid: string, showSuccessAlert: boolean): Promise { - return getBackendSrv().delete(`/api/dashboards/uid/${uid}`, { showSuccessAlert }); + return getBackendSrv().delete(`/api/dashboards/uid/${uid}`, undefined, { + showSuccessAlert, + }); } async getDashboardDTO(uid: string, params?: UrlQueryMap) { diff --git a/public/app/features/dashboard/api/v0.ts b/public/app/features/dashboard/api/v0.ts index f06e4e81000..f4d90551a66 100644 --- a/public/app/features/dashboard/api/v0.ts +++ b/public/app/features/dashboard/api/v0.ts @@ -85,7 +85,7 @@ export class K8sDashboardAPI implements DashboardAPI { } deleteDashboard(uid: string, showSuccessAlert: boolean): Promise { - return this.client.delete(uid).then((v) => ({ + return this.client.delete(uid, showSuccessAlert).then((v) => ({ id: 0, message: v.message, title: 'deleted', diff --git a/public/app/features/dashboard/api/v2.ts b/public/app/features/dashboard/api/v2.ts index ca9bb75745e..2913f313144 100644 --- a/public/app/features/dashboard/api/v2.ts +++ b/public/app/features/dashboard/api/v2.ts @@ -87,7 +87,11 @@ export class K8sDashboardV2API } deleteDashboard(uid: string, showSuccessAlert: boolean): Promise { - throw new Error('Method not implemented.'); + return this.client.delete(uid, showSuccessAlert).then((v) => ({ + id: 0, + message: v.message, + title: 'deleted', + })); } async saveDashboard(options: SaveDashboardCommand): Promise { From 95278d7552eb85311a4fc38810c2a68664dd2f59 Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Wed, 19 Feb 2025 11:06:26 -0700 Subject: [PATCH 05/10] K8s: Folders: Add pagination for children (#100978) --- .../folderimpl/folder_unifiedstorage.go | 10 +- .../folderimpl/folder_unifiedstorage_test.go | 8 +- .../folder/folderimpl/unifiedstore.go | 74 ++++++-- .../folder/folderimpl/unifiedstore_test.go | 161 ++++++++++++++++++ 4 files changed, 233 insertions(+), 20 deletions(-) diff --git a/pkg/services/folder/folderimpl/folder_unifiedstorage.go b/pkg/services/folder/folderimpl/folder_unifiedstorage.go index 283f119accd..92bb8e7180e 100644 --- a/pkg/services/folder/folderimpl/folder_unifiedstorage.go +++ b/pkg/services/folder/folderimpl/folder_unifiedstorage.go @@ -33,6 +33,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +const folderSearchLimit = 100000 + func (s *Service) getFoldersFromApiServer(ctx context.Context, q folder.GetFoldersQuery) ([]*folder.Folder, error) { if q.SignedInUser == nil { return nil, folder.ErrBadRequest.Errorf("missing signed in user") @@ -171,7 +173,7 @@ func (s *Service) searchFoldersFromApiServer(ctx context.Context, query folder.S Fields: []*resource.Requirement{}, Labels: []*resource.Requirement{}, }, - Limit: 100000} + Limit: folderSearchLimit} if len(query.UIDs) > 0 { request.Options.Fields = []*resource.Requirement{{ @@ -269,7 +271,7 @@ func (s *Service) getFolderByIDFromApiServer(ctx context.Context, id int64, orgI }, }, }, - Limit: 100000} + Limit: folderSearchLimit} res, err := s.k8sclient.Search(ctx, orgID, request) if err != nil { @@ -322,7 +324,7 @@ func (s *Service) getFolderByTitleFromApiServer(ctx context.Context, orgID int64 }, Labels: []*resource.Requirement{}, }, - Limit: 100000} + Limit: folderSearchLimit} if parentUID != nil { req := []*resource.Requirement{{ @@ -671,7 +673,7 @@ func (s *Service) deleteFromApiServer(ctx context.Context, cmd *folder.DeleteFol }, }, }, - Limit: 100000} + Limit: folderSearchLimit} res, err := s.dashboardK8sClient.Search(ctx, cmd.OrgID, request) if err != nil { diff --git a/pkg/services/folder/folderimpl/folder_unifiedstorage_test.go b/pkg/services/folder/folderimpl/folder_unifiedstorage_test.go index 04aab0fa8b0..6ed300d80f5 100644 --- a/pkg/services/folder/folderimpl/folder_unifiedstorage_test.go +++ b/pkg/services/folder/folderimpl/folder_unifiedstorage_test.go @@ -554,7 +554,7 @@ func TestSearchFoldersFromApiServer(t *testing.T) { }, Labels: []*resource.Requirement{}, }, - Limit: 100000}).Return(&resource.ResourceSearchResponse{ + Limit: folderSearchLimit}).Return(&resource.ResourceSearchResponse{ Results: &resource.ResourceTable{ Columns: []*resource.ResourceTableColumnDefinition{ { @@ -649,7 +649,7 @@ func TestSearchFoldersFromApiServer(t *testing.T) { }, }, }, - Limit: 100000}).Return(&resource.ResourceSearchResponse{ + Limit: folderSearchLimit}).Return(&resource.ResourceSearchResponse{ Results: &resource.ResourceTable{ Columns: []*resource.ResourceTableColumnDefinition{ { @@ -716,7 +716,7 @@ func TestSearchFoldersFromApiServer(t *testing.T) { }, Query: "*test*", Fields: dashboardsearch.IncludeFields, - Limit: 100000}).Return(&resource.ResourceSearchResponse{ + Limit: folderSearchLimit}).Return(&resource.ResourceSearchResponse{ Results: &resource.ResourceTable{ Columns: []*resource.ResourceTableColumnDefinition{ { @@ -829,7 +829,7 @@ func TestDeleteFoldersFromApiServer(t *testing.T) { }, }, }, - Limit: 100000}).Return(&resource.ResourceSearchResponse{ + Limit: folderSearchLimit}).Return(&resource.ResourceSearchResponse{ Results: &resource.ResourceTable{ Columns: []*resource.ResourceTableColumnDefinition{ { diff --git a/pkg/services/folder/folderimpl/unifiedstore.go b/pkg/services/folder/folderimpl/unifiedstore.go index c46f9ada849..12452a7f2de 100644 --- a/pkg/services/folder/folderimpl/unifiedstore.go +++ b/pkg/services/folder/folderimpl/unifiedstore.go @@ -8,14 +8,19 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/selection" + claims "github.com/grafana/authlib/types" "github.com/grafana/grafana/pkg/apimachinery/utils" + "github.com/grafana/grafana/pkg/storage/unified/resource" "github.com/grafana/grafana/pkg/apis/folder/v0alpha1" "github.com/grafana/grafana/pkg/infra/log" internalfolders "github.com/grafana/grafana/pkg/registry/apis/folders" + "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/apiserver/client" "github.com/grafana/grafana/pkg/services/dashboards" + dashboardsearch "github.com/grafana/grafana/pkg/services/dashboards/service/search" "github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/util" @@ -159,26 +164,71 @@ func (ss *FolderUnifiedStoreImpl) GetParents(ctx context.Context, q folder.GetPa } func (ss *FolderUnifiedStoreImpl) GetChildren(ctx context.Context, q folder.GetChildrenQuery) ([]*folder.Folder, error) { - out, err := ss.k8sclient.List(ctx, q.OrgID, v1.ListOptions{}) + // the general folder is saved as an empty string in the database + if q.UID == folder.GeneralFolderUID { + q.UID = "" + } + if q.Limit == 0 { + q.Limit = folderSearchLimit + } + if q.Page == 0 { + q.Page = 1 + } + + req := &resource.ResourceSearchRequest{ + Options: &resource.ListOptions{ + Fields: []*resource.Requirement{ + { + Key: resource.SEARCH_FIELD_FOLDER, + Operator: string(selection.In), + Values: []string{q.UID}, + }, + }, + }, + Limit: q.Limit, + // legacy fallback search requires page, unistore requires offset, + // so set both + Offset: q.Limit * (q.Page - 1), + Page: q.Page, + } + + // only filter the folder UIDs if they are provided in the query + if len(q.FolderUIDs) > 0 { + req.Options.Fields = append(req.Options.Fields, &resource.Requirement{ + Key: resource.SEARCH_FIELD_NAME, + Operator: string(selection.In), + Values: q.FolderUIDs, + }) + } + + // now, get children of the parent folder + out, err := ss.k8sclient.Search(ctx, q.OrgID, req) if err != nil { return nil, err } + res, err := dashboardsearch.ParseResults(out, 0) + if err != nil { + return nil, err + } + + allowK6Folder := (q.SignedInUser != nil && q.SignedInUser.IsIdentityType(claims.TypeServiceAccount)) hits := make([]*folder.Folder, 0) - for _, item := range out.Items { - // convert item to legacy folder format - f, err := ss.UnstructuredToLegacyFolder(ctx, &item) - if f == nil { - return nil, fmt.Errorf("unable to convert unstructured item to legacy folder %w", err) + for _, item := range res.Hits { + // filter out k6 folders if request is not from a service account + if item.Name == accesscontrol.K6FolderUID && !allowK6Folder { + continue } - // it we are at root level, skip subfolder - if q.UID == "" && f.ParentUID != "" { - continue // query filter + // search only returns a subset of info, get all info of the folder + item, err := ss.k8sclient.Get(ctx, item.Name, q.OrgID, v1.GetOptions{}) + if err != nil { + return nil, err } - // if we are at a nested folder, then skip folders that don't belong to parentUid - if q.UID != "" && !strings.EqualFold(f.ParentUID, q.UID) { - continue + + f, err := ss.UnstructuredToLegacyFolder(ctx, item) + if err != nil { + return nil, err } hits = append(hits, f) diff --git a/pkg/services/folder/folderimpl/unifiedstore_test.go b/pkg/services/folder/folderimpl/unifiedstore_test.go index d25cffa6e27..89c68f6d0df 100644 --- a/pkg/services/folder/folderimpl/unifiedstore_test.go +++ b/pkg/services/folder/folderimpl/unifiedstore_test.go @@ -1,10 +1,19 @@ package folderimpl import ( + "context" "testing" + claims "github.com/grafana/authlib/types" + "github.com/grafana/grafana/pkg/apimachinery/identity" + "github.com/grafana/grafana/pkg/services/accesscontrol" + "github.com/grafana/grafana/pkg/services/apiserver/client" "github.com/grafana/grafana/pkg/services/folder" + "github.com/grafana/grafana/pkg/storage/unified/resource" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/selection" ) func TestComputeFullPath(t *testing.T) { @@ -75,3 +84,155 @@ func TestComputeFullPath(t *testing.T) { }) } } + +func TestGetChildren(t *testing.T) { + mockCli := new(client.MockK8sHandler) + store := FolderUnifiedStoreImpl{ + k8sclient: mockCli, + } + + ctx := context.Background() + orgID := int64(2) + + t.Run("should be able to find children folders, and set defaults for pages", func(t *testing.T) { + mockCli.On("Search", mock.Anything, orgID, &resource.ResourceSearchRequest{ + Options: &resource.ListOptions{ + Fields: []*resource.Requirement{ + { + Key: resource.SEARCH_FIELD_FOLDER, + Operator: string(selection.In), + Values: []string{"folder1"}, + }, + }, + }, + Limit: folderSearchLimit, // should default to folderSearchLimit + Offset: 0, // should be set as limit * (page - 1) + Page: 1, // should be set to 1 by default + }).Return(&resource.ResourceSearchResponse{ + Results: &resource.ResourceTable{ + Columns: []*resource.ResourceTableColumnDefinition{ + {Name: "folder", Type: resource.ResourceTableColumnDefinition_STRING}, + }, + Rows: []*resource.ResourceTableRow{ + { + Key: &resource.ResourceKey{Name: "folder2", Resource: "folder"}, + Cells: [][]byte{[]byte("folder1")}, + }, + { + Key: &resource.ResourceKey{Name: "folder3", Resource: "folder"}, + Cells: [][]byte{[]byte("folder1")}, + }, + }, + }, + TotalHits: 1, + }, nil).Once() + mockCli.On("Get", mock.Anything, "folder2", orgID, mock.Anything, mock.Anything).Return(&unstructured.Unstructured{ + Object: map[string]interface{}{ + "metadata": map[string]interface{}{"name": "folder2"}, + }, + }, nil).Once() + mockCli.On("Get", mock.Anything, "folder3", orgID, mock.Anything, mock.Anything).Return(&unstructured.Unstructured{ + Object: map[string]interface{}{ + "metadata": map[string]interface{}{"name": "folder3"}, + }, + }, nil).Once() + + // don't set page or limit - should be automatically added + result, err := store.GetChildren(ctx, folder.GetChildrenQuery{ + UID: "folder1", + OrgID: orgID, + }) + require.NoError(t, err) + require.Len(t, result, 2) + require.Equal(t, "folder2", result[0].UID) + require.Equal(t, "folder3", result[1].UID) + }) + + t.Run("pages should be able to be set, general folder should be turned to empty string, and folder uids should be passed in", func(t *testing.T) { + mockCli.On("Search", mock.Anything, orgID, &resource.ResourceSearchRequest{ + Options: &resource.ListOptions{ + Fields: []*resource.Requirement{ + { + Key: resource.SEARCH_FIELD_FOLDER, + Operator: string(selection.In), + Values: []string{""}, // should be an empty string if general is passed in + }, + { + Key: resource.SEARCH_FIELD_NAME, + Operator: string(selection.In), + Values: []string{"folder2"}, + }, + }, + }, + Limit: 10, + Offset: 20, // should be set as limit * (page - 1) + Page: 3, + }).Return(&resource.ResourceSearchResponse{ + Results: &resource.ResourceTable{ + Columns: []*resource.ResourceTableColumnDefinition{ + {Name: "folder", Type: resource.ResourceTableColumnDefinition_STRING}, + }, + Rows: []*resource.ResourceTableRow{ + { + Key: &resource.ResourceKey{Name: "folder2", Resource: "folder"}, + Cells: [][]byte{[]byte("folder1")}, + }, + }, + }, + TotalHits: 1, + }, nil).Once() + mockCli.On("Get", mock.Anything, "folder2", orgID, mock.Anything, mock.Anything).Return(&unstructured.Unstructured{ + Object: map[string]interface{}{ + "metadata": map[string]interface{}{"name": "folder2"}, + }, + }, nil).Once() + + result, err := store.GetChildren(ctx, folder.GetChildrenQuery{ + UID: "general", + OrgID: orgID, + Limit: 10, + Page: 3, + FolderUIDs: []string{"folder2"}, + }) + require.NoError(t, err) + require.Len(t, result, 1) + require.Equal(t, "folder2", result[0].UID) + }) + + t.Run("k6 folder should only be returned to service accounts", func(t *testing.T) { + mockCli.On("Search", mock.Anything, orgID, mock.Anything).Return(&resource.ResourceSearchResponse{ + Results: &resource.ResourceTable{ + Columns: []*resource.ResourceTableColumnDefinition{ + {Name: "folder", Type: resource.ResourceTableColumnDefinition_STRING}, + }, + Rows: []*resource.ResourceTableRow{ + { + Key: &resource.ResourceKey{Name: accesscontrol.K6FolderUID, Resource: "folder"}, + Cells: [][]byte{[]byte("folder1")}, + }, + }, + }, + TotalHits: 1, + }, nil) + mockCli.On("Get", mock.Anything, accesscontrol.K6FolderUID, orgID, mock.Anything, mock.Anything).Return(&unstructured.Unstructured{ + Object: map[string]interface{}{ + "metadata": map[string]interface{}{"name": accesscontrol.K6FolderUID}, + }, + }, nil) + + result, err := store.GetChildren(ctx, folder.GetChildrenQuery{ + UID: "folder", + OrgID: orgID, + }) + require.NoError(t, err) + require.Len(t, result, 0) + + result, err = store.GetChildren(ctx, folder.GetChildrenQuery{ + UID: "folder", + OrgID: orgID, + SignedInUser: &identity.StaticRequester{Type: claims.TypeServiceAccount}, + }) + require.NoError(t, err) + require.Len(t, result, 1) + }) +} From fd377cfe665b6f6182c5dc12b8e932e0c96fc18e Mon Sep 17 00:00:00 2001 From: maicon Date: Wed, 19 Feb 2025 15:29:57 -0300 Subject: [PATCH 06/10] Unistore: map grpc status to http status (#100942) * Unistore: map grpc status to http status Signed-off-by: Maicon Costa --------- Signed-off-by: Maicon Costa Co-authored-by: Georges Chaudy --- pkg/storage/unified/apistore/store.go | 17 ++++---- pkg/storage/unified/apistore/store_test.go | 49 ++++++++++++++++++++++ pkg/storage/unified/resource/errors.go | 13 +++++- pkg/storage/unified/resource/go.mod | 2 +- 4 files changed, 70 insertions(+), 11 deletions(-) diff --git a/pkg/storage/unified/apistore/store.go b/pkg/storage/unified/apistore/store.go index 472952b2c2f..8d3da4b7c33 100644 --- a/pkg/storage/unified/apistore/store.go +++ b/pkg/storage/unified/apistore/store.go @@ -171,7 +171,7 @@ func (s *Storage) Create(ctx context.Context, key string, obj runtime.Object, ou } rsp, err := s.store.Create(ctx, req) if err != nil { - return err + return resource.GetError(resource.AsErrorResult(err)) } if rsp.Error != nil { if rsp.Error.Code == http.StatusConflict { @@ -249,7 +249,7 @@ func (s *Storage) Delete( } rsp, err := s.store.Delete(ctx, cmd) if err != nil { - return err + return resource.GetError(resource.AsErrorResult(err)) } if rsp.Error != nil { return resource.GetError(rsp.Error) @@ -289,7 +289,8 @@ func (s *Storage) Watch(ctx context.Context, key string, opts storage.ListOption if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) || errors.Is(err, io.EOF) { return watch.NewEmptyWatch(), nil } - return nil, err + + return nil, resource.GetError(resource.AsErrorResult(err)) } reporter := apierrors.NewClientErrorReporter(500, "WATCH", "") @@ -323,7 +324,7 @@ func (s *Storage) Get(ctx context.Context, key string, opts storage.GetOptions, rsp, err := s.store.Read(ctx, req) if err != nil { - return err + return resource.GetError(resource.AsErrorResult(err)) } if rsp.Error != nil { if rsp.Error.Code == http.StatusNotFound { @@ -361,7 +362,7 @@ func (s *Storage) GetList(ctx context.Context, key string, opts storage.ListOpti rsp, err := s.store.List(ctx, req) if err != nil { - return err + return resource.GetError(resource.AsErrorResult(err)) } if rsp.Error != nil { return resource.GetError(rsp.Error) @@ -469,7 +470,7 @@ func (s *Storage) GuaranteedUpdate( // Read the latest value rsp, err := s.store.Read(ctx, &resource.ReadRequest{Key: req.Key}) if err != nil { - return err + return resource.GetError(resource.AsErrorResult(err)) } if rsp.Error != nil { @@ -554,7 +555,7 @@ func (s *Storage) GuaranteedUpdate( Value: value, }) if err != nil { - return err + return resource.GetError(resource.AsErrorResult(err)) } if rsp2.Error != nil { return resource.GetError(rsp2.Error) @@ -567,7 +568,7 @@ func (s *Storage) GuaranteedUpdate( } rsp2, err := s.store.Update(ctx, req) if err != nil { - return err + return resource.GetError(resource.AsErrorResult(err)) } if rsp2.Error != nil { return resource.GetError(rsp2.Error) diff --git a/pkg/storage/unified/apistore/store_test.go b/pkg/storage/unified/apistore/store_test.go index ec1013de44a..12d9629d311 100644 --- a/pkg/storage/unified/apistore/store_test.go +++ b/pkg/storage/unified/apistore/store_test.go @@ -7,10 +7,17 @@ package apistore_test import ( "context" + "errors" "fmt" + "net/http" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" @@ -19,10 +26,13 @@ import ( "k8s.io/apiserver/pkg/apis/example" examplev1 "k8s.io/apiserver/pkg/apis/example/v1" "k8s.io/apiserver/pkg/storage" + "k8s.io/apiserver/pkg/storage/storagebackend" claims "github.com/grafana/authlib/types" "github.com/grafana/grafana/pkg/apimachinery/identity" storagetesting "github.com/grafana/grafana/pkg/apiserver/storage/testing" + "github.com/grafana/grafana/pkg/storage/unified/apistore" + "github.com/grafana/grafana/pkg/storage/unified/resource" ) func init() { @@ -142,6 +152,45 @@ func TestDeleteWithSuggestionAndConflict(t *testing.T) { storagetesting.RunTestDeleteWithSuggestionAndConflict(ctx, t, store) } +type resourceClientMock struct { + resource.ResourceStoreClient + resource.ResourceIndexClient + resource.RepositoryIndexClient + resource.BatchStoreClient + resource.BlobStoreClient + resource.DiagnosticsClient +} + +// always return GRPC Unauthenticated code +func (r resourceClientMock) List(ctx context.Context, in *resource.ListRequest, opts ...grpc.CallOption) (*resource.ListResponse, error) { + return &resource.ListResponse{}, status.Error(codes.Unauthenticated, "missing token") +} + +func TestGRPCtoHTTPStatusMapping(t *testing.T) { + t.Run("ensure that GRPC Unauthenticated code gets translated to HTTP StatusUnauthorized", func(t *testing.T) { + s, _, err := apistore.NewStorage( + &storagebackend.ConfigForResource{}, + resourceClientMock{}, + nil, + nil, + nil, + nil, + nil, + nil, + nil, + apistore.StorageOptions{}) + require.NoError(t, err) + + err = s.GetList(context.Background(), "/group/resource.grafana.app/resource/resources/namespace/default", storage.ListOptions{}, nil) + require.Error(t, err) + + var statusError *apierrors.StatusError + ok := errors.As(err, &statusError) + require.Equal(t, true, ok) + require.Equal(t, int(statusError.Status().Code), http.StatusUnauthorized) + }) +} + // TODO: this test relies on update //func TestDeleteWithSuggestionOfDeletedObject(t *testing.T) { // ctx, store, destroyFunc, err := testSetup(t) diff --git a/pkg/storage/unified/resource/errors.go b/pkg/storage/unified/resource/errors.go index 7f1d3a3ca56..48faa27a303 100644 --- a/pkg/storage/unified/resource/errors.go +++ b/pkg/storage/unified/resource/errors.go @@ -7,6 +7,9 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + grpcstatus "google.golang.org/grpc/status" ) // Package-level errors. @@ -67,10 +70,16 @@ func AsErrorResult(err error) *ErrorResult { return res } - // TODO... better conversion?? + code := 500 + + st, ok := grpcstatus.FromError(err) + if ok { + code = runtime.HTTPStatusFromCode(st.Code()) + } + return &ErrorResult{ Message: err.Error(), - Code: 500, + Code: int32(code), } } diff --git a/pkg/storage/unified/resource/go.mod b/pkg/storage/unified/resource/go.mod index 82aff1d7974..b245031350a 100644 --- a/pkg/storage/unified/resource/go.mod +++ b/pkg/storage/unified/resource/go.mod @@ -19,6 +19,7 @@ require ( github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250121113133-e747350fee2d github.com/grafana/grafana/pkg/apiserver v0.0.0-20250121113133-e747350fee2d // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.2.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/prometheus/client_golang v1.20.5 github.com/stretchr/testify v1.10.0 @@ -125,7 +126,6 @@ require ( github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect github.com/grafana/sqlds/v4 v4.1.3 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect From 62d502086ebc1701f43288eef347e2ab14c76964 Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Wed, 19 Feb 2025 11:40:17 -0700 Subject: [PATCH 07/10] K8s: Dualwriter mode3: Return error from unistore (#100992) --- pkg/apiserver/rest/dualwriter_mode3.go | 1 + pkg/apiserver/rest/dualwriter_mode3_test.go | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pkg/apiserver/rest/dualwriter_mode3.go b/pkg/apiserver/rest/dualwriter_mode3.go index ecf0e21b80d..bd28ef3c31c 100644 --- a/pkg/apiserver/rest/dualwriter_mode3.go +++ b/pkg/apiserver/rest/dualwriter_mode3.go @@ -118,6 +118,7 @@ func (d *DualWriterMode3) Get(ctx context.Context, name string, options *metav1. d.recordStorageDuration(err != nil, mode3Str, d.resource, method, startStorage) if err != nil { log.Error(err, "unable to get object in storage") + return nil, err } //nolint:errcheck diff --git a/pkg/apiserver/rest/dualwriter_mode3_test.go b/pkg/apiserver/rest/dualwriter_mode3_test.go index bc8635b2fd7..f68287f4ead 100644 --- a/pkg/apiserver/rest/dualwriter_mode3_test.go +++ b/pkg/apiserver/rest/dualwriter_mode3_test.go @@ -107,10 +107,7 @@ func TestMode3_Get(t *testing.T) { }, }, { - name: "should return an error when getting an object in the unified store fails", - setupLegacyFn: func(m *mock.Mock, name string) { - m.On("Get", mock.Anything, name, mock.Anything).Return(exampleObj, nil) - }, + name: "should return an error when getting an object in the unified store fails, and should not go to legacy", setupStorageFn: func(m *mock.Mock, name string) { m.On("Get", mock.Anything, name, mock.Anything).Return(nil, errors.New("error")) }, From 3f8a34303ce1b9a7cb0879a7f88f031d50e431e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Philippe=20Qu=C3=A9m=C3=A9ner?= Date: Wed, 19 Feb 2025 19:58:10 +0100 Subject: [PATCH 08/10] feat(unified-storage): enhance gRPC client with dskit (#100993) --- pkg/storage/unified/client.go | 52 +++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/pkg/storage/unified/client.go b/pkg/storage/unified/client.go index 7b34b95ab92..75febc247e0 100644 --- a/pkg/storage/unified/client.go +++ b/pkg/storage/unified/client.go @@ -6,6 +6,7 @@ import ( "path/filepath" "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "gocloud.dev/blob/fileblob" "google.golang.org/grpc" @@ -13,6 +14,8 @@ import ( authnlib "github.com/grafana/authlib/authn" "github.com/grafana/authlib/types" + "github.com/grafana/dskit/grpcclient" + "github.com/grafana/dskit/middleware" infraDB "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/tracing" @@ -39,6 +42,10 @@ type Options struct { Docs resource.DocumentBuilderSupplier } +type ClientMetrics struct { + requestDuration *prometheus.HistogramVec +} + // This adds a UnifiedStorage client into the wire dependency tree func ProvideUnifiedStorageClient(opts *Options) (resource.ResourceClient, error) { // See: apiserver.ApplyGrafanaConfig(cfg, features, o) @@ -104,11 +111,8 @@ func newClient(opts options.StorageOptions, return nil, fmt.Errorf("expecting address for storage_type: %s", opts.StorageType) } - // Create a connection to the gRPC server - conn, err := grpc.NewClient(opts.Address, - grpc.WithStatsHandler(otelgrpc.NewClientHandler()), - grpc.WithTransportCredentials(insecure.NewCredentials()), - ) + // Create a connection to the gRPC server. + conn, err := grpcConn(opts.Address, reg) if err != nil { return nil, err } @@ -153,3 +157,41 @@ func newResourceClient(conn *grpc.ClientConn, cfg *setting.Cfg, features feature } return resource.NewRemoteResourceClient(tracer, conn, clientCfgMapping(grpcutils.ReadGrpcClientConfig(cfg)), cfg.Env == setting.Dev) } + +// grpcConn creates a new gRPC connection to the provided address. +func grpcConn(address string, reg prometheus.Registerer) (*grpc.ClientConn, error) { + // This works for now as the Provide function is only called once during startup. + // We might eventually want to tie this factory to a struct for more runtime control. + metrics := ClientMetrics{ + requestDuration: promauto.With(reg).NewHistogramVec(prometheus.HistogramOpts{ + Name: "resource_server_client_request_duration_seconds", + Help: "Time spent executing requests to the resource server.", + Buckets: prometheus.ExponentialBuckets(0.008, 4, 7), + }, []string{"operation", "status_code"}), + } + + // Report gRPC status code errors as labels. + var instrumentationOptions []middleware.InstrumentationOption + instrumentationOptions = append(instrumentationOptions, middleware.ReportGRPCStatusOption) + unary, stream := grpcclient.Instrument(metrics.requestDuration, instrumentationOptions...) + + // We can later pass in the gRPC config here, i.e. to set MaxRecvMsgSize etc. + cfg := grpcclient.Config{} + opts, err := cfg.DialOption(unary, stream) + if err != nil { + return nil, fmt.Errorf("could not instrument grpc client: %w", err) + } + + opts = append(opts, grpc.WithStatsHandler(otelgrpc.NewClientHandler())) + opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) + + // Use round_robin to balance requests more evenly over the available Storage server. + opts = append(opts, grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"round_robin"}`)) + + // Disable looking up service config from TXT DNS records. + // This reduces the number of requests made to the DNS servers. + opts = append(opts, grpc.WithDisableServiceConfig()) + + // Create a connection to the gRPC server + return grpc.NewClient(address, opts...) +} From 634142eca33ac06ecadfb54ba0c92f387ad01ac9 Mon Sep 17 00:00:00 2001 From: tab0r Date: Wed, 19 Feb 2025 11:05:11 -0800 Subject: [PATCH 09/10] [docs/configure/logging] include detail about multiple log filters (#100888) --- docs/sources/setup-grafana/configure-grafana/_index.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/sources/setup-grafana/configure-grafana/_index.md b/docs/sources/setup-grafana/configure-grafana/_index.md index e0b265a30d1..527fc60d7a5 100644 --- a/docs/sources/setup-grafana/configure-grafana/_index.md +++ b/docs/sources/setup-grafana/configure-grafana/_index.md @@ -1515,6 +1515,16 @@ Options are `debug`, `info`, `warn`, `error`, and `critical`. Default is `info`. Optional settings to set different levels for specific loggers. For example: `filters = sqlstore:debug` +You can use multiple filters with a comma-seperated list: +For example: `filters = sqlstore:debug,plugins:info` + +The equivalent for a `docker-compose.yaml` looks like this: + +``` +GF_LOG_FILTERS: sqlstore:debug,plugins:info +GF_LOG_LEVEL: error +``` + #### `user_facing_default_error` Use this configuration option to set the default error message shown to users. This message is displayed instead of sensitive backend errors, which should be obfuscated. The default message is `Please inspect the Grafana server log for details.`. From 8c21a49c353374919093024fb6aee258e9c00c26 Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Wed, 19 Feb 2025 22:06:46 +0300 Subject: [PATCH 10/10] Chore: Update go-github dependencies (#100994) --- go.work.sum | 2 ++ pkg/build/cmd/publishgithub.go | 2 +- pkg/build/cmd/publishgithub_test.go | 5 +++-- pkg/build/git/git.go | 2 +- pkg/build/go.mod | 3 +-- pkg/build/go.sum | 6 ++---- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/go.work.sum b/go.work.sum index 45b22055290..297372e3a99 100644 --- a/go.work.sum +++ b/go.work.sum @@ -585,6 +585,8 @@ github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs0 github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/cel-go v0.22.0/go.mod h1:BuznPXXfQDpXKWQ9sPW3TzlAJN5zzFe+i9tIs0yC4s8= +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-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= diff --git a/pkg/build/cmd/publishgithub.go b/pkg/build/cmd/publishgithub.go index 610b702d7c7..c0209ee4228 100644 --- a/pkg/build/cmd/publishgithub.go +++ b/pkg/build/cmd/publishgithub.go @@ -8,7 +8,7 @@ import ( "path" "strings" - "github.com/google/go-github/github" + "github.com/google/go-github/v69/github" "github.com/urfave/cli/v2" "golang.org/x/oauth2" diff --git a/pkg/build/cmd/publishgithub_test.go b/pkg/build/cmd/publishgithub_test.go index 79464391810..3aa917a33e5 100644 --- a/pkg/build/cmd/publishgithub_test.go +++ b/pkg/build/cmd/publishgithub_test.go @@ -9,10 +9,11 @@ import ( "path/filepath" "testing" - "github.com/google/go-github/github" - "github.com/grafana/grafana/pkg/build/cmd/util" + "github.com/google/go-github/v69/github" "github.com/stretchr/testify/assert" "github.com/urfave/cli/v2" + + "github.com/grafana/grafana/pkg/build/cmd/util" ) type githubPublishTestCases struct { diff --git a/pkg/build/git/git.go b/pkg/build/git/git.go index 2977cf13775..f0219d3c64b 100644 --- a/pkg/build/git/git.go +++ b/pkg/build/git/git.go @@ -6,7 +6,7 @@ import ( "fmt" "regexp" - "github.com/google/go-github/v45/github" + "github.com/google/go-github/v69/github" ) const ( diff --git a/pkg/build/go.mod b/pkg/build/go.mod index 8f500929041..d404a6ce87e 100644 --- a/pkg/build/go.mod +++ b/pkg/build/go.mod @@ -15,8 +15,7 @@ require ( github.com/drone/drone-cli v1.8.0 // @grafana/grafana-developer-enablement-squad github.com/gogo/protobuf v1.3.2 // indirect; @grafana/alerting-backend github.com/google/go-cmp v0.6.0 // @grafana/grafana-backend-group - github.com/google/go-github v17.0.0+incompatible // @grafana/grafana-developer-enablement-squad - github.com/google/go-github/v45 v45.2.0 // @grafana/grafana-developer-enablement-squad + github.com/google/go-github/v69 v69.2.0 // @grafana/grafana-developer-enablement-squad github.com/google/uuid v1.6.0 // indirect; @grafana/grafana-backend-group github.com/googleapis/gax-go/v2 v2.14.1 // indirect; @grafana/grafana-backend-group github.com/jmespath/go-jmespath v0.4.0 // indirect; @grafana/grafana-backend-group diff --git a/pkg/build/go.sum b/pkg/build/go.sum index 762068aef69..e1c3f80a9a7 100644 --- a/pkg/build/go.sum +++ b/pkg/build/go.sum @@ -128,10 +128,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -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/v45 v45.2.0 h1:5oRLszbrkvxDDqBCNj2hjDZMKmvexaZ1xw/FCD+K3FI= -github.com/google/go-github/v45 v45.2.0/go.mod h1:FObaZJEDSTa/WGCzZ2Z3eoCDXWJKMenWWTrd8jrta28= +github.com/google/go-github/v69 v69.2.0 h1:wR+Wi/fN2zdUx9YxSmYE0ktiX9IAR/BeePzeaUUbEHE= +github.com/google/go-github/v69 v69.2.0/go.mod h1:xne4jymxLR6Uj9b7J7PyTpkMYstEMMwGZa0Aehh1azM= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc=