mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Plugins: Use handler middleware from the SDK (#93445)
updates sdk to v0.251.0
This commit is contained in:
parent
54faa541c3
commit
b7a7f2bd62
2
go.mod
2
go.mod
@ -88,7 +88,7 @@ require (
|
|||||||
github.com/grafana/grafana-cloud-migration-snapshot v1.3.0 // @grafana/grafana-operator-experience-squad
|
github.com/grafana/grafana-cloud-migration-snapshot v1.3.0 // @grafana/grafana-operator-experience-squad
|
||||||
github.com/grafana/grafana-google-sdk-go v0.1.0 // @grafana/partner-datasources
|
github.com/grafana/grafana-google-sdk-go v0.1.0 // @grafana/partner-datasources
|
||||||
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79 // @grafana/grafana-backend-group
|
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79 // @grafana/grafana-backend-group
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.250.0 // @grafana/plugins-platform-backend
|
github.com/grafana/grafana-plugin-sdk-go v0.251.0 // @grafana/plugins-platform-backend
|
||||||
github.com/grafana/grafana/pkg/aggregator v0.0.0-20240813192817-1b0e6b5c09b2 // @grafana/grafana-app-platform-squad
|
github.com/grafana/grafana/pkg/aggregator v0.0.0-20240813192817-1b0e6b5c09b2 // @grafana/grafana-app-platform-squad
|
||||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240821155123-6891eb1d35da // @grafana/grafana-app-platform-squad
|
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240821155123-6891eb1d35da // @grafana/grafana-app-platform-squad
|
||||||
github.com/grafana/grafana/pkg/apiserver v0.0.0-20240821155123-6891eb1d35da // @grafana/grafana-app-platform-squad
|
github.com/grafana/grafana/pkg/apiserver v0.0.0-20240821155123-6891eb1d35da // @grafana/grafana-app-platform-squad
|
||||||
|
4
go.sum
4
go.sum
@ -2293,8 +2293,8 @@ github.com/grafana/grafana-google-sdk-go v0.1.0/go.mod h1:Vo2TKWfDVmNTELBUM+3lkr
|
|||||||
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 h1:r+mU5bGMzcXCRVAuOrTn54S80qbfVkvTdUJZfSfTNbs=
|
||||||
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79/go.mod h1:wc6Hbh3K2TgCUSfBC/BOzabItujtHMESZeFk5ZhdxhQ=
|
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.114.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk=
|
github.com/grafana/grafana-plugin-sdk-go v0.114.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk=
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.250.0 h1:9EBucp9jLqMx2b8NTlOXH+4OuQWUh6L85c6EJUN8Jdo=
|
github.com/grafana/grafana-plugin-sdk-go v0.251.0 h1:gnOtxrC/1rqFvpSbQYyoZqkr47oWDlz4Q2L6Ozmsi3w=
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.250.0/go.mod h1:gCGN9kHY3KeX4qyni3+Kead38Q+85pYOrsDcxZp6AIk=
|
github.com/grafana/grafana-plugin-sdk-go v0.251.0/go.mod h1:gCGN9kHY3KeX4qyni3+Kead38Q+85pYOrsDcxZp6AIk=
|
||||||
github.com/grafana/grafana/apps/playlist v0.0.0-20240917082838-e2bce38a7990 h1:uQMZE/z+Y+o/U0z/g8ckAHss7U7LswedilByA2535DU=
|
github.com/grafana/grafana/apps/playlist v0.0.0-20240917082838-e2bce38a7990 h1:uQMZE/z+Y+o/U0z/g8ckAHss7U7LswedilByA2535DU=
|
||||||
github.com/grafana/grafana/apps/playlist v0.0.0-20240917082838-e2bce38a7990/go.mod h1:3Vi0xv/4OBkBw4R9GAERkSrBnx06qrjpmNBRisucuSM=
|
github.com/grafana/grafana/apps/playlist v0.0.0-20240917082838-e2bce38a7990/go.mod h1:3Vi0xv/4OBkBw4R9GAERkSrBnx06qrjpmNBRisucuSM=
|
||||||
github.com/grafana/grafana/pkg/aggregator v0.0.0-20240813192817-1b0e6b5c09b2 h1:2H9x4q53pkfUGtSNYD1qSBpNnxrFgylof/TYADb5xMI=
|
github.com/grafana/grafana/pkg/aggregator v0.0.0-20240813192817-1b0e6b5c09b2 h1:2H9x4q53pkfUGtSNYD1qSBpNnxrFgylof/TYADb5xMI=
|
||||||
|
@ -470,6 +470,8 @@ 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 h1:AlYZOldA+UJ0/2nBuqWdo90GFCgG9xuyw9SYzGUtJm0=
|
||||||
github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss=
|
github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss=
|
||||||
github.com/elazarl/goproxy v0.0.0-20230731152917-f99041a5c027/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
github.com/elazarl/goproxy v0.0.0-20230731152917-f99041a5c027/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||||
|
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
|
||||||
|
github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw=
|
||||||
github.com/expr-lang/expr v1.16.2 h1:JvMnzUs3LeVHBvGFcXYmXo+Q6DPDmzrlcSBO6Wy3w4s=
|
github.com/expr-lang/expr v1.16.2 h1:JvMnzUs3LeVHBvGFcXYmXo+Q6DPDmzrlcSBO6Wy3w4s=
|
||||||
github.com/expr-lang/expr v1.16.2/go.mod h1:uCkhfG+x7fcZ5A5sXHKuQ07jGZRl6J0FCAaf2k4PtVQ=
|
github.com/expr-lang/expr v1.16.2/go.mod h1:uCkhfG+x7fcZ5A5sXHKuQ07jGZRl6J0FCAaf2k4PtVQ=
|
||||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||||
@ -792,6 +794,7 @@ github.com/relvacode/iso8601 v1.4.0 h1:GsInVSEJfkYuirYFxa80nMLbH2aydgZpIf52gYZXU
|
|||||||
github.com/relvacode/iso8601 v1.4.0/go.mod h1:FlNp+jz+TXpyRqgmM7tnzHHzBnz776kmAH2h3sZCn0I=
|
github.com/relvacode/iso8601 v1.4.0/go.mod h1:FlNp+jz+TXpyRqgmM7tnzHHzBnz776kmAH2h3sZCn0I=
|
||||||
github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s=
|
github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s=
|
||||||
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4 h1:BN/Nyn2nWMoqGRA7G7paDNDqTXE30mXGqzzybrfo05w=
|
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4 h1:BN/Nyn2nWMoqGRA7G7paDNDqTXE30mXGqzzybrfo05w=
|
||||||
|
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
|
||||||
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
|
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
|
||||||
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
|
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
|
||||||
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245 h1:K1Xf3bKttbF+koVGaX5xngRIZ5bVjbmPnaxE/dR08uY=
|
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245 h1:K1Xf3bKttbF+koVGaX5xngRIZ5bVjbmPnaxE/dR08uY=
|
||||||
@ -995,11 +998,9 @@ golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
|||||||
golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
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.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.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.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||||
golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
|
||||||
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||||
golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||||
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -1011,7 +1012,6 @@ golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|||||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 h1:zf5N6UOrA487eEFacMePxjXAJctxKmyjKUsjA11Uzuk=
|
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 h1:zf5N6UOrA487eEFacMePxjXAJctxKmyjKUsjA11Uzuk=
|
||||||
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0=
|
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0=
|
||||||
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.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
@ -1023,14 +1023,12 @@ gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPj
|
|||||||
gonum.org/v1/plot v0.10.1 h1:dnifSs43YJuNMDzB7v8wV64O4ABBHReuAVAoBxqBqS4=
|
gonum.org/v1/plot v0.10.1 h1:dnifSs43YJuNMDzB7v8wV64O4ABBHReuAVAoBxqBqS4=
|
||||||
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||||
google.golang.org/genproto v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:mCr1K1c8kX+1iSBREvU3Juo11CB+QOEWxbRS01wWl5M=
|
google.golang.org/genproto v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:mCr1K1c8kX+1iSBREvU3Juo11CB+QOEWxbRS01wWl5M=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU=
|
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo=
|
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:AHT0dDg3SoMOgZGnZk29b5xTbPHMoEC8qthmBLJCpys=
|
google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:AHT0dDg3SoMOgZGnZk29b5xTbPHMoEC8qthmBLJCpys=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:OFMYQFHJ4TM3JRlWDZhJbZfra2uqc3WLBZiaaqP4DtU=
|
google.golang.org/genproto/googleapis/api v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:OFMYQFHJ4TM3JRlWDZhJbZfra2uqc3WLBZiaaqP4DtU=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
|
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
|
||||||
google.golang.org/genproto/googleapis/bytestream v0.0.0-20240730163845-b1a4ccb954bf h1:T4tsZBlZYXK3j40sQNP5MBO32I+rn6ypV1PpklsiV8k=
|
google.golang.org/genproto/googleapis/bytestream v0.0.0-20240730163845-b1a4ccb954bf h1:T4tsZBlZYXK3j40sQNP5MBO32I+rn6ypV1PpklsiV8k=
|
||||||
google.golang.org/genproto/googleapis/bytestream v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:5/MT647Cn/GGhwTpXC7QqcaR5Cnee4v4MKCU1/nwnIQ=
|
google.golang.org/genproto/googleapis/bytestream v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:5/MT647Cn/GGhwTpXC7QqcaR5Cnee4v4MKCU1/nwnIQ=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
|
||||||
|
@ -4,7 +4,7 @@ go 1.23.1
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/emicklei/go-restful/v3 v3.11.0
|
github.com/emicklei/go-restful/v3 v3.11.0
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.250.0
|
github.com/grafana/grafana-plugin-sdk-go v0.251.0
|
||||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808213237-f4d2e064f435
|
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808213237-f4d2e064f435
|
||||||
github.com/grafana/grafana/pkg/semconv v0.0.0-20240808213237-f4d2e064f435
|
github.com/grafana/grafana/pkg/semconv v0.0.0-20240808213237-f4d2e064f435
|
||||||
github.com/mattbaird/jsonpatch v0.0.0-20240118010651-0ba75a80ca38
|
github.com/mattbaird/jsonpatch v0.0.0-20240118010651-0ba75a80ca38
|
||||||
|
@ -130,8 +130,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
|||||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.250.0 h1:9EBucp9jLqMx2b8NTlOXH+4OuQWUh6L85c6EJUN8Jdo=
|
github.com/grafana/grafana-plugin-sdk-go v0.251.0 h1:gnOtxrC/1rqFvpSbQYyoZqkr47oWDlz4Q2L6Ozmsi3w=
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.250.0/go.mod h1:gCGN9kHY3KeX4qyni3+Kead38Q+85pYOrsDcxZp6AIk=
|
github.com/grafana/grafana-plugin-sdk-go v0.251.0/go.mod h1:gCGN9kHY3KeX4qyni3+Kead38Q+85pYOrsDcxZp6AIk=
|
||||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808213237-f4d2e064f435 h1:lmw60EW7JWlAEvgggktOyVkH4hF1m/+LSF/Ap0NCyi8=
|
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808213237-f4d2e064f435 h1:lmw60EW7JWlAEvgggktOyVkH4hF1m/+LSF/Ap0NCyi8=
|
||||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808213237-f4d2e064f435/go.mod h1:ORVFiW/KNRY52lNjkGwnFWCxNVfE97bJG2jr2fetq0I=
|
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808213237-f4d2e064f435/go.mod h1:ORVFiW/KNRY52lNjkGwnFWCxNVfE97bJG2jr2fetq0I=
|
||||||
github.com/grafana/grafana/pkg/semconv v0.0.0-20240808213237-f4d2e064f435 h1:SNEeqY22DrGr5E9kGF1mKSqlOom14W9+b1u4XEGJowA=
|
github.com/grafana/grafana/pkg/semconv v0.0.0-20240808213237-f4d2e064f435 h1:SNEeqY22DrGr5E9kGF1mKSqlOom14W9+b1u4XEGJowA=
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
|
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
|
||||||
pluginClient "github.com/grafana/grafana/pkg/plugins/manager/client"
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
"github.com/grafana/grafana/pkg/services/caching"
|
"github.com/grafana/grafana/pkg/services/caching"
|
||||||
@ -172,7 +171,7 @@ func TestCallResource(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
middlewares := pluginsintegration.CreateMiddlewares(cfg, &oauthtokentest.Service{}, tracing.InitializeTracerForTest(), &caching.OSSCachingService{}, featuremgmt.WithFeatures(), prometheus.DefaultRegisterer, pluginRegistry)
|
middlewares := pluginsintegration.CreateMiddlewares(cfg, &oauthtokentest.Service{}, tracing.InitializeTracerForTest(), &caching.OSSCachingService{}, featuremgmt.WithFeatures(), prometheus.DefaultRegisterer, pluginRegistry)
|
||||||
pc, err := pluginClient.NewDecorator(&fakes.FakePluginClient{
|
pc, err := backend.HandlerFromMiddlewares(&fakes.FakePluginClient{
|
||||||
CallResourceHandlerFunc: backend.CallResourceHandlerFunc(func(ctx context.Context,
|
CallResourceHandlerFunc: backend.CallResourceHandlerFunc(func(ctx context.Context,
|
||||||
req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||||
return errors.New("something went wrong")
|
return errors.New("something went wrong")
|
||||||
|
@ -88,13 +88,7 @@ type FoundPlugin struct {
|
|||||||
|
|
||||||
// Client is used to communicate with backend plugin implementations.
|
// Client is used to communicate with backend plugin implementations.
|
||||||
type Client interface {
|
type Client interface {
|
||||||
backend.QueryDataHandler
|
backend.Handler
|
||||||
backend.CheckHealthHandler
|
|
||||||
backend.StreamHandler
|
|
||||||
backend.AdmissionHandler
|
|
||||||
backend.ConversionHandler
|
|
||||||
backend.CallResourceHandler
|
|
||||||
backend.CollectMetricsHandler
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BackendFactoryProvider provides a backend factory for a provided plugin.
|
// BackendFactoryProvider provides a backend factory for a provided plugin.
|
||||||
@ -131,23 +125,6 @@ type Licensing interface {
|
|||||||
AppURL() string
|
AppURL() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientMiddleware is an interface representing the ability to create a middleware
|
|
||||||
// that implements the Client interface.
|
|
||||||
type ClientMiddleware interface {
|
|
||||||
// CreateClientMiddleware creates a new client middleware.
|
|
||||||
CreateClientMiddleware(next Client) Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// The ClientMiddlewareFunc type is an adapter to allow the use of ordinary
|
|
||||||
// functions as ClientMiddleware's. If f is a function with the appropriate
|
|
||||||
// signature, ClientMiddlewareFunc(f) is a ClientMiddleware that calls f.
|
|
||||||
type ClientMiddlewareFunc func(next Client) Client
|
|
||||||
|
|
||||||
// CreateClientMiddleware implements the ClientMiddleware interface.
|
|
||||||
func (fn ClientMiddlewareFunc) CreateClientMiddleware(next Client) Client {
|
|
||||||
return fn(next)
|
|
||||||
}
|
|
||||||
|
|
||||||
type SignatureCalculator interface {
|
type SignatureCalculator interface {
|
||||||
Calculate(ctx context.Context, src PluginSource, plugin FoundPlugin) (Signature, error)
|
Calculate(ctx context.Context, src PluginSource, plugin FoundPlugin) (Signature, error)
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/registry"
|
"github.com/grafana/grafana/pkg/plugins/manager/registry"
|
||||||
|
"github.com/grafana/grafana/pkg/util/proxyutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -101,8 +102,11 @@ func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceReq
|
|||||||
removeConnectionHeaders(res.Headers)
|
removeConnectionHeaders(res.Headers)
|
||||||
removeHopByHopHeaders(res.Headers)
|
removeHopByHopHeaders(res.Headers)
|
||||||
removeNonAllowedHeaders(res.Headers)
|
removeNonAllowedHeaders(res.Headers)
|
||||||
|
} else {
|
||||||
|
res.Headers = map[string][]string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proxyutil.SetProxyResponseHeaders(res.Headers)
|
||||||
ensureContentTypeHeader(res)
|
ensureContentTypeHeader(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,6 +310,48 @@ func TestCallResource(t *testing.T) {
|
|||||||
require.Equal(t, "should not be deleted", res.Headers["X-Custom"][0])
|
require.Equal(t, "should not be deleted", res.Headers["X-Custom"][0])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("Should set proxy response headers", func(t *testing.T) {
|
||||||
|
resHeaders := map[string][]string{
|
||||||
|
"X-Custom": {"should not be deleted"},
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &backend.CallResourceRequest{
|
||||||
|
PluginContext: backend.PluginContext{
|
||||||
|
PluginID: "pid",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
responses := []*backend.CallResourceResponse{}
|
||||||
|
sender := backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error {
|
||||||
|
responses = append(responses, res)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
p.RegisterClient(&fakePluginBackend{
|
||||||
|
crr: func(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||||
|
return sender.Send(&backend.CallResourceResponse{
|
||||||
|
Headers: resHeaders,
|
||||||
|
Status: http.StatusOK,
|
||||||
|
Body: []byte(backendResponse),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
err := registry.Add(context.Background(), p)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
client := ProvideService(registry)
|
||||||
|
|
||||||
|
err = client.CallResource(context.Background(), req, sender)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Len(t, responses, 1)
|
||||||
|
res := responses[0]
|
||||||
|
require.Equal(t, http.StatusOK, res.Status)
|
||||||
|
require.Equal(t, []byte(backendResponse), res.Body)
|
||||||
|
require.Equal(t, "sandbox", res.Headers["Content-Security-Policy"][0])
|
||||||
|
require.Equal(t, "should not be deleted", res.Headers["X-Custom"][0])
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("Should ensure content type header", func(t *testing.T) {
|
t.Run("Should ensure content type header", func(t *testing.T) {
|
||||||
tcs := []struct {
|
tcs := []struct {
|
||||||
contentType string
|
contentType string
|
||||||
|
@ -1,331 +0,0 @@
|
|||||||
package clienttest
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/client"
|
|
||||||
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
|
||||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
|
||||||
"github.com/grafana/grafana/pkg/web"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TestClient struct {
|
|
||||||
plugins.Client
|
|
||||||
QueryDataFunc backend.QueryDataHandlerFunc
|
|
||||||
CallResourceFunc backend.CallResourceHandlerFunc
|
|
||||||
CheckHealthFunc backend.CheckHealthHandlerFunc
|
|
||||||
CollectMetricsFunc backend.CollectMetricsHandlerFunc
|
|
||||||
SubscribeStreamFunc func(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error)
|
|
||||||
PublishStreamFunc func(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error)
|
|
||||||
RunStreamFunc func(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error
|
|
||||||
ValidateAdmissionFunc backend.ValidateAdmissionFunc
|
|
||||||
MutateAdmissionFunc backend.MutateAdmissionFunc
|
|
||||||
ConvertObjectsFunc backend.ConvertObjectsFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TestClient) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
|
||||||
if c.QueryDataFunc != nil {
|
|
||||||
return c.QueryDataFunc(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TestClient) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
|
||||||
if c.CallResourceFunc != nil {
|
|
||||||
return c.CallResourceFunc(ctx, req, sender)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TestClient) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
|
||||||
if c.CheckHealthFunc != nil {
|
|
||||||
return c.CheckHealthFunc(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TestClient) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
|
|
||||||
if c.CollectMetricsFunc != nil {
|
|
||||||
return c.CollectMetricsFunc(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TestClient) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
|
|
||||||
if c.PublishStreamFunc != nil {
|
|
||||||
return c.PublishStreamFunc(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TestClient) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
|
|
||||||
if c.SubscribeStreamFunc != nil {
|
|
||||||
return c.SubscribeStreamFunc(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TestClient) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
|
|
||||||
if c.RunStreamFunc != nil {
|
|
||||||
return c.RunStreamFunc(ctx, req, sender)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TestClient) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
|
|
||||||
if c.ValidateAdmissionFunc != nil {
|
|
||||||
return c.ValidateAdmissionFunc(ctx, req)
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TestClient) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
|
|
||||||
if c.MutateAdmissionFunc != nil {
|
|
||||||
return c.MutateAdmissionFunc(ctx, req)
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TestClient) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
|
|
||||||
if c.ConvertObjectsFunc != nil {
|
|
||||||
return c.ConvertObjectsFunc(ctx, req)
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type MiddlewareScenarioContext struct {
|
|
||||||
QueryDataCallChain []string
|
|
||||||
CallResourceCallChain []string
|
|
||||||
CollectMetricsCallChain []string
|
|
||||||
CheckHealthCallChain []string
|
|
||||||
SubscribeStreamCallChain []string
|
|
||||||
PublishStreamCallChain []string
|
|
||||||
RunStreamCallChain []string
|
|
||||||
InstanceSettingsCallChain []string
|
|
||||||
ValidateAdmissionCallChain []string
|
|
||||||
MutateAdmissionCallChain []string
|
|
||||||
ConvertObjectsCallChain []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *MiddlewareScenarioContext) NewMiddleware(name string) plugins.ClientMiddleware {
|
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
|
||||||
return &TestMiddleware{
|
|
||||||
next: next,
|
|
||||||
Name: name,
|
|
||||||
sCtx: ctx,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type TestMiddleware struct {
|
|
||||||
next plugins.Client
|
|
||||||
sCtx *MiddlewareScenarioContext
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
|
||||||
m.sCtx.QueryDataCallChain = append(m.sCtx.QueryDataCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.QueryData(ctx, req)
|
|
||||||
m.sCtx.QueryDataCallChain = append(m.sCtx.QueryDataCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
|
||||||
m.sCtx.CallResourceCallChain = append(m.sCtx.CallResourceCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
err := m.next.CallResource(ctx, req, sender)
|
|
||||||
m.sCtx.CallResourceCallChain = append(m.sCtx.CallResourceCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
|
|
||||||
m.sCtx.CollectMetricsCallChain = append(m.sCtx.CollectMetricsCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.CollectMetrics(ctx, req)
|
|
||||||
m.sCtx.CollectMetricsCallChain = append(m.sCtx.CollectMetricsCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
|
|
||||||
m.sCtx.ValidateAdmissionCallChain = append(m.sCtx.ValidateAdmissionCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.ValidateAdmission(ctx, req)
|
|
||||||
m.sCtx.ValidateAdmissionCallChain = append(m.sCtx.ValidateAdmissionCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
|
|
||||||
m.sCtx.MutateAdmissionCallChain = append(m.sCtx.MutateAdmissionCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.MutateAdmission(ctx, req)
|
|
||||||
m.sCtx.MutateAdmissionCallChain = append(m.sCtx.MutateAdmissionCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
|
|
||||||
m.sCtx.ConvertObjectsCallChain = append(m.sCtx.ConvertObjectsCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.ConvertObjects(ctx, req)
|
|
||||||
m.sCtx.ConvertObjectsCallChain = append(m.sCtx.ConvertObjectsCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
|
||||||
m.sCtx.CheckHealthCallChain = append(m.sCtx.CheckHealthCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.CheckHealth(ctx, req)
|
|
||||||
m.sCtx.CheckHealthCallChain = append(m.sCtx.CheckHealthCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
|
|
||||||
m.sCtx.SubscribeStreamCallChain = append(m.sCtx.SubscribeStreamCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.SubscribeStream(ctx, req)
|
|
||||||
m.sCtx.SubscribeStreamCallChain = append(m.sCtx.SubscribeStreamCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
|
|
||||||
m.sCtx.PublishStreamCallChain = append(m.sCtx.PublishStreamCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.PublishStream(ctx, req)
|
|
||||||
m.sCtx.PublishStreamCallChain = append(m.sCtx.PublishStreamCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
|
|
||||||
m.sCtx.RunStreamCallChain = append(m.sCtx.RunStreamCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
err := m.next.RunStream(ctx, req, sender)
|
|
||||||
m.sCtx.RunStreamCallChain = append(m.sCtx.RunStreamCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ plugins.Client = &TestClient{}
|
|
||||||
|
|
||||||
type ClientDecoratorTest struct {
|
|
||||||
T *testing.T
|
|
||||||
Context context.Context
|
|
||||||
TestClient *TestClient
|
|
||||||
Middlewares []plugins.ClientMiddleware
|
|
||||||
Decorator *client.Decorator
|
|
||||||
ReqContext *contextmodel.ReqContext
|
|
||||||
QueryDataReq *backend.QueryDataRequest
|
|
||||||
QueryDataCtx context.Context
|
|
||||||
CallResourceReq *backend.CallResourceRequest
|
|
||||||
CallResourceCtx context.Context
|
|
||||||
CheckHealthReq *backend.CheckHealthRequest
|
|
||||||
CheckHealthCtx context.Context
|
|
||||||
CollectMetricsReq *backend.CollectMetricsRequest
|
|
||||||
CollectMetricsCtx context.Context
|
|
||||||
SubscribeStreamReq *backend.SubscribeStreamRequest
|
|
||||||
SubscribeStreamCtx context.Context
|
|
||||||
PublishStreamReq *backend.PublishStreamRequest
|
|
||||||
PublishStreamCtx context.Context
|
|
||||||
|
|
||||||
// When CallResource is called, the sender will be called with these values
|
|
||||||
callResourceResponses []*backend.CallResourceResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
type ClientDecoratorTestOption func(*ClientDecoratorTest)
|
|
||||||
|
|
||||||
func NewClientDecoratorTest(t *testing.T, opts ...ClientDecoratorTestOption) *ClientDecoratorTest {
|
|
||||||
cdt := &ClientDecoratorTest{
|
|
||||||
T: t,
|
|
||||||
Context: context.Background(),
|
|
||||||
}
|
|
||||||
cdt.TestClient = &TestClient{
|
|
||||||
QueryDataFunc: func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
|
||||||
cdt.QueryDataReq = req
|
|
||||||
cdt.QueryDataCtx = ctx
|
|
||||||
return nil, nil
|
|
||||||
},
|
|
||||||
CallResourceFunc: func(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
|
||||||
cdt.CallResourceReq = req
|
|
||||||
cdt.CallResourceCtx = ctx
|
|
||||||
if cdt.callResourceResponses != nil {
|
|
||||||
for _, r := range cdt.callResourceResponses {
|
|
||||||
if err := sender.Send(r); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
CheckHealthFunc: func(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
|
||||||
cdt.CheckHealthReq = req
|
|
||||||
cdt.CheckHealthCtx = ctx
|
|
||||||
return nil, nil
|
|
||||||
},
|
|
||||||
CollectMetricsFunc: func(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
|
|
||||||
cdt.CollectMetricsReq = req
|
|
||||||
cdt.CollectMetricsCtx = ctx
|
|
||||||
return nil, nil
|
|
||||||
},
|
|
||||||
SubscribeStreamFunc: func(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
|
|
||||||
cdt.SubscribeStreamReq = req
|
|
||||||
cdt.SubscribeStreamCtx = ctx
|
|
||||||
return nil, nil
|
|
||||||
},
|
|
||||||
PublishStreamFunc: func(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
|
|
||||||
cdt.PublishStreamReq = req
|
|
||||||
cdt.PublishStreamCtx = ctx
|
|
||||||
return nil, nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
require.NotNil(t, cdt)
|
|
||||||
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(cdt)
|
|
||||||
}
|
|
||||||
|
|
||||||
d, err := client.NewDecorator(cdt.TestClient, cdt.Middlewares...)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, d)
|
|
||||||
|
|
||||||
cdt.Decorator = d
|
|
||||||
|
|
||||||
return cdt
|
|
||||||
}
|
|
||||||
|
|
||||||
func WithReqContext(req *http.Request, user *user.SignedInUser) ClientDecoratorTestOption {
|
|
||||||
return ClientDecoratorTestOption(func(cdt *ClientDecoratorTest) {
|
|
||||||
if cdt.ReqContext == nil {
|
|
||||||
cdt.ReqContext = &contextmodel.ReqContext{
|
|
||||||
Context: &web.Context{
|
|
||||||
Resp: web.NewResponseWriter(req.Method, httptest.NewRecorder()),
|
|
||||||
},
|
|
||||||
SignedInUser: user,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cdt.Context = ctxkey.Set(cdt.Context, cdt.ReqContext)
|
|
||||||
|
|
||||||
*req = *req.WithContext(cdt.Context)
|
|
||||||
cdt.ReqContext.Req = req
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func WithMiddlewares(middlewares ...plugins.ClientMiddleware) ClientDecoratorTestOption {
|
|
||||||
return ClientDecoratorTestOption(func(cdt *ClientDecoratorTest) {
|
|
||||||
if cdt.Middlewares == nil {
|
|
||||||
cdt.Middlewares = []plugins.ClientMiddleware{}
|
|
||||||
}
|
|
||||||
|
|
||||||
cdt.Middlewares = append(cdt.Middlewares, middlewares...)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithResourceResponses can be used to make the test client send simulated resource responses back over the sender stream
|
|
||||||
func WithResourceResponses(responses []*backend.CallResourceResponse) ClientDecoratorTestOption {
|
|
||||||
return ClientDecoratorTestOption(func(cdt *ClientDecoratorTest) {
|
|
||||||
cdt.callResourceResponses = responses
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,196 +0,0 @@
|
|||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Decorator allows a plugins.Client to be decorated with middlewares.
|
|
||||||
type Decorator struct {
|
|
||||||
client plugins.Client
|
|
||||||
middlewares []plugins.ClientMiddleware
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ = plugins.Client(&Decorator{})
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewDecorator creates a new plugins.client decorator.
|
|
||||||
func NewDecorator(client plugins.Client, middlewares ...plugins.ClientMiddleware) (*Decorator, error) {
|
|
||||||
if client == nil {
|
|
||||||
return nil, errors.New("client cannot be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Decorator{
|
|
||||||
client: client,
|
|
||||||
middlewares: middlewares,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decorator) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
|
||||||
if req == nil {
|
|
||||||
return nil, errNilRequest
|
|
||||||
}
|
|
||||||
ctx = backend.WithEndpoint(ctx, backend.EndpointQueryData)
|
|
||||||
ctx = backend.WithPluginContext(ctx, req.PluginContext)
|
|
||||||
ctx = backend.WithUser(ctx, req.PluginContext.User)
|
|
||||||
|
|
||||||
client := clientFromMiddlewares(d.middlewares, d.client)
|
|
||||||
|
|
||||||
return client.QueryData(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decorator) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
|
||||||
if req == nil {
|
|
||||||
return errNilRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = backend.WithEndpoint(ctx, backend.EndpointCallResource)
|
|
||||||
ctx = backend.WithPluginContext(ctx, req.PluginContext)
|
|
||||||
ctx = backend.WithUser(ctx, req.PluginContext.User)
|
|
||||||
|
|
||||||
if sender == nil {
|
|
||||||
return errors.New("sender cannot be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client := clientFromMiddlewares(d.middlewares, d.client)
|
|
||||||
return client.CallResource(ctx, req, sender)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decorator) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
|
|
||||||
if req == nil {
|
|
||||||
return nil, errNilRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = backend.WithEndpoint(ctx, backend.EndpointCollectMetrics)
|
|
||||||
ctx = backend.WithPluginContext(ctx, req.PluginContext)
|
|
||||||
ctx = backend.WithUser(ctx, req.PluginContext.User)
|
|
||||||
|
|
||||||
client := clientFromMiddlewares(d.middlewares, d.client)
|
|
||||||
return client.CollectMetrics(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decorator) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
|
||||||
if req == nil {
|
|
||||||
return nil, errNilRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = backend.WithEndpoint(ctx, backend.EndpointCheckHealth)
|
|
||||||
ctx = backend.WithPluginContext(ctx, req.PluginContext)
|
|
||||||
ctx = backend.WithUser(ctx, req.PluginContext.User)
|
|
||||||
|
|
||||||
client := clientFromMiddlewares(d.middlewares, d.client)
|
|
||||||
return client.CheckHealth(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decorator) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
|
|
||||||
if req == nil {
|
|
||||||
return nil, errNilRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = backend.WithEndpoint(ctx, backend.EndpointSubscribeStream)
|
|
||||||
ctx = backend.WithPluginContext(ctx, req.PluginContext)
|
|
||||||
ctx = backend.WithUser(ctx, req.PluginContext.User)
|
|
||||||
|
|
||||||
client := clientFromMiddlewares(d.middlewares, d.client)
|
|
||||||
return client.SubscribeStream(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decorator) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
|
|
||||||
if req == nil {
|
|
||||||
return nil, errNilRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = backend.WithEndpoint(ctx, backend.EndpointPublishStream)
|
|
||||||
ctx = backend.WithPluginContext(ctx, req.PluginContext)
|
|
||||||
ctx = backend.WithUser(ctx, req.PluginContext.User)
|
|
||||||
|
|
||||||
client := clientFromMiddlewares(d.middlewares, d.client)
|
|
||||||
return client.PublishStream(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decorator) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
|
|
||||||
if req == nil {
|
|
||||||
return errNilRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = backend.WithEndpoint(ctx, backend.EndpointRunStream)
|
|
||||||
ctx = backend.WithPluginContext(ctx, req.PluginContext)
|
|
||||||
ctx = backend.WithUser(ctx, req.PluginContext.User)
|
|
||||||
|
|
||||||
if sender == nil {
|
|
||||||
return errors.New("sender cannot be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client := clientFromMiddlewares(d.middlewares, d.client)
|
|
||||||
return client.RunStream(ctx, req, sender)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decorator) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
|
|
||||||
if req == nil {
|
|
||||||
return nil, errNilRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = backend.WithEndpoint(ctx, backend.EndpointValidateAdmission)
|
|
||||||
ctx = backend.WithPluginContext(ctx, req.PluginContext)
|
|
||||||
ctx = backend.WithUser(ctx, req.PluginContext.User)
|
|
||||||
|
|
||||||
client := clientFromMiddlewares(d.middlewares, d.client)
|
|
||||||
return client.ValidateAdmission(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decorator) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
|
|
||||||
if req == nil {
|
|
||||||
return nil, errNilRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = backend.WithEndpoint(ctx, backend.EndpointMutateAdmission)
|
|
||||||
ctx = backend.WithPluginContext(ctx, req.PluginContext)
|
|
||||||
ctx = backend.WithUser(ctx, req.PluginContext.User)
|
|
||||||
|
|
||||||
client := clientFromMiddlewares(d.middlewares, d.client)
|
|
||||||
return client.MutateAdmission(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decorator) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
|
|
||||||
if req == nil {
|
|
||||||
return nil, errNilRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = backend.WithEndpoint(ctx, backend.EndpointConvertObject)
|
|
||||||
ctx = backend.WithPluginContext(ctx, req.PluginContext)
|
|
||||||
ctx = backend.WithUser(ctx, req.PluginContext.User)
|
|
||||||
|
|
||||||
client := clientFromMiddlewares(d.middlewares, d.client)
|
|
||||||
return client.ConvertObjects(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func clientFromMiddlewares(middlewares []plugins.ClientMiddleware, finalClient plugins.Client) plugins.Client {
|
|
||||||
if len(middlewares) == 0 {
|
|
||||||
return finalClient
|
|
||||||
}
|
|
||||||
|
|
||||||
reversed := reverseMiddlewares(middlewares)
|
|
||||||
next := finalClient
|
|
||||||
|
|
||||||
for _, m := range reversed {
|
|
||||||
next = m.CreateClientMiddleware(next)
|
|
||||||
}
|
|
||||||
|
|
||||||
return next
|
|
||||||
}
|
|
||||||
|
|
||||||
func reverseMiddlewares(middlewares []plugins.ClientMiddleware) []plugins.ClientMiddleware {
|
|
||||||
reversed := make([]plugins.ClientMiddleware, len(middlewares))
|
|
||||||
copy(reversed, middlewares)
|
|
||||||
|
|
||||||
for i, j := 0, len(reversed)-1; i < j; i, j = i+1, j-1 {
|
|
||||||
reversed[i], reversed[j] = reversed[j], reversed[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
return reversed
|
|
||||||
}
|
|
@ -1,249 +0,0 @@
|
|||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDecorator(t *testing.T) {
|
|
||||||
var queryDataCalled bool
|
|
||||||
var callResourceCalled bool
|
|
||||||
var checkHealthCalled bool
|
|
||||||
c := &TestClient{
|
|
||||||
QueryDataFunc: func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
|
||||||
queryDataCalled = true
|
|
||||||
return nil, nil
|
|
||||||
},
|
|
||||||
CallResourceFunc: func(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
|
||||||
callResourceCalled = true
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
CheckHealthFunc: func(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
|
||||||
checkHealthCalled = true
|
|
||||||
return nil, nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
require.NotNil(t, c)
|
|
||||||
|
|
||||||
ctx := MiddlewareScenarioContext{}
|
|
||||||
|
|
||||||
mwOne := ctx.NewMiddleware("mw1")
|
|
||||||
mwTwo := ctx.NewMiddleware("mw2")
|
|
||||||
|
|
||||||
d, err := NewDecorator(c, mwOne, mwTwo)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, d)
|
|
||||||
|
|
||||||
_, _ = d.QueryData(context.Background(), &backend.QueryDataRequest{})
|
|
||||||
require.True(t, queryDataCalled)
|
|
||||||
|
|
||||||
sender := backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error {
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
_ = d.CallResource(context.Background(), &backend.CallResourceRequest{}, sender)
|
|
||||||
require.True(t, callResourceCalled)
|
|
||||||
|
|
||||||
_, _ = d.CheckHealth(context.Background(), &backend.CheckHealthRequest{})
|
|
||||||
require.True(t, checkHealthCalled)
|
|
||||||
|
|
||||||
require.Len(t, ctx.QueryDataCallChain, 4)
|
|
||||||
require.EqualValues(t, []string{"before mw1", "before mw2", "after mw2", "after mw1"}, ctx.QueryDataCallChain)
|
|
||||||
require.Len(t, ctx.CallResourceCallChain, 4)
|
|
||||||
require.EqualValues(t, []string{"before mw1", "before mw2", "after mw2", "after mw1"}, ctx.CallResourceCallChain)
|
|
||||||
require.Len(t, ctx.CheckHealthCallChain, 4)
|
|
||||||
require.EqualValues(t, []string{"before mw1", "before mw2", "after mw2", "after mw1"}, ctx.CheckHealthCallChain)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReverseMiddlewares(t *testing.T) {
|
|
||||||
t.Run("Should reverse 1 middleware", func(t *testing.T) {
|
|
||||||
ctx := MiddlewareScenarioContext{}
|
|
||||||
middlewares := []plugins.ClientMiddleware{
|
|
||||||
ctx.NewMiddleware("mw1"),
|
|
||||||
}
|
|
||||||
reversed := reverseMiddlewares(middlewares)
|
|
||||||
require.Len(t, reversed, 1)
|
|
||||||
require.Equal(t, "mw1", reversed[0].CreateClientMiddleware(nil).(*TestMiddleware).Name)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Should reverse 2 middlewares", func(t *testing.T) {
|
|
||||||
ctx := MiddlewareScenarioContext{}
|
|
||||||
middlewares := []plugins.ClientMiddleware{
|
|
||||||
ctx.NewMiddleware("mw1"),
|
|
||||||
ctx.NewMiddleware("mw2"),
|
|
||||||
}
|
|
||||||
reversed := reverseMiddlewares(middlewares)
|
|
||||||
require.Len(t, reversed, 2)
|
|
||||||
require.Equal(t, "mw2", reversed[0].CreateClientMiddleware(nil).(*TestMiddleware).Name)
|
|
||||||
require.Equal(t, "mw1", reversed[1].CreateClientMiddleware(nil).(*TestMiddleware).Name)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Should reverse 3 middlewares", func(t *testing.T) {
|
|
||||||
ctx := MiddlewareScenarioContext{}
|
|
||||||
middlewares := []plugins.ClientMiddleware{
|
|
||||||
ctx.NewMiddleware("mw1"),
|
|
||||||
ctx.NewMiddleware("mw2"),
|
|
||||||
ctx.NewMiddleware("mw3"),
|
|
||||||
}
|
|
||||||
reversed := reverseMiddlewares(middlewares)
|
|
||||||
require.Len(t, reversed, 3)
|
|
||||||
require.Equal(t, "mw3", reversed[0].CreateClientMiddleware(nil).(*TestMiddleware).Name)
|
|
||||||
require.Equal(t, "mw2", reversed[1].CreateClientMiddleware(nil).(*TestMiddleware).Name)
|
|
||||||
require.Equal(t, "mw1", reversed[2].CreateClientMiddleware(nil).(*TestMiddleware).Name)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Should reverse 4 middlewares", func(t *testing.T) {
|
|
||||||
ctx := MiddlewareScenarioContext{}
|
|
||||||
middlewares := []plugins.ClientMiddleware{
|
|
||||||
ctx.NewMiddleware("mw1"),
|
|
||||||
ctx.NewMiddleware("mw2"),
|
|
||||||
ctx.NewMiddleware("mw3"),
|
|
||||||
ctx.NewMiddleware("mw4"),
|
|
||||||
}
|
|
||||||
reversed := reverseMiddlewares(middlewares)
|
|
||||||
require.Len(t, reversed, 4)
|
|
||||||
require.Equal(t, "mw4", reversed[0].CreateClientMiddleware(nil).(*TestMiddleware).Name)
|
|
||||||
require.Equal(t, "mw3", reversed[1].CreateClientMiddleware(nil).(*TestMiddleware).Name)
|
|
||||||
require.Equal(t, "mw2", reversed[2].CreateClientMiddleware(nil).(*TestMiddleware).Name)
|
|
||||||
require.Equal(t, "mw1", reversed[3].CreateClientMiddleware(nil).(*TestMiddleware).Name)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type TestClient struct {
|
|
||||||
plugins.Client
|
|
||||||
QueryDataFunc backend.QueryDataHandlerFunc
|
|
||||||
CallResourceFunc backend.CallResourceHandlerFunc
|
|
||||||
CheckHealthFunc backend.CheckHealthHandlerFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TestClient) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
|
||||||
if c.QueryDataFunc != nil {
|
|
||||||
return c.QueryDataFunc(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TestClient) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
|
||||||
if c.CallResourceFunc != nil {
|
|
||||||
return c.CallResourceFunc(ctx, req, sender)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TestClient) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
|
||||||
if c.CheckHealthFunc != nil {
|
|
||||||
return c.CheckHealthFunc(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type MiddlewareScenarioContext struct {
|
|
||||||
QueryDataCallChain []string
|
|
||||||
CallResourceCallChain []string
|
|
||||||
CollectMetricsCallChain []string
|
|
||||||
CheckHealthCallChain []string
|
|
||||||
SubscribeStreamCallChain []string
|
|
||||||
PublishStreamCallChain []string
|
|
||||||
RunStreamCallChain []string
|
|
||||||
InstanceSettingsCallChain []string
|
|
||||||
ValidateAdmissionCallChain []string
|
|
||||||
MutateAdmissionCallChain []string
|
|
||||||
ConvertObjectCallChain []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *MiddlewareScenarioContext) NewMiddleware(name string) plugins.ClientMiddleware {
|
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
|
||||||
return &TestMiddleware{
|
|
||||||
next: next,
|
|
||||||
Name: name,
|
|
||||||
sCtx: ctx,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type TestMiddleware struct {
|
|
||||||
next plugins.Client
|
|
||||||
sCtx *MiddlewareScenarioContext
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
|
||||||
m.sCtx.QueryDataCallChain = append(m.sCtx.QueryDataCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.QueryData(ctx, req)
|
|
||||||
m.sCtx.QueryDataCallChain = append(m.sCtx.QueryDataCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
|
||||||
m.sCtx.CallResourceCallChain = append(m.sCtx.CallResourceCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
err := m.next.CallResource(ctx, req, sender)
|
|
||||||
m.sCtx.CallResourceCallChain = append(m.sCtx.CallResourceCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
|
|
||||||
m.sCtx.CollectMetricsCallChain = append(m.sCtx.CollectMetricsCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.CollectMetrics(ctx, req)
|
|
||||||
m.sCtx.CollectMetricsCallChain = append(m.sCtx.CollectMetricsCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
|
||||||
m.sCtx.CheckHealthCallChain = append(m.sCtx.CheckHealthCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.CheckHealth(ctx, req)
|
|
||||||
m.sCtx.CheckHealthCallChain = append(m.sCtx.CheckHealthCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
|
|
||||||
m.sCtx.SubscribeStreamCallChain = append(m.sCtx.SubscribeStreamCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.SubscribeStream(ctx, req)
|
|
||||||
m.sCtx.SubscribeStreamCallChain = append(m.sCtx.SubscribeStreamCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
|
|
||||||
m.sCtx.PublishStreamCallChain = append(m.sCtx.PublishStreamCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.PublishStream(ctx, req)
|
|
||||||
m.sCtx.PublishStreamCallChain = append(m.sCtx.PublishStreamCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
|
|
||||||
m.sCtx.RunStreamCallChain = append(m.sCtx.RunStreamCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
err := m.next.RunStream(ctx, req, sender)
|
|
||||||
m.sCtx.RunStreamCallChain = append(m.sCtx.RunStreamCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
|
|
||||||
m.sCtx.ValidateAdmissionCallChain = append(m.sCtx.ValidateAdmissionCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.ValidateAdmission(ctx, req)
|
|
||||||
m.sCtx.ValidateAdmissionCallChain = append(m.sCtx.ValidateAdmissionCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
|
|
||||||
m.sCtx.MutateAdmissionCallChain = append(m.sCtx.MutateAdmissionCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.MutateAdmission(ctx, req)
|
|
||||||
m.sCtx.MutateAdmissionCallChain = append(m.sCtx.MutateAdmissionCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TestMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
|
|
||||||
m.sCtx.ConvertObjectCallChain = append(m.sCtx.ConvertObjectCallChain, fmt.Sprintf("before %s", m.Name))
|
|
||||||
res, err := m.next.ConvertObjects(ctx, req)
|
|
||||||
m.sCtx.ConvertObjectCallChain = append(m.sCtx.ConvertObjectCallChain, fmt.Sprintf("after %s", m.Name))
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ plugins.Client = &TestClient{}
|
|
@ -4,7 +4,7 @@ go 1.23.1
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/grafana/dskit v0.0.0-20240805174438-dfa83b4ed2d3
|
github.com/grafana/dskit v0.0.0-20240805174438-dfa83b4ed2d3
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.250.0
|
github.com/grafana/grafana-plugin-sdk-go v0.251.0
|
||||||
github.com/json-iterator/go v1.1.12
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/prometheus/client_golang v1.20.3
|
github.com/prometheus/client_golang v1.20.3
|
||||||
|
@ -98,8 +98,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
|||||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||||
github.com/grafana/dskit v0.0.0-20240805174438-dfa83b4ed2d3 h1:as4PmrFoYI1byS5JjsgPC7uSGTMh+SgS0ePv6hOyDGU=
|
github.com/grafana/dskit v0.0.0-20240805174438-dfa83b4ed2d3 h1:as4PmrFoYI1byS5JjsgPC7uSGTMh+SgS0ePv6hOyDGU=
|
||||||
github.com/grafana/dskit v0.0.0-20240805174438-dfa83b4ed2d3/go.mod h1:lcjGB6SuaZ2o44A9nD6p/tR4QXSPbzViRY520Gy6pTQ=
|
github.com/grafana/dskit v0.0.0-20240805174438-dfa83b4ed2d3/go.mod h1:lcjGB6SuaZ2o44A9nD6p/tR4QXSPbzViRY520Gy6pTQ=
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.250.0 h1:9EBucp9jLqMx2b8NTlOXH+4OuQWUh6L85c6EJUN8Jdo=
|
github.com/grafana/grafana-plugin-sdk-go v0.251.0 h1:gnOtxrC/1rqFvpSbQYyoZqkr47oWDlz4Q2L6Ozmsi3w=
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.250.0/go.mod h1:gCGN9kHY3KeX4qyni3+Kead38Q+85pYOrsDcxZp6AIk=
|
github.com/grafana/grafana-plugin-sdk-go v0.251.0/go.mod h1:gCGN9kHY3KeX4qyni3+Kead38Q+85pYOrsDcxZp6AIk=
|
||||||
github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8=
|
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/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 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg=
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
package clientmiddleware
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = plugins.Client(&baseMiddleware{})
|
|
||||||
|
|
||||||
// The base middleware simply passes the request down the chain
|
|
||||||
// This allows middleware to avoid implementing all the noop functions
|
|
||||||
type baseMiddleware struct {
|
|
||||||
next plugins.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *baseMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
|
||||||
return m.next.QueryData(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *baseMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
|
||||||
return m.next.CallResource(ctx, req, sender)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *baseMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
|
||||||
return m.next.CheckHealth(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *baseMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
|
|
||||||
return m.next.CollectMetrics(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *baseMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
|
|
||||||
return m.next.SubscribeStream(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *baseMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
|
|
||||||
return m.next.PublishStream(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *baseMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
|
|
||||||
return m.next.RunStream(ctx, req, sender)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateAdmission implements backend.AdmissionHandler.
|
|
||||||
func (m *baseMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
|
|
||||||
return m.next.ValidateAdmission(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MutateAdmission implements backend.AdmissionHandler.
|
|
||||||
func (m *baseMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
|
|
||||||
return m.next.MutateAdmission(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConvertObject implements backend.AdmissionHandler.
|
|
||||||
func (m *baseMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
|
|
||||||
return m.next.ConvertObjects(ctx, req)
|
|
||||||
}
|
|
@ -10,7 +10,6 @@ import (
|
|||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/services/caching"
|
"github.com/grafana/grafana/pkg/services/caching"
|
||||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
@ -19,15 +18,15 @@ import (
|
|||||||
// needed to mock the function for testing
|
// needed to mock the function for testing
|
||||||
var shouldCacheQuery = awsds.ShouldCacheQuery
|
var shouldCacheQuery = awsds.ShouldCacheQuery
|
||||||
|
|
||||||
// NewCachingMiddleware creates a new plugins.ClientMiddleware that will
|
// NewCachingMiddleware creates a new backend.HandlerMiddleware that will
|
||||||
// attempt to read and write query results to the cache
|
// attempt to read and write query results to the cache
|
||||||
func NewCachingMiddleware(cachingService caching.CachingService) plugins.ClientMiddleware {
|
func NewCachingMiddleware(cachingService caching.CachingService) backend.HandlerMiddleware {
|
||||||
return NewCachingMiddlewareWithFeatureManager(cachingService, nil)
|
return NewCachingMiddlewareWithFeatureManager(cachingService, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCachingMiddlewareWithFeatureManager creates a new plugins.ClientMiddleware that will
|
// NewCachingMiddlewareWithFeatureManager creates a new backend.HandlerMiddleware that will
|
||||||
// attempt to read and write query results to the cache with a feature manager
|
// attempt to read and write query results to the cache with a feature manager
|
||||||
func NewCachingMiddlewareWithFeatureManager(cachingService caching.CachingService, features featuremgmt.FeatureToggles) plugins.ClientMiddleware {
|
func NewCachingMiddlewareWithFeatureManager(cachingService caching.CachingService, features featuremgmt.FeatureToggles) backend.HandlerMiddleware {
|
||||||
log := log.New("caching_middleware")
|
log := log.New("caching_middleware")
|
||||||
if err := prometheus.Register(QueryCachingRequestHistogram); err != nil {
|
if err := prometheus.Register(QueryCachingRequestHistogram); err != nil {
|
||||||
log.Error("Error registering prometheus collector 'QueryRequestHistogram'", "error", err)
|
log.Error("Error registering prometheus collector 'QueryRequestHistogram'", "error", err)
|
||||||
@ -35,20 +34,18 @@ func NewCachingMiddlewareWithFeatureManager(cachingService caching.CachingServic
|
|||||||
if err := prometheus.Register(ResourceCachingRequestHistogram); err != nil {
|
if err := prometheus.Register(ResourceCachingRequestHistogram); err != nil {
|
||||||
log.Error("Error registering prometheus collector 'ResourceRequestHistogram'", "error", err)
|
log.Error("Error registering prometheus collector 'ResourceRequestHistogram'", "error", err)
|
||||||
}
|
}
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &CachingMiddleware{
|
return &CachingMiddleware{
|
||||||
baseMiddleware: baseMiddleware{
|
BaseHandler: backend.NewBaseHandler(next),
|
||||||
next: next,
|
caching: cachingService,
|
||||||
},
|
log: log,
|
||||||
caching: cachingService,
|
features: features,
|
||||||
log: log,
|
|
||||||
features: features,
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type CachingMiddleware struct {
|
type CachingMiddleware struct {
|
||||||
baseMiddleware
|
backend.BaseHandler
|
||||||
|
|
||||||
caching caching.CachingService
|
caching caching.CachingService
|
||||||
log log.Logger
|
log log.Logger
|
||||||
@ -60,12 +57,12 @@ type CachingMiddleware struct {
|
|||||||
// If the cache service is implemented, we capture the request duration as a metric. The service is expected to write any response headers.
|
// If the cache service is implemented, we capture the request duration as a metric. The service is expected to write any response headers.
|
||||||
func (m *CachingMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (m *CachingMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
reqCtx := contexthandler.FromContext(ctx)
|
reqCtx := contexthandler.FromContext(ctx)
|
||||||
if reqCtx == nil {
|
if reqCtx == nil {
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// time how long this request takes
|
// time how long this request takes
|
||||||
@ -92,7 +89,7 @@ func (m *CachingMiddleware) QueryData(ctx context.Context, req *backend.QueryDat
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cache miss; do the actual queries
|
// Cache miss; do the actual queries
|
||||||
resp, err := m.next.QueryData(ctx, req)
|
resp, err := m.BaseHandler.QueryData(ctx, req)
|
||||||
|
|
||||||
// Update the query cache with the result for this metrics request
|
// Update the query cache with the result for this metrics request
|
||||||
if err == nil && cr.UpdateCacheFn != nil {
|
if err == nil && cr.UpdateCacheFn != nil {
|
||||||
@ -125,12 +122,12 @@ func (m *CachingMiddleware) QueryData(ctx context.Context, req *backend.QueryDat
|
|||||||
// If the cache service is implemented, we capture the request duration as a metric. The service is expected to write any response headers.
|
// If the cache service is implemented, we capture the request duration as a metric. The service is expected to write any response headers.
|
||||||
func (m *CachingMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
func (m *CachingMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
reqCtx := contexthandler.FromContext(ctx)
|
reqCtx := contexthandler.FromContext(ctx)
|
||||||
if reqCtx == nil {
|
if reqCtx == nil {
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
// time how long this request takes
|
// time how long this request takes
|
||||||
@ -157,7 +154,7 @@ func (m *CachingMiddleware) CallResource(ctx context.Context, req *backend.CallR
|
|||||||
// Cache miss; do the actual request
|
// Cache miss; do the actual request
|
||||||
// If there is no update cache func, just pass in the original sender
|
// If there is no update cache func, just pass in the original sender
|
||||||
if cr.UpdateCacheFn == nil {
|
if cr.UpdateCacheFn == nil {
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
// Otherwise, intercept the responses in a wrapped sender so we can cache them first
|
// Otherwise, intercept the responses in a wrapped sender so we can cache them first
|
||||||
cacheSender := backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error {
|
cacheSender := backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error {
|
||||||
@ -165,5 +162,5 @@ func (m *CachingMiddleware) CallResource(ctx context.Context, req *backend.CallR
|
|||||||
return sender.Send(res)
|
return sender.Send(res)
|
||||||
})
|
})
|
||||||
|
|
||||||
return m.next.CallResource(ctx, req, cacheSender)
|
return m.BaseHandler.CallResource(ctx, req, cacheSender)
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
|
||||||
"github.com/grafana/grafana/pkg/services/caching"
|
"github.com/grafana/grafana/pkg/services/caching"
|
||||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
@ -22,9 +22,9 @@ func TestCachingMiddleware(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
cs := caching.NewFakeOSSCachingService()
|
cs := caching.NewFakeOSSCachingService()
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{}),
|
WithReqContext(req, &user.SignedInUser{}),
|
||||||
clienttest.WithMiddlewares(NewCachingMiddleware(cs)),
|
handlertest.WithMiddlewares(NewCachingMiddleware(cs)),
|
||||||
)
|
)
|
||||||
|
|
||||||
jsonDataMap := map[string]any{}
|
jsonDataMap := map[string]any{}
|
||||||
@ -63,7 +63,7 @@ func TestCachingMiddleware(t *testing.T) {
|
|||||||
cs.ReturnHit = true
|
cs.ReturnHit = true
|
||||||
cs.ReturnQueryResponse = dataResponse
|
cs.ReturnQueryResponse = dataResponse
|
||||||
|
|
||||||
resp, err := cdt.Decorator.QueryData(req.Context(), qdr)
|
resp, err := cdt.MiddlewareHandler.QueryData(req.Context(), qdr)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// Cache service is called once
|
// Cache service is called once
|
||||||
cs.AssertCalls(t, "HandleQueryRequest", 1)
|
cs.AssertCalls(t, "HandleQueryRequest", 1)
|
||||||
@ -92,7 +92,7 @@ func TestCachingMiddleware(t *testing.T) {
|
|||||||
cs.ReturnHit = false
|
cs.ReturnHit = false
|
||||||
cs.ReturnQueryResponse = dataResponse
|
cs.ReturnQueryResponse = dataResponse
|
||||||
|
|
||||||
resp, err := cdt.Decorator.QueryData(req.Context(), qdr)
|
resp, err := cdt.MiddlewareHandler.QueryData(req.Context(), qdr)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// Cache service is called once
|
// Cache service is called once
|
||||||
cs.AssertCalls(t, "HandleQueryRequest", 1)
|
cs.AssertCalls(t, "HandleQueryRequest", 1)
|
||||||
@ -105,9 +105,9 @@ func TestCachingMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("with async queries", func(t *testing.T) {
|
t.Run("with async queries", func(t *testing.T) {
|
||||||
asyncCdt := clienttest.NewClientDecoratorTest(t,
|
asyncCdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{}),
|
WithReqContext(req, &user.SignedInUser{}),
|
||||||
clienttest.WithMiddlewares(
|
handlertest.WithMiddlewares(
|
||||||
NewCachingMiddlewareWithFeatureManager(cs, featuremgmt.WithFeatures(featuremgmt.FlagAwsAsyncQueryCaching))),
|
NewCachingMiddlewareWithFeatureManager(cs, featuremgmt.WithFeatures(featuremgmt.FlagAwsAsyncQueryCaching))),
|
||||||
)
|
)
|
||||||
t.Run("If shoudCacheQuery returns true update cache function is called", func(t *testing.T) {
|
t.Run("If shoudCacheQuery returns true update cache function is called", func(t *testing.T) {
|
||||||
@ -128,7 +128,7 @@ func TestCachingMiddleware(t *testing.T) {
|
|||||||
cs.ReturnHit = false
|
cs.ReturnHit = false
|
||||||
cs.ReturnQueryResponse = dataResponse
|
cs.ReturnQueryResponse = dataResponse
|
||||||
|
|
||||||
resp, err := asyncCdt.Decorator.QueryData(req.Context(), qdr)
|
resp, err := asyncCdt.MiddlewareHandler.QueryData(req.Context(), qdr)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// Cache service is called once
|
// Cache service is called once
|
||||||
cs.AssertCalls(t, "HandleQueryRequest", 1)
|
cs.AssertCalls(t, "HandleQueryRequest", 1)
|
||||||
@ -158,7 +158,7 @@ func TestCachingMiddleware(t *testing.T) {
|
|||||||
cs.ReturnHit = false
|
cs.ReturnHit = false
|
||||||
cs.ReturnQueryResponse = dataResponse
|
cs.ReturnQueryResponse = dataResponse
|
||||||
|
|
||||||
resp, err := asyncCdt.Decorator.QueryData(req.Context(), qdr)
|
resp, err := asyncCdt.MiddlewareHandler.QueryData(req.Context(), qdr)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// Cache service is called once
|
// Cache service is called once
|
||||||
cs.AssertCalls(t, "HandleQueryRequest", 1)
|
cs.AssertCalls(t, "HandleQueryRequest", 1)
|
||||||
@ -196,10 +196,10 @@ func TestCachingMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cs := caching.NewFakeOSSCachingService()
|
cs := caching.NewFakeOSSCachingService()
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{}),
|
WithReqContext(req, &user.SignedInUser{}),
|
||||||
clienttest.WithMiddlewares(NewCachingMiddleware(cs)),
|
handlertest.WithMiddlewares(NewCachingMiddleware(cs)),
|
||||||
clienttest.WithResourceResponses([]*backend.CallResourceResponse{simulatedPluginResponse}),
|
handlertest.WithResourceResponses([]*backend.CallResourceResponse{simulatedPluginResponse}),
|
||||||
)
|
)
|
||||||
|
|
||||||
jsonDataMap := map[string]any{}
|
jsonDataMap := map[string]any{}
|
||||||
@ -235,7 +235,7 @@ func TestCachingMiddleware(t *testing.T) {
|
|||||||
cs.ReturnHit = true
|
cs.ReturnHit = true
|
||||||
cs.ReturnResourceResponse = dataResponse
|
cs.ReturnResourceResponse = dataResponse
|
||||||
|
|
||||||
err := cdt.Decorator.CallResource(req.Context(), crr, storeOneResponseCallResourceSender)
|
err := cdt.MiddlewareHandler.CallResource(req.Context(), crr, storeOneResponseCallResourceSender)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// Cache service is called once
|
// Cache service is called once
|
||||||
cs.AssertCalls(t, "HandleResourceRequest", 1)
|
cs.AssertCalls(t, "HandleResourceRequest", 1)
|
||||||
@ -255,7 +255,7 @@ func TestCachingMiddleware(t *testing.T) {
|
|||||||
cs.ReturnHit = false
|
cs.ReturnHit = false
|
||||||
cs.ReturnResourceResponse = dataResponse
|
cs.ReturnResourceResponse = dataResponse
|
||||||
|
|
||||||
err := cdt.Decorator.CallResource(req.Context(), crr, storeOneResponseCallResourceSender)
|
err := cdt.MiddlewareHandler.CallResource(req.Context(), crr, storeOneResponseCallResourceSender)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// Cache service is called once
|
// Cache service is called once
|
||||||
cs.AssertCalls(t, "HandleResourceRequest", 1)
|
cs.AssertCalls(t, "HandleResourceRequest", 1)
|
||||||
@ -272,9 +272,9 @@ func TestCachingMiddleware(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
cs := caching.NewFakeOSSCachingService()
|
cs := caching.NewFakeOSSCachingService()
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
// Skip the request context in this case
|
// Skip the request context in this case
|
||||||
clienttest.WithMiddlewares(NewCachingMiddleware(cs)),
|
handlertest.WithMiddlewares(NewCachingMiddleware(cs)),
|
||||||
)
|
)
|
||||||
reqCtx := contexthandler.FromContext(req.Context())
|
reqCtx := contexthandler.FromContext(req.Context())
|
||||||
require.Nil(t, reqCtx)
|
require.Nil(t, reqCtx)
|
||||||
@ -298,7 +298,7 @@ func TestCachingMiddleware(t *testing.T) {
|
|||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := cdt.Decorator.QueryData(context.Background(), qdr)
|
resp, err := cdt.MiddlewareHandler.QueryData(context.Background(), qdr)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// Cache service is never called
|
// Cache service is never called
|
||||||
cs.AssertCalls(t, "HandleQueryRequest", 0)
|
cs.AssertCalls(t, "HandleQueryRequest", 0)
|
||||||
@ -315,7 +315,7 @@ func TestCachingMiddleware(t *testing.T) {
|
|||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := cdt.Decorator.CallResource(req.Context(), crr, nopCallResourceSender)
|
err := cdt.MiddlewareHandler.CallResource(req.Context(), crr, nopCallResourceSender)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// Cache service is never called
|
// Cache service is never called
|
||||||
cs.AssertCalls(t, "HandleResourceRequest", 0)
|
cs.AssertCalls(t, "HandleResourceRequest", 0)
|
||||||
|
@ -5,25 +5,22 @@ import (
|
|||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewClearAuthHeadersMiddleware creates a new plugins.ClientMiddleware
|
// NewClearAuthHeadersMiddleware creates a new backend.HandlerMiddleware
|
||||||
// that will clear any outgoing HTTP headers that was part of the incoming
|
// that will clear any outgoing HTTP headers that was part of the incoming
|
||||||
// HTTP request and used when authenticating to Grafana.
|
// HTTP request and used when authenticating to Grafana.
|
||||||
func NewClearAuthHeadersMiddleware() plugins.ClientMiddleware {
|
func NewClearAuthHeadersMiddleware() backend.HandlerMiddleware {
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &ClearAuthHeadersMiddleware{
|
return &ClearAuthHeadersMiddleware{
|
||||||
baseMiddleware: baseMiddleware{
|
BaseHandler: backend.NewBaseHandler(next),
|
||||||
next: next,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClearAuthHeadersMiddleware struct {
|
type ClearAuthHeadersMiddleware struct {
|
||||||
baseMiddleware
|
backend.BaseHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ClearAuthHeadersMiddleware) clearHeaders(ctx context.Context, h backend.ForwardHTTPHeaders) {
|
func (m *ClearAuthHeadersMiddleware) clearHeaders(ctx context.Context, h backend.ForwardHTTPHeaders) {
|
||||||
@ -43,30 +40,30 @@ func (m *ClearAuthHeadersMiddleware) clearHeaders(ctx context.Context, h backend
|
|||||||
|
|
||||||
func (m *ClearAuthHeadersMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (m *ClearAuthHeadersMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.clearHeaders(ctx, req)
|
m.clearHeaders(ctx, req)
|
||||||
|
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ClearAuthHeadersMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
func (m *ClearAuthHeadersMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.clearHeaders(ctx, req)
|
m.clearHeaders(ctx, req)
|
||||||
|
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ClearAuthHeadersMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
func (m *ClearAuthHeadersMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.clearHeaders(ctx, req)
|
m.clearHeaders(ctx, req)
|
||||||
|
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
|
||||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
@ -23,9 +23,9 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
req.Header.Set(otherHeader, "test")
|
req.Header.Set(otherHeader, "test")
|
||||||
|
|
||||||
t.Run("And requests are for a datasource", func(t *testing.T) {
|
t.Run("And requests are for a datasource", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{}),
|
WithReqContext(req, &user.SignedInUser{}),
|
||||||
clienttest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
|
handlertest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
pluginCtx := backend.PluginContext{
|
pluginCtx := backend.PluginContext{
|
||||||
@ -33,7 +33,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should not attach delete headers middleware when calling QueryData", func(t *testing.T) {
|
t.Run("Should not attach delete headers middleware when calling QueryData", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
@ -43,7 +43,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not attach delete headers middleware when calling CallResource", func(t *testing.T) {
|
t.Run("Should not attach delete headers middleware when calling CallResource", func(t *testing.T) {
|
||||||
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string][]string{otherHeader: {"test"}},
|
Headers: map[string][]string{otherHeader: {"test"}},
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
@ -53,7 +53,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not attach delete headers middleware when calling CheckHealth", func(t *testing.T) {
|
t.Run("Should not attach delete headers middleware when calling CheckHealth", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
@ -64,9 +64,9 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("And requests are for an app", func(t *testing.T) {
|
t.Run("And requests are for an app", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{}),
|
WithReqContext(req, &user.SignedInUser{}),
|
||||||
clienttest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
|
handlertest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
pluginCtx := backend.PluginContext{
|
pluginCtx := backend.PluginContext{
|
||||||
@ -74,7 +74,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should not attach delete headers middleware when calling QueryData", func(t *testing.T) {
|
t.Run("Should not attach delete headers middleware when calling QueryData", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
@ -84,7 +84,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not attach delete headers middleware when calling CallResource", func(t *testing.T) {
|
t.Run("Should not attach delete headers middleware when calling CallResource", func(t *testing.T) {
|
||||||
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string][]string{otherHeader: {"test"}},
|
Headers: map[string][]string{otherHeader: {"test"}},
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
@ -94,7 +94,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not attach delete headers middleware when calling CheckHealth", func(t *testing.T) {
|
t.Run("Should not attach delete headers middleware when calling CheckHealth", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
@ -110,9 +110,9 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Run("And requests are for a datasource", func(t *testing.T) {
|
t.Run("And requests are for a datasource", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{}),
|
WithReqContext(req, &user.SignedInUser{}),
|
||||||
clienttest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
|
handlertest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
req := req.WithContext(contexthandler.WithAuthHTTPHeaders(req.Context(), setting.NewCfg()))
|
req := req.WithContext(contexthandler.WithAuthHTTPHeaders(req.Context(), setting.NewCfg()))
|
||||||
@ -126,7 +126,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should attach delete headers middleware when calling QueryData", func(t *testing.T) {
|
t.Run("Should attach delete headers middleware when calling QueryData", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
@ -137,7 +137,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should attach delete headers middleware when calling CallResource", func(t *testing.T) {
|
t.Run("Should attach delete headers middleware when calling CallResource", func(t *testing.T) {
|
||||||
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string][]string{otherHeader: {"test"}},
|
Headers: map[string][]string{otherHeader: {"test"}},
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
@ -148,7 +148,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should attach delete headers middleware when calling CheckHealth", func(t *testing.T) {
|
t.Run("Should attach delete headers middleware when calling CheckHealth", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
@ -160,9 +160,9 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("And requests are for an app", func(t *testing.T) {
|
t.Run("And requests are for an app", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{}),
|
WithReqContext(req, &user.SignedInUser{}),
|
||||||
clienttest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
|
handlertest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
req := req.WithContext(contexthandler.WithAuthHTTPHeaders(req.Context(), setting.NewCfg()))
|
req := req.WithContext(contexthandler.WithAuthHTTPHeaders(req.Context(), setting.NewCfg()))
|
||||||
@ -176,7 +176,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should attach delete headers middleware when calling QueryData", func(t *testing.T) {
|
t.Run("Should attach delete headers middleware when calling QueryData", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
@ -187,7 +187,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should attach delete headers middleware when calling CallResource", func(t *testing.T) {
|
t.Run("Should attach delete headers middleware when calling CallResource", func(t *testing.T) {
|
||||||
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string][]string{otherHeader: {"test"}},
|
Headers: map[string][]string{otherHeader: {"test"}},
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
@ -198,7 +198,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should attach delete headers middleware when calling CheckHealth", func(t *testing.T) {
|
t.Run("Should attach delete headers middleware when calling CheckHealth", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
|
@ -6,21 +6,20 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewContextualLoggerMiddleware creates a new plugins.ClientMiddleware that adds
|
// NewContextualLoggerMiddleware creates a new backend.HandlerMiddleware that adds
|
||||||
// a contextual logger to the request context.
|
// a contextual logger to the request context.
|
||||||
func NewContextualLoggerMiddleware() plugins.ClientMiddleware {
|
func NewContextualLoggerMiddleware() backend.HandlerMiddleware {
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &ContextualLoggerMiddleware{
|
return &ContextualLoggerMiddleware{
|
||||||
next: next,
|
BaseHandler: backend.NewBaseHandler(next),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContextualLoggerMiddleware struct {
|
type ContextualLoggerMiddleware struct {
|
||||||
next plugins.Client
|
backend.BaseHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// instrumentContext adds a contextual logger with plugin and request details to the given context.
|
// instrumentContext adds a contextual logger with plugin and request details to the given context.
|
||||||
@ -45,53 +44,53 @@ func instrumentContext(ctx context.Context, pCtx backend.PluginContext) context.
|
|||||||
|
|
||||||
func (m *ContextualLoggerMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (m *ContextualLoggerMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
ctx = instrumentContext(ctx, req.PluginContext)
|
ctx = instrumentContext(ctx, req.PluginContext)
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ContextualLoggerMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
func (m *ContextualLoggerMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||||
ctx = instrumentContext(ctx, req.PluginContext)
|
ctx = instrumentContext(ctx, req.PluginContext)
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ContextualLoggerMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
func (m *ContextualLoggerMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||||
ctx = instrumentContext(ctx, req.PluginContext)
|
ctx = instrumentContext(ctx, req.PluginContext)
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ContextualLoggerMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
|
func (m *ContextualLoggerMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
|
||||||
ctx = instrumentContext(ctx, req.PluginContext)
|
ctx = instrumentContext(ctx, req.PluginContext)
|
||||||
return m.next.CollectMetrics(ctx, req)
|
return m.BaseHandler.CollectMetrics(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ContextualLoggerMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
|
func (m *ContextualLoggerMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
|
||||||
ctx = instrumentContext(ctx, req.PluginContext)
|
ctx = instrumentContext(ctx, req.PluginContext)
|
||||||
return m.next.SubscribeStream(ctx, req)
|
return m.BaseHandler.SubscribeStream(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ContextualLoggerMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
|
func (m *ContextualLoggerMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
|
||||||
ctx = instrumentContext(ctx, req.PluginContext)
|
ctx = instrumentContext(ctx, req.PluginContext)
|
||||||
return m.next.PublishStream(ctx, req)
|
return m.BaseHandler.PublishStream(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ContextualLoggerMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
|
func (m *ContextualLoggerMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
|
||||||
ctx = instrumentContext(ctx, req.PluginContext)
|
ctx = instrumentContext(ctx, req.PluginContext)
|
||||||
return m.next.RunStream(ctx, req, sender)
|
return m.BaseHandler.RunStream(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateAdmission implements backend.AdmissionHandler.
|
// ValidateAdmission implements backend.AdmissionHandler.
|
||||||
func (m *ContextualLoggerMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
|
func (m *ContextualLoggerMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
|
||||||
ctx = instrumentContext(ctx, req.PluginContext)
|
ctx = instrumentContext(ctx, req.PluginContext)
|
||||||
return m.next.ValidateAdmission(ctx, req)
|
return m.BaseHandler.ValidateAdmission(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MutateAdmission implements backend.AdmissionHandler.
|
// MutateAdmission implements backend.AdmissionHandler.
|
||||||
func (m *ContextualLoggerMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
|
func (m *ContextualLoggerMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
|
||||||
ctx = instrumentContext(ctx, req.PluginContext)
|
ctx = instrumentContext(ctx, req.PluginContext)
|
||||||
return m.next.MutateAdmission(ctx, req)
|
return m.BaseHandler.MutateAdmission(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertObject implements backend.AdmissionHandler.
|
// ConvertObject implements backend.AdmissionHandler.
|
||||||
func (m *ContextualLoggerMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
|
func (m *ContextualLoggerMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
|
||||||
ctx = instrumentContext(ctx, req.PluginContext)
|
ctx = instrumentContext(ctx, req.PluginContext)
|
||||||
return m.next.ConvertObjects(ctx, req)
|
return m.BaseHandler.ConvertObjects(ctx, req)
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||||
"github.com/grafana/grafana/pkg/services/datasources"
|
"github.com/grafana/grafana/pkg/services/datasources"
|
||||||
"github.com/grafana/grafana/pkg/util/proxyutil"
|
"github.com/grafana/grafana/pkg/util/proxyutil"
|
||||||
@ -14,22 +13,20 @@ import (
|
|||||||
|
|
||||||
const cookieHeaderName = "Cookie"
|
const cookieHeaderName = "Cookie"
|
||||||
|
|
||||||
// NewCookiesMiddleware creates a new plugins.ClientMiddleware that will
|
// NewCookiesMiddleware creates a new backend.HandlerMiddleware that will
|
||||||
// forward incoming HTTP request Cookies to outgoing plugins.Client requests
|
// forward incoming HTTP request Cookies to outgoing backend.Handler requests
|
||||||
// if the datasource has enabled forwarding of cookies (keepCookies).
|
// if the datasource has enabled forwarding of cookies (keepCookies).
|
||||||
func NewCookiesMiddleware(skipCookiesNames []string) plugins.ClientMiddleware {
|
func NewCookiesMiddleware(skipCookiesNames []string) backend.HandlerMiddleware {
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &CookiesMiddleware{
|
return &CookiesMiddleware{
|
||||||
baseMiddleware: baseMiddleware{
|
BaseHandler: backend.NewBaseHandler(next),
|
||||||
next: next,
|
|
||||||
},
|
|
||||||
skipCookiesNames: skipCookiesNames,
|
skipCookiesNames: skipCookiesNames,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type CookiesMiddleware struct {
|
type CookiesMiddleware struct {
|
||||||
baseMiddleware
|
backend.BaseHandler
|
||||||
skipCookiesNames []string
|
skipCookiesNames []string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +84,7 @@ func (m *CookiesMiddleware) applyCookies(ctx context.Context, pCtx backend.Plugi
|
|||||||
|
|
||||||
func (m *CookiesMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (m *CookiesMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.applyCookies(ctx, req.PluginContext, req)
|
err := m.applyCookies(ctx, req.PluginContext, req)
|
||||||
@ -95,12 +92,12 @@ func (m *CookiesMiddleware) QueryData(ctx context.Context, req *backend.QueryDat
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *CookiesMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
func (m *CookiesMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.applyCookies(ctx, req.PluginContext, req)
|
err := m.applyCookies(ctx, req.PluginContext, req)
|
||||||
@ -108,12 +105,12 @@ func (m *CookiesMiddleware) CallResource(ctx context.Context, req *backend.CallR
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *CookiesMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
func (m *CookiesMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.applyCookies(ctx, req.PluginContext, req)
|
err := m.applyCookies(ctx, req.PluginContext, req)
|
||||||
@ -121,5 +118,5 @@ func (m *CookiesMiddleware) CheckHealth(ctx context.Context, req *backend.CheckH
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@ -28,9 +28,9 @@ func TestCookiesMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
req.Header.Set(otherHeader, "test")
|
req.Header.Set(otherHeader, "test")
|
||||||
|
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{}),
|
WithReqContext(req, &user.SignedInUser{}),
|
||||||
clienttest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})),
|
handlertest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})),
|
||||||
)
|
)
|
||||||
|
|
||||||
jsonDataMap := map[string]any{}
|
jsonDataMap := map[string]any{}
|
||||||
@ -44,7 +44,7 @@ func TestCookiesMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should not forward cookies when calling QueryData", func(t *testing.T) {
|
t.Run("Should not forward cookies when calling QueryData", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
@ -60,7 +60,7 @@ func TestCookiesMiddleware(t *testing.T) {
|
|||||||
Headers: map[string][]string{otherHeader: {"test"}},
|
Headers: map[string][]string{otherHeader: {"test"}},
|
||||||
}
|
}
|
||||||
pReq.Headers[backend.CookiesHeaderName] = []string{req.Header.Get(backend.CookiesHeaderName)}
|
pReq.Headers[backend.CookiesHeaderName] = []string{req.Header.Get(backend.CookiesHeaderName)}
|
||||||
err = cdt.Decorator.CallResource(req.Context(), pReq, nopCallResourceSender)
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), pReq, nopCallResourceSender)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, cdt.CallResourceReq)
|
require.NotNil(t, cdt.CallResourceReq)
|
||||||
require.Len(t, cdt.CallResourceReq.Headers, 1)
|
require.Len(t, cdt.CallResourceReq.Headers, 1)
|
||||||
@ -68,7 +68,7 @@ func TestCookiesMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not forward cookies when calling CheckHealth", func(t *testing.T) {
|
t.Run("Should not forward cookies when calling CheckHealth", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
@ -97,9 +97,9 @@ func TestCookiesMiddleware(t *testing.T) {
|
|||||||
|
|
||||||
req.Header.Set(otherHeader, "test")
|
req.Header.Set(otherHeader, "test")
|
||||||
|
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{}),
|
WithReqContext(req, &user.SignedInUser{}),
|
||||||
clienttest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})),
|
handlertest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})),
|
||||||
)
|
)
|
||||||
|
|
||||||
jsonDataMap := map[string]any{
|
jsonDataMap := map[string]any{
|
||||||
@ -115,7 +115,7 @@ func TestCookiesMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should forward cookies when calling QueryData", func(t *testing.T) {
|
t.Run("Should forward cookies when calling QueryData", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
@ -127,7 +127,7 @@ func TestCookiesMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should forward cookies when calling CallResource", func(t *testing.T) {
|
t.Run("Should forward cookies when calling CallResource", func(t *testing.T) {
|
||||||
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string][]string{otherHeader: {"test"}},
|
Headers: map[string][]string{otherHeader: {"test"}},
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
@ -140,7 +140,7 @@ func TestCookiesMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should forward cookies when calling CheckHealth", func(t *testing.T) {
|
t.Run("Should forward cookies when calling CheckHealth", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
@ -166,9 +166,9 @@ func TestCookiesMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
req.Header.Set(otherHeader, "test")
|
req.Header.Set(otherHeader, "test")
|
||||||
|
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{}),
|
WithReqContext(req, &user.SignedInUser{}),
|
||||||
clienttest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})),
|
handlertest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})),
|
||||||
)
|
)
|
||||||
|
|
||||||
pluginCtx := backend.PluginContext{
|
pluginCtx := backend.PluginContext{
|
||||||
@ -181,7 +181,7 @@ func TestCookiesMiddleware(t *testing.T) {
|
|||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
}
|
}
|
||||||
pReq.Headers[backend.CookiesHeaderName] = req.Header.Get(backend.CookiesHeaderName)
|
pReq.Headers[backend.CookiesHeaderName] = req.Header.Get(backend.CookiesHeaderName)
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), pReq)
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), pReq)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, cdt.QueryDataReq)
|
require.NotNil(t, cdt.QueryDataReq)
|
||||||
require.Len(t, cdt.QueryDataReq.Headers, 1)
|
require.Len(t, cdt.QueryDataReq.Headers, 1)
|
||||||
@ -194,7 +194,7 @@ func TestCookiesMiddleware(t *testing.T) {
|
|||||||
Headers: map[string][]string{otherHeader: {"test"}},
|
Headers: map[string][]string{otherHeader: {"test"}},
|
||||||
}
|
}
|
||||||
pReq.Headers[backend.CookiesHeaderName] = []string{req.Header.Get(backend.CookiesHeaderName)}
|
pReq.Headers[backend.CookiesHeaderName] = []string{req.Header.Get(backend.CookiesHeaderName)}
|
||||||
err = cdt.Decorator.CallResource(req.Context(), pReq, nopCallResourceSender)
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), pReq, nopCallResourceSender)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, cdt.CallResourceReq)
|
require.NotNil(t, cdt.CallResourceReq)
|
||||||
require.Len(t, cdt.CallResourceReq.Headers, 1)
|
require.Len(t, cdt.CallResourceReq.Headers, 1)
|
||||||
@ -207,7 +207,7 @@ func TestCookiesMiddleware(t *testing.T) {
|
|||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
}
|
}
|
||||||
pReq.Headers[backend.CookiesHeaderName] = req.Header.Get(backend.CookiesHeaderName)
|
pReq.Headers[backend.CookiesHeaderName] = req.Header.Get(backend.CookiesHeaderName)
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), pReq)
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), pReq)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, cdt.CheckHealthReq)
|
require.NotNil(t, cdt.CheckHealthReq)
|
||||||
require.Len(t, cdt.CheckHealthReq.Headers, 1)
|
require.Len(t, cdt.CheckHealthReq.Headers, 1)
|
||||||
|
@ -5,26 +5,23 @@ import (
|
|||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||||
)
|
)
|
||||||
|
|
||||||
const forwardIDHeaderName = "X-Grafana-Id"
|
const forwardIDHeaderName = "X-Grafana-Id"
|
||||||
|
|
||||||
// NewForwardIDMiddleware creates a new plugins.ClientMiddleware that will
|
// NewForwardIDMiddleware creates a new backend.HandlerMiddleware that will
|
||||||
// set grafana id header on outgoing plugins.Client requests
|
// set grafana id header on outgoing backend.Handler requests
|
||||||
func NewForwardIDMiddleware() plugins.ClientMiddleware {
|
func NewForwardIDMiddleware() backend.HandlerMiddleware {
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &ForwardIDMiddleware{
|
return &ForwardIDMiddleware{
|
||||||
baseMiddleware: baseMiddleware{
|
BaseHandler: backend.NewBaseHandler(next),
|
||||||
next: next,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type ForwardIDMiddleware struct {
|
type ForwardIDMiddleware struct {
|
||||||
baseMiddleware
|
backend.BaseHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ForwardIDMiddleware) applyToken(ctx context.Context, pCtx backend.PluginContext, req backend.ForwardHTTPHeaders) error {
|
func (m *ForwardIDMiddleware) applyToken(ctx context.Context, pCtx backend.PluginContext, req backend.ForwardHTTPHeaders) error {
|
||||||
@ -43,7 +40,7 @@ func (m *ForwardIDMiddleware) applyToken(ctx context.Context, pCtx backend.Plugi
|
|||||||
|
|
||||||
func (m *ForwardIDMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (m *ForwardIDMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.applyToken(ctx, req.PluginContext, req)
|
err := m.applyToken(ctx, req.PluginContext, req)
|
||||||
@ -51,12 +48,12 @@ func (m *ForwardIDMiddleware) QueryData(ctx context.Context, req *backend.QueryD
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ForwardIDMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
func (m *ForwardIDMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.applyToken(ctx, req.PluginContext, req)
|
err := m.applyToken(ctx, req.PluginContext, req)
|
||||||
@ -64,12 +61,12 @@ func (m *ForwardIDMiddleware) CallResource(ctx context.Context, req *backend.Cal
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ForwardIDMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
func (m *ForwardIDMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.applyToken(ctx, req.PluginContext, req)
|
err := m.applyToken(ctx, req.PluginContext, req)
|
||||||
@ -77,5 +74,5 @@ func (m *ForwardIDMiddleware) CheckHealth(ctx context.Context, req *backend.Chec
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
|
|
||||||
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
||||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
@ -21,14 +21,14 @@ func TestForwardIDMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should set forwarded id header if present", func(t *testing.T) {
|
t.Run("Should set forwarded id header if present", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewForwardIDMiddleware()))
|
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewForwardIDMiddleware()))
|
||||||
|
|
||||||
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
|
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
|
||||||
Context: &web.Context{Req: &http.Request{}},
|
Context: &web.Context{Req: &http.Request{}},
|
||||||
SignedInUser: &user.SignedInUser{IDToken: "some-token"},
|
SignedInUser: &user.SignedInUser{IDToken: "some-token"},
|
||||||
})
|
})
|
||||||
|
|
||||||
err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{
|
err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{
|
||||||
PluginContext: pluginContext,
|
PluginContext: pluginContext,
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -37,14 +37,14 @@ func TestForwardIDMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not set forwarded id header if not present", func(t *testing.T) {
|
t.Run("Should not set forwarded id header if not present", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewForwardIDMiddleware()))
|
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewForwardIDMiddleware()))
|
||||||
|
|
||||||
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
|
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
|
||||||
Context: &web.Context{Req: &http.Request{}},
|
Context: &web.Context{Req: &http.Request{}},
|
||||||
SignedInUser: &user.SignedInUser{},
|
SignedInUser: &user.SignedInUser{},
|
||||||
})
|
})
|
||||||
|
|
||||||
err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{
|
err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{
|
||||||
PluginContext: pluginContext,
|
PluginContext: pluginContext,
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -57,14 +57,14 @@ func TestForwardIDMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should set forwarded id header to app plugin if present", func(t *testing.T) {
|
t.Run("Should set forwarded id header to app plugin if present", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewForwardIDMiddleware()))
|
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewForwardIDMiddleware()))
|
||||||
|
|
||||||
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
|
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
|
||||||
Context: &web.Context{Req: &http.Request{}},
|
Context: &web.Context{Req: &http.Request{}},
|
||||||
SignedInUser: &user.SignedInUser{IDToken: "some-token"},
|
SignedInUser: &user.SignedInUser{IDToken: "some-token"},
|
||||||
})
|
})
|
||||||
|
|
||||||
err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{
|
err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{
|
||||||
PluginContext: pluginContext,
|
PluginContext: pluginContext,
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -13,7 +13,6 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
"github.com/grafana/grafana/pkg/web"
|
"github.com/grafana/grafana/pkg/web"
|
||||||
@ -24,24 +23,22 @@ const GrafanaSignedRequestID = "X-Grafana-Signed-Request-Id"
|
|||||||
const XRealIPHeader = "X-Real-Ip"
|
const XRealIPHeader = "X-Real-Ip"
|
||||||
const GrafanaInternalRequest = "X-Grafana-Internal-Request"
|
const GrafanaInternalRequest = "X-Grafana-Internal-Request"
|
||||||
|
|
||||||
// NewHostedGrafanaACHeaderMiddleware creates a new plugins.ClientMiddleware that will
|
// NewHostedGrafanaACHeaderMiddleware creates a new backend.HandlerMiddleware that will
|
||||||
// generate a random request ID, sign it using internal key and populate X-Grafana-Request-ID with the request ID
|
// generate a random request ID, sign it using internal key and populate X-Grafana-Request-ID with the request ID
|
||||||
// and X-Grafana-Signed-Request-ID with signed request ID. We can then use this to verify that the request
|
// and X-Grafana-Signed-Request-ID with signed request ID. We can then use this to verify that the request
|
||||||
// is coming from hosted Grafana and is not an external request. This is used for IP range access control.
|
// is coming from hosted Grafana and is not an external request. This is used for IP range access control.
|
||||||
func NewHostedGrafanaACHeaderMiddleware(cfg *setting.Cfg) plugins.ClientMiddleware {
|
func NewHostedGrafanaACHeaderMiddleware(cfg *setting.Cfg) backend.HandlerMiddleware {
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &HostedGrafanaACHeaderMiddleware{
|
return &HostedGrafanaACHeaderMiddleware{
|
||||||
baseMiddleware: baseMiddleware{
|
BaseHandler: backend.NewBaseHandler(next),
|
||||||
next: next,
|
log: log.New("ip_header_middleware"),
|
||||||
},
|
cfg: cfg,
|
||||||
log: log.New("ip_header_middleware"),
|
|
||||||
cfg: cfg,
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type HostedGrafanaACHeaderMiddleware struct {
|
type HostedGrafanaACHeaderMiddleware struct {
|
||||||
baseMiddleware
|
backend.BaseHandler
|
||||||
log log.Logger
|
log log.Logger
|
||||||
cfg *setting.Cfg
|
cfg *setting.Cfg
|
||||||
}
|
}
|
||||||
@ -120,30 +117,30 @@ func GetGrafanaRequestIDHeaders(req *http.Request, cfg *setting.Cfg, logger log.
|
|||||||
|
|
||||||
func (m *HostedGrafanaACHeaderMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (m *HostedGrafanaACHeaderMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.applyGrafanaRequestIDHeader(ctx, req.PluginContext, req)
|
m.applyGrafanaRequestIDHeader(ctx, req.PluginContext, req)
|
||||||
|
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *HostedGrafanaACHeaderMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
func (m *HostedGrafanaACHeaderMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.applyGrafanaRequestIDHeader(ctx, req.PluginContext, req)
|
m.applyGrafanaRequestIDHeader(ctx, req.PluginContext, req)
|
||||||
|
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *HostedGrafanaACHeaderMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
func (m *HostedGrafanaACHeaderMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.applyGrafanaRequestIDHeader(ctx, req.PluginContext, req)
|
m.applyGrafanaRequestIDHeader(ctx, req.PluginContext, req)
|
||||||
|
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
|
||||||
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
||||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
@ -26,7 +26,7 @@ func Test_HostedGrafanaACHeaderMiddleware(t *testing.T) {
|
|||||||
allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"}
|
allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"}
|
||||||
cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL}
|
cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL}
|
||||||
cfg.IPRangeACSecretKey = "secret"
|
cfg.IPRangeACSecretKey = "secret"
|
||||||
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
|
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
|
||||||
|
|
||||||
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
|
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
|
||||||
Context: &web.Context{Req: &http.Request{
|
Context: &web.Context{Req: &http.Request{
|
||||||
@ -35,7 +35,7 @@ func Test_HostedGrafanaACHeaderMiddleware(t *testing.T) {
|
|||||||
SignedInUser: &user.SignedInUser{},
|
SignedInUser: &user.SignedInUser{},
|
||||||
})
|
})
|
||||||
|
|
||||||
err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{
|
err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{
|
||||||
PluginContext: backend.PluginContext{
|
PluginContext: backend.PluginContext{
|
||||||
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
|
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
|
||||||
URL: "https://logs.grafana.net",
|
URL: "https://logs.grafana.net",
|
||||||
@ -68,14 +68,14 @@ func Test_HostedGrafanaACHeaderMiddleware(t *testing.T) {
|
|||||||
allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"}
|
allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"}
|
||||||
cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL}
|
cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL}
|
||||||
cfg.IPRangeACSecretKey = "secret"
|
cfg.IPRangeACSecretKey = "secret"
|
||||||
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
|
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
|
||||||
|
|
||||||
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
|
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
|
||||||
Context: &web.Context{Req: &http.Request{}},
|
Context: &web.Context{Req: &http.Request{}},
|
||||||
SignedInUser: &user.SignedInUser{},
|
SignedInUser: &user.SignedInUser{},
|
||||||
})
|
})
|
||||||
|
|
||||||
err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{
|
err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{
|
||||||
PluginContext: backend.PluginContext{
|
PluginContext: backend.PluginContext{
|
||||||
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
|
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
|
||||||
URL: "https://logs.not-grafana.net",
|
URL: "https://logs.not-grafana.net",
|
||||||
@ -93,14 +93,14 @@ func Test_HostedGrafanaACHeaderMiddleware(t *testing.T) {
|
|||||||
allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"}
|
allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"}
|
||||||
cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL}
|
cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL}
|
||||||
cfg.IPRangeACSecretKey = "secret"
|
cfg.IPRangeACSecretKey = "secret"
|
||||||
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
|
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
|
||||||
|
|
||||||
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
|
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
|
||||||
Context: &web.Context{Req: &http.Request{}},
|
Context: &web.Context{Req: &http.Request{}},
|
||||||
SignedInUser: &user.SignedInUser{},
|
SignedInUser: &user.SignedInUser{},
|
||||||
})
|
})
|
||||||
|
|
||||||
err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{
|
err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{
|
||||||
PluginContext: backend.PluginContext{
|
PluginContext: backend.PluginContext{
|
||||||
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
|
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
|
||||||
URL: "https://logs.grafana.net/abc/../some/path",
|
URL: "https://logs.grafana.net/abc/../some/path",
|
||||||
@ -118,14 +118,14 @@ func Test_HostedGrafanaACHeaderMiddleware(t *testing.T) {
|
|||||||
allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"}
|
allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"}
|
||||||
cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL}
|
cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL}
|
||||||
cfg.IPRangeACSecretKey = "secret"
|
cfg.IPRangeACSecretKey = "secret"
|
||||||
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
|
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
|
||||||
|
|
||||||
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
|
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
|
||||||
Context: &web.Context{Req: &http.Request{}},
|
Context: &web.Context{Req: &http.Request{}},
|
||||||
SignedInUser: &user.SignedInUser{},
|
SignedInUser: &user.SignedInUser{},
|
||||||
})
|
})
|
||||||
|
|
||||||
err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{
|
err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{
|
||||||
PluginContext: backend.PluginContext{
|
PluginContext: backend.PluginContext{
|
||||||
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
|
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
|
||||||
URL: "https://logs.grafana.net",
|
URL: "https://logs.grafana.net",
|
||||||
|
@ -7,26 +7,23 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
ngalertmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
ngalertmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
const forwardPluginRequestHTTPHeaders = "forward-plugin-request-http-headers"
|
const forwardPluginRequestHTTPHeaders = "forward-plugin-request-http-headers"
|
||||||
|
|
||||||
// NewHTTPClientMiddleware creates a new plugins.ClientMiddleware
|
// NewHTTPClientMiddleware creates a new backend.HandlerMiddleware
|
||||||
// that will forward plugin request headers as outgoing HTTP headers.
|
// that will forward plugin request headers as outgoing HTTP headers.
|
||||||
func NewHTTPClientMiddleware() plugins.ClientMiddleware {
|
func NewHTTPClientMiddleware() backend.HandlerMiddleware {
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &HTTPClientMiddleware{
|
return &HTTPClientMiddleware{
|
||||||
baseMiddleware: baseMiddleware{
|
BaseHandler: backend.NewBaseHandler(next),
|
||||||
next: next,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type HTTPClientMiddleware struct {
|
type HTTPClientMiddleware struct {
|
||||||
baseMiddleware
|
backend.BaseHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *HTTPClientMiddleware) applyHeaders(ctx context.Context, pReq any) context.Context {
|
func (m *HTTPClientMiddleware) applyHeaders(ctx context.Context, pReq any) context.Context {
|
||||||
@ -69,30 +66,30 @@ func (m *HTTPClientMiddleware) applyHeaders(ctx context.Context, pReq any) conte
|
|||||||
|
|
||||||
func (m *HTTPClientMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (m *HTTPClientMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = m.applyHeaders(ctx, req)
|
ctx = m.applyHeaders(ctx, req)
|
||||||
|
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *HTTPClientMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
func (m *HTTPClientMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = m.applyHeaders(ctx, req)
|
ctx = m.applyHeaders(ctx, req)
|
||||||
|
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *HTTPClientMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
func (m *HTTPClientMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = m.applyHeaders(ctx, req)
|
ctx = m.applyHeaders(ctx, req)
|
||||||
|
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
|
|
||||||
ngalertmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
ngalertmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
"github.com/grafana/grafana/pkg/util/proxyutil"
|
"github.com/grafana/grafana/pkg/util/proxyutil"
|
||||||
@ -23,9 +23,9 @@ func TestHTTPClientMiddleware(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Run("And requests are for a datasource", func(t *testing.T) {
|
t.Run("And requests are for a datasource", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{}),
|
WithReqContext(req, &user.SignedInUser{}),
|
||||||
clienttest.WithMiddlewares(NewHTTPClientMiddleware()),
|
handlertest.WithMiddlewares(NewHTTPClientMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
pluginCtx := backend.PluginContext{
|
pluginCtx := backend.PluginContext{
|
||||||
@ -33,7 +33,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should not forward headers when calling QueryData", func(t *testing.T) {
|
t.Run("Should not forward headers when calling QueryData", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "val"},
|
Headers: map[string]string{otherHeader: "val"},
|
||||||
})
|
})
|
||||||
@ -53,7 +53,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not forward headers when calling CallResource", func(t *testing.T) {
|
t.Run("Should not forward headers when calling CallResource", func(t *testing.T) {
|
||||||
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string][]string{otherHeader: {"val"}},
|
Headers: map[string][]string{otherHeader: {"val"}},
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
@ -73,7 +73,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not forward headers when calling CheckHealth", func(t *testing.T) {
|
t.Run("Should not forward headers when calling CheckHealth", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "val"},
|
Headers: map[string]string{otherHeader: "val"},
|
||||||
})
|
})
|
||||||
@ -94,9 +94,9 @@ func TestHTTPClientMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("And requests are for an app", func(t *testing.T) {
|
t.Run("And requests are for an app", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{}),
|
WithReqContext(req, &user.SignedInUser{}),
|
||||||
clienttest.WithMiddlewares(NewHTTPClientMiddleware()),
|
handlertest.WithMiddlewares(NewHTTPClientMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
pluginCtx := backend.PluginContext{
|
pluginCtx := backend.PluginContext{
|
||||||
@ -104,7 +104,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should not forward headers when calling QueryData", func(t *testing.T) {
|
t.Run("Should not forward headers when calling QueryData", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
@ -124,7 +124,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not forward headers when calling CallResource", func(t *testing.T) {
|
t.Run("Should not forward headers when calling CallResource", func(t *testing.T) {
|
||||||
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string][]string{},
|
Headers: map[string][]string{},
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
@ -144,7 +144,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not forward headers when calling CheckHealth", func(t *testing.T) {
|
t.Run("Should not forward headers when calling CheckHealth", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
@ -184,9 +184,9 @@ func TestHTTPClientMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("And requests are for a datasource", func(t *testing.T) {
|
t.Run("And requests are for a datasource", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{}),
|
WithReqContext(req, &user.SignedInUser{}),
|
||||||
clienttest.WithMiddlewares(NewHTTPClientMiddleware()),
|
handlertest.WithMiddlewares(NewHTTPClientMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
pluginCtx := backend.PluginContext{
|
pluginCtx := backend.PluginContext{
|
||||||
@ -194,7 +194,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should forward headers when calling QueryData", func(t *testing.T) {
|
t.Run("Should forward headers when calling QueryData", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: headers,
|
Headers: headers,
|
||||||
})
|
})
|
||||||
@ -222,7 +222,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should forward headers when calling CallResource", func(t *testing.T) {
|
t.Run("Should forward headers when calling CallResource", func(t *testing.T) {
|
||||||
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: crHeaders,
|
Headers: crHeaders,
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
@ -250,7 +250,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should forward headers when calling CheckHealth", func(t *testing.T) {
|
t.Run("Should forward headers when calling CheckHealth", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: headers,
|
Headers: headers,
|
||||||
})
|
})
|
||||||
@ -278,7 +278,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not overwrite an existing header", func(t *testing.T) {
|
t.Run("Should not overwrite an existing header", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: headers,
|
Headers: headers,
|
||||||
})
|
})
|
||||||
|
@ -7,21 +7,18 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/instrumentationutils"
|
"github.com/grafana/grafana/pkg/plugins/instrumentationutils"
|
||||||
plog "github.com/grafana/grafana/pkg/plugins/log"
|
plog "github.com/grafana/grafana/pkg/plugins/log"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/registry"
|
"github.com/grafana/grafana/pkg/plugins/manager/registry"
|
||||||
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
|
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewLoggerMiddleware creates a new plugins.ClientMiddleware that will
|
// NewLoggerMiddleware creates a new backend.HandlerMiddleware that will
|
||||||
// log requests.
|
// log requests.
|
||||||
func NewLoggerMiddleware(logger plog.Logger, pluginRegistry registry.Service) plugins.ClientMiddleware {
|
func NewLoggerMiddleware(logger plog.Logger, pluginRegistry registry.Service) backend.HandlerMiddleware {
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &LoggerMiddleware{
|
return &LoggerMiddleware{
|
||||||
baseMiddleware: baseMiddleware{
|
BaseHandler: backend.NewBaseHandler(next),
|
||||||
next: next,
|
|
||||||
},
|
|
||||||
logger: logger,
|
logger: logger,
|
||||||
pluginRegistry: pluginRegistry,
|
pluginRegistry: pluginRegistry,
|
||||||
}
|
}
|
||||||
@ -29,7 +26,7 @@ func NewLoggerMiddleware(logger plog.Logger, pluginRegistry registry.Service) pl
|
|||||||
}
|
}
|
||||||
|
|
||||||
type LoggerMiddleware struct {
|
type LoggerMiddleware struct {
|
||||||
baseMiddleware
|
backend.BaseHandler
|
||||||
logger plog.Logger
|
logger plog.Logger
|
||||||
pluginRegistry registry.Service
|
pluginRegistry registry.Service
|
||||||
}
|
}
|
||||||
@ -77,13 +74,13 @@ func (m *LoggerMiddleware) logRequest(ctx context.Context, pCtx backend.PluginCo
|
|||||||
|
|
||||||
func (m *LoggerMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (m *LoggerMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp *backend.QueryDataResponse
|
var resp *backend.QueryDataResponse
|
||||||
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.QueryData(ctx, req)
|
resp, innerErr = m.BaseHandler.QueryData(ctx, req)
|
||||||
|
|
||||||
if innerErr != nil {
|
if innerErr != nil {
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
@ -110,11 +107,11 @@ func (m *LoggerMiddleware) QueryData(ctx context.Context, req *backend.QueryData
|
|||||||
|
|
||||||
func (m *LoggerMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
func (m *LoggerMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
innerErr := m.next.CallResource(ctx, req, sender)
|
innerErr := m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -123,13 +120,13 @@ func (m *LoggerMiddleware) CallResource(ctx context.Context, req *backend.CallRe
|
|||||||
|
|
||||||
func (m *LoggerMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
func (m *LoggerMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp *backend.CheckHealthResult
|
var resp *backend.CheckHealthResult
|
||||||
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.CheckHealth(ctx, req)
|
resp, innerErr = m.BaseHandler.CheckHealth(ctx, req)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -138,13 +135,13 @@ func (m *LoggerMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHe
|
|||||||
|
|
||||||
func (m *LoggerMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
|
func (m *LoggerMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CollectMetrics(ctx, req)
|
return m.BaseHandler.CollectMetrics(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp *backend.CollectMetricsResult
|
var resp *backend.CollectMetricsResult
|
||||||
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.CollectMetrics(ctx, req)
|
resp, innerErr = m.BaseHandler.CollectMetrics(ctx, req)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -153,13 +150,13 @@ func (m *LoggerMiddleware) CollectMetrics(ctx context.Context, req *backend.Coll
|
|||||||
|
|
||||||
func (m *LoggerMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
|
func (m *LoggerMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.SubscribeStream(ctx, req)
|
return m.BaseHandler.SubscribeStream(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp *backend.SubscribeStreamResponse
|
var resp *backend.SubscribeStreamResponse
|
||||||
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.SubscribeStream(ctx, req)
|
resp, innerErr = m.BaseHandler.SubscribeStream(ctx, req)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -168,13 +165,13 @@ func (m *LoggerMiddleware) SubscribeStream(ctx context.Context, req *backend.Sub
|
|||||||
|
|
||||||
func (m *LoggerMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
|
func (m *LoggerMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.PublishStream(ctx, req)
|
return m.BaseHandler.PublishStream(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp *backend.PublishStreamResponse
|
var resp *backend.PublishStreamResponse
|
||||||
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.PublishStream(ctx, req)
|
resp, innerErr = m.BaseHandler.PublishStream(ctx, req)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -183,11 +180,11 @@ func (m *LoggerMiddleware) PublishStream(ctx context.Context, req *backend.Publi
|
|||||||
|
|
||||||
func (m *LoggerMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
|
func (m *LoggerMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.RunStream(ctx, req, sender)
|
return m.BaseHandler.RunStream(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
innerErr := m.next.RunStream(ctx, req, sender)
|
innerErr := m.BaseHandler.RunStream(ctx, req, sender)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -196,13 +193,13 @@ func (m *LoggerMiddleware) RunStream(ctx context.Context, req *backend.RunStream
|
|||||||
|
|
||||||
func (m *LoggerMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
|
func (m *LoggerMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.ValidateAdmission(ctx, req)
|
return m.BaseHandler.ValidateAdmission(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp *backend.ValidationResponse
|
var resp *backend.ValidationResponse
|
||||||
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.ValidateAdmission(ctx, req)
|
resp, innerErr = m.BaseHandler.ValidateAdmission(ctx, req)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -211,13 +208,13 @@ func (m *LoggerMiddleware) ValidateAdmission(ctx context.Context, req *backend.A
|
|||||||
|
|
||||||
func (m *LoggerMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
|
func (m *LoggerMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.MutateAdmission(ctx, req)
|
return m.BaseHandler.MutateAdmission(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp *backend.MutationResponse
|
var resp *backend.MutationResponse
|
||||||
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.MutateAdmission(ctx, req)
|
resp, innerErr = m.BaseHandler.MutateAdmission(ctx, req)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -226,13 +223,13 @@ func (m *LoggerMiddleware) MutateAdmission(ctx context.Context, req *backend.Adm
|
|||||||
|
|
||||||
func (m *LoggerMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
|
func (m *LoggerMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.ConvertObjects(ctx, req)
|
return m.BaseHandler.ConvertObjects(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp *backend.ConversionResponse
|
var resp *backend.ConversionResponse
|
||||||
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.ConvertObjects(ctx, req)
|
resp, innerErr = m.BaseHandler.ConvertObjects(ctx, req)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ type pluginMetrics struct {
|
|||||||
// MetricsMiddleware is a middleware that instruments plugin requests.
|
// MetricsMiddleware is a middleware that instruments plugin requests.
|
||||||
// It tracks requests count, duration and size as prometheus metrics.
|
// It tracks requests count, duration and size as prometheus metrics.
|
||||||
type MetricsMiddleware struct {
|
type MetricsMiddleware struct {
|
||||||
baseMiddleware
|
backend.BaseHandler
|
||||||
pluginMetrics
|
pluginMetrics
|
||||||
pluginRegistry registry.Service
|
pluginRegistry registry.Service
|
||||||
}
|
}
|
||||||
@ -75,12 +75,10 @@ func newMetricsMiddleware(promRegisterer prometheus.Registerer, pluginRegistry r
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewMetricsMiddleware returns a new MetricsMiddleware.
|
// NewMetricsMiddleware returns a new MetricsMiddleware.
|
||||||
func NewMetricsMiddleware(promRegisterer prometheus.Registerer, pluginRegistry registry.Service) plugins.ClientMiddleware {
|
func NewMetricsMiddleware(promRegisterer prometheus.Registerer, pluginRegistry registry.Service) backend.HandlerMiddleware {
|
||||||
imw := newMetricsMiddleware(promRegisterer, pluginRegistry)
|
imw := newMetricsMiddleware(promRegisterer, pluginRegistry)
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
imw.baseMiddleware = baseMiddleware{
|
imw.BaseHandler = backend.NewBaseHandler(next)
|
||||||
next: next,
|
|
||||||
}
|
|
||||||
return imw
|
return imw
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -154,7 +152,7 @@ func (m *MetricsMiddleware) QueryData(ctx context.Context, req *backend.QueryDat
|
|||||||
var resp *backend.QueryDataResponse
|
var resp *backend.QueryDataResponse
|
||||||
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.QueryData(ctx, req)
|
resp, innerErr = m.BaseHandler.QueryData(ctx, req)
|
||||||
return instrumentationutils.RequestStatusFromQueryDataResponse(resp, innerErr), innerErr
|
return instrumentationutils.RequestStatusFromQueryDataResponse(resp, innerErr), innerErr
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -166,7 +164,7 @@ func (m *MetricsMiddleware) CallResource(ctx context.Context, req *backend.CallR
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
return m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
innerErr := m.next.CallResource(ctx, req, sender)
|
innerErr := m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -175,7 +173,7 @@ func (m *MetricsMiddleware) CheckHealth(ctx context.Context, req *backend.CheckH
|
|||||||
var resp *backend.CheckHealthResult
|
var resp *backend.CheckHealthResult
|
||||||
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.CheckHealth(ctx, req)
|
resp, innerErr = m.BaseHandler.CheckHealth(ctx, req)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -186,7 +184,7 @@ func (m *MetricsMiddleware) CollectMetrics(ctx context.Context, req *backend.Col
|
|||||||
var resp *backend.CollectMetricsResult
|
var resp *backend.CollectMetricsResult
|
||||||
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.CollectMetrics(ctx, req)
|
resp, innerErr = m.BaseHandler.CollectMetrics(ctx, req)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
return resp, err
|
return resp, err
|
||||||
@ -196,7 +194,7 @@ func (m *MetricsMiddleware) SubscribeStream(ctx context.Context, req *backend.Su
|
|||||||
var resp *backend.SubscribeStreamResponse
|
var resp *backend.SubscribeStreamResponse
|
||||||
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.SubscribeStream(ctx, req)
|
resp, innerErr = m.BaseHandler.SubscribeStream(ctx, req)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
return resp, err
|
return resp, err
|
||||||
@ -206,7 +204,7 @@ func (m *MetricsMiddleware) PublishStream(ctx context.Context, req *backend.Publ
|
|||||||
var resp *backend.PublishStreamResponse
|
var resp *backend.PublishStreamResponse
|
||||||
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.PublishStream(ctx, req)
|
resp, innerErr = m.BaseHandler.PublishStream(ctx, req)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
return resp, err
|
return resp, err
|
||||||
@ -214,7 +212,7 @@ func (m *MetricsMiddleware) PublishStream(ctx context.Context, req *backend.Publ
|
|||||||
|
|
||||||
func (m *MetricsMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
|
func (m *MetricsMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
|
||||||
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
innerErr := m.next.RunStream(ctx, req, sender)
|
innerErr := m.BaseHandler.RunStream(ctx, req, sender)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
@ -224,7 +222,7 @@ func (m *MetricsMiddleware) ValidateAdmission(ctx context.Context, req *backend.
|
|||||||
var resp *backend.ValidationResponse
|
var resp *backend.ValidationResponse
|
||||||
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.ValidateAdmission(ctx, req)
|
resp, innerErr = m.BaseHandler.ValidateAdmission(ctx, req)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -235,7 +233,7 @@ func (m *MetricsMiddleware) MutateAdmission(ctx context.Context, req *backend.Ad
|
|||||||
var resp *backend.MutationResponse
|
var resp *backend.MutationResponse
|
||||||
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.MutateAdmission(ctx, req)
|
resp, innerErr = m.BaseHandler.MutateAdmission(ctx, req)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -246,7 +244,7 @@ func (m *MetricsMiddleware) ConvertObjects(ctx context.Context, req *backend.Con
|
|||||||
var resp *backend.ConversionResponse
|
var resp *backend.ConversionResponse
|
||||||
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
|
||||||
var innerErr error
|
var innerErr error
|
||||||
resp, innerErr = m.next.ConvertObjects(ctx, req)
|
resp, innerErr = m.BaseHandler.ConvertObjects(ctx, req)
|
||||||
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/testutil"
|
"github.com/prometheus/client_golang/prometheus/testutil"
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
@ -15,7 +16,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/plugins"
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||||
"github.com/grafana/grafana/pkg/plugins/instrumentationutils"
|
"github.com/grafana/grafana/pkg/plugins/instrumentationutils"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
||||||
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
|
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
|
||||||
)
|
)
|
||||||
@ -34,36 +34,36 @@ func TestInstrumentationMiddleware(t *testing.T) {
|
|||||||
t.Run("should instrument requests", func(t *testing.T) {
|
t.Run("should instrument requests", func(t *testing.T) {
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
expEndpoint backend.Endpoint
|
expEndpoint backend.Endpoint
|
||||||
fn func(cdt *clienttest.ClientDecoratorTest) error
|
fn func(cdt *handlertest.HandlerMiddlewareTest) error
|
||||||
shouldInstrumentRequestSize bool
|
shouldInstrumentRequestSize bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
expEndpoint: backend.EndpointCheckHealth,
|
expEndpoint: backend.EndpointCheckHealth,
|
||||||
fn: func(cdt *clienttest.ClientDecoratorTest) error {
|
fn: func(cdt *handlertest.HandlerMiddlewareTest) error {
|
||||||
_, err := cdt.Decorator.CheckHealth(context.Background(), &backend.CheckHealthRequest{PluginContext: pCtx})
|
_, err := cdt.MiddlewareHandler.CheckHealth(context.Background(), &backend.CheckHealthRequest{PluginContext: pCtx})
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
shouldInstrumentRequestSize: false,
|
shouldInstrumentRequestSize: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expEndpoint: backend.EndpointCallResource,
|
expEndpoint: backend.EndpointCallResource,
|
||||||
fn: func(cdt *clienttest.ClientDecoratorTest) error {
|
fn: func(cdt *handlertest.HandlerMiddlewareTest) error {
|
||||||
return cdt.Decorator.CallResource(context.Background(), &backend.CallResourceRequest{PluginContext: pCtx}, nopCallResourceSender)
|
return cdt.MiddlewareHandler.CallResource(context.Background(), &backend.CallResourceRequest{PluginContext: pCtx}, nopCallResourceSender)
|
||||||
},
|
},
|
||||||
shouldInstrumentRequestSize: true,
|
shouldInstrumentRequestSize: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expEndpoint: backend.EndpointQueryData,
|
expEndpoint: backend.EndpointQueryData,
|
||||||
fn: func(cdt *clienttest.ClientDecoratorTest) error {
|
fn: func(cdt *handlertest.HandlerMiddlewareTest) error {
|
||||||
_, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx})
|
_, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx})
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
shouldInstrumentRequestSize: true,
|
shouldInstrumentRequestSize: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expEndpoint: backend.EndpointCollectMetrics,
|
expEndpoint: backend.EndpointCollectMetrics,
|
||||||
fn: func(cdt *clienttest.ClientDecoratorTest) error {
|
fn: func(cdt *handlertest.HandlerMiddlewareTest) error {
|
||||||
_, err := cdt.Decorator.CollectMetrics(context.Background(), &backend.CollectMetricsRequest{PluginContext: pCtx})
|
_, err := cdt.MiddlewareHandler.CollectMetrics(context.Background(), &backend.CollectMetricsRequest{PluginContext: pCtx})
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
shouldInstrumentRequestSize: false,
|
shouldInstrumentRequestSize: false,
|
||||||
@ -77,9 +77,9 @@ func TestInstrumentationMiddleware(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
mw := newMetricsMiddleware(promRegistry, pluginsRegistry)
|
mw := newMetricsMiddleware(promRegistry, pluginsRegistry)
|
||||||
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(
|
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(
|
||||||
plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
mw.next = next
|
mw.BaseHandler = backend.NewBaseHandler(next)
|
||||||
return mw
|
return mw
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
@ -154,10 +154,10 @@ func TestInstrumentationMiddlewareStatusSource(t *testing.T) {
|
|||||||
JSONData: plugins.JSONData{ID: pluginID, Backend: true},
|
JSONData: plugins.JSONData{ID: pluginID, Backend: true},
|
||||||
}))
|
}))
|
||||||
metricsMw := newMetricsMiddleware(promRegistry, pluginsRegistry)
|
metricsMw := newMetricsMiddleware(promRegistry, pluginsRegistry)
|
||||||
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(
|
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(
|
||||||
NewPluginRequestMetaMiddleware(),
|
NewPluginRequestMetaMiddleware(),
|
||||||
plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
metricsMw.next = next
|
metricsMw.BaseHandler = backend.NewBaseHandler(next)
|
||||||
return metricsMw
|
return metricsMw
|
||||||
}),
|
}),
|
||||||
NewStatusSourceMiddleware(),
|
NewStatusSourceMiddleware(),
|
||||||
@ -166,10 +166,10 @@ func TestInstrumentationMiddlewareStatusSource(t *testing.T) {
|
|||||||
t.Run("Metrics", func(t *testing.T) {
|
t.Run("Metrics", func(t *testing.T) {
|
||||||
metricsMw.pluginMetrics.pluginRequestCounter.Reset()
|
metricsMw.pluginMetrics.pluginRequestCounter.Reset()
|
||||||
|
|
||||||
cdt.TestClient.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
cdt.TestHandler.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
return &backend.QueryDataResponse{Responses: map[string]backend.DataResponse{"A": downstreamErrorResponse}}, nil
|
return &backend.QueryDataResponse{Responses: map[string]backend.DataResponse{"A": downstreamErrorResponse}}, nil
|
||||||
}
|
}
|
||||||
_, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx})
|
_, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
counter, err := metricsMw.pluginMetrics.pluginRequestCounter.GetMetricWith(newLabels(
|
counter, err := metricsMw.pluginMetrics.pluginRequestCounter.GetMetricWith(newLabels(
|
||||||
queryDataErrorCounterLabels,
|
queryDataErrorCounterLabels,
|
||||||
@ -235,12 +235,12 @@ func TestInstrumentationMiddlewareStatusSource(t *testing.T) {
|
|||||||
cdt.QueryDataCtx = nil
|
cdt.QueryDataCtx = nil
|
||||||
cdt.QueryDataReq = nil
|
cdt.QueryDataReq = nil
|
||||||
})
|
})
|
||||||
cdt.TestClient.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
cdt.TestHandler.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
cdt.QueryDataCtx = ctx
|
cdt.QueryDataCtx = ctx
|
||||||
cdt.QueryDataReq = req
|
cdt.QueryDataReq = req
|
||||||
return &backend.QueryDataResponse{Responses: tc.responses}, nil
|
return &backend.QueryDataResponse{Responses: tc.responses}, nil
|
||||||
}
|
}
|
||||||
_, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx})
|
_, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
ctxStatusSource := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx)
|
ctxStatusSource := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx)
|
||||||
require.Equal(t, tc.expStatusSource, ctxStatusSource)
|
require.Equal(t, tc.expStatusSource, ctxStatusSource)
|
||||||
|
@ -7,28 +7,25 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||||
"github.com/grafana/grafana/pkg/services/datasources"
|
"github.com/grafana/grafana/pkg/services/datasources"
|
||||||
"github.com/grafana/grafana/pkg/services/oauthtoken"
|
"github.com/grafana/grafana/pkg/services/oauthtoken"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewOAuthTokenMiddleware creates a new plugins.ClientMiddleware that will
|
// NewOAuthTokenMiddleware creates a new backend.HandlerMiddleware that will
|
||||||
// set OAuth token headers on outgoing plugins.Client requests if the
|
// set OAuth token headers on outgoing backend.Handler requests if the
|
||||||
// datasource has enabled Forward OAuth Identity (oauthPassThru).
|
// datasource has enabled Forward OAuth Identity (oauthPassThru).
|
||||||
func NewOAuthTokenMiddleware(oAuthTokenService oauthtoken.OAuthTokenService) plugins.ClientMiddleware {
|
func NewOAuthTokenMiddleware(oAuthTokenService oauthtoken.OAuthTokenService) backend.HandlerMiddleware {
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &OAuthTokenMiddleware{
|
return &OAuthTokenMiddleware{
|
||||||
baseMiddleware: baseMiddleware{
|
BaseHandler: backend.NewBaseHandler(next),
|
||||||
next: next,
|
|
||||||
},
|
|
||||||
oAuthTokenService: oAuthTokenService,
|
oAuthTokenService: oAuthTokenService,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type OAuthTokenMiddleware struct {
|
type OAuthTokenMiddleware struct {
|
||||||
baseMiddleware
|
backend.BaseHandler
|
||||||
oAuthTokenService oauthtoken.OAuthTokenService
|
oAuthTokenService oauthtoken.OAuthTokenService
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +84,7 @@ func (m *OAuthTokenMiddleware) applyToken(ctx context.Context, pCtx backend.Plug
|
|||||||
|
|
||||||
func (m *OAuthTokenMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (m *OAuthTokenMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.applyToken(ctx, req.PluginContext, req)
|
err := m.applyToken(ctx, req.PluginContext, req)
|
||||||
@ -95,12 +92,12 @@ func (m *OAuthTokenMiddleware) QueryData(ctx context.Context, req *backend.Query
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *OAuthTokenMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
func (m *OAuthTokenMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.applyToken(ctx, req.PluginContext, req)
|
err := m.applyToken(ctx, req.PluginContext, req)
|
||||||
@ -108,12 +105,12 @@ func (m *OAuthTokenMiddleware) CallResource(ctx context.Context, req *backend.Ca
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *OAuthTokenMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
func (m *OAuthTokenMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.applyToken(ctx, req.PluginContext, req)
|
err := m.applyToken(ctx, req.PluginContext, req)
|
||||||
@ -121,5 +118,5 @@ func (m *OAuthTokenMiddleware) CheckHealth(ctx context.Context, req *backend.Che
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
|
||||||
"github.com/grafana/grafana/pkg/services/oauthtoken/oauthtokentest"
|
"github.com/grafana/grafana/pkg/services/oauthtoken/oauthtokentest"
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -23,9 +23,9 @@ func TestOAuthTokenMiddleware(t *testing.T) {
|
|||||||
req.Header.Set(otherHeader, "test")
|
req.Header.Set(otherHeader, "test")
|
||||||
|
|
||||||
oAuthTokenService := &oauthtokentest.Service{}
|
oAuthTokenService := &oauthtokentest.Service{}
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{}),
|
WithReqContext(req, &user.SignedInUser{}),
|
||||||
clienttest.WithMiddlewares(NewOAuthTokenMiddleware(oAuthTokenService)),
|
handlertest.WithMiddlewares(NewOAuthTokenMiddleware(oAuthTokenService)),
|
||||||
)
|
)
|
||||||
|
|
||||||
jsonDataMap := map[string]any{}
|
jsonDataMap := map[string]any{}
|
||||||
@ -39,7 +39,7 @@ func TestOAuthTokenMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should not forward OAuth Identity when calling QueryData", func(t *testing.T) {
|
t.Run("Should not forward OAuth Identity when calling QueryData", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
@ -50,7 +50,7 @@ func TestOAuthTokenMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not forward OAuth Identity when calling CallResource", func(t *testing.T) {
|
t.Run("Should not forward OAuth Identity when calling CallResource", func(t *testing.T) {
|
||||||
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string][]string{otherHeader: {"test"}},
|
Headers: map[string][]string{otherHeader: {"test"}},
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
@ -61,7 +61,7 @@ func TestOAuthTokenMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not forward OAuth Identity when calling CheckHealth", func(t *testing.T) {
|
t.Run("Should not forward OAuth Identity when calling CheckHealth", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
@ -86,9 +86,9 @@ func TestOAuthTokenMiddleware(t *testing.T) {
|
|||||||
oAuthTokenService := &oauthtokentest.Service{
|
oAuthTokenService := &oauthtokentest.Service{
|
||||||
Token: token,
|
Token: token,
|
||||||
}
|
}
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{}),
|
WithReqContext(req, &user.SignedInUser{}),
|
||||||
clienttest.WithMiddlewares(NewOAuthTokenMiddleware(oAuthTokenService)),
|
handlertest.WithMiddlewares(NewOAuthTokenMiddleware(oAuthTokenService)),
|
||||||
)
|
)
|
||||||
|
|
||||||
jsonDataMap := map[string]any{
|
jsonDataMap := map[string]any{
|
||||||
@ -104,7 +104,7 @@ func TestOAuthTokenMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should forward OAuth Identity when calling QueryData", func(t *testing.T) {
|
t.Run("Should forward OAuth Identity when calling QueryData", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
@ -117,7 +117,7 @@ func TestOAuthTokenMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should forward OAuth Identity when calling CallResource", func(t *testing.T) {
|
t.Run("Should forward OAuth Identity when calling CallResource", func(t *testing.T) {
|
||||||
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string][]string{otherHeader: {"test"}},
|
Headers: map[string][]string{otherHeader: {"test"}},
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
@ -132,7 +132,7 @@ func TestOAuthTokenMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should forward OAuth Identity when calling CheckHealth", func(t *testing.T) {
|
t.Run("Should forward OAuth Identity when calling CheckHealth", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{otherHeader: "test"},
|
Headers: map[string]string{otherHeader: "test"},
|
||||||
})
|
})
|
||||||
|
@ -5,24 +5,23 @@ import (
|
|||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
|
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewPluginRequestMetaMiddleware returns a new plugins.ClientMiddleware that sets up the default
|
// NewPluginRequestMetaMiddleware returns a new backend.HandlerMiddleware that sets up the default
|
||||||
// values for the plugin request meta in the context.Context. All middlewares that are executed
|
// values for the plugin request meta in the context.Context. All middlewares that are executed
|
||||||
// after this one are be able to access plugin request meta via the pluginrequestmeta package.
|
// after this one are be able to access plugin request meta via the pluginrequestmeta package.
|
||||||
func NewPluginRequestMetaMiddleware() plugins.ClientMiddleware {
|
func NewPluginRequestMetaMiddleware() backend.HandlerMiddleware {
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &PluginRequestMetaMiddleware{
|
return &PluginRequestMetaMiddleware{
|
||||||
next: next,
|
BaseHandler: backend.NewBaseHandler(next),
|
||||||
defaultStatusSource: pluginrequestmeta.DefaultStatusSource,
|
defaultStatusSource: pluginrequestmeta.DefaultStatusSource,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type PluginRequestMetaMiddleware struct {
|
type PluginRequestMetaMiddleware struct {
|
||||||
next plugins.Client
|
backend.BaseHandler
|
||||||
defaultStatusSource pluginrequestmeta.StatusSource
|
defaultStatusSource pluginrequestmeta.StatusSource
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,53 +34,53 @@ func (m *PluginRequestMetaMiddleware) withDefaultPluginRequestMeta(ctx context.C
|
|||||||
|
|
||||||
func (m *PluginRequestMetaMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (m *PluginRequestMetaMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
ctx = m.withDefaultPluginRequestMeta(ctx)
|
ctx = m.withDefaultPluginRequestMeta(ctx)
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PluginRequestMetaMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
func (m *PluginRequestMetaMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||||
ctx = m.withDefaultPluginRequestMeta(ctx)
|
ctx = m.withDefaultPluginRequestMeta(ctx)
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PluginRequestMetaMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
func (m *PluginRequestMetaMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||||
ctx = m.withDefaultPluginRequestMeta(ctx)
|
ctx = m.withDefaultPluginRequestMeta(ctx)
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PluginRequestMetaMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
|
func (m *PluginRequestMetaMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
|
||||||
ctx = m.withDefaultPluginRequestMeta(ctx)
|
ctx = m.withDefaultPluginRequestMeta(ctx)
|
||||||
return m.next.CollectMetrics(ctx, req)
|
return m.BaseHandler.CollectMetrics(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PluginRequestMetaMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
|
func (m *PluginRequestMetaMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
|
||||||
ctx = m.withDefaultPluginRequestMeta(ctx)
|
ctx = m.withDefaultPluginRequestMeta(ctx)
|
||||||
return m.next.SubscribeStream(ctx, req)
|
return m.BaseHandler.SubscribeStream(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PluginRequestMetaMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
|
func (m *PluginRequestMetaMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
|
||||||
ctx = m.withDefaultPluginRequestMeta(ctx)
|
ctx = m.withDefaultPluginRequestMeta(ctx)
|
||||||
return m.next.PublishStream(ctx, req)
|
return m.BaseHandler.PublishStream(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PluginRequestMetaMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
|
func (m *PluginRequestMetaMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
|
||||||
ctx = m.withDefaultPluginRequestMeta(ctx)
|
ctx = m.withDefaultPluginRequestMeta(ctx)
|
||||||
return m.next.RunStream(ctx, req, sender)
|
return m.BaseHandler.RunStream(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateAdmission implements backend.AdmissionHandler.
|
// ValidateAdmission implements backend.AdmissionHandler.
|
||||||
func (m *PluginRequestMetaMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
|
func (m *PluginRequestMetaMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
|
||||||
ctx = m.withDefaultPluginRequestMeta(ctx)
|
ctx = m.withDefaultPluginRequestMeta(ctx)
|
||||||
return m.next.ValidateAdmission(ctx, req)
|
return m.BaseHandler.ValidateAdmission(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MutateAdmission implements backend.AdmissionHandler.
|
// MutateAdmission implements backend.AdmissionHandler.
|
||||||
func (m *PluginRequestMetaMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
|
func (m *PluginRequestMetaMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
|
||||||
ctx = m.withDefaultPluginRequestMeta(ctx)
|
ctx = m.withDefaultPluginRequestMeta(ctx)
|
||||||
return m.next.MutateAdmission(ctx, req)
|
return m.BaseHandler.MutateAdmission(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertObject implements backend.AdmissionHandler.
|
// ConvertObject implements backend.AdmissionHandler.
|
||||||
func (m *PluginRequestMetaMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
|
func (m *PluginRequestMetaMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
|
||||||
ctx = m.withDefaultPluginRequestMeta(ctx)
|
ctx = m.withDefaultPluginRequestMeta(ctx)
|
||||||
return m.next.ConvertObjects(ctx, req)
|
return m.BaseHandler.ConvertObjects(ctx, req)
|
||||||
}
|
}
|
||||||
|
@ -5,34 +5,33 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
|
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPluginRequestMetaMiddleware(t *testing.T) {
|
func TestPluginRequestMetaMiddleware(t *testing.T) {
|
||||||
t.Run("default", func(t *testing.T) {
|
t.Run("default", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithMiddlewares(NewPluginRequestMetaMiddleware()),
|
handlertest.WithMiddlewares(NewPluginRequestMetaMiddleware()),
|
||||||
)
|
)
|
||||||
_, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{})
|
_, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
ss := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx)
|
ss := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx)
|
||||||
require.Equal(t, pluginrequestmeta.StatusSourcePlugin, ss)
|
require.Equal(t, pluginrequestmeta.StatusSourcePlugin, ss)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("other value", func(t *testing.T) {
|
t.Run("other value", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithMiddlewares(plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
handlertest.WithMiddlewares(backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &PluginRequestMetaMiddleware{
|
return &PluginRequestMetaMiddleware{
|
||||||
next: next,
|
BaseHandler: backend.NewBaseHandler(next),
|
||||||
defaultStatusSource: "test",
|
defaultStatusSource: "test",
|
||||||
}
|
}
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
_, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{})
|
_, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
ss := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx)
|
ss := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx)
|
||||||
require.Equal(t, pluginrequestmeta.StatusSource("test"), ss)
|
require.Equal(t, pluginrequestmeta.StatusSource("test"), ss)
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
package clientmiddleware
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/util/proxyutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewResourceResponseMiddleware creates a new plugins.ClientMiddleware
|
|
||||||
// that will enforce HTTP header rules for backend.CallResourceResponse's.
|
|
||||||
func NewResourceResponseMiddleware() plugins.ClientMiddleware {
|
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
|
||||||
return &ResourceResponseMiddleware{
|
|
||||||
baseMiddleware: baseMiddleware{
|
|
||||||
next: next,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResourceResponseMiddleware struct {
|
|
||||||
baseMiddleware
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *ResourceResponseMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
|
||||||
return m.next.QueryData(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *ResourceResponseMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
|
||||||
if req == nil || sender == nil {
|
|
||||||
return m.next.CallResource(ctx, req, sender)
|
|
||||||
}
|
|
||||||
|
|
||||||
processedStreams := 0
|
|
||||||
wrappedSender := backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error {
|
|
||||||
if processedStreams == 0 {
|
|
||||||
if res.Headers == nil {
|
|
||||||
res.Headers = map[string][]string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
proxyutil.SetProxyResponseHeaders(res.Headers)
|
|
||||||
}
|
|
||||||
|
|
||||||
processedStreams++
|
|
||||||
return sender.Send(res)
|
|
||||||
})
|
|
||||||
|
|
||||||
return m.next.CallResource(ctx, req, wrappedSender)
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
package clientmiddleware
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestResourceResponseMiddleware(t *testing.T) {
|
|
||||||
t.Run("Should set proxy response headers when calling CallResource", func(t *testing.T) {
|
|
||||||
crResp := &backend.CallResourceResponse{
|
|
||||||
Status: http.StatusOK,
|
|
||||||
Headers: map[string][]string{
|
|
||||||
"X-Custom": {"Should not be deleted"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
|
||||||
clienttest.WithMiddlewares(NewResourceResponseMiddleware()),
|
|
||||||
clienttest.WithResourceResponses([]*backend.CallResourceResponse{crResp}),
|
|
||||||
)
|
|
||||||
|
|
||||||
var sentResponse *backend.CallResourceResponse
|
|
||||||
sender := backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error {
|
|
||||||
sentResponse = res
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
err := cdt.Decorator.CallResource(context.Background(), &backend.CallResourceRequest{
|
|
||||||
PluginContext: backend.PluginContext{},
|
|
||||||
}, sender)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
require.NotNil(t, sentResponse)
|
|
||||||
require.Equal(t, "sandbox", sentResponse.Headers["Content-Security-Policy"][0])
|
|
||||||
require.Equal(t, "Should not be deleted", sentResponse.Headers["X-Custom"][0])
|
|
||||||
})
|
|
||||||
}
|
|
@ -6,30 +6,27 @@ import (
|
|||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
|
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewStatusSourceMiddleware returns a new plugins.ClientMiddleware that sets the status source in the
|
// NewStatusSourceMiddleware returns a new backend.HandlerMiddleware that sets the status source in the
|
||||||
// plugin request meta stored in the context.Context, according to the query data responses returned by QueryError.
|
// plugin request meta stored in the context.Context, according to the query data responses returned by QueryError.
|
||||||
// If at least one query data response has a "downstream" status source and there isn't one with a "plugin" status source,
|
// If at least one query data response has a "downstream" status source and there isn't one with a "plugin" status source,
|
||||||
// the plugin request meta in the context is set to "downstream".
|
// the plugin request meta in the context is set to "downstream".
|
||||||
func NewStatusSourceMiddleware() plugins.ClientMiddleware {
|
func NewStatusSourceMiddleware() backend.HandlerMiddleware {
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &StatusSourceMiddleware{
|
return &StatusSourceMiddleware{
|
||||||
baseMiddleware: baseMiddleware{
|
BaseHandler: backend.NewBaseHandler(next),
|
||||||
next: next,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type StatusSourceMiddleware struct {
|
type StatusSourceMiddleware struct {
|
||||||
baseMiddleware
|
backend.BaseHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *StatusSourceMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (m *StatusSourceMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
resp, err := m.next.QueryData(ctx, req)
|
resp, err := m.BaseHandler.QueryData(ctx, req)
|
||||||
if resp == nil || len(resp.Responses) == 0 {
|
if resp == nil || len(resp.Responses) == 0 {
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
|
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -68,18 +68,18 @@ func TestStatusSourceMiddleware(t *testing.T) {
|
|||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithMiddlewares(
|
handlertest.WithMiddlewares(
|
||||||
NewPluginRequestMetaMiddleware(),
|
NewPluginRequestMetaMiddleware(),
|
||||||
NewStatusSourceMiddleware(),
|
NewStatusSourceMiddleware(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
cdt.TestClient.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
cdt.TestHandler.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
cdt.QueryDataCtx = ctx
|
cdt.QueryDataCtx = ctx
|
||||||
return tc.queryDataResponse, nil
|
return tc.queryDataResponse, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _ = cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{})
|
_, _ = cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{})
|
||||||
|
|
||||||
ss := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx)
|
ss := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx)
|
||||||
require.Equal(t, tc.expStatusSource, ss)
|
require.Equal(t, tc.expStatusSource, ss)
|
||||||
|
@ -1,6 +1,31 @@
|
|||||||
package clientmiddleware
|
package clientmiddleware
|
||||||
|
|
||||||
import "github.com/grafana/grafana-plugin-sdk-go/backend"
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
|
||||||
|
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
||||||
|
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||||
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
|
"github.com/grafana/grafana/pkg/web"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WithReqContext(req *http.Request, user *user.SignedInUser) handlertest.HandlerMiddlewareTestOption {
|
||||||
|
return handlertest.HandlerMiddlewareTestOption(func(cdt *handlertest.HandlerMiddlewareTest) {
|
||||||
|
reqContext := &contextmodel.ReqContext{
|
||||||
|
Context: &web.Context{
|
||||||
|
Req: req,
|
||||||
|
Resp: web.NewResponseWriter(req.Method, httptest.NewRecorder()),
|
||||||
|
},
|
||||||
|
SignedInUser: user,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := ctxkey.Set(req.Context(), reqContext)
|
||||||
|
*req = *req.WithContext(ctx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
var nopCallResourceSender = backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error {
|
var nopCallResourceSender = backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error {
|
||||||
return nil
|
return nil
|
||||||
|
@ -5,28 +5,25 @@ import (
|
|||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||||
"github.com/grafana/grafana/pkg/services/query"
|
"github.com/grafana/grafana/pkg/services/query"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewTracingHeaderMiddleware creates a new plugins.ClientMiddleware that will
|
// NewTracingHeaderMiddleware creates a new backend.HandlerMiddleware that will
|
||||||
// populate useful tracing headers on outgoing plugins.Client and HTTP
|
// populate useful tracing headers on outgoing backend.Handler and HTTP
|
||||||
// requests.
|
// requests.
|
||||||
// Tracing headers are X-Datasource-Uid, X-Dashboard-Uid,
|
// Tracing headers are X-Datasource-Uid, X-Dashboard-Uid,
|
||||||
// X-Panel-Id, X-Grafana-Org-Id.
|
// X-Panel-Id, X-Grafana-Org-Id.
|
||||||
func NewTracingHeaderMiddleware() plugins.ClientMiddleware {
|
func NewTracingHeaderMiddleware() backend.HandlerMiddleware {
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &TracingHeaderMiddleware{
|
return &TracingHeaderMiddleware{
|
||||||
baseMiddleware: baseMiddleware{
|
BaseHandler: backend.NewBaseHandler(next),
|
||||||
next: next,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type TracingHeaderMiddleware struct {
|
type TracingHeaderMiddleware struct {
|
||||||
baseMiddleware
|
backend.BaseHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *TracingHeaderMiddleware) applyHeaders(ctx context.Context, req backend.ForwardHTTPHeaders) {
|
func (m *TracingHeaderMiddleware) applyHeaders(ctx context.Context, req backend.ForwardHTTPHeaders) {
|
||||||
@ -49,22 +46,22 @@ func (m *TracingHeaderMiddleware) applyHeaders(ctx context.Context, req backend.
|
|||||||
|
|
||||||
func (m *TracingHeaderMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (m *TracingHeaderMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.applyHeaders(ctx, req)
|
m.applyHeaders(ctx, req)
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *TracingHeaderMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
func (m *TracingHeaderMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *TracingHeaderMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
func (m *TracingHeaderMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.applyHeaders(ctx, req)
|
m.applyHeaders(ctx, req)
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@ -25,15 +25,15 @@ func TestTracingHeaderMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("tracing headers are not set for query data", func(t *testing.T) {
|
t.Run("tracing headers are not set for query data", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{
|
WithReqContext(req, &user.SignedInUser{
|
||||||
IsAnonymous: true,
|
IsAnonymous: true,
|
||||||
Login: "anonymous"},
|
Login: "anonymous"},
|
||||||
),
|
),
|
||||||
clienttest.WithMiddlewares(NewTracingHeaderMiddleware()),
|
handlertest.WithMiddlewares(NewTracingHeaderMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
@ -43,15 +43,15 @@ func TestTracingHeaderMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("tracing headers are not set for health check", func(t *testing.T) {
|
t.Run("tracing headers are not set for health check", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{
|
WithReqContext(req, &user.SignedInUser{
|
||||||
IsAnonymous: true,
|
IsAnonymous: true,
|
||||||
Login: "anonymous"},
|
Login: "anonymous"},
|
||||||
),
|
),
|
||||||
clienttest.WithMiddlewares(NewTracingHeaderMiddleware()),
|
handlertest.WithMiddlewares(NewTracingHeaderMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
@ -69,15 +69,15 @@ func TestTracingHeaderMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("tracing headers are not set for query data", func(t *testing.T) {
|
t.Run("tracing headers are not set for query data", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{
|
WithReqContext(req, &user.SignedInUser{
|
||||||
IsAnonymous: true,
|
IsAnonymous: true,
|
||||||
Login: "anonymous"},
|
Login: "anonymous"},
|
||||||
),
|
),
|
||||||
clienttest.WithMiddlewares(NewTracingHeaderMiddleware()),
|
handlertest.WithMiddlewares(NewTracingHeaderMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
@ -87,15 +87,15 @@ func TestTracingHeaderMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("tracing headers are not set for health check", func(t *testing.T) {
|
t.Run("tracing headers are not set for health check", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{
|
WithReqContext(req, &user.SignedInUser{
|
||||||
IsAnonymous: true,
|
IsAnonymous: true,
|
||||||
Login: "anonymous"},
|
Login: "anonymous"},
|
||||||
),
|
),
|
||||||
clienttest.WithMiddlewares(NewTracingHeaderMiddleware()),
|
handlertest.WithMiddlewares(NewTracingHeaderMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
@ -120,15 +120,15 @@ func TestTracingHeaderMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("tracing headers are set for query data", func(t *testing.T) {
|
t.Run("tracing headers are set for query data", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{
|
WithReqContext(req, &user.SignedInUser{
|
||||||
IsAnonymous: true,
|
IsAnonymous: true,
|
||||||
Login: "anonymous"},
|
Login: "anonymous"},
|
||||||
),
|
),
|
||||||
clienttest.WithMiddlewares(NewTracingHeaderMiddleware()),
|
handlertest.WithMiddlewares(NewTracingHeaderMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
@ -144,15 +144,15 @@ func TestTracingHeaderMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("tracing headers are set for health check", func(t *testing.T) {
|
t.Run("tracing headers are set for health check", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{
|
WithReqContext(req, &user.SignedInUser{
|
||||||
IsAnonymous: true,
|
IsAnonymous: true,
|
||||||
Login: "anonymous"},
|
Login: "anonymous"},
|
||||||
),
|
),
|
||||||
clienttest.WithMiddlewares(NewTracingHeaderMiddleware()),
|
handlertest.WithMiddlewares(NewTracingHeaderMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
|
@ -11,24 +11,23 @@ import (
|
|||||||
"go.opentelemetry.io/otel/trace"
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||||
"github.com/grafana/grafana/pkg/services/query"
|
"github.com/grafana/grafana/pkg/services/query"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewTracingMiddleware returns a new middleware that creates a new span on every method call.
|
// NewTracingMiddleware returns a new middleware that creates a new span on every method call.
|
||||||
func NewTracingMiddleware(tracer tracing.Tracer) plugins.ClientMiddleware {
|
func NewTracingMiddleware(tracer tracing.Tracer) backend.HandlerMiddleware {
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &TracingMiddleware{
|
return &TracingMiddleware{
|
||||||
tracer: tracer,
|
tracer: tracer,
|
||||||
next: next,
|
BaseHandler: backend.NewBaseHandler(next),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type TracingMiddleware struct {
|
type TracingMiddleware struct {
|
||||||
|
backend.BaseHandler
|
||||||
tracer tracing.Tracer
|
tracer tracing.Tracer
|
||||||
next plugins.Client
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// setSpanAttributeFromHTTPHeader takes a ReqContext and a span, and adds the specified HTTP header as a span attribute
|
// setSpanAttributeFromHTTPHeader takes a ReqContext and a span, and adds the specified HTTP header as a span attribute
|
||||||
@ -84,7 +83,7 @@ func (m *TracingMiddleware) QueryData(ctx context.Context, req *backend.QueryDat
|
|||||||
var err error
|
var err error
|
||||||
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
||||||
defer func() { end(err) }()
|
defer func() { end(err) }()
|
||||||
resp, err := m.next.QueryData(ctx, req)
|
resp, err := m.BaseHandler.QueryData(ctx, req)
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +91,7 @@ func (m *TracingMiddleware) CallResource(ctx context.Context, req *backend.CallR
|
|||||||
var err error
|
var err error
|
||||||
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
||||||
defer func() { end(err) }()
|
defer func() { end(err) }()
|
||||||
err = m.next.CallResource(ctx, req, sender)
|
err = m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +99,7 @@ func (m *TracingMiddleware) CheckHealth(ctx context.Context, req *backend.CheckH
|
|||||||
var err error
|
var err error
|
||||||
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
||||||
defer func() { end(err) }()
|
defer func() { end(err) }()
|
||||||
resp, err := m.next.CheckHealth(ctx, req)
|
resp, err := m.BaseHandler.CheckHealth(ctx, req)
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +107,7 @@ func (m *TracingMiddleware) CollectMetrics(ctx context.Context, req *backend.Col
|
|||||||
var err error
|
var err error
|
||||||
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
||||||
defer func() { end(err) }()
|
defer func() { end(err) }()
|
||||||
resp, err := m.next.CollectMetrics(ctx, req)
|
resp, err := m.BaseHandler.CollectMetrics(ctx, req)
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +115,7 @@ func (m *TracingMiddleware) SubscribeStream(ctx context.Context, req *backend.Su
|
|||||||
var err error
|
var err error
|
||||||
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
||||||
defer func() { end(err) }()
|
defer func() { end(err) }()
|
||||||
resp, err := m.next.SubscribeStream(ctx, req)
|
resp, err := m.BaseHandler.SubscribeStream(ctx, req)
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +123,7 @@ func (m *TracingMiddleware) PublishStream(ctx context.Context, req *backend.Publ
|
|||||||
var err error
|
var err error
|
||||||
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
||||||
defer func() { end(err) }()
|
defer func() { end(err) }()
|
||||||
resp, err := m.next.PublishStream(ctx, req)
|
resp, err := m.BaseHandler.PublishStream(ctx, req)
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +131,7 @@ func (m *TracingMiddleware) RunStream(ctx context.Context, req *backend.RunStrea
|
|||||||
var err error
|
var err error
|
||||||
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
||||||
defer func() { end(err) }()
|
defer func() { end(err) }()
|
||||||
err = m.next.RunStream(ctx, req, sender)
|
err = m.BaseHandler.RunStream(ctx, req, sender)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +140,7 @@ func (m *TracingMiddleware) ValidateAdmission(ctx context.Context, req *backend.
|
|||||||
var err error
|
var err error
|
||||||
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
||||||
defer func() { end(err) }()
|
defer func() { end(err) }()
|
||||||
resp, err := m.next.ValidateAdmission(ctx, req)
|
resp, err := m.BaseHandler.ValidateAdmission(ctx, req)
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +149,7 @@ func (m *TracingMiddleware) MutateAdmission(ctx context.Context, req *backend.Ad
|
|||||||
var err error
|
var err error
|
||||||
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
||||||
defer func() { end(err) }()
|
defer func() { end(err) }()
|
||||||
resp, err := m.next.MutateAdmission(ctx, req)
|
resp, err := m.BaseHandler.MutateAdmission(ctx, req)
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +158,6 @@ func (m *TracingMiddleware) ConvertObjects(ctx context.Context, req *backend.Con
|
|||||||
var err error
|
var err error
|
||||||
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
ctx, end := m.traceWrap(ctx, req.PluginContext)
|
||||||
defer func() { end(err) }()
|
defer func() { end(err) }()
|
||||||
resp, err := m.next.ConvertObjects(ctx, req)
|
resp, err := m.BaseHandler.ConvertObjects(ctx, req)
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.opentelemetry.io/otel/attribute"
|
"go.opentelemetry.io/otel/attribute"
|
||||||
@ -16,8 +17,6 @@ import (
|
|||||||
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
|
|
||||||
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
||||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||||
"github.com/grafana/grafana/pkg/web"
|
"github.com/grafana/grafana/pkg/web"
|
||||||
@ -30,13 +29,13 @@ func TestTracingMiddleware(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
name string
|
name string
|
||||||
run func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error
|
run func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error
|
||||||
expSpanName string
|
expSpanName string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "QueryData",
|
name: "QueryData",
|
||||||
run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error {
|
run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error {
|
||||||
_, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{
|
_, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
@ -45,8 +44,8 @@ func TestTracingMiddleware(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "CallResource",
|
name: "CallResource",
|
||||||
run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error {
|
run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error {
|
||||||
return cdt.Decorator.CallResource(context.Background(), &backend.CallResourceRequest{
|
return cdt.MiddlewareHandler.CallResource(context.Background(), &backend.CallResourceRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
},
|
},
|
||||||
@ -54,8 +53,8 @@ func TestTracingMiddleware(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "CheckHealth",
|
name: "CheckHealth",
|
||||||
run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error {
|
run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error {
|
||||||
_, err := cdt.Decorator.CheckHealth(context.Background(), &backend.CheckHealthRequest{
|
_, err := cdt.MiddlewareHandler.CheckHealth(context.Background(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
@ -64,8 +63,8 @@ func TestTracingMiddleware(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "CollectMetrics",
|
name: "CollectMetrics",
|
||||||
run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error {
|
run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error {
|
||||||
_, err := cdt.Decorator.CollectMetrics(context.Background(), &backend.CollectMetricsRequest{
|
_, err := cdt.MiddlewareHandler.CollectMetrics(context.Background(), &backend.CollectMetricsRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
@ -74,8 +73,8 @@ func TestTracingMiddleware(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "SubscribeStream",
|
name: "SubscribeStream",
|
||||||
run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error {
|
run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error {
|
||||||
_, err := cdt.Decorator.SubscribeStream(context.Background(), &backend.SubscribeStreamRequest{
|
_, err := cdt.MiddlewareHandler.SubscribeStream(context.Background(), &backend.SubscribeStreamRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
@ -84,8 +83,8 @@ func TestTracingMiddleware(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "PublishStream",
|
name: "PublishStream",
|
||||||
run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error {
|
run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error {
|
||||||
_, err := cdt.Decorator.PublishStream(context.Background(), &backend.PublishStreamRequest{
|
_, err := cdt.MiddlewareHandler.PublishStream(context.Background(), &backend.PublishStreamRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
@ -94,8 +93,8 @@ func TestTracingMiddleware(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "RunStream",
|
name: "RunStream",
|
||||||
run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error {
|
run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error {
|
||||||
return cdt.Decorator.RunStream(context.Background(), &backend.RunStreamRequest{
|
return cdt.MiddlewareHandler.RunStream(context.Background(), &backend.RunStreamRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
}, &backend.StreamSender{})
|
}, &backend.StreamSender{})
|
||||||
},
|
},
|
||||||
@ -107,9 +106,9 @@ func TestTracingMiddleware(t *testing.T) {
|
|||||||
spanRecorder := tracetest.NewSpanRecorder()
|
spanRecorder := tracetest.NewSpanRecorder()
|
||||||
tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder))
|
tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder))
|
||||||
|
|
||||||
cdt := clienttest.NewClientDecoratorTest(
|
cdt := handlertest.NewHandlerMiddlewareTest(
|
||||||
t,
|
t,
|
||||||
clienttest.WithMiddlewares(NewTracingMiddleware(tracer)),
|
handlertest.WithMiddlewares(NewTracingMiddleware(tracer)),
|
||||||
)
|
)
|
||||||
|
|
||||||
err := tc.run(pluginCtx, cdt)
|
err := tc.run(pluginCtx, cdt)
|
||||||
@ -126,9 +125,9 @@ func TestTracingMiddleware(t *testing.T) {
|
|||||||
spanRecorder := tracetest.NewSpanRecorder()
|
spanRecorder := tracetest.NewSpanRecorder()
|
||||||
tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder))
|
tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder))
|
||||||
|
|
||||||
cdt := clienttest.NewClientDecoratorTest(
|
cdt := handlertest.NewHandlerMiddlewareTest(
|
||||||
t,
|
t,
|
||||||
clienttest.WithMiddlewares(
|
handlertest.WithMiddlewares(
|
||||||
NewTracingMiddleware(tracer),
|
NewTracingMiddleware(tracer),
|
||||||
newAlwaysErrorMiddleware(errors.New("ops")),
|
newAlwaysErrorMiddleware(errors.New("ops")),
|
||||||
),
|
),
|
||||||
@ -150,9 +149,9 @@ func TestTracingMiddleware(t *testing.T) {
|
|||||||
spanRecorder := tracetest.NewSpanRecorder()
|
spanRecorder := tracetest.NewSpanRecorder()
|
||||||
tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder))
|
tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder))
|
||||||
|
|
||||||
cdt := clienttest.NewClientDecoratorTest(
|
cdt := handlertest.NewHandlerMiddlewareTest(
|
||||||
t,
|
t,
|
||||||
clienttest.WithMiddlewares(
|
handlertest.WithMiddlewares(
|
||||||
NewTracingMiddleware(tracer),
|
NewTracingMiddleware(tracer),
|
||||||
newAlwaysPanicMiddleware("panic!"),
|
newAlwaysPanicMiddleware("panic!"),
|
||||||
),
|
),
|
||||||
@ -314,12 +313,12 @@ func TestTracingMiddlewareAttributes(t *testing.T) {
|
|||||||
spanRecorder := tracetest.NewSpanRecorder()
|
spanRecorder := tracetest.NewSpanRecorder()
|
||||||
tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder))
|
tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder))
|
||||||
|
|
||||||
cdt := clienttest.NewClientDecoratorTest(
|
cdt := handlertest.NewHandlerMiddlewareTest(
|
||||||
t,
|
t,
|
||||||
clienttest.WithMiddlewares(NewTracingMiddleware(tracer)),
|
handlertest.WithMiddlewares(NewTracingMiddleware(tracer)),
|
||||||
)
|
)
|
||||||
|
|
||||||
_, err := cdt.Decorator.QueryData(ctx, req)
|
_, err := cdt.MiddlewareHandler.QueryData(ctx, req)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
spans := spanRecorder.Ended()
|
spans := spanRecorder.Ended()
|
||||||
require.Len(t, spans, 1, "must have 1 span")
|
require.Len(t, spans, 1, "must have 1 span")
|
||||||
@ -403,8 +402,8 @@ func (m *alwaysErrorFuncMiddleware) ConvertObjects(ctx context.Context, req *bac
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newAlwaysErrorMiddleware returns a new middleware that always returns the specified error.
|
// newAlwaysErrorMiddleware returns a new middleware that always returns the specified error.
|
||||||
func newAlwaysErrorMiddleware(err error) plugins.ClientMiddleware {
|
func newAlwaysErrorMiddleware(err error) backend.HandlerMiddleware {
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &alwaysErrorFuncMiddleware{func() error {
|
return &alwaysErrorFuncMiddleware{func() error {
|
||||||
return err
|
return err
|
||||||
}}
|
}}
|
||||||
@ -412,8 +411,8 @@ func newAlwaysErrorMiddleware(err error) plugins.ClientMiddleware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newAlwaysPanicMiddleware returns a new middleware that always panics with the specified message,
|
// newAlwaysPanicMiddleware returns a new middleware that always panics with the specified message,
|
||||||
func newAlwaysPanicMiddleware(message string) plugins.ClientMiddleware {
|
func newAlwaysPanicMiddleware(message string) backend.HandlerMiddleware {
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &alwaysErrorFuncMiddleware{func() error {
|
return &alwaysErrorFuncMiddleware{func() error {
|
||||||
panic(message)
|
panic(message)
|
||||||
}}
|
}}
|
||||||
|
@ -6,25 +6,22 @@ import (
|
|||||||
"github.com/grafana/authlib/claims"
|
"github.com/grafana/authlib/claims"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||||
"github.com/grafana/grafana/pkg/util/proxyutil"
|
"github.com/grafana/grafana/pkg/util/proxyutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewUserHeaderMiddleware creates a new plugins.ClientMiddleware that will
|
// NewUserHeaderMiddleware creates a new backend.HandlerMiddleware that will
|
||||||
// populate the X-Grafana-User header on outgoing plugins.Client requests.
|
// populate the X-Grafana-User header on outgoing backend.Handler requests.
|
||||||
func NewUserHeaderMiddleware() plugins.ClientMiddleware {
|
func NewUserHeaderMiddleware() backend.HandlerMiddleware {
|
||||||
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
|
||||||
return &UserHeaderMiddleware{
|
return &UserHeaderMiddleware{
|
||||||
baseMiddleware: baseMiddleware{
|
BaseHandler: backend.NewBaseHandler(next),
|
||||||
next: next,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserHeaderMiddleware struct {
|
type UserHeaderMiddleware struct {
|
||||||
baseMiddleware
|
backend.BaseHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UserHeaderMiddleware) applyUserHeader(ctx context.Context, h backend.ForwardHTTPHeaders) {
|
func (m *UserHeaderMiddleware) applyUserHeader(ctx context.Context, h backend.ForwardHTTPHeaders) {
|
||||||
@ -42,30 +39,30 @@ func (m *UserHeaderMiddleware) applyUserHeader(ctx context.Context, h backend.Fo
|
|||||||
|
|
||||||
func (m *UserHeaderMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (m *UserHeaderMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.applyUserHeader(ctx, req)
|
m.applyUserHeader(ctx, req)
|
||||||
|
|
||||||
return m.next.QueryData(ctx, req)
|
return m.BaseHandler.QueryData(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UserHeaderMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
func (m *UserHeaderMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.applyUserHeader(ctx, req)
|
m.applyUserHeader(ctx, req)
|
||||||
|
|
||||||
return m.next.CallResource(ctx, req, sender)
|
return m.BaseHandler.CallResource(ctx, req, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UserHeaderMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
func (m *UserHeaderMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.applyUserHeader(ctx, req)
|
m.applyUserHeader(ctx, req)
|
||||||
|
|
||||||
return m.next.CheckHealth(ctx, req)
|
return m.BaseHandler.CheckHealth(ctx, req)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
"github.com/grafana/grafana/pkg/util/proxyutil"
|
"github.com/grafana/grafana/pkg/util/proxyutil"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -17,12 +17,12 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Run("And requests are for a datasource", func(t *testing.T) {
|
t.Run("And requests are for a datasource", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{
|
WithReqContext(req, &user.SignedInUser{
|
||||||
IsAnonymous: true,
|
IsAnonymous: true,
|
||||||
Login: "anonymous"},
|
Login: "anonymous"},
|
||||||
),
|
),
|
||||||
clienttest.WithMiddlewares(NewUserHeaderMiddleware()),
|
handlertest.WithMiddlewares(NewUserHeaderMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
pluginCtx := backend.PluginContext{
|
pluginCtx := backend.PluginContext{
|
||||||
@ -30,7 +30,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should not forward user header when calling QueryData", func(t *testing.T) {
|
t.Run("Should not forward user header when calling QueryData", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
@ -40,7 +40,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not forward user header when calling CallResource", func(t *testing.T) {
|
t.Run("Should not forward user header when calling CallResource", func(t *testing.T) {
|
||||||
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string][]string{},
|
Headers: map[string][]string{},
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
@ -50,7 +50,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not forward user header when calling CheckHealth", func(t *testing.T) {
|
t.Run("Should not forward user header when calling CheckHealth", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
@ -61,12 +61,12 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("And requests are for an app", func(t *testing.T) {
|
t.Run("And requests are for an app", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{
|
WithReqContext(req, &user.SignedInUser{
|
||||||
IsAnonymous: true,
|
IsAnonymous: true,
|
||||||
Login: "anonymous"},
|
Login: "anonymous"},
|
||||||
),
|
),
|
||||||
clienttest.WithMiddlewares(NewUserHeaderMiddleware()),
|
handlertest.WithMiddlewares(NewUserHeaderMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
pluginCtx := backend.PluginContext{
|
pluginCtx := backend.PluginContext{
|
||||||
@ -74,7 +74,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should not forward user header when calling QueryData", func(t *testing.T) {
|
t.Run("Should not forward user header when calling QueryData", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
@ -84,7 +84,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not forward user header when calling CallResource", func(t *testing.T) {
|
t.Run("Should not forward user header when calling CallResource", func(t *testing.T) {
|
||||||
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string][]string{},
|
Headers: map[string][]string{},
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
@ -94,7 +94,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should not forward user header when calling CheckHealth", func(t *testing.T) {
|
t.Run("Should not forward user header when calling CheckHealth", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
@ -110,11 +110,11 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Run("And requests are for a datasource", func(t *testing.T) {
|
t.Run("And requests are for a datasource", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{
|
WithReqContext(req, &user.SignedInUser{
|
||||||
Login: "admin",
|
Login: "admin",
|
||||||
}),
|
}),
|
||||||
clienttest.WithMiddlewares(NewUserHeaderMiddleware()),
|
handlertest.WithMiddlewares(NewUserHeaderMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
pluginCtx := backend.PluginContext{
|
pluginCtx := backend.PluginContext{
|
||||||
@ -122,7 +122,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should forward user header when calling QueryData", func(t *testing.T) {
|
t.Run("Should forward user header when calling QueryData", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
@ -133,7 +133,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should forward user header when calling CallResource", func(t *testing.T) {
|
t.Run("Should forward user header when calling CallResource", func(t *testing.T) {
|
||||||
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string][]string{},
|
Headers: map[string][]string{},
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
@ -144,7 +144,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should forward user header when calling CheckHealth", func(t *testing.T) {
|
t.Run("Should forward user header when calling CheckHealth", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
@ -156,11 +156,11 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("And requests are for an app", func(t *testing.T) {
|
t.Run("And requests are for an app", func(t *testing.T) {
|
||||||
cdt := clienttest.NewClientDecoratorTest(t,
|
cdt := handlertest.NewHandlerMiddlewareTest(t,
|
||||||
clienttest.WithReqContext(req, &user.SignedInUser{
|
WithReqContext(req, &user.SignedInUser{
|
||||||
Login: "admin",
|
Login: "admin",
|
||||||
}),
|
}),
|
||||||
clienttest.WithMiddlewares(NewUserHeaderMiddleware()),
|
handlertest.WithMiddlewares(NewUserHeaderMiddleware()),
|
||||||
)
|
)
|
||||||
|
|
||||||
pluginCtx := backend.PluginContext{
|
pluginCtx := backend.PluginContext{
|
||||||
@ -168,7 +168,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should forward user header when calling QueryData", func(t *testing.T) {
|
t.Run("Should forward user header when calling QueryData", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
|
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
@ -179,7 +179,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should forward user header when calling CallResource", func(t *testing.T) {
|
t.Run("Should forward user header when calling CallResource", func(t *testing.T) {
|
||||||
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
|
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string][]string{},
|
Headers: map[string][]string{},
|
||||||
}, nopCallResourceSender)
|
}, nopCallResourceSender)
|
||||||
@ -190,7 +190,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should forward user header when calling CheckHealth", func(t *testing.T) {
|
t.Run("Should forward user header when calling CheckHealth", func(t *testing.T) {
|
||||||
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
|
||||||
PluginContext: pluginCtx,
|
PluginContext: pluginCtx,
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
})
|
})
|
||||||
|
@ -3,6 +3,7 @@ package pluginsintegration
|
|||||||
import (
|
import (
|
||||||
"github.com/google/wire"
|
"github.com/google/wire"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||||
@ -139,13 +140,13 @@ var WireExtensionSet = wire.NewSet(
|
|||||||
wire.Bind(new(plugins.PluginLoaderAuthorizer), new(*signature.UnsignedPluginAuthorizer)),
|
wire.Bind(new(plugins.PluginLoaderAuthorizer), new(*signature.UnsignedPluginAuthorizer)),
|
||||||
finder.ProvideLocalFinder,
|
finder.ProvideLocalFinder,
|
||||||
wire.Bind(new(finder.Finder), new(*finder.Local)),
|
wire.Bind(new(finder.Finder), new(*finder.Local)),
|
||||||
ProvideClientDecorator,
|
ProvideClientWithMiddlewares,
|
||||||
wire.Bind(new(plugins.Client), new(*client.Decorator)),
|
wire.Bind(new(plugins.Client), new(*backend.MiddlewareHandler)),
|
||||||
managedplugins.NewNoop,
|
managedplugins.NewNoop,
|
||||||
wire.Bind(new(managedplugins.Manager), new(*managedplugins.Noop)),
|
wire.Bind(new(managedplugins.Manager), new(*managedplugins.Noop)),
|
||||||
)
|
)
|
||||||
|
|
||||||
func ProvideClientDecorator(
|
func ProvideClientWithMiddlewares(
|
||||||
cfg *setting.Cfg,
|
cfg *setting.Cfg,
|
||||||
pluginRegistry registry.Service,
|
pluginRegistry registry.Service,
|
||||||
oAuthTokenService oauthtoken.OAuthTokenService,
|
oAuthTokenService oauthtoken.OAuthTokenService,
|
||||||
@ -153,23 +154,23 @@ func ProvideClientDecorator(
|
|||||||
cachingService caching.CachingService,
|
cachingService caching.CachingService,
|
||||||
features featuremgmt.FeatureToggles,
|
features featuremgmt.FeatureToggles,
|
||||||
promRegisterer prometheus.Registerer,
|
promRegisterer prometheus.Registerer,
|
||||||
) (*client.Decorator, error) {
|
) (*backend.MiddlewareHandler, error) {
|
||||||
return NewClientDecorator(cfg, pluginRegistry, oAuthTokenService, tracer, cachingService, features, promRegisterer, pluginRegistry)
|
return NewMiddlewareHandler(cfg, pluginRegistry, oAuthTokenService, tracer, cachingService, features, promRegisterer, pluginRegistry)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientDecorator(
|
func NewMiddlewareHandler(
|
||||||
cfg *setting.Cfg,
|
cfg *setting.Cfg,
|
||||||
pluginRegistry registry.Service, oAuthTokenService oauthtoken.OAuthTokenService,
|
pluginRegistry registry.Service, oAuthTokenService oauthtoken.OAuthTokenService,
|
||||||
tracer tracing.Tracer, cachingService caching.CachingService, features featuremgmt.FeatureToggles,
|
tracer tracing.Tracer, cachingService caching.CachingService, features featuremgmt.FeatureToggles,
|
||||||
promRegisterer prometheus.Registerer, registry registry.Service,
|
promRegisterer prometheus.Registerer, registry registry.Service,
|
||||||
) (*client.Decorator, error) {
|
) (*backend.MiddlewareHandler, error) {
|
||||||
c := client.ProvideService(pluginRegistry)
|
c := client.ProvideService(pluginRegistry)
|
||||||
middlewares := CreateMiddlewares(cfg, oAuthTokenService, tracer, cachingService, features, promRegisterer, registry)
|
middlewares := CreateMiddlewares(cfg, oAuthTokenService, tracer, cachingService, features, promRegisterer, registry)
|
||||||
return client.NewDecorator(c, middlewares...)
|
return backend.HandlerFromMiddlewares(c, middlewares...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateMiddlewares(cfg *setting.Cfg, oAuthTokenService oauthtoken.OAuthTokenService, tracer tracing.Tracer, cachingService caching.CachingService, features featuremgmt.FeatureToggles, promRegisterer prometheus.Registerer, registry registry.Service) []plugins.ClientMiddleware {
|
func CreateMiddlewares(cfg *setting.Cfg, oAuthTokenService oauthtoken.OAuthTokenService, tracer tracing.Tracer, cachingService caching.CachingService, features featuremgmt.FeatureToggles, promRegisterer prometheus.Registerer, registry registry.Service) []backend.HandlerMiddleware {
|
||||||
middlewares := []plugins.ClientMiddleware{
|
middlewares := []backend.HandlerMiddleware{
|
||||||
clientmiddleware.NewPluginRequestMetaMiddleware(),
|
clientmiddleware.NewPluginRequestMetaMiddleware(),
|
||||||
clientmiddleware.NewTracingMiddleware(tracer),
|
clientmiddleware.NewTracingMiddleware(tracer),
|
||||||
clientmiddleware.NewMetricsMiddleware(promRegisterer, registry),
|
clientmiddleware.NewMetricsMiddleware(promRegisterer, registry),
|
||||||
@ -187,7 +188,6 @@ func CreateMiddlewares(cfg *setting.Cfg, oAuthTokenService oauthtoken.OAuthToken
|
|||||||
clientmiddleware.NewClearAuthHeadersMiddleware(),
|
clientmiddleware.NewClearAuthHeadersMiddleware(),
|
||||||
clientmiddleware.NewOAuthTokenMiddleware(oAuthTokenService),
|
clientmiddleware.NewOAuthTokenMiddleware(oAuthTokenService),
|
||||||
clientmiddleware.NewCookiesMiddleware(skipCookiesNames),
|
clientmiddleware.NewCookiesMiddleware(skipCookiesNames),
|
||||||
clientmiddleware.NewResourceResponseMiddleware(),
|
|
||||||
clientmiddleware.NewCachingMiddlewareWithFeatureManager(cachingService, features),
|
clientmiddleware.NewCachingMiddlewareWithFeatureManager(cachingService, features),
|
||||||
clientmiddleware.NewForwardIDMiddleware(),
|
clientmiddleware.NewForwardIDMiddleware(),
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user