diff --git a/public/app/plugins/datasource/cloud-monitoring/__mocks__/cloudMonitoringInstanceSettings.ts b/public/app/plugins/datasource/cloud-monitoring/__mocks__/cloudMonitoringInstanceSettings.ts new file mode 100644 index 00000000000..ad219a42330 --- /dev/null +++ b/public/app/plugins/datasource/cloud-monitoring/__mocks__/cloudMonitoringInstanceSettings.ts @@ -0,0 +1,25 @@ +import { DataSourceInstanceSettings, DataSourcePluginMeta } from '@grafana/data'; +import { GoogleAuthType } from '@grafana/google-sdk'; + +import { CloudMonitoringOptions } from '../types'; + +export const createMockInstanceSetttings = ( + overrides?: Partial> +): DataSourceInstanceSettings => ({ + url: '/ds/1', + id: 1, + uid: 'abc', + type: 'stackdriver', + access: 'proxy', + meta: {} as DataSourcePluginMeta, + name: 'stackdriver', + + jsonData: { + authenticationType: GoogleAuthType.JWT, + defaultProject: 'test-project', + gceDefaultProject: 'test-project', + clientEmail: 'test-email@test.com', + tokenUri: 'https://oauth2.googleapis.com/token', + }, + ...overrides, +}); diff --git a/public/app/plugins/datasource/cloud-monitoring/__mocks__/cloudMonitoringQuery.ts b/public/app/plugins/datasource/cloud-monitoring/__mocks__/cloudMonitoringQuery.ts index a5aa7e49749..f41e0d8c8bb 100644 --- a/public/app/plugins/datasource/cloud-monitoring/__mocks__/cloudMonitoringQuery.ts +++ b/public/app/plugins/datasource/cloud-monitoring/__mocks__/cloudMonitoringQuery.ts @@ -1,5 +1,9 @@ import { AlignmentTypes, CloudMonitoringQuery, EditorMode, MetricQuery, QueryType, SLOQuery } from '../types'; +type Subset = { + [attr in keyof K]?: K[attr] extends object ? Subset : K[attr]; +}; + export const createMockMetricQuery: (overrides?: Partial) => MetricQuery = ( overrides?: Partial ) => { @@ -9,6 +13,9 @@ export const createMockMetricQuery: (overrides?: Partial) => Metric crossSeriesReducer: 'REDUCE_NONE', query: '', projectName: 'cloud-monitoring-default-project', + filters: [], + groupBys: [], + view: 'FULL', ...overrides, }; }; @@ -28,12 +35,17 @@ export const createMockSLOQuery: (overrides?: Partial) => SLOQuery = ( }; }; -export const createMockQuery: (overrides?: Partial) => CloudMonitoringQuery = (overrides) => { +export const createMockQuery: (overrides?: Subset) => CloudMonitoringQuery = (overrides) => { return { + datasource: { + type: 'stackdriver', + uid: 'abc', + }, refId: 'cloudMonitoringRefId', queryType: QueryType.METRICS, intervalMs: 0, type: 'timeSeriesQuery', + hide: false, ...overrides, metricQuery: createMockMetricQuery(overrides?.metricQuery), sloQuery: createMockSLOQuery(overrides?.sloQuery), diff --git a/public/app/plugins/datasource/cloud-monitoring/datasource.test.ts b/public/app/plugins/datasource/cloud-monitoring/datasource.test.ts new file mode 100644 index 00000000000..792544145cf --- /dev/null +++ b/public/app/plugins/datasource/cloud-monitoring/datasource.test.ts @@ -0,0 +1,28 @@ +import { TemplateSrv } from 'app/features/templating/template_srv'; + +import { createMockInstanceSetttings } from './__mocks__/cloudMonitoringInstanceSettings'; +import { createMockQuery } from './__mocks__/cloudMonitoringQuery'; +import Datasource from './datasource'; + +describe('Cloud Monitoring Datasource', () => { + describe('interpolateVariablesInQueries', () => { + it('should leave a query unchanged if there are no template variables', () => { + const mockInstanceSettings = createMockInstanceSetttings(); + const ds = new Datasource(mockInstanceSettings); + const query = createMockQuery(); + const templateVariablesApplied = ds.interpolateVariablesInQueries([query], {}); + expect(templateVariablesApplied[0]).toEqual(query); + }); + + it('should correctly apply template variables', () => { + const templateSrv = new TemplateSrv(); + templateSrv.replace = jest.fn().mockReturnValue('project-variable'); + const mockInstanceSettings = createMockInstanceSetttings(); + const ds = new Datasource(mockInstanceSettings, templateSrv); + const query = createMockQuery({ metricQuery: { projectName: '$testVar' } }); + const templatedQuery = ds.interpolateVariablesInQueries([query], {}); + expect(templatedQuery[0]).toHaveProperty('datasource'); + expect(templatedQuery[0].metricQuery.projectName).toEqual('project-variable'); + }); + }); +}); diff --git a/public/app/plugins/datasource/cloud-monitoring/datasource.ts b/public/app/plugins/datasource/cloud-monitoring/datasource.ts index 20b28f7a229..178c72d3c37 100644 --- a/public/app/plugins/datasource/cloud-monitoring/datasource.ts +++ b/public/app/plugins/datasource/cloud-monitoring/datasource.ts @@ -57,16 +57,12 @@ export default class CloudMonitoringDatasource extends DataSourceWithBackend< return super.query(request); } - applyTemplateVariables( - { metricQuery, refId, queryType, sloQuery, type = 'timeSeriesQuery' }: CloudMonitoringQuery, - scopedVars: ScopedVars - ): Record { + applyTemplateVariables(target: CloudMonitoringQuery, scopedVars: ScopedVars): Record { + const { metricQuery, sloQuery } = target; return { + ...target, datasource: this.getRef(), - refId, intervalMs: this.intervalMs, - type, - queryType, metricQuery: { ...this.interpolateProps(metricQuery, scopedVars), projectName: this.templateSrv.replace( diff --git a/public/app/plugins/datasource/cloud-monitoring/functions.ts b/public/app/plugins/datasource/cloud-monitoring/functions.ts index fb7c1ab2ccb..598053ebf87 100644 --- a/public/app/plugins/datasource/cloud-monitoring/functions.ts +++ b/public/app/plugins/datasource/cloud-monitoring/functions.ts @@ -7,8 +7,6 @@ import { AGGREGATIONS, ALIGNMENTS, SYSTEM_LABELS } from './constants'; import CloudMonitoringDatasource from './datasource'; import { AlignmentTypes, CustomMetaData, MetricDescriptor, MetricKind, PreprocessorType, ValueTypes } from './types'; -const templateSrv: TemplateSrv = getTemplateSrv(); - export const extractServicesFromMetricDescriptors = (metricDescriptors: MetricDescriptor[]) => uniqBy(metricDescriptors, 'service'); @@ -79,6 +77,7 @@ export const getAlignmentPickerData = ( perSeriesAligner: string | undefined = AlignmentTypes.ALIGN_MEAN, preprocessor?: PreprocessorType ) => { + const templateSrv: TemplateSrv = getTemplateSrv(); const alignOptions = getAlignmentOptionsByMetric(valueType!, metricKind!, preprocessor!).map((option) => ({ ...option, label: option.text,