From 10016d9d38ab511e371208c7a96b609fcc7a0cb8 Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanda Date: Mon, 4 Jan 2016 16:56:18 +0900 Subject: [PATCH 1/5] add CloudWatch DescribeAlarms API support --- pkg/api/cloudwatch/cloudwatch.go | 52 +++++++++++++++++++ .../datasource/cloudwatch/datasource.js | 8 +++ 2 files changed, 60 insertions(+) diff --git a/pkg/api/cloudwatch/cloudwatch.go b/pkg/api/cloudwatch/cloudwatch.go index babcf9fddb0..bf281864da5 100644 --- a/pkg/api/cloudwatch/cloudwatch.go +++ b/pkg/api/cloudwatch/cloudwatch.go @@ -33,6 +33,7 @@ func init() { actionHandlers = map[string]actionHandler{ "GetMetricStatistics": handleGetMetricStatistics, "ListMetrics": handleListMetrics, + "DescribeAlarms": handleDescribeAlarms, "DescribeAlarmsForMetric": handleDescribeAlarmsForMetric, "DescribeAlarmHistory": handleDescribeAlarmHistory, "DescribeInstances": handleDescribeInstances, @@ -142,6 +143,57 @@ func handleListMetrics(req *cwRequest, c *middleware.Context) { c.JSON(200, resp) } +func handleDescribeAlarms(req *cwRequest, c *middleware.Context) { + sess := session.New() + creds := credentials.NewChainCredentials( + []credentials.Provider{ + &credentials.EnvProvider{}, + &credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database}, + &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute}, + }) + + cfg := &aws.Config{ + Region: aws.String(req.Region), + Credentials: creds, + } + + svc := cloudwatch.New(session.New(cfg), cfg) + + reqParam := &struct { + Parameters struct { + ActionPrefix string `json:"actionPrefix"` + AlarmNamePrefix string `json:"alarmNamePrefix"` + AlarmNames []*string `json:"alarmNames"` + StateValue string `json:"stateValue"` + } `json:"parameters"` + }{} + json.Unmarshal(req.Body, reqParam) + + params := &cloudwatch.DescribeAlarmsInput{ + MaxRecords: aws.Int64(100), + } + if reqParam.Parameters.ActionPrefix != "" { + params.ActionPrefix = aws.String(reqParam.Parameters.ActionPrefix) + } + if reqParam.Parameters.AlarmNamePrefix != "" { + params.AlarmNamePrefix = aws.String(reqParam.Parameters.AlarmNamePrefix) + } + if len(reqParam.Parameters.AlarmNames) != 0 { + params.AlarmNames = reqParam.Parameters.AlarmNames + } + if reqParam.Parameters.StateValue != "" { + params.StateValue = aws.String(reqParam.Parameters.StateValue) + } + + resp, err := svc.DescribeAlarms(params) + if err != nil { + c.JsonApiErr(500, "Unable to call AWS API", err) + return + } + + c.JSON(200, resp) +} + func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) { cfg := &aws.Config{ Region: aws.String(req.Region), diff --git a/public/app/plugins/datasource/cloudwatch/datasource.js b/public/app/plugins/datasource/cloudwatch/datasource.js index 119c4a83167..ab97e4eedd5 100644 --- a/public/app/plugins/datasource/cloudwatch/datasource.js +++ b/public/app/plugins/datasource/cloudwatch/datasource.js @@ -204,6 +204,14 @@ function (angular, _, moment, dateMath) { return $q.when([]); }; + this.performDescribeAlarms = function(region, actionPrefix, alarmNamePrefix, alarmNames, stateValue) { + return this.awsRequest({ + region: region, + action: 'DescribeAlarms', + parameters: { actionPrefix: actionPrefix, alarmNamePrefix: alarmNamePrefix, alarmNames: alarmNames, stateValue: stateValue } + }); + }; + this.performDescribeAlarmsForMetric = function(region, namespace, metricName, dimensions, statistic, period) { return this.awsRequest({ region: region, From defb15bea1625bb0d2df93a09bce744b5003d747 Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanda Date: Mon, 4 Jan 2016 18:53:18 +0900 Subject: [PATCH 2/5] CloudWatch multiple alarm annotation support --- .../datasource/cloudwatch/datasource.js | 48 ++++++++++++++++--- .../partials/annotations.editor.html | 18 +++++++ 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/public/app/plugins/datasource/cloudwatch/datasource.js b/public/app/plugins/datasource/cloudwatch/datasource.js index ab97e4eedd5..881d4e48c3d 100644 --- a/public/app/plugins/datasource/cloudwatch/datasource.js +++ b/public/app/plugins/datasource/cloudwatch/datasource.js @@ -230,21 +230,57 @@ function (angular, _, moment, dateMath) { this.annotationQuery = function(options) { var annotation = options.annotation; + var usePrefixMatch = annotation.prefixMatching; var region = templateSrv.replace(annotation.region); var namespace = templateSrv.replace(annotation.namespace); var metricName = templateSrv.replace(annotation.metricName); var dimensions = convertDimensionFormat(annotation.dimensions); var statistics = _.map(annotation.statistics, function(s) { return templateSrv.replace(s); }); - var period = annotation.period || '300'; + var defaultPeriod = usePrefixMatch ? '' : '300'; + var period = annotation.period || defaultPeriod; period = parseInt(period, 10); - - if (!region || !namespace || !metricName || _.isEmpty(statistics)) { return $q.when([]); } + var actionPrefix = annotation.actionPrefix || ''; + var alarmNamePrefix = annotation.alarmNamePrefix || ''; var d = $q.defer(); var self = this; - var allQueryPromise = _.map(statistics, function(statistic) { - return self.performDescribeAlarmsForMetric(region, namespace, metricName, dimensions, statistic, period); - }); + var allQueryPromise; + if (usePrefixMatch) { + allQueryPromise = [ + this.performDescribeAlarms(region, actionPrefix, alarmNamePrefix, [], '').then(function(alarms) { + alarms.MetricAlarms = _.filter(alarms.MetricAlarms, function(alarm) { + if (!_.isEmpty(namespace) && alarm.Namespace !== namespace) { + return false; + } + if (!_.isEmpty(metricName) && alarm.MetricName !== metricName) { + return false; + } + var sd = function(d) { + return d.Name; + }; + var isSameDimensions = JSON.stringify(_.sortBy(alarm.Dimensions, sd)) === JSON.stringify(_.sortBy(dimensions, sd)); + if (!_.isEmpty(dimensions) && !isSameDimensions) { + return false; + } + if (!_.isEmpty(statistics) && !_.contains(statistics, alarm.Statistic)) { + return false; + } + if (!_.isNaN(period) && alarm.Period !== period) { + return false; + } + return true; + }); + + return alarms; + }) + ]; + } else { + if (!region || !namespace || !metricName || _.isEmpty(statistics)) { return $q.when([]); } + + allQueryPromise = _.map(statistics, function(statistic) { + return self.performDescribeAlarmsForMetric(region, namespace, metricName, dimensions, statistic, period); + }); + } $q.all(allQueryPromise).then(function(alarms) { var eventList = []; diff --git a/public/app/plugins/datasource/cloudwatch/partials/annotations.editor.html b/public/app/plugins/datasource/cloudwatch/partials/annotations.editor.html index 050698f3ff2..a82f82edf96 100644 --- a/public/app/plugins/datasource/cloudwatch/partials/annotations.editor.html +++ b/public/app/plugins/datasource/cloudwatch/partials/annotations.editor.html @@ -1 +1,19 @@ +
+
+
Prefix matching
+
+ +
+ +
+ + +
+ +
+ + +
+
+
From e96d72d66926fb2726bb01c8995f3a3507893b55 Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanda Date: Sat, 9 Jan 2016 09:50:10 +0900 Subject: [PATCH 3/5] reuse credentials --- pkg/api/cloudwatch/cloudwatch.go | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/pkg/api/cloudwatch/cloudwatch.go b/pkg/api/cloudwatch/cloudwatch.go index bf281864da5..88d22800d65 100644 --- a/pkg/api/cloudwatch/cloudwatch.go +++ b/pkg/api/cloudwatch/cloudwatch.go @@ -144,17 +144,9 @@ func handleListMetrics(req *cwRequest, c *middleware.Context) { } func handleDescribeAlarms(req *cwRequest, c *middleware.Context) { - sess := session.New() - creds := credentials.NewChainCredentials( - []credentials.Provider{ - &credentials.EnvProvider{}, - &credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database}, - &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute}, - }) - cfg := &aws.Config{ Region: aws.String(req.Region), - Credentials: creds, + Credentials: getCredentials(req.DataSource.Database), } svc := cloudwatch.New(session.New(cfg), cfg) From a20443b5772ce78f58d22aed59d5d8b7cdaaec4b Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanda Date: Fri, 15 Jan 2016 21:34:34 +0900 Subject: [PATCH 4/5] (cloudwatch) refactor annotation query --- .../cloudwatch/annotation_query.d.ts | 2 + .../datasource/cloudwatch/annotation_query.js | 105 +++++++++++++++++ .../datasource/cloudwatch/datasource.js | 107 +++--------------- .../specs/annotation_query_specs.ts | 81 +++++++++++++ .../cloudwatch/specs/datasource_specs.ts | 55 --------- 5 files changed, 201 insertions(+), 149 deletions(-) create mode 100644 public/app/plugins/datasource/cloudwatch/annotation_query.d.ts create mode 100644 public/app/plugins/datasource/cloudwatch/annotation_query.js create mode 100644 public/app/plugins/datasource/cloudwatch/specs/annotation_query_specs.ts diff --git a/public/app/plugins/datasource/cloudwatch/annotation_query.d.ts b/public/app/plugins/datasource/cloudwatch/annotation_query.d.ts new file mode 100644 index 00000000000..c3318b8e133 --- /dev/null +++ b/public/app/plugins/datasource/cloudwatch/annotation_query.d.ts @@ -0,0 +1,2 @@ +declare var test: any; +export default test; diff --git a/public/app/plugins/datasource/cloudwatch/annotation_query.js b/public/app/plugins/datasource/cloudwatch/annotation_query.js new file mode 100644 index 00000000000..46fbd3a87a9 --- /dev/null +++ b/public/app/plugins/datasource/cloudwatch/annotation_query.js @@ -0,0 +1,105 @@ +define([ + 'lodash', +], +function (_) { + 'use strict'; + + function CloudWatchAnnotationQuery(datasource, annotation, $q, templateSrv) { + this.datasource = datasource; + this.annotation = annotation; + this.$q = $q; + this.templateSrv = templateSrv; + } + + CloudWatchAnnotationQuery.prototype.process = function(from, to) { + var self = this; + var usePrefixMatch = this.annotation.prefixMatching; + var region = this.templateSrv.replace(this.annotation.region); + var namespace = this.templateSrv.replace(this.annotation.namespace); + var metricName = this.templateSrv.replace(this.annotation.metricName); + var dimensions = this.datasource.convertDimensionFormat(this.annotation.dimensions); + var statistics = _.map(this.annotation.statistics, function(s) { return self.templateSrv.replace(s); }); + var defaultPeriod = usePrefixMatch ? '' : '300'; + var period = this.annotation.period || defaultPeriod; + period = parseInt(period, 10); + var actionPrefix = this.annotation.actionPrefix || ''; + var alarmNamePrefix = this.annotation.alarmNamePrefix || ''; + + var d = this.$q.defer(); + var allQueryPromise; + if (usePrefixMatch) { + allQueryPromise = [ + this.datasource.performDescribeAlarms(region, actionPrefix, alarmNamePrefix, [], '').then(function(alarms) { + alarms.MetricAlarms = self.filterAlarms(alarms, namespace, metricName, dimensions, statistics, period); + return alarms; + }) + ]; + } else { + if (!region || !namespace || !metricName || _.isEmpty(statistics)) { return this.$q.when([]); } + + allQueryPromise = _.map(statistics, function(statistic) { + return self.datasource.performDescribeAlarmsForMetric(region, namespace, metricName, dimensions, statistic, period); + }); + } + this.$q.all(allQueryPromise).then(function(alarms) { + var eventList = []; + + var start = self.datasource.convertToCloudWatchTime(from, false); + var end = self.datasource.convertToCloudWatchTime(to, true); + _.chain(alarms) + .pluck('MetricAlarms') + .flatten() + .each(function(alarm) { + if (!alarm) { + d.resolve(eventList); + return; + } + + self.datasource.performDescribeAlarmHistory(region, alarm.AlarmName, start, end).then(function(history) { + _.each(history.AlarmHistoryItems, function(h) { + var event = { + annotation: self.annotation, + time: Date.parse(h.Timestamp), + title: h.AlarmName, + tags: [h.HistoryItemType], + text: h.HistorySummary + }; + + eventList.push(event); + }); + + d.resolve(eventList); + }); + }); + }); + + return d.promise; + }; + + CloudWatchAnnotationQuery.prototype.filterAlarms = function(alarms, namespace, metricName, dimensions, statistics, period) { + return _.filter(alarms.MetricAlarms, function(alarm) { + if (!_.isEmpty(namespace) && alarm.Namespace !== namespace) { + return false; + } + if (!_.isEmpty(metricName) && alarm.MetricName !== metricName) { + return false; + } + var sd = function(d) { + return d.Name; + }; + var isSameDimensions = JSON.stringify(_.sortBy(alarm.Dimensions, sd)) === JSON.stringify(_.sortBy(dimensions, sd)); + if (!_.isEmpty(dimensions) && !isSameDimensions) { + return false; + } + if (!_.isEmpty(statistics) && !_.contains(statistics, alarm.Statistic)) { + return false; + } + if (!_.isNaN(period) && alarm.Period !== period) { + return false; + } + return true; + }); + }; + + return CloudWatchAnnotationQuery; +}); diff --git a/public/app/plugins/datasource/cloudwatch/datasource.js b/public/app/plugins/datasource/cloudwatch/datasource.js index 881d4e48c3d..153ca28b54f 100644 --- a/public/app/plugins/datasource/cloudwatch/datasource.js +++ b/public/app/plugins/datasource/cloudwatch/datasource.js @@ -3,8 +3,9 @@ define([ 'lodash', 'moment', 'app/core/utils/datemath', + './annotation_query', ], -function (angular, _, moment, dateMath) { +function (angular, _, moment, dateMath, CloudWatchAnnotationQuery) { 'use strict'; /** @ngInject */ @@ -15,9 +16,10 @@ function (angular, _, moment, dateMath) { this.proxyUrl = instanceSettings.url; this.defaultRegion = instanceSettings.jsonData.defaultRegion; + var self = this; this.query = function(options) { - var start = convertToCloudWatchTime(options.range.from, false); - var end = convertToCloudWatchTime(options.range.to, true); + var start = self.convertToCloudWatchTime(options.range.from, false); + var end = self.convertToCloudWatchTime(options.range.to, true); var queries = []; options = angular.copy(options); @@ -30,7 +32,7 @@ function (angular, _, moment, dateMath) { query.region = templateSrv.replace(target.region, options.scopedVars); query.namespace = templateSrv.replace(target.namespace, options.scopedVars); query.metricName = templateSrv.replace(target.metricName, options.scopedVars); - query.dimensions = convertDimensionFormat(target.dimensions, options.scopedVars); + query.dimensions = self.convertDimensionFormat(target.dimensions, options.scopedVars); query.statistics = target.statistics; var range = end - start; @@ -115,7 +117,7 @@ function (angular, _, moment, dateMath) { parameters: { namespace: templateSrv.replace(namespace), metricName: templateSrv.replace(metricName), - dimensions: convertDimensionFormat(filterDimensions, {}), + dimensions: this.convertDimensionFormat(filterDimensions, {}), } }; @@ -229,91 +231,8 @@ function (angular, _, moment, dateMath) { }; this.annotationQuery = function(options) { - var annotation = options.annotation; - var usePrefixMatch = annotation.prefixMatching; - var region = templateSrv.replace(annotation.region); - var namespace = templateSrv.replace(annotation.namespace); - var metricName = templateSrv.replace(annotation.metricName); - var dimensions = convertDimensionFormat(annotation.dimensions); - var statistics = _.map(annotation.statistics, function(s) { return templateSrv.replace(s); }); - var defaultPeriod = usePrefixMatch ? '' : '300'; - var period = annotation.period || defaultPeriod; - period = parseInt(period, 10); - var actionPrefix = annotation.actionPrefix || ''; - var alarmNamePrefix = annotation.alarmNamePrefix || ''; - - var d = $q.defer(); - var self = this; - var allQueryPromise; - if (usePrefixMatch) { - allQueryPromise = [ - this.performDescribeAlarms(region, actionPrefix, alarmNamePrefix, [], '').then(function(alarms) { - alarms.MetricAlarms = _.filter(alarms.MetricAlarms, function(alarm) { - if (!_.isEmpty(namespace) && alarm.Namespace !== namespace) { - return false; - } - if (!_.isEmpty(metricName) && alarm.MetricName !== metricName) { - return false; - } - var sd = function(d) { - return d.Name; - }; - var isSameDimensions = JSON.stringify(_.sortBy(alarm.Dimensions, sd)) === JSON.stringify(_.sortBy(dimensions, sd)); - if (!_.isEmpty(dimensions) && !isSameDimensions) { - return false; - } - if (!_.isEmpty(statistics) && !_.contains(statistics, alarm.Statistic)) { - return false; - } - if (!_.isNaN(period) && alarm.Period !== period) { - return false; - } - return true; - }); - - return alarms; - }) - ]; - } else { - if (!region || !namespace || !metricName || _.isEmpty(statistics)) { return $q.when([]); } - - allQueryPromise = _.map(statistics, function(statistic) { - return self.performDescribeAlarmsForMetric(region, namespace, metricName, dimensions, statistic, period); - }); - } - $q.all(allQueryPromise).then(function(alarms) { - var eventList = []; - - var start = convertToCloudWatchTime(options.range.from, false); - var end = convertToCloudWatchTime(options.range.to, true); - _.chain(alarms) - .pluck('MetricAlarms') - .flatten() - .each(function(alarm) { - if (!alarm) { - d.resolve(eventList); - return; - } - - self.performDescribeAlarmHistory(region, alarm.AlarmName, start, end).then(function(history) { - _.each(history.AlarmHistoryItems, function(h) { - var event = { - annotation: annotation, - time: Date.parse(h.Timestamp), - title: h.AlarmName, - tags: [h.HistoryItemType], - text: h.HistorySummary - }; - - eventList.push(event); - }); - - d.resolve(eventList); - }); - }); - }); - - return d.promise; + var annotationQuery = new CloudWatchAnnotationQuery(this, options.annotation, $q, templateSrv); + return annotationQuery.process(options.range.from, options.range.to); }; this.testDatasource = function() { @@ -383,21 +302,21 @@ function (angular, _, moment, dateMath) { }); } - function convertToCloudWatchTime(date, roundUp) { + this.convertToCloudWatchTime = function(date, roundUp) { if (_.isString(date)) { date = dateMath.parse(date, roundUp); } return Math.round(date.valueOf() / 1000); - } + }; - function convertDimensionFormat(dimensions, scopedVars) { + this.convertDimensionFormat = function(dimensions, scopedVars) { return _.map(dimensions, function(value, key) { return { Name: templateSrv.replace(key, scopedVars), Value: templateSrv.replace(value, scopedVars) }; }); - } + }; } diff --git a/public/app/plugins/datasource/cloudwatch/specs/annotation_query_specs.ts b/public/app/plugins/datasource/cloudwatch/specs/annotation_query_specs.ts new file mode 100644 index 00000000000..dbdbc8d1fd6 --- /dev/null +++ b/public/app/plugins/datasource/cloudwatch/specs/annotation_query_specs.ts @@ -0,0 +1,81 @@ +import "../datasource"; +import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/common'; +import moment from 'moment'; +import helpers from 'test/specs/helpers'; +import Datasource from "../datasource"; +import CloudWatchAnnotationQuery from '../annotation_query'; + +describe('CloudWatchAnnotationQuery', function() { + var ctx = new helpers.ServiceTestContext(); + var instanceSettings = { + jsonData: {defaultRegion: 'us-east-1', access: 'proxy'}, + }; + + beforeEach(angularMocks.module('grafana.core')); + beforeEach(angularMocks.module('grafana.services')); + beforeEach(angularMocks.module('grafana.controllers')); + beforeEach(ctx.providePhase(['templateSrv', 'backendSrv'])); + + beforeEach(angularMocks.inject(function($q, $rootScope, $httpBackend, $injector) { + ctx.$q = $q; + ctx.$httpBackend = $httpBackend; + ctx.$rootScope = $rootScope; + ctx.ds = $injector.instantiate(Datasource, {instanceSettings: instanceSettings}); + })); + + describe('When performing annotationQuery', function() { + var parameter = { + annotation: { + region: 'us-east-1', + namespace: 'AWS/EC2', + metricName: 'CPUUtilization', + dimensions: { + InstanceId: 'i-12345678' + }, + statistics: ['Average'], + period: 300 + }, + range: { + from: moment(1443438674760), + to: moment(1443460274760) + } + }; + var alarmResponse = { + MetricAlarms: [ + { + AlarmName: 'test_alarm_name' + } + ] + }; + var historyResponse = { + AlarmHistoryItems: [ + { + Timestamp: '2015-01-01T00:00:00.000Z', + HistoryItemType: 'StateUpdate', + AlarmName: 'test_alarm_name', + HistoryData: '{}', + HistorySummary: 'test_history_summary' + } + ] + }; + beforeEach(function() { + ctx.backendSrv.datasourceRequest = function(params) { + switch (params.data.action) { + case 'DescribeAlarmsForMetric': + return ctx.$q.when({data: alarmResponse}); + case 'DescribeAlarmHistory': + return ctx.$q.when({data: historyResponse}); + } + }; + }); + it('should return annotation list', function(done) { + var annotationQuery = new CloudWatchAnnotationQuery(ctx.ds, parameter.annotation, ctx.$q, ctx.templateSrv); + annotationQuery.process(parameter.range.from, parameter.range.to).then(function(result) { + expect(result[0].title).to.be('test_alarm_name'); + expect(result[0].text).to.be('test_history_summary'); + done(); + }); + ctx.$rootScope.$apply(); + }); + }); +}); diff --git a/public/app/plugins/datasource/cloudwatch/specs/datasource_specs.ts b/public/app/plugins/datasource/cloudwatch/specs/datasource_specs.ts index cec32420aea..c03e5085cc2 100644 --- a/public/app/plugins/datasource/cloudwatch/specs/datasource_specs.ts +++ b/public/app/plugins/datasource/cloudwatch/specs/datasource_specs.ts @@ -187,59 +187,4 @@ describe('CloudWatchDatasource', function() { expect(scenario.request.data.action).to.be('ListMetrics'); }); }); - - describe('When performing annotationQuery', function() { - var parameter = { - annotation: { - region: 'us-east-1', - namespace: 'AWS/EC2', - metricName: 'CPUUtilization', - dimensions: { - InstanceId: 'i-12345678' - }, - statistics: ['Average'], - period: 300 - }, - range: { - from: moment(1443438674760), - to: moment(1443460274760) - } - }; - var alarmResponse = { - MetricAlarms: [ - { - AlarmName: 'test_alarm_name' - } - ] - }; - var historyResponse = { - AlarmHistoryItems: [ - { - Timestamp: '2015-01-01T00:00:00.000Z', - HistoryItemType: 'StateUpdate', - AlarmName: 'test_alarm_name', - HistoryData: '{}', - HistorySummary: 'test_history_summary' - } - ] - }; - beforeEach(function() { - ctx.backendSrv.datasourceRequest = function(params) { - switch (params.data.action) { - case 'DescribeAlarmsForMetric': - return ctx.$q.when({data: alarmResponse}); - case 'DescribeAlarmHistory': - return ctx.$q.when({data: historyResponse}); - } - }; - }); - it('should return annotation list', function(done) { - ctx.ds.annotationQuery(parameter).then(function(result) { - expect(result[0].title).to.be('test_alarm_name'); - expect(result[0].text).to.be('test_history_summary'); - done(); - }); - ctx.$rootScope.$apply(); - }); - }); }); From a4e5b7ea379e9f8a92ea0432158e9071a7a89ccc Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanda Date: Thu, 4 Feb 2016 13:21:29 +0900 Subject: [PATCH 5/5] fix cloudwatch test error --- .../datasource/cloudwatch/specs/annotation_query_specs.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/app/plugins/datasource/cloudwatch/specs/annotation_query_specs.ts b/public/app/plugins/datasource/cloudwatch/specs/annotation_query_specs.ts index dbdbc8d1fd6..e3a8fc3f9cb 100644 --- a/public/app/plugins/datasource/cloudwatch/specs/annotation_query_specs.ts +++ b/public/app/plugins/datasource/cloudwatch/specs/annotation_query_specs.ts @@ -2,7 +2,7 @@ import "../datasource"; import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/common'; import moment from 'moment'; import helpers from 'test/specs/helpers'; -import Datasource from "../datasource"; +import {CloudWatchDatasource} from "../datasource"; import CloudWatchAnnotationQuery from '../annotation_query'; describe('CloudWatchAnnotationQuery', function() { @@ -20,7 +20,7 @@ describe('CloudWatchAnnotationQuery', function() { ctx.$q = $q; ctx.$httpBackend = $httpBackend; ctx.$rootScope = $rootScope; - ctx.ds = $injector.instantiate(Datasource, {instanceSettings: instanceSettings}); + ctx.ds = $injector.instantiate(CloudWatchDatasource, {instanceSettings: instanceSettings}); })); describe('When performing annotationQuery', function() {