From 801a2a240aeb068dbff3d2626bd6efe990ee989c Mon Sep 17 00:00:00 2001 From: Isabella Siu Date: Mon, 25 Apr 2022 10:33:49 -0400 Subject: [PATCH] Cloudwatch: fix template variables in variable queries (#48140) --- .../__mocks__/CloudWatchDataSource.ts | 18 +++++++++++++++++- .../datasource/cloudwatch/datasource.ts | 2 +- .../datasource/cloudwatch/variables.test.ts | 14 +++++++------- .../plugins/datasource/cloudwatch/variables.ts | 9 ++++++--- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/public/app/plugins/datasource/cloudwatch/__mocks__/CloudWatchDataSource.ts b/public/app/plugins/datasource/cloudwatch/__mocks__/CloudWatchDataSource.ts index f846d4e254c..7cc2ab389e1 100644 --- a/public/app/plugins/datasource/cloudwatch/__mocks__/CloudWatchDataSource.ts +++ b/public/app/plugins/datasource/cloudwatch/__mocks__/CloudWatchDataSource.ts @@ -47,7 +47,7 @@ export function setupMockedDataSource({ data = [], variables }: { data?: any; va const fetchMock = jest.fn().mockReturnValue(of({ data })); setBackendSrv({ fetch: fetchMock } as any); - return { datasource, fetchMock }; + return { datasource, fetchMock, templateService }; } export const metricVariable: CustomVariableModel = { @@ -125,3 +125,19 @@ export const aggregationvariable: CustomVariableModel = { ], multi: false, }; + +export const dimensionVariable: CustomVariableModel = { + ...initialCustomVariableModelState, + id: 'dimension', + name: 'dimension', + current: { + value: 'env', + text: 'env', + selected: true, + }, + options: [ + { value: 'env', text: 'env', selected: false }, + { value: 'tag', text: 'tag', selected: false }, + ], + multi: false, +}; diff --git a/public/app/plugins/datasource/cloudwatch/datasource.ts b/public/app/plugins/datasource/cloudwatch/datasource.ts index 6d7cdebe903..379ea6e4d45 100644 --- a/public/app/plugins/datasource/cloudwatch/datasource.ts +++ b/public/app/plugins/datasource/cloudwatch/datasource.ts @@ -125,7 +125,7 @@ export class CloudWatchDatasource this.logsTimeout = instanceSettings.jsonData.logsTimeout || '15m'; this.sqlCompletionItemProvider = new SQLCompletionItemProvider(this, this.templateSrv); this.metricMathCompletionItemProvider = new MetricMathCompletionItemProvider(this, this.templateSrv); - this.variables = new CloudWatchVariableSupport(this); + this.variables = new CloudWatchVariableSupport(this, this.templateSrv); } query(options: DataQueryRequest): Observable { diff --git a/public/app/plugins/datasource/cloudwatch/variables.test.ts b/public/app/plugins/datasource/cloudwatch/variables.test.ts index 592506cba98..a6e48356153 100644 --- a/public/app/plugins/datasource/cloudwatch/variables.test.ts +++ b/public/app/plugins/datasource/cloudwatch/variables.test.ts @@ -1,4 +1,4 @@ -import { setupMockedDataSource } from './__mocks__/CloudWatchDataSource'; +import { dimensionVariable, labelsVariable, setupMockedDataSource } from './__mocks__/CloudWatchDataSource'; import { VariableQuery, VariableQueryType } from './types'; import { CloudWatchVariableSupport } from './variables'; @@ -16,7 +16,7 @@ const defaultQuery: VariableQuery = { refId: '', }; -const ds = setupMockedDataSource(); +const ds = setupMockedDataSource({ variables: [labelsVariable, dimensionVariable] }); ds.datasource.getRegions = jest.fn().mockResolvedValue([{ label: 'a', value: 'a' }]); ds.datasource.getNamespaces = jest.fn().mockResolvedValue([{ label: 'b', value: 'b' }]); ds.datasource.getMetrics = jest.fn().mockResolvedValue([{ label: 'c', value: 'c' }]); @@ -26,7 +26,7 @@ const getEbsVolumeIds = jest.fn().mockResolvedValue([{ label: 'f', value: 'f' }] const getEc2InstanceAttribute = jest.fn().mockResolvedValue([{ label: 'g', value: 'g' }]); const getResourceARNs = jest.fn().mockResolvedValue([{ label: 'h', value: 'h' }]); -const variables = new CloudWatchVariableSupport(ds.datasource); +const variables = new CloudWatchVariableSupport(ds.datasource, ds.templateService); describe('variables', () => { it('should run regions', async () => { @@ -114,7 +114,7 @@ describe('variables', () => { ...defaultQuery, queryType: VariableQueryType.EC2InstanceAttributes, attributeName: 'abc', - ec2Filters: '{"a":["b"]}', + ec2Filters: '{"$dimension":["b"]}', }; beforeEach(() => { ds.datasource.getEc2InstanceAttribute = getEc2InstanceAttribute; @@ -129,7 +129,7 @@ describe('variables', () => { it('should run if instance id set', async () => { const result = await variables.execute(query); - expect(getEc2InstanceAttribute).toBeCalledWith(query.region, query.attributeName, { a: ['b'] }); + expect(getEc2InstanceAttribute).toBeCalledWith(query.region, query.attributeName, { env: ['b'] }); expect(result).toEqual([{ text: 'g', value: 'g', expandable: true }]); }); }); @@ -139,7 +139,7 @@ describe('variables', () => { ...defaultQuery, queryType: VariableQueryType.ResourceArns, resourceType: 'abc', - tags: '{"a":["b"]}', + tags: '{"a":${labels:json}}', }; beforeEach(() => { ds.datasource.getResourceARNs = getResourceARNs; @@ -154,7 +154,7 @@ describe('variables', () => { it('should run if instance id set', async () => { const result = await variables.execute(query); - expect(getResourceARNs).toBeCalledWith(query.region, query.resourceType, { a: ['b'] }); + expect(getResourceARNs).toBeCalledWith(query.region, query.resourceType, { a: ['InstanceId', 'InstanceType'] }); expect(result).toEqual([{ text: 'h', value: 'h', expandable: true }]); }); }); diff --git a/public/app/plugins/datasource/cloudwatch/variables.ts b/public/app/plugins/datasource/cloudwatch/variables.ts index 3a6932b3ca7..a4eb2ea5397 100644 --- a/public/app/plugins/datasource/cloudwatch/variables.ts +++ b/public/app/plugins/datasource/cloudwatch/variables.ts @@ -2,6 +2,7 @@ import { from, Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { CustomVariableSupport, DataQueryRequest, DataQueryResponse } from '@grafana/data'; +import { getTemplateSrv, TemplateSrv } from '@grafana/runtime'; import { VariableQueryEditor } from './components/VariableQueryEditor/VariableQueryEditor'; import { CloudWatchDatasource } from './datasource'; @@ -10,10 +11,12 @@ import { VariableQuery, VariableQueryType } from './types'; export class CloudWatchVariableSupport extends CustomVariableSupport { private readonly datasource: CloudWatchDatasource; + private readonly templateSrv: TemplateSrv; - constructor(datasource: CloudWatchDatasource) { + constructor(datasource: CloudWatchDatasource, templateSrv: TemplateSrv = getTemplateSrv()) { super(); this.datasource = datasource; + this.templateSrv = templateSrv; this.query = this.query.bind(this); } @@ -124,7 +127,7 @@ export class CloudWatchVariableSupport extends CustomVariableSupport ({ @@ -140,7 +143,7 @@ export class CloudWatchVariableSupport extends CustomVariableSupport ({