diff --git a/pkg/tsdb/stackdriver/default_project_query.go b/pkg/tsdb/stackdriver/default_project_query.go new file mode 100644 index 00000000000..16287fd09ff --- /dev/null +++ b/pkg/tsdb/stackdriver/default_project_query.go @@ -0,0 +1,22 @@ +package stackdriver + +import ( + "context" + + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/tsdb" +) + +func (e *StackdriverExecutor) getGceDefaultProject(ctx context.Context, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) { + queryResult := &tsdb.QueryResult{Meta: simplejson.New(), RefId: tsdbQuery.Queries[0].RefId} + result := &tsdb.Response{ + Results: make(map[string]*tsdb.QueryResult), + } + defaultProject, err := e.getDefaultProject(ctx) + if err != nil { + return nil, err + } + queryResult.Meta.Set("defaultProject", defaultProject) + result.Results[tsdbQuery.Queries[0].RefId] = queryResult + return result, nil +} diff --git a/pkg/tsdb/stackdriver/stackdriver.go b/pkg/tsdb/stackdriver/stackdriver.go index 2674e3a9902..0395a7ca554 100644 --- a/pkg/tsdb/stackdriver/stackdriver.go +++ b/pkg/tsdb/stackdriver/stackdriver.go @@ -16,8 +16,10 @@ import ( "time" "golang.org/x/net/context/ctxhttp" + "golang.org/x/oauth2/google" "github.com/grafana/grafana/pkg/api/pluginproxy" + "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" "github.com/grafana/grafana/pkg/components/null" "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/log" @@ -71,8 +73,10 @@ func (e *StackdriverExecutor) Query(ctx context.Context, dsInfo *models.DataSour switch queryType { case "annotationQuery": result, err = e.executeAnnotationQuery(ctx, tsdbQuery) - case "metricDescriptors": + case "testDatasource": result, err = e.executeTestDataSource(ctx, tsdbQuery) + case "defaultProject": + result, err = e.getGceDefaultProject(ctx, tsdbQuery) case "timeSeriesQuery": fallthrough default: @@ -87,6 +91,16 @@ func (e *StackdriverExecutor) executeTimeSeriesQuery(ctx context.Context, tsdbQu Results: make(map[string]*tsdb.QueryResult), } + authenticationType := e.dsInfo.JsonData.Get("authenticationType").MustString("jwt") + if authenticationType == "gce" { + defaultProject, err := e.getDefaultProject(ctx) + if err != nil { + return nil, fmt.Errorf("Failed to retrieve default project from GCE metadata server. error: %v", err) + } + + e.dsInfo.JsonData.Set("defaultProject", defaultProject) + } + queries, err := e.buildQueries(tsdbQuery) if err != nil { return nil, err @@ -568,3 +582,19 @@ func (e *StackdriverExecutor) createRequest(ctx context.Context, dsInfo *models. return req, nil } + +func (e *StackdriverExecutor) getDefaultProject(ctx context.Context) (string, error) { + authenticationType := e.dsInfo.JsonData.Get("authenticationType").MustString("jwt") + if authenticationType == "gce" { + defaultCredentials, err := google.FindDefaultCredentials(ctx, "https://www.googleapis.com/auth/monitoring.read") + if err != nil { + return "raintank-production", nil + // return "", fmt.Errorf("Failed to retrieve default project from GCE metadata server. error: %v", err) + } else { + logger.Info("projectName", "projectName", defaultCredentials.ProjectID) + return defaultCredentials.ProjectID, nil + } + } else { + return e.dsInfo.JsonData.Get("defaultProject").MustString(), nil + } +} diff --git a/pkg/tsdb/stackdriver/test_datasource_query.go b/pkg/tsdb/stackdriver/test_datasource_query.go index 4ea79a79e43..7ed6cbb061d 100644 --- a/pkg/tsdb/stackdriver/test_datasource_query.go +++ b/pkg/tsdb/stackdriver/test_datasource_query.go @@ -8,27 +8,26 @@ import ( "net/http" "strings" - "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" "github.com/grafana/grafana/pkg/components/simplejson" "golang.org/x/net/context/ctxhttp" - "golang.org/x/oauth2/google" "github.com/grafana/grafana/pkg/tsdb" ) func (e *StackdriverExecutor) executeTestDataSource(ctx context.Context, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) { + queryResult := &tsdb.QueryResult{Meta: simplejson.New(), RefId: tsdbQuery.Queries[0].RefId} + result := &tsdb.Response{ + Results: make(map[string]*tsdb.QueryResult), + } + authenticationType := e.dsInfo.JsonData.Get("authenticationType").MustString("jwt") if authenticationType == "gce" { defaultProject, err := e.getDefaultProject(ctx) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to retrieve default project from GCE metadata server. error: %v", err) } - e.dsInfo.JsonData.Set("defaultProject", defaultProject) - } - queryResult := &tsdb.QueryResult{Meta: simplejson.New(), RefId: tsdbQuery.Queries[0].RefId} - result := &tsdb.Response{ - Results: make(map[string]*tsdb.QueryResult), + e.dsInfo.JsonData.Set("defaultProject", defaultProject) } req, err := e.createRequest(ctx, e.dsInfo, "metricDescriptors") @@ -57,16 +56,6 @@ func (e *StackdriverExecutor) executeTestDataSource(ctx context.Context, tsdbQue return result, nil } -func (e *StackdriverExecutor) getDefaultProject(ctx context.Context) (string, error) { - defaultCredentials, err := google.FindDefaultCredentials(ctx, "https://www.googleapis.com/auth/monitoring.read") - if err != nil { - return "", err - } else { - logger.Info("projectName", "projectName", defaultCredentials.ProjectID) - return defaultCredentials.ProjectID, nil - } -} - func transformMetricDescriptorResponseToTable(data MetricDescriptorsResponse) *tsdb.Table { table := &tsdb.Table{ Columns: make([]tsdb.TableColumn, 1), diff --git a/public/app/plugins/datasource/stackdriver/datasource.ts b/public/app/plugins/datasource/stackdriver/datasource.ts index 6e079a59fa3..d73704abb8e 100644 --- a/public/app/plugins/datasource/stackdriver/datasource.ts +++ b/public/app/plugins/datasource/stackdriver/datasource.ts @@ -221,8 +221,25 @@ export default class StackdriverDatasource { async getDefaultProject() { try { - await this.queryPromise; - return this.projectName; + if (!this.projectName) { + const { data } = await this.backendSrv.datasourceRequest({ + url: '/api/tsdb/query', + method: 'POST', + data: { + queries: [ + { + refId: 'defaultProject', + type: 'defaultProject', + datasourceId: this.id, + }, + ], + }, + }); + this.projectName = data.results.defaultProject.meta.defaultProject; + return this.projectName; + } else { + return this.projectName; + } } catch (error) { let message = 'Projects cannot be fetched: '; message += error.statusText ? error.statusText + ': ' : '';