Commit 109dd324 by Torkel Ödegaard

Work on new datasource plugin model, #1276 #1472

parent c1982422
...@@ -27,6 +27,7 @@ func Register(r *macaron.Macaron) { ...@@ -27,6 +27,7 @@ func Register(r *macaron.Macaron) {
r.Get("/profile/", reqSignedIn, Index) r.Get("/profile/", reqSignedIn, Index)
r.Get("/org/", reqSignedIn, Index) r.Get("/org/", reqSignedIn, Index)
r.Get("/datasources/", reqSignedIn, Index) r.Get("/datasources/", reqSignedIn, Index)
r.Get("/datasources/edit/*", reqSignedIn, Index)
r.Get("/org/users/", reqSignedIn, Index) r.Get("/org/users/", reqSignedIn, Index)
r.Get("/org/apikeys/", reqSignedIn, Index) r.Get("/org/apikeys/", reqSignedIn, Index)
r.Get("/dashboard/import/", reqSignedIn, Index) r.Get("/dashboard/import/", reqSignedIn, Index)
...@@ -75,6 +76,7 @@ func Register(r *macaron.Macaron) { ...@@ -75,6 +76,7 @@ func Register(r *macaron.Macaron) {
r.Combo("/").Get(GetDataSources).Put(AddDataSource).Post(UpdateDataSource) r.Combo("/").Get(GetDataSources).Put(AddDataSource).Post(UpdateDataSource)
r.Delete("/:id", DeleteDataSource) r.Delete("/:id", DeleteDataSource)
r.Get("/:id", GetDataSourceById) r.Get("/:id", GetDataSourceById)
r.Get("/plugins", GetDataSourcePlugins)
}, reqAccountAdmin) }, reqAccountAdmin)
r.Get("/frontend/settings/", GetFrontendSettings) r.Get("/frontend/settings/", GetFrontendSettings)
......
...@@ -21,12 +21,12 @@ func NewReverseProxy(ds *m.DataSource, proxyPath string) *httputil.ReverseProxy ...@@ -21,12 +21,12 @@ func NewReverseProxy(ds *m.DataSource, proxyPath string) *httputil.ReverseProxy
reqQueryVals := req.URL.Query() reqQueryVals := req.URL.Query()
if ds.Type == m.DS_INFLUXDB { if ds.Type == m.DS_INFLUXDB_08 {
req.URL.Path = util.JoinUrlFragments(target.Path, "db/"+ds.Database+"/"+proxyPath) req.URL.Path = util.JoinUrlFragments(target.Path, "db/"+ds.Database+"/"+proxyPath)
reqQueryVals.Add("u", ds.User) reqQueryVals.Add("u", ds.User)
reqQueryVals.Add("p", ds.Password) reqQueryVals.Add("p", ds.Password)
req.URL.RawQuery = reqQueryVals.Encode() req.URL.RawQuery = reqQueryVals.Encode()
} else if ds.Type == m.DS_INFLUXDB_08 { } else if ds.Type == m.DS_INFLUXDB {
req.URL.Path = util.JoinUrlFragments(target.Path, proxyPath) req.URL.Path = util.JoinUrlFragments(target.Path, proxyPath)
reqQueryVals.Add("db", ds.Database) reqQueryVals.Add("db", ds.Database)
reqQueryVals.Add("u", ds.User) reqQueryVals.Add("u", ds.User)
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/middleware" "github.com/grafana/grafana/pkg/middleware"
m "github.com/grafana/grafana/pkg/models" m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
) )
func GetDataSources(c *middleware.Context) { func GetDataSources(c *middleware.Context) {
...@@ -118,3 +119,7 @@ func UpdateDataSource(c *middleware.Context) { ...@@ -118,3 +119,7 @@ func UpdateDataSource(c *middleware.Context) {
c.JsonOK("Datasource updated") c.JsonOK("Datasource updated")
} }
func GetDataSourcePlugins(c *middleware.Context) {
c.JSON(200, plugins.DataSources)
}
...@@ -15,7 +15,7 @@ define([ ...@@ -15,7 +15,7 @@ define([
'extend-jquery', 'extend-jquery',
'bindonce', 'bindonce',
], ],
function (angular, $, _, appLevelRequire, config) { function (angular, $, _, appLevelRequire) {
"use strict"; "use strict";
......
...@@ -6,8 +6,9 @@ function (angular) { ...@@ -6,8 +6,9 @@ function (angular) {
'use strict'; 'use strict';
var module = angular.module('grafana.controllers'); var module = angular.module('grafana.controllers');
var datasourceTypes = [];
module.controller('DataSourceEditCtrl', function($scope, $http, backendSrv, $routeParams, $location, datasourceSrv) { module.controller('DataSourceEditCtrl', function($scope, $q, backendSrv, $routeParams, $location, datasourceSrv) {
var defaults = { var defaults = {
name: '', name: '',
...@@ -16,32 +17,44 @@ function (angular) { ...@@ -16,32 +17,44 @@ function (angular) {
access: 'proxy' access: 'proxy'
}; };
$scope.types = [
{ name: 'Graphite', type: 'graphite' },
{ name: 'InfluxDB 0.9.x (Experimental support)', type: 'influxdb' },
{ name: 'InfluxDB 0.8.x', type: 'influxdb_08' },
{ name: 'Elasticsearch', type: 'elasticsearch' },
{ name: 'OpenTSDB', type: 'opentsdb' },
];
$scope.init = function() { $scope.init = function() {
$scope.isNew = true; $scope.isNew = true;
$scope.datasources = []; $scope.datasources = [];
if ($routeParams.id) { $scope.loadDatasourceTypes().then(function() {
$scope.isNew = false; if ($routeParams.id) {
$scope.getDatasourceById($routeParams.id); $scope.isNew = false;
} else { $scope.getDatasourceById($routeParams.id);
$scope.current = angular.copy(defaults); } else {
$scope.current = angular.copy(defaults);
$scope.typeChanged();
}
});
};
$scope.loadDatasourceTypes = function() {
if (datasourceTypes.length > 0) {
$scope.types = datasourceTypes;
return $q.when(null);
} }
return backendSrv.get('/api/datasources/plugins').then(function(plugins) {
datasourceTypes = plugins;
$scope.types = plugins;
});
}; };
$scope.getDatasourceById = function(id) { $scope.getDatasourceById = function(id) {
backendSrv.get('/api/datasources/' + id).then(function(ds) { backendSrv.get('/api/datasources/' + id).then(function(ds) {
$scope.current = ds; $scope.current = ds;
$scope.typeChanged();
}); });
}; };
$scope.typeChanged = function() {
$scope.datasourceMeta = $scope.types[$scope.current.type];
};
$scope.updateFrontendSettings = function() { $scope.updateFrontendSettings = function() {
backendSrv.get('/api/frontend/settings').then(function(settings) { backendSrv.get('/api/frontend/settings').then(function(settings) {
datasourceSrv.init(settings.datasources); datasourceSrv.init(settings.datasources);
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
</div> </div>
<div class="editor-option"> <div class="editor-option">
<label class="small">Type</label> <label class="small">Type</label>
<select class="input-large" ng-model="current.type" ng-options="f.type as f.name for f in types" ng-change="typeChanged()"></select> <select class="input-large" ng-model="current.type" ng-options="k as v.name for (k, v) in types" ng-change="typeChanged()"></select>
</div> </div>
<editor-opt-bool text="Mark as default" model="current.isDefault" change="render()"></editor-opt-bool> <editor-opt-bool text="Mark as default" model="current.isDefault" change="render()"></editor-opt-bool>
</div> </div>
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
<div class="editor-row"> <div class="editor-row">
<div class="editor-option"> <div class="editor-option">
<label class="small">Url</label> <label class="small">Url</label>
<input type="text" class="input-xxlarge" ng-model='current.url' placeholder="http://my.graphite.com:8080" required></input> <input type="text" style="width: 450px" ng-model='current.url' placeholder="http://my.graphite.com:8080" required></input>
</div> </div>
<div class="editor-option"> <div class="editor-option">
<label class="small">Access method <tip>Direct = url is used directly from browser, Proxy = Grafana backend will proxy the request</label> <label class="small">Access method <tip>Direct = url is used directly from browser, Proxy = Grafana backend will proxy the request</label>
...@@ -35,33 +35,7 @@ ...@@ -35,33 +35,7 @@
</div> </div>
</div> </div>
<div class="editor-row" ng-if="current.type === 'influxdb'"> <div ng-include="datasourceMeta.partials.config" ng-if="datasourceMeta.partials.config"></div>
<div class="section">
<h5>InfluxDB Details</h5>
<div class="editor-option">
<label class="small">Database name</label>
<input type="text" class="input-large" required ng-model='current.database' placeholder=""></input>
</div>
<div class="editor-option">
<label class="small">User</label>
<input type="text" class="input-large" ng-model='current.user' placeholder=""></input>
</div>
<div class="editor-option">
<label class="small">Password</label>
<input type="password" class="input-large" ng-model='current.password' placeholder=""></input>
</div>
</div>
</div>
<div class="editor-row" ng-if="current.type === 'elasticsearch'">
<div class="section">
<h5>Elastic search details</h5>
<div class="editor-option">
<label class="small">Index name</label>
<input type="text" class="input-large" required ng-model='current.database' placeholder=""></input>
</div>
</div>
</div>
<br> <br>
......
...@@ -57,7 +57,6 @@ function (angular, _, config) { ...@@ -57,7 +57,6 @@ function (angular, _, config) {
$scope.setDatasource = function(datasource) { $scope.setDatasource = function(datasource) {
$scope.panel.datasource = datasource; $scope.panel.datasource = datasource;
debugger;
datasourceSrv.get(datasource).then(function(ds) { datasourceSrv.get(datasource).then(function(ds) {
$scope.datasource = ds; $scope.datasource = ds;
}); });
......
...@@ -2,10 +2,16 @@ ...@@ -2,10 +2,16 @@
<div class="editor-row" style="margin-top: 30px"> <div class="editor-row" style="margin-top: 30px">
<button class="btn btn-success pull-right" ng-click="addDataQuery(panel.target)">Add query</button> <button class="btn btn-inverse pull-right" ng-click="addDataQuery(panel.target)">
<i class="fa fa-plus"></i>&nbsp;
Add query
</button>
<div class="btn-group pull-right" style="margin-right: 10px;"> <div class="btn-group pull-right" style="margin-right: 10px;">
<button class="btn btn-info dropdown-toggle" data-toggle="dropdown" bs-tooltip="'Datasource'">{{datasource.name}} <span class="caret"></span></button> <button class="btn btn-inverse dropdown-toggle" data-toggle="dropdown" bs-tooltip="'Datasource'">
<i class="fa fa-database"></i>&nbsp;
{{datasource.name}} <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu"> <ul class="dropdown-menu" role="menu">
<li ng-repeat="datasource in datasources" role="menuitem"> <li ng-repeat="datasource in datasources" role="menuitem">
......
<div class="editor-row">
<div class="section">
<h5>Elastic search details</h5>
<div class="editor-option">
<label class="small">Index name</label>
<input type="text" class="input-large" required ng-model='current.database' placeholder=""></input>
</div>
</div>
</div>
{
"pluginType": "datasource",
"name": "Elasticsearch",
"type": "elasticsearch",
"serviceName": "ElasticDatasource",
"module": "plugins/datasource/elasticsearch/datasource",
"partials": {
"config": "app/plugins/datasource/elasticsearch/partials/config.html",
"annotations": "app/plugins/datasource/elasticsearch/partials/query.editor.html"
},
"annotations": true
}
{ {
"pluginType": "datasource", "pluginType": "datasource",
"description": "Graphite", "name": "Graphite",
"type": "graphite", "type": "graphite",
"serviceName": "GraphiteDatasource", "serviceName": "GraphiteDatasource",
"module": "plugins/datasources/graphite/datasource", "module": "plugins/datasource/graphite/datasource",
"partials": { "partials": {
"config": "app/plugins/datasources/graphite/partials/config.html", "config": "app/plugins/datasource/graphite/partials/config.html",
"query": "app/plugins/datasources/graphite/partials/query.editor.html", "query": "app/plugins/datasource/graphite/partials/query.editor.html",
"annotations": "app/plugins/datasources/graphite/partials/query.editor.html" "annotations": "app/plugins/datasource/graphite/partials/query.editor.html"
}, },
"metrics": true, "metrics": true,
......
<div class="editor-row">
<div class="section">
<h5>InfluxDB Details</h5>
<div class="editor-option">
<label class="small">Database name</label>
<input type="text" class="input-medium" required ng-model='current.database' placeholder=""></input>
</div>
<div class="editor-option">
<label class="small">User</label>
<input type="text" class="input-medium" ng-model='current.user' placeholder=""></input>
</div>
<div class="editor-option">
<label class="small">Password</label>
<input type="password" class="input-medium" ng-model='current.password' placeholder=""></input>
</div>
</div>
</div>
<div class="editor-row"> <div class="editor-row">
<div ng-repeat="target in panel.targets" ng-controller="InfluxQueryCtrl" ng-init="init()" ng-class="{'tight-form-disabled': target.hide}" class="tight-form-container"> <div ng-repeat="target in panel.targets" ng-controller="InfluxQueryCtrl_08" ng-init="init()" ng-class="{'tight-form-disabled': target.hide}" class="tight-form-container">
<div class="tight-form"> <div class="tight-form">
<ul class="tight-form-list pull-right"> <ul class="tight-form-list pull-right">
<li class="tight-form-item"> <li class="tight-form-item">
......
{ {
"pluginType": "datasource", "pluginType": "datasource",
"description": "InfluxDB 0.8.x", "name": "InfluxDB 0.8.x",
"type": "influxdb_08", "type": "influxdb_08",
"serviceName": "InfluxDatasource08", "serviceName": "InfluxDatasource_08",
"module": "plugins/datasources/influxdb_08/datasource", "module": "plugins/datasource/influxdb_08/datasource",
"partials": { "partials": {
"config": "app/plugins/datasources/influxdb_08/partials/config.html", "config": "app/plugins/datasource/influxdb_08/partials/config.html",
"query": "app/plugins/datasources/influxdb_08/partials/query.editor.html", "query": "app/plugins/datasource/influxdb_08/partials/query.editor.html",
"annotations": "app/plugins/datasources/influxdb_08/partials/query.editor.html" "annotations": "app/plugins/datasource/influxdb_08/partials/query.editor.html"
}, },
"metrics": true, "metrics": true,
......
...@@ -9,7 +9,7 @@ function (angular, _) { ...@@ -9,7 +9,7 @@ function (angular, _) {
var seriesList = null; var seriesList = null;
module.controller('InfluxQueryCtrl', function($scope, $timeout) { module.controller('InfluxQueryCtrl_08', function($scope, $timeout) {
$scope.init = function() { $scope.init = function() {
var target = $scope.target; var target = $scope.target;
......
...@@ -11,14 +11,15 @@ function (angular, _, config) { ...@@ -11,14 +11,15 @@ function (angular, _, config) {
module.service('datasourceSrv', function($q, $injector, $rootScope) { module.service('datasourceSrv', function($q, $injector, $rootScope) {
var self = this; var self = this;
this.datasources = {};
this.metricSources = [];
this.annotationSources = [];
this.grafanaDB = new ($injector.get("GrafanaDatasource")); this.grafanaDB = new ($injector.get("GrafanaDatasource"));
this.init = function(dsSettingList) { this.init = function(dsSettingList) {
config.datasources = dsSettingList; config.datasources = dsSettingList;
this.datasources = {};
this.metricSources = [];
this.annotationSources = [];
_.each(config.datasources, function(value, key) { _.each(config.datasources, function(value, key) {
if (value.meta && value.meta.metrics) { if (value.meta && value.meta.metrics) {
self.metricSources.push({ value: key, name: key }); self.metricSources.push({ value: key, name: key });
......
define([ define([
'features/graphite/gfunc' 'plugins/datasource/graphite/gfunc'
], function(gfunc) { ], function(gfunc) {
'use strict'; 'use strict';
......
define([ define([
'helpers', 'helpers',
'features/graphite/datasource' 'plugins/datasource/graphite/datasource'
], function(helpers) { ], function(helpers) {
'use strict'; 'use strict';
......
define([ define([
'helpers', 'helpers',
'features/graphite/gfunc', 'plugins/datasource/graphite/gfunc',
'features/graphite/queryCtrl' 'plugins/datasource/graphite/queryCtrl'
], function(helpers, gfunc) { ], function(helpers, gfunc) {
'use strict'; 'use strict';
......
define([ define([
'features/graphite/lexer' 'plugins/datasource/graphite/lexer'
], function(Lexer) { ], function(Lexer) {
'use strict'; 'use strict';
......
define([ define([
'features/graphite/parser' 'plugins/datasource/graphite/parser'
], function(Parser) { ], function(Parser) {
'use strict'; 'use strict';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment