mirror of
https://github.com/grafana/grafana.git
synced 2024-11-26 02:40:26 -06:00
feat(plugins): major improvement in plugins golang code
This commit is contained in:
parent
35f40b7312
commit
1ffcea1952
38
pkg/plugins/app_plugin.go
Normal file
38
pkg/plugins/app_plugin.go
Normal file
@ -0,0 +1,38 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
type AppPluginPage struct {
|
||||
Text string `json:"text"`
|
||||
Icon string `json:"icon"`
|
||||
Url string `json:"url"`
|
||||
ReqRole models.RoleType `json:"reqRole"`
|
||||
}
|
||||
|
||||
type AppPluginCss struct {
|
||||
Light string `json:"light"`
|
||||
Dark string `json:"dark"`
|
||||
}
|
||||
|
||||
type AppPlugin struct {
|
||||
FrontendPluginBase
|
||||
Enabled bool `json:"enabled"`
|
||||
Pinned bool `json:"pinned"`
|
||||
Css *AppPluginCss `json:"css"`
|
||||
Page *AppPluginPage `json:"page"`
|
||||
}
|
||||
|
||||
func (p *AppPlugin) Load(decoder *json.Decoder, pluginDir string) error {
|
||||
if err := decoder.Decode(&p); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.PluginDir = pluginDir
|
||||
p.initFrontendPlugin()
|
||||
Apps[p.Id] = p
|
||||
return nil
|
||||
}
|
25
pkg/plugins/datasource_plugin.go
Normal file
25
pkg/plugins/datasource_plugin.go
Normal file
@ -0,0 +1,25 @@
|
||||
package plugins
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type DataSourcePlugin struct {
|
||||
FrontendPluginBase
|
||||
DefaultMatchFormat string `json:"defaultMatchFormat"`
|
||||
Annotations bool `json:"annotations"`
|
||||
Metrics bool `json:"metrics"`
|
||||
BuiltIn bool `json:"builtIn"`
|
||||
Mixed bool `json:"mixed"`
|
||||
App string `json:"app"`
|
||||
}
|
||||
|
||||
func (p *DataSourcePlugin) Load(decoder *json.Decoder, pluginDir string) error {
|
||||
if err := decoder.Decode(&p); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.PluginDir = pluginDir
|
||||
p.initFrontendPlugin()
|
||||
DataSources[p.Id] = p
|
||||
|
||||
return nil
|
||||
}
|
47
pkg/plugins/frontend_plugin.go
Normal file
47
pkg/plugins/frontend_plugin.go
Normal file
@ -0,0 +1,47 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"path"
|
||||
)
|
||||
|
||||
type FrontendPluginBase struct {
|
||||
PluginBase
|
||||
Module string `json:"module"`
|
||||
StaticRoot string `json:"staticRoot"`
|
||||
}
|
||||
|
||||
func (fp *FrontendPluginBase) initFrontendPlugin() {
|
||||
if fp.StaticRoot != "" {
|
||||
StaticRoutes = append(StaticRoutes, &PluginStaticRoute{
|
||||
Directory: fp.StaticRoot,
|
||||
PluginId: fp.Id,
|
||||
})
|
||||
}
|
||||
|
||||
fp.Info.Logos.Small = evalRelativePluginUrlPath(fp.Info.Logos.Small, fp.Id)
|
||||
fp.Info.Logos.Large = evalRelativePluginUrlPath(fp.Info.Logos.Large, fp.Id)
|
||||
|
||||
fp.handleModuleDefaults()
|
||||
}
|
||||
|
||||
func (fp *FrontendPluginBase) handleModuleDefaults() {
|
||||
if fp.Module != "" {
|
||||
return
|
||||
}
|
||||
|
||||
if fp.StaticRoot != "" {
|
||||
fp.Module = path.Join("plugins", fp.Type, fp.Id, "module")
|
||||
return
|
||||
}
|
||||
|
||||
fp.Module = path.Join("app/plugins", fp.Type, fp.Id, "module")
|
||||
}
|
||||
|
||||
func evalRelativePluginUrlPath(pathStr string, pluginId string) string {
|
||||
u, _ := url.Parse(pathStr)
|
||||
if u.IsAbs() {
|
||||
return pathStr
|
||||
}
|
||||
return path.Join("public/plugins", pluginId, pathStr)
|
||||
}
|
@ -1,15 +1,22 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
type PluginCommon struct {
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Id string `json:"id"`
|
||||
StaticRoot string `json:"staticRoot"`
|
||||
Info PluginInfo `json:"info"`
|
||||
type PluginLoader interface {
|
||||
Load(decoder *json.Decoder, pluginDir string) error
|
||||
}
|
||||
|
||||
type PluginBase struct {
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Id string `json:"id"`
|
||||
App string `json:"app"`
|
||||
Info PluginInfo `json:"info"`
|
||||
PluginDir string `json:"-"`
|
||||
}
|
||||
|
||||
type PluginInfo struct {
|
||||
@ -29,30 +36,11 @@ type PluginLogos struct {
|
||||
Large string `json:"large"`
|
||||
}
|
||||
|
||||
type DataSourcePlugin struct {
|
||||
PluginCommon
|
||||
Module string `json:"module"`
|
||||
ServiceName string `json:"serviceName"`
|
||||
Partials map[string]interface{} `json:"partials"`
|
||||
DefaultMatchFormat string `json:"defaultMatchFormat"`
|
||||
Annotations bool `json:"annotations"`
|
||||
Metrics bool `json:"metrics"`
|
||||
BuiltIn bool `json:"builtIn"`
|
||||
Mixed bool `json:"mixed"`
|
||||
App string `json:"app"`
|
||||
}
|
||||
|
||||
type PluginStaticRoute struct {
|
||||
Directory string
|
||||
PluginId string
|
||||
}
|
||||
|
||||
type PanelPlugin struct {
|
||||
PluginCommon
|
||||
Module string `json:"module"`
|
||||
App string `json:"app"`
|
||||
}
|
||||
|
||||
type ApiPluginRoute struct {
|
||||
Path string `json:"path"`
|
||||
Method string `json:"method"`
|
||||
@ -60,34 +48,11 @@ type ApiPluginRoute struct {
|
||||
ReqGrafanaAdmin bool `json:"reqGrafanaAdmin"`
|
||||
ReqRole models.RoleType `json:"reqRole"`
|
||||
Url string `json:"url"`
|
||||
App string `json:"app"`
|
||||
}
|
||||
|
||||
type AppPluginPage struct {
|
||||
Text string `json:"text"`
|
||||
Icon string `json:"icon"`
|
||||
Url string `json:"url"`
|
||||
ReqRole models.RoleType `json:"reqRole"`
|
||||
}
|
||||
|
||||
type AppPluginCss struct {
|
||||
Light string `json:"light"`
|
||||
Dark string `json:"dark"`
|
||||
}
|
||||
|
||||
type ApiPlugin struct {
|
||||
PluginCommon
|
||||
PluginBase
|
||||
Routes []*ApiPluginRoute `json:"routes"`
|
||||
App string `json:"app"`
|
||||
}
|
||||
|
||||
type AppPlugin struct {
|
||||
PluginCommon
|
||||
Enabled bool `json:"enabled"`
|
||||
Pinned bool `json:"pinned"`
|
||||
Module string `json:"module"`
|
||||
Css *AppPluginCss `json:"css"`
|
||||
Page *AppPluginPage `json:"page"`
|
||||
}
|
||||
|
||||
type EnabledPlugins struct {
|
||||
|
19
pkg/plugins/panel_plugin.go
Normal file
19
pkg/plugins/panel_plugin.go
Normal file
@ -0,0 +1,19 @@
|
||||
package plugins
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type PanelPlugin struct {
|
||||
FrontendPluginBase
|
||||
}
|
||||
|
||||
func (p *PanelPlugin) Load(decoder *json.Decoder, pluginDir string) error {
|
||||
if err := decoder.Decode(&p); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.PluginDir = pluginDir
|
||||
p.initFrontendPlugin()
|
||||
Panels[p.Id] = p
|
||||
|
||||
return nil
|
||||
}
|
@ -5,10 +5,10 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
@ -24,6 +24,7 @@ var (
|
||||
ApiPlugins map[string]*ApiPlugin
|
||||
StaticRoutes []*PluginStaticRoute
|
||||
Apps map[string]*AppPlugin
|
||||
PluginTypes map[string]interface{}
|
||||
)
|
||||
|
||||
type PluginScanner struct {
|
||||
@ -37,6 +38,12 @@ func Init() error {
|
||||
StaticRoutes = make([]*PluginStaticRoute, 0)
|
||||
Panels = make(map[string]*PanelPlugin)
|
||||
Apps = make(map[string]*AppPlugin)
|
||||
PluginTypes = map[string]interface{}{
|
||||
"panel": PanelPlugin{},
|
||||
"datasource": DataSourcePlugin{},
|
||||
"api": ApiPlugin{},
|
||||
"app": AppPlugin{},
|
||||
}
|
||||
|
||||
scan(path.Join(setting.StaticRootPath, "app/plugins"))
|
||||
checkPluginPaths()
|
||||
@ -115,27 +122,7 @@ func (scanner *PluginScanner) walker(currentPath string, f os.FileInfo, err erro
|
||||
return nil
|
||||
}
|
||||
|
||||
func evalRelativePluginUrlPath(pathStr string, pluginId string) string {
|
||||
u, _ := url.Parse(pathStr)
|
||||
if u.IsAbs() {
|
||||
return pathStr
|
||||
}
|
||||
return path.Join("public/plugins", pluginId, pathStr)
|
||||
}
|
||||
|
||||
func addPublicContent(plugin *PluginCommon, currentDir string) {
|
||||
if plugin.StaticRoot != "" {
|
||||
StaticRoutes = append(StaticRoutes, &PluginStaticRoute{
|
||||
Directory: path.Join(currentDir, plugin.StaticRoot),
|
||||
PluginId: plugin.Id,
|
||||
})
|
||||
}
|
||||
|
||||
plugin.Info.Logos.Small = evalRelativePluginUrlPath(plugin.Info.Logos.Small, plugin.Id)
|
||||
plugin.Info.Logos.Large = evalRelativePluginUrlPath(plugin.Info.Logos.Large, plugin.Id)
|
||||
}
|
||||
|
||||
func interpolatePluginJson(reader io.Reader, pluginCommon *PluginCommon) (io.Reader, error) {
|
||||
func interpolatePluginJson(reader io.Reader, pluginCommon *PluginBase) (io.Reader, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.ReadFrom(reader)
|
||||
jsonStr := buf.String() //
|
||||
@ -167,7 +154,7 @@ func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error {
|
||||
defer reader.Close()
|
||||
|
||||
jsonParser := json.NewDecoder(reader)
|
||||
pluginCommon := PluginCommon{}
|
||||
pluginCommon := PluginBase{}
|
||||
if err := jsonParser.Decode(&pluginCommon); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -177,52 +164,21 @@ func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error {
|
||||
}
|
||||
|
||||
reader.Seek(0, 0)
|
||||
|
||||
if newReader, err := interpolatePluginJson(reader, &pluginCommon); err != nil {
|
||||
return err
|
||||
} else {
|
||||
jsonParser = json.NewDecoder(newReader)
|
||||
}
|
||||
|
||||
switch pluginCommon.Type {
|
||||
case "datasource":
|
||||
p := DataSourcePlugin{}
|
||||
if err := jsonParser.Decode(&p); err != nil {
|
||||
return err
|
||||
}
|
||||
var loader PluginLoader
|
||||
|
||||
DataSources[p.Id] = &p
|
||||
addPublicContent(&p.PluginCommon, currentDir)
|
||||
|
||||
case "panel":
|
||||
p := PanelPlugin{}
|
||||
reader.Seek(0, 0)
|
||||
if err := jsonParser.Decode(&p); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Panels[p.Id] = &p
|
||||
addPublicContent(&p.PluginCommon, currentDir)
|
||||
case "api":
|
||||
p := ApiPlugin{}
|
||||
reader.Seek(0, 0)
|
||||
if err := jsonParser.Decode(&p); err != nil {
|
||||
return err
|
||||
}
|
||||
ApiPlugins[p.Id] = &p
|
||||
case "app":
|
||||
p := AppPlugin{}
|
||||
reader.Seek(0, 0)
|
||||
if err := jsonParser.Decode(&p); err != nil {
|
||||
return err
|
||||
}
|
||||
Apps[p.Id] = &p
|
||||
addPublicContent(&p.PluginCommon, currentDir)
|
||||
default:
|
||||
if pluginGoType, exists := PluginTypes[pluginCommon.Type]; !exists {
|
||||
return errors.New("Unkown plugin type " + pluginCommon.Type)
|
||||
} else {
|
||||
loader = reflect.New(reflect.TypeOf(pluginGoType)).Interface().(PluginLoader)
|
||||
}
|
||||
|
||||
return nil
|
||||
return loader.Load(jsonParser, currentDir)
|
||||
}
|
||||
|
||||
func GetEnabledPlugins(orgApps []*models.AppPlugin) EnabledPlugins {
|
||||
|
@ -19,6 +19,10 @@ func TestPluginScans(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
So(len(DataSources), ShouldBeGreaterThan, 1)
|
||||
So(len(Panels), ShouldBeGreaterThan, 1)
|
||||
|
||||
Convey("Should set module automatically", func() {
|
||||
So(DataSources["graphite"].Module, ShouldEqual, "app/plugins/datasource/graphite/module")
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When reading app plugin definition", t, func() {
|
||||
|
@ -3,13 +3,6 @@
|
||||
"name": "CloudWatch",
|
||||
"id": "cloudwatch",
|
||||
|
||||
"module": "app/plugins/datasource/cloudwatch/module",
|
||||
|
||||
"partials": {
|
||||
"config": "app/plugins/datasource/cloudwatch/partials/config.html",
|
||||
"query": "app/plugins/datasource/cloudwatch/partials/query.editor.html"
|
||||
},
|
||||
|
||||
"metrics": true,
|
||||
"annotations": true
|
||||
}
|
||||
|
@ -3,8 +3,6 @@
|
||||
"name": "Elasticsearch",
|
||||
"id": "elasticsearch",
|
||||
|
||||
"module": "app/plugins/datasource/elasticsearch/module",
|
||||
|
||||
"defaultMatchFormat": "lucene",
|
||||
"annotations": true,
|
||||
"metrics": true
|
||||
|
@ -3,8 +3,6 @@
|
||||
"name": "Grafana",
|
||||
"id": "grafana",
|
||||
|
||||
"module": "app/plugins/datasource/grafana/module",
|
||||
|
||||
"builtIn": true,
|
||||
"metrics": true
|
||||
}
|
||||
|
@ -19,6 +19,10 @@ function (angular, GraphiteDatasource) {
|
||||
return {templateUrl: 'app/plugins/datasource/graphite/partials/annotations.editor.html'};
|
||||
});
|
||||
|
||||
module.directive('datasourceCustomSettingsViewGraphite', function() {
|
||||
return {templateUrl: 'app/plugins/datasource/graphite/partials/config.html'};
|
||||
});
|
||||
|
||||
return {
|
||||
Datasource: GraphiteDatasource,
|
||||
};
|
||||
|
@ -3,8 +3,6 @@
|
||||
"type": "datasource",
|
||||
"id": "graphite",
|
||||
|
||||
"module": "app/plugins/datasource/graphite/module",
|
||||
|
||||
"defaultMatchFormat": "glob",
|
||||
"metrics": true,
|
||||
"annotations": true
|
||||
|
@ -3,8 +3,6 @@
|
||||
"name": "InfluxDB 0.9.x",
|
||||
"id": "influxdb",
|
||||
|
||||
"module": "app/plugins/datasource/influxdb/module",
|
||||
|
||||
"defaultMatchFormat": "regex values",
|
||||
"metrics": true,
|
||||
"annotations": true
|
||||
|
@ -5,9 +5,5 @@
|
||||
|
||||
"builtIn": true,
|
||||
"mixed": true,
|
||||
|
||||
"serviceName": "MixedDatasource",
|
||||
|
||||
"module": "app/plugins/datasource/mixed/datasource",
|
||||
"metrics": true
|
||||
}
|
||||
|
@ -3,8 +3,6 @@
|
||||
"name": "OpenTSDB",
|
||||
"id": "opentsdb",
|
||||
|
||||
"module": "app/plugins/datasource/opentsdb/module",
|
||||
|
||||
"metrics": true,
|
||||
"defaultMatchFormat": "pipe"
|
||||
}
|
||||
|
3
public/app/plugins/datasource/prometheus/datasource.d.ts
vendored
Normal file
3
public/app/plugins/datasource/prometheus/datasource.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
declare var Datasource: any;
|
||||
export default Datasource;
|
||||
|
@ -3,31 +3,25 @@ define([
|
||||
'lodash',
|
||||
'moment',
|
||||
'app/core/utils/datemath',
|
||||
'./directives',
|
||||
'./query_ctrl',
|
||||
],
|
||||
function (angular, _, moment, dateMath) {
|
||||
'use strict';
|
||||
|
||||
var module = angular.module('grafana.services');
|
||||
|
||||
var durationSplitRegexp = /(\d+)(ms|s|m|h|d|w|M|y)/;
|
||||
|
||||
module.factory('PrometheusDatasource', function($q, backendSrv, templateSrv) {
|
||||
function PrometheusDatasource(instanceSettings, $q, backendSrv, templateSrv) {
|
||||
this.type = 'prometheus';
|
||||
this.editorSrc = 'app/features/prometheus/partials/query.editor.html';
|
||||
this.name = instanceSettings.name;
|
||||
this.supportMetrics = true;
|
||||
this.url = instanceSettings.url;
|
||||
this.directUrl = instanceSettings.directUrl;
|
||||
this.basicAuth = instanceSettings.basicAuth;
|
||||
this.withCredentials = instanceSettings.withCredentials;
|
||||
this.lastErrors = {};
|
||||
|
||||
function PrometheusDatasource(datasource) {
|
||||
this.type = 'prometheus';
|
||||
this.editorSrc = 'app/features/prometheus/partials/query.editor.html';
|
||||
this.name = datasource.name;
|
||||
this.supportMetrics = true;
|
||||
this.url = datasource.url;
|
||||
this.directUrl = datasource.directUrl;
|
||||
this.basicAuth = datasource.basicAuth;
|
||||
this.withCredentials = datasource.withCredentials;
|
||||
this.lastErrors = {};
|
||||
}
|
||||
|
||||
PrometheusDatasource.prototype._request = function(method, url) {
|
||||
this._request = function(method, url) {
|
||||
var options = {
|
||||
url: this.url + url,
|
||||
method: method
|
||||
@ -46,7 +40,7 @@ function (angular, _, moment, dateMath) {
|
||||
};
|
||||
|
||||
// Called once per panel (graph)
|
||||
PrometheusDatasource.prototype.query = function(options) {
|
||||
this.query = function(options) {
|
||||
var start = getPrometheusTime(options.range.from, false);
|
||||
var end = getPrometheusTime(options.range.to, true);
|
||||
|
||||
@ -86,31 +80,31 @@ function (angular, _, moment, dateMath) {
|
||||
|
||||
var self = this;
|
||||
return $q.all(allQueryPromise)
|
||||
.then(function(allResponse) {
|
||||
var result = [];
|
||||
.then(function(allResponse) {
|
||||
var result = [];
|
||||
|
||||
_.each(allResponse, function(response, index) {
|
||||
if (response.status === 'error') {
|
||||
self.lastErrors.query = response.error;
|
||||
throw response.error;
|
||||
}
|
||||
delete self.lastErrors.query;
|
||||
_.each(allResponse, function(response, index) {
|
||||
if (response.status === 'error') {
|
||||
self.lastErrors.query = response.error;
|
||||
throw response.error;
|
||||
}
|
||||
delete self.lastErrors.query;
|
||||
|
||||
_.each(response.data.data.result, function(metricData) {
|
||||
result.push(transformMetricData(metricData, options.targets[index]));
|
||||
});
|
||||
_.each(response.data.data.result, function(metricData) {
|
||||
result.push(transformMetricData(metricData, options.targets[index]));
|
||||
});
|
||||
|
||||
return { data: result };
|
||||
});
|
||||
|
||||
return { data: result };
|
||||
});
|
||||
};
|
||||
|
||||
PrometheusDatasource.prototype.performTimeSeriesQuery = function(query, start, end) {
|
||||
this.performTimeSeriesQuery = function(query, start, end) {
|
||||
var url = '/api/v1/query_range?query=' + encodeURIComponent(query.expr) + '&start=' + start + '&end=' + end + '&step=' + query.step;
|
||||
return this._request('GET', url);
|
||||
};
|
||||
|
||||
PrometheusDatasource.prototype.performSuggestQuery = function(query) {
|
||||
this.performSuggestQuery = function(query) {
|
||||
var url = '/api/v1/label/__name__/values';
|
||||
|
||||
return this._request('GET', url).then(function(result) {
|
||||
@ -120,7 +114,7 @@ function (angular, _, moment, dateMath) {
|
||||
});
|
||||
};
|
||||
|
||||
PrometheusDatasource.prototype.metricFindQuery = function(query) {
|
||||
this.metricFindQuery = function(query) {
|
||||
if (!query) { return $q.when([]); }
|
||||
|
||||
var interpolated;
|
||||
@ -196,7 +190,7 @@ function (angular, _, moment, dateMath) {
|
||||
}
|
||||
};
|
||||
|
||||
PrometheusDatasource.prototype.testDatasource = function() {
|
||||
this.testDatasource = function() {
|
||||
return this.metricFindQuery('metrics(.*)').then(function() {
|
||||
return { status: 'success', message: 'Data source is working', title: 'Success' };
|
||||
});
|
||||
@ -276,8 +270,7 @@ function (angular, _, moment, dateMath) {
|
||||
}
|
||||
return (date.valueOf() / 1000).toFixed(0);
|
||||
}
|
||||
}
|
||||
|
||||
return PrometheusDatasource;
|
||||
});
|
||||
|
||||
return PrometheusDatasource;
|
||||
});
|
||||
|
@ -1,7 +1,8 @@
|
||||
define([
|
||||
'angular',
|
||||
'./datasource',
|
||||
],
|
||||
function (angular) {
|
||||
function (angular, PromDatasource) {
|
||||
'use strict';
|
||||
|
||||
var module = angular.module('grafana.directives');
|
||||
@ -10,4 +11,11 @@ function (angular) {
|
||||
return {controller: 'PrometheusQueryCtrl', templateUrl: 'app/plugins/datasource/prometheus/partials/query.editor.html'};
|
||||
});
|
||||
|
||||
module.directive('datasourceCustomSettingsViewPrometheus', function() {
|
||||
return {templateUrl: 'app/plugins/datasource/prometheus/partials/config.html'};
|
||||
});
|
||||
|
||||
return {
|
||||
Datasource: PromDatasource
|
||||
};
|
||||
});
|
@ -3,13 +3,5 @@
|
||||
"name": "Prometheus",
|
||||
"id": "prometheus",
|
||||
|
||||
"serviceName": "PrometheusDatasource",
|
||||
|
||||
"module": "app/plugins/datasource/prometheus/datasource",
|
||||
|
||||
"partials": {
|
||||
"config": "app/plugins/datasource/prometheus/partials/config.html"
|
||||
},
|
||||
|
||||
"metrics": true
|
||||
}
|
||||
|
@ -1,17 +1,20 @@
|
||||
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';
|
||||
|
||||
describe('PrometheusDatasource', function() {
|
||||
|
||||
var ctx = new helpers.ServiceTestContext();
|
||||
var instanceSettings = {url: 'proxied', directUrl: 'direct', user: 'test', password: 'mupp' };
|
||||
|
||||
beforeEach(angularMocks.module('grafana.core'));
|
||||
beforeEach(angularMocks.module('grafana.services'));
|
||||
beforeEach(ctx.createService('PrometheusDatasource'));
|
||||
beforeEach(function() {
|
||||
ctx.ds = new ctx.service({ url: 'proxied', directUrl: 'direct', user: 'test', password: 'mupp' });
|
||||
});
|
||||
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 querying prometheus with one target using query editor target spec', function() {
|
||||
var results;
|
||||
|
Loading…
Reference in New Issue
Block a user