@ -5,6 +5,8 @@ import (
"fmt"
"io/ioutil"
"math"
"net/url"
"reflect"
"strconv"
"testing"
"time"
@ -53,18 +55,57 @@ func TestCloudMonitoring(t *testing.T) {
So ( queries [ 0 ] . Params [ "filter" ] [ 0 ] , ShouldEqual , "metric.type=\"a/metric/type\"" )
So ( queries [ 0 ] . Params [ "view" ] [ 0 ] , ShouldEqual , "FULL" )
So ( queries [ 0 ] . AliasBy , ShouldEqual , "testalias" )
Convey ( "and generated deep link has correct parameters" , func ( ) {
dl := queries [ 0 ] . buildDeepLink ( )
So ( dl , ShouldBeEmpty ) // no resource type found
// assign resource type to query parameters to be included in the deep link filter
// in the actual workflow this information comes from the response of the Monitoring API
queries [ 0 ] . Params . Set ( "resourceType" , "a/resource/type" )
dl = queries [ 0 ] . buildDeepLink ( )
expectedTimeSelection := map [ string ] string {
"timeRange" : "custom" ,
"start" : "2018-03-15T13:00:00Z" ,
"end" : "2018-03-15T13:34:00Z" ,
}
expectedTimeSeriesFilter := map [ string ] interface { } {
"perSeriesAligner" : "ALIGN_MEAN" ,
"filter" : "resource.type=\"a/resource/type\" metric.type=\"a/metric/type\"" ,
}
verifyDeepLink ( dl , expectedTimeSelection , expectedTimeSeriesFilter )
} )
} )
Convey ( "and query has filters" , func ( ) {
tsdbQuery . Queries [ 0 ] . Model = simplejson . NewFromAny ( map [ string ] interface { } {
"metricType" : "a/metric/type" ,
"filters" : [ ] interface { } { "key" , "=" , "value" , "AND" , "key2" , "=" , "value2" } ,
"filters" : [ ] interface { } { "key" , "=" , "value" , "AND" , "key2" , "=" , "value2" , "AND" , "resource.type" , "=" , "another/resource/type" } ,
} )
queries , err := executor . buildQueries ( tsdbQuery )
So ( err , ShouldBeNil )
So ( len ( queries ) , ShouldEqual , 1 )
So ( queries [ 0 ] . Params [ "filter" ] [ 0 ] , ShouldEqual , ` metric.type="a/metric/type" key="value" key2="value2" ` )
So ( queries [ 0 ] . Params [ "filter" ] [ 0 ] , ShouldEqual , ` metric.type="a/metric/type" key="value" key2="value2" resource.type="another/resource/type" ` )
Convey ( "and generated deep link has correct parameters" , func ( ) {
// assign a resource type to query parameters
// in the actual workflow this information comes from the response of the Monitoring API
// the deep link should not contain this resource type since another resource type is included in the query filters
queries [ 0 ] . Params . Set ( "resourceType" , "a/resource/type" )
dl := queries [ 0 ] . buildDeepLink ( )
expectedTimeSelection := map [ string ] string {
"timeRange" : "custom" ,
"start" : "2018-03-15T13:00:00Z" ,
"end" : "2018-03-15T13:34:00Z" ,
}
expectedTimeSeriesFilter := map [ string ] interface { } {
"filter" : ` metric.type="a/metric/type" key="value" key2="value2" resource.type="another/resource/type" ` ,
}
verifyDeepLink ( dl , expectedTimeSelection , expectedTimeSeriesFilter )
} )
} )
Convey ( "and alignmentPeriod is set to grafana-auto" , func ( ) {
@ -78,6 +119,23 @@ func TestCloudMonitoring(t *testing.T) {
queries , err := executor . buildQueries ( tsdbQuery )
So ( err , ShouldBeNil )
So ( queries [ 0 ] . Params [ "aggregation.alignmentPeriod" ] [ 0 ] , ShouldEqual , ` +1000s ` )
Convey ( "and generated deep link has correct parameters" , func ( ) {
// assign resource type to query parameters to be included in the deep link filter
// in the actual workflow this information comes from the response of the Monitoring API
queries [ 0 ] . Params . Set ( "resourceType" , "a/resource/type" )
dl := queries [ 0 ] . buildDeepLink ( )
expectedTimeSelection := map [ string ] string {
"timeRange" : "custom" ,
"start" : "2018-03-15T13:00:00Z" ,
"end" : "2018-03-15T13:34:00Z" ,
}
expectedTimeSeriesFilter := map [ string ] interface { } {
"minAlignmentPeriod" : ` 1000s ` ,
}
verifyDeepLink ( dl , expectedTimeSelection , expectedTimeSeriesFilter )
} )
} )
Convey ( "and IntervalMs is less than 60000" , func ( ) {
tsdbQuery . Queries [ 0 ] . IntervalMs = 30000
@ -89,6 +147,23 @@ func TestCloudMonitoring(t *testing.T) {
queries , err := executor . buildQueries ( tsdbQuery )
So ( err , ShouldBeNil )
So ( queries [ 0 ] . Params [ "aggregation.alignmentPeriod" ] [ 0 ] , ShouldEqual , ` +60s ` )
Convey ( "and generated deep link has correct parameters" , func ( ) {
// assign resource type to query parameters to be included in the deep link filter
// in the actual workflow this information comes from the response of the Monitoring API
queries [ 0 ] . Params . Set ( "resourceType" , "a/resource/type" )
dl := queries [ 0 ] . buildDeepLink ( )
expectedTimeSelection := map [ string ] string {
"timeRange" : "custom" ,
"start" : "2018-03-15T13:00:00Z" ,
"end" : "2018-03-15T13:34:00Z" ,
}
expectedTimeSeriesFilter := map [ string ] interface { } {
"minAlignmentPeriod" : ` 60s ` ,
}
verifyDeepLink ( dl , expectedTimeSelection , expectedTimeSeriesFilter )
} )
} )
} )
@ -158,6 +233,23 @@ func TestCloudMonitoring(t *testing.T) {
queries , err := executor . buildQueries ( tsdbQuery )
So ( err , ShouldBeNil )
So ( queries [ 0 ] . Params [ "aggregation.alignmentPeriod" ] [ 0 ] , ShouldEqual , ` +60s ` )
Convey ( "and generated deep link has correct parameters" , func ( ) {
// assign resource type to query parameters to be included in the deep link filter
// in the actual workflow this information comes from the response of the Monitoring API
queries [ 0 ] . Params . Set ( "resourceType" , "a/resource/type" )
dl := queries [ 0 ] . buildDeepLink ( )
expectedTimeSelection := map [ string ] string {
"timeRange" : "custom" ,
"start" : "2018-09-27T07:28:42Z" ,
"end" : "2018-09-27T09:28:42Z" ,
}
expectedTimeSeriesFilter := map [ string ] interface { } {
"minAlignmentPeriod" : ` 60s ` ,
}
verifyDeepLink ( dl , expectedTimeSelection , expectedTimeSeriesFilter )
} )
} )
Convey ( "and range is 22 hours" , func ( ) {
@ -171,6 +263,23 @@ func TestCloudMonitoring(t *testing.T) {
queries , err := executor . buildQueries ( tsdbQuery )
So ( err , ShouldBeNil )
So ( queries [ 0 ] . Params [ "aggregation.alignmentPeriod" ] [ 0 ] , ShouldEqual , ` +60s ` )
Convey ( "and generated deep link has correct parameters" , func ( ) {
// assign resource type to query parameters to be included in the deep link filter
// in the actual workflow this information comes from the response of the Monitoring API
queries [ 0 ] . Params . Set ( "resourceType" , "a/resource/type" )
dl := queries [ 0 ] . buildDeepLink ( )
expectedTimeSelection := map [ string ] string {
"timeRange" : "custom" ,
"start" : "2018-09-27T07:48:44Z" ,
"end" : "2018-09-28T05:48:44Z" ,
}
expectedTimeSeriesFilter := map [ string ] interface { } {
"minAlignmentPeriod" : ` 60s ` ,
}
verifyDeepLink ( dl , expectedTimeSelection , expectedTimeSeriesFilter )
} )
} )
Convey ( "and range is 23 hours" , func ( ) {
@ -184,6 +293,23 @@ func TestCloudMonitoring(t *testing.T) {
queries , err := executor . buildQueries ( tsdbQuery )
So ( err , ShouldBeNil )
So ( queries [ 0 ] . Params [ "aggregation.alignmentPeriod" ] [ 0 ] , ShouldEqual , ` +300s ` )
Convey ( "and generated deep link has correct parameters" , func ( ) {
// assign resource type to query parameters to be included in the deep link filter
// in the actual workflow this information comes from the response of the Monitoring API
queries [ 0 ] . Params . Set ( "resourceType" , "a/resource/type" )
dl := queries [ 0 ] . buildDeepLink ( )
expectedTimeSelection := map [ string ] string {
"timeRange" : "custom" ,
"start" : "2018-09-27T07:49:27Z" ,
"end" : "2018-09-28T06:49:27Z" ,
}
expectedTimeSeriesFilter := map [ string ] interface { } {
"minAlignmentPeriod" : ` 300s ` ,
}
verifyDeepLink ( dl , expectedTimeSelection , expectedTimeSeriesFilter )
} )
} )
Convey ( "and range is 7 days" , func ( ) {
@ -197,6 +323,23 @@ func TestCloudMonitoring(t *testing.T) {
queries , err := executor . buildQueries ( tsdbQuery )
So ( err , ShouldBeNil )
So ( queries [ 0 ] . Params [ "aggregation.alignmentPeriod" ] [ 0 ] , ShouldEqual , ` +3600s ` )
Convey ( "and generated deep link has correct parameters" , func ( ) {
// assign resource type to query parameters to be included in the deep link filter
// in the actual workflow this information comes from the response of the Monitoring API
queries [ 0 ] . Params . Set ( "resourceType" , "a/resource/type" )
dl := queries [ 0 ] . buildDeepLink ( )
expectedTimeSelection := map [ string ] string {
"timeRange" : "custom" ,
"start" : "2018-09-27T08:18:44Z" ,
"end" : "2018-10-04T08:18:44Z" ,
}
expectedTimeSeriesFilter := map [ string ] interface { } {
"minAlignmentPeriod" : ` 3600s ` ,
}
verifyDeepLink ( dl , expectedTimeSelection , expectedTimeSeriesFilter )
} )
} )
} )
@ -210,6 +353,23 @@ func TestCloudMonitoring(t *testing.T) {
queries , err := executor . buildQueries ( tsdbQuery )
So ( err , ShouldBeNil )
So ( queries [ 0 ] . Params [ "aggregation.alignmentPeriod" ] [ 0 ] , ShouldEqual , ` +600s ` )
Convey ( "and generated deep link has correct parameters" , func ( ) {
// assign resource type to query parameters to be included in the deep link filter
// in the actual workflow this information comes from the response of the Monitoring API
queries [ 0 ] . Params . Set ( "resourceType" , "a/resource/type" )
dl := queries [ 0 ] . buildDeepLink ( )
expectedTimeSelection := map [ string ] string {
"timeRange" : "custom" ,
"start" : "2018-03-15T13:00:00Z" ,
"end" : "2018-03-15T13:34:00Z" ,
}
expectedTimeSeriesFilter := map [ string ] interface { } {
"minAlignmentPeriod" : ` 600s ` ,
}
verifyDeepLink ( dl , expectedTimeSelection , expectedTimeSeriesFilter )
} )
} )
} )
@ -234,6 +394,26 @@ func TestCloudMonitoring(t *testing.T) {
So ( queries [ 0 ] . Params [ "aggregation.alignmentPeriod" ] [ 0 ] , ShouldEqual , "+60s" )
So ( queries [ 0 ] . Params [ "filter" ] [ 0 ] , ShouldEqual , "metric.type=\"a/metric/type\"" )
So ( queries [ 0 ] . Params [ "view" ] [ 0 ] , ShouldEqual , "FULL" )
Convey ( "and generated deep link has correct parameters" , func ( ) {
// assign resource type to query parameters to be included in the deep link filter
// in the actual workflow this information comes from the response of the Monitoring API
queries [ 0 ] . Params . Set ( "resourceType" , "a/resource/type" )
dl := queries [ 0 ] . buildDeepLink ( )
expectedTimeSelection := map [ string ] string {
"timeRange" : "custom" ,
"start" : "2018-03-15T13:00:00Z" ,
"end" : "2018-03-15T13:34:00Z" ,
}
expectedTimeSeriesFilter := map [ string ] interface { } {
"minAlignmentPeriod" : ` 60s ` ,
"crossSeriesReducer" : "REDUCE_SUM" ,
"perSeriesAligner" : "ALIGN_MEAN" ,
"filter" : "resource.type=\"a/resource/type\" metric.type=\"a/metric/type\"" ,
}
verifyDeepLink ( dl , expectedTimeSelection , expectedTimeSeriesFilter )
} )
} )
Convey ( "and query has group bys" , func ( ) {
@ -258,6 +438,26 @@ func TestCloudMonitoring(t *testing.T) {
So ( queries [ 0 ] . Params [ "aggregation.groupByFields" ] [ 1 ] , ShouldEqual , "metric.label.group2" )
So ( queries [ 0 ] . Params [ "filter" ] [ 0 ] , ShouldEqual , "metric.type=\"a/metric/type\"" )
So ( queries [ 0 ] . Params [ "view" ] [ 0 ] , ShouldEqual , "FULL" )
Convey ( "and generated deep link has correct parameters" , func ( ) {
// assign resource type to query parameters to be included in the deep link filter
// in the actual workflow this information comes from the response of the Monitoring API
queries [ 0 ] . Params . Set ( "resourceType" , "a/resource/type" )
dl := queries [ 0 ] . buildDeepLink ( )
expectedTimeSelection := map [ string ] string {
"timeRange" : "custom" ,
"start" : "2018-03-15T13:00:00Z" ,
"end" : "2018-03-15T13:34:00Z" ,
}
expectedTimeSeriesFilter := map [ string ] interface { } {
"minAlignmentPeriod" : ` 60s ` ,
"perSeriesAligner" : "ALIGN_MEAN" ,
"filter" : "resource.type=\"a/resource/type\" metric.type=\"a/metric/type\"" ,
"groupByFields" : [ ] interface { } { "metric.label.group1" , "metric.label.group2" } ,
}
verifyDeepLink ( dl , expectedTimeSelection , expectedTimeSeriesFilter )
} )
} )
} )
@ -303,6 +503,26 @@ func TestCloudMonitoring(t *testing.T) {
So ( queries [ 0 ] . Params [ "view" ] [ 0 ] , ShouldEqual , "FULL" )
So ( queries [ 0 ] . AliasBy , ShouldEqual , "testalias" )
So ( queries [ 0 ] . GroupBys , ShouldResemble , [ ] string { "metric.label.group1" , "metric.label.group2" } )
Convey ( "and generated deep link has correct parameters" , func ( ) {
// assign resource type to query parameters to be included in the deep link filter
// in the actual workflow this information comes from the response of the Monitoring API
queries [ 0 ] . Params . Set ( "resourceType" , "a/resource/type" )
dl := queries [ 0 ] . buildDeepLink ( )
expectedTimeSelection := map [ string ] string {
"timeRange" : "custom" ,
"start" : "2018-03-15T13:00:00Z" ,
"end" : "2018-03-15T13:34:00Z" ,
}
expectedTimeSeriesFilter := map [ string ] interface { } {
"minAlignmentPeriod" : ` 60s ` ,
"perSeriesAligner" : "ALIGN_MEAN" ,
"filter" : "resource.type=\"a/resource/type\" metric.type=\"a/metric/type\"" ,
"groupByFields" : [ ] interface { } { "metric.label.group1" , "metric.label.group2" } ,
}
verifyDeepLink ( dl , expectedTimeSelection , expectedTimeSeriesFilter )
} )
} )
Convey ( "and query type is SLOs" , func ( ) {
@ -351,6 +571,11 @@ func TestCloudMonitoring(t *testing.T) {
queries , err := executor . buildQueries ( tsdbQuery )
So ( err , ShouldBeNil )
So ( queries [ 0 ] . Params [ "aggregation.perSeriesAligner" ] [ 0 ] , ShouldEqual , "ALIGN_NEXT_OLDER" )
Convey ( "and empty deep link" , func ( ) {
dl := queries [ 0 ] . buildDeepLink ( )
So ( dl , ShouldBeEmpty )
} )
} )
} )
} )
@ -774,3 +999,58 @@ func loadTestFile(path string) (cloudMonitoringResponse, error) {
err = json . Unmarshal ( jsonBody , & data )
return data , err
}
func verifyDeepLink ( dl string , expectedTimeSelection map [ string ] string , expectedTimeSeriesFilter map [ string ] interface { } ) {
u , err := url . Parse ( dl )
So ( err , ShouldBeNil )
So ( u . Scheme , ShouldEqual , "https" )
So ( u . Host , ShouldEqual , "accounts.google.com" )
So ( u . Path , ShouldEqual , "/AccountChooser" )
params , err := url . ParseQuery ( u . RawQuery )
So ( err , ShouldBeNil )
continueParam := params . Get ( "continue" )
So ( continueParam , ShouldNotBeEmpty )
u , err = url . Parse ( continueParam )
So ( err , ShouldBeNil )
params , err = url . ParseQuery ( u . RawQuery )
So ( err , ShouldBeNil )
pageStateStr := params . Get ( "pageState" )
So ( pageStateStr , ShouldNotBeEmpty )
var pageState map [ string ] map [ string ] interface { }
err = json . Unmarshal ( [ ] byte ( pageStateStr ) , & pageState )
So ( err , ShouldBeNil )
timeSelection , ok := pageState [ "timeSelection" ]
So ( ok , ShouldBeTrue )
for k , v := range expectedTimeSelection {
s , ok := timeSelection [ k ] . ( string )
So ( ok , ShouldBeTrue )
So ( s , ShouldEqual , v )
}
dataSets , ok := pageState [ "xyChart" ] [ "dataSets" ] . ( [ ] interface { } )
So ( ok , ShouldBeTrue )
So ( len ( dataSets ) , ShouldEqual , 1 )
dataSet , ok := dataSets [ 0 ] . ( map [ string ] interface { } )
So ( ok , ShouldBeTrue )
i , ok := dataSet [ "timeSeriesFilter" ]
So ( ok , ShouldBeTrue )
timeSeriesFilter := i . ( map [ string ] interface { } )
for k , v := range expectedTimeSeriesFilter {
s , ok := timeSeriesFilter [ k ]
So ( ok , ShouldBeTrue )
rt := reflect . TypeOf ( v )
switch rt . Kind ( ) {
case reflect . Slice , reflect . Array :
So ( s , ShouldResemble , v )
default :
So ( s , ShouldEqual , v )
}
}
}