mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
AzureMonitor: Add data links to deep link to Azure Portal Azure Resource Graph (#35591)
* Add deep link in ARG * add soverigh clouds * add query to Azure portal link * move deep link to backend * cloud specific to ARG * Add unit test * fix lint * fix escape issue * use constant & fix test * fix constant & use pathEscape * use cmp.Equal for test
This commit is contained in:
@@ -179,15 +179,38 @@ func (e *AzureResourceGraphDatasource) executeQuery(ctx context.Context, query *
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return dataResponseErrorWithExecuted(err)
|
return dataResponseErrorWithExecuted(err)
|
||||||
}
|
}
|
||||||
if frame.Meta == nil {
|
|
||||||
frame.Meta = &data.FrameMeta{}
|
|
||||||
}
|
|
||||||
frame.Meta.ExecutedQueryString = req.URL.RawQuery
|
|
||||||
|
|
||||||
dataResponse.Frames = data.Frames{frame}
|
azurePortalUrl, err := getAzurePortalUrl(dsInfo.Cloud)
|
||||||
|
if err != nil {
|
||||||
|
return dataResponseErrorWithExecuted(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
url := azurePortalUrl + "/#blade/HubsExtension/ArgQueryBlade/query/" + url.PathEscape(query.InterpolatedQuery)
|
||||||
|
frameWithLink := addConfigData(*frame, url)
|
||||||
|
if frameWithLink.Meta == nil {
|
||||||
|
frameWithLink.Meta = &data.FrameMeta{}
|
||||||
|
}
|
||||||
|
frameWithLink.Meta.ExecutedQueryString = req.URL.RawQuery
|
||||||
|
|
||||||
|
dataResponse.Frames = data.Frames{&frameWithLink}
|
||||||
return dataResponse
|
return dataResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addConfigData(frame data.Frame, dl string) data.Frame {
|
||||||
|
for i := range frame.Fields {
|
||||||
|
if frame.Fields[i].Config == nil {
|
||||||
|
frame.Fields[i].Config = &data.FieldConfig{}
|
||||||
|
}
|
||||||
|
deepLink := data.DataLink{
|
||||||
|
Title: "View in Azure Portal",
|
||||||
|
TargetBlank: true,
|
||||||
|
URL: dl,
|
||||||
|
}
|
||||||
|
frame.Fields[i].Config.Links = append(frame.Fields[i].Config.Links, deepLink)
|
||||||
|
}
|
||||||
|
return frame
|
||||||
|
}
|
||||||
|
|
||||||
func (e *AzureResourceGraphDatasource) createRequest(ctx context.Context, dsInfo datasourceInfo, reqBody []byte, url string) (*http.Request, error) {
|
func (e *AzureResourceGraphDatasource) createRequest(ctx context.Context, dsInfo datasourceInfo, reqBody []byte, url string) (*http.Request, error) {
|
||||||
req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(reqBody))
|
req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(reqBody))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -228,3 +251,18 @@ func (e *AzureResourceGraphDatasource) unmarshalResponse(res *http.Response) (Az
|
|||||||
|
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getAzurePortalUrl(azureCloud string) (string, error) {
|
||||||
|
switch azureCloud {
|
||||||
|
case setting.AzurePublic:
|
||||||
|
return "https://portal.azure.com", nil
|
||||||
|
case setting.AzureChina:
|
||||||
|
return "https://portal.azure.cn", nil
|
||||||
|
case setting.AzureUSGovernment:
|
||||||
|
return "https://portal.azure.us", nil
|
||||||
|
case setting.AzureGermany:
|
||||||
|
return "https://portal.microsoftazure.de", nil
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("the cloud is not supported")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,8 +10,11 @@ import (
|
|||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||||
"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/plugins"
|
||||||
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -110,3 +113,42 @@ func TestAzureResourceGraphCreateRequest(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAddConfigData(t *testing.T) {
|
||||||
|
field := data.Field{}
|
||||||
|
dataLink := data.DataLink{Title: "View in Azure Portal", TargetBlank: true, URL: "http://ds"}
|
||||||
|
frame := data.Frame{
|
||||||
|
Fields: []*data.Field{&field},
|
||||||
|
}
|
||||||
|
frameWithLink := addConfigData(frame, "http://ds")
|
||||||
|
expectedFrameWithLink := data.Frame{
|
||||||
|
Fields: []*data.Field{
|
||||||
|
{
|
||||||
|
Config: &data.FieldConfig{
|
||||||
|
Links: []data.DataLink{dataLink},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if !cmp.Equal(frameWithLink, expectedFrameWithLink, data.FrameTestCompareOptions()...) {
|
||||||
|
t.Errorf("unexpepcted frame: %v", cmp.Diff(frameWithLink, expectedFrameWithLink, data.FrameTestCompareOptions()...))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetAzurePortalUrl(t *testing.T) {
|
||||||
|
clouds := []string{setting.AzurePublic, setting.AzureChina, setting.AzureUSGovernment, setting.AzureGermany}
|
||||||
|
expectedAzurePortalUrl := map[string]interface{}{
|
||||||
|
setting.AzurePublic: "https://portal.azure.com",
|
||||||
|
setting.AzureChina: "https://portal.azure.cn",
|
||||||
|
setting.AzureUSGovernment: "https://portal.azure.us",
|
||||||
|
setting.AzureGermany: "https://portal.microsoftazure.de",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cloud := range clouds {
|
||||||
|
azurePortalUrl, err := getAzurePortalUrl(cloud)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("The cloud not supported")
|
||||||
|
}
|
||||||
|
assert.Equal(t, expectedAzurePortalUrl[cloud], azurePortalUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user