From e2f6633d57624664654463578e8d2502bfd7ffef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 1 Jun 2015 12:15:49 +0200 Subject: [PATCH] Began work on data source test / validation, #1997 & #2043 --- CHANGELOG.md | 1 + pkg/api/api.go | 7 ++- pkg/api/datasources.go | 4 +- pkg/models/datasource.go | 2 +- public/app/features/org/datasourceEditCtrl.js | 46 +++++++++++++------ .../features/org/partials/datasourceEdit.html | 21 +++++++-- .../plugins/datasource/graphite/datasource.js | 16 +++++++ public/css/less/overrides.less | 45 +++++++++--------- 8 files changed, 95 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed6265738ef..f03c7f34891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ - [Issue #1928](https://github.com/grafana/grafana/issues/1928). HTTP API: GET /api/dashboards/db/:slug response changed property `model` to `dashboard` to match the POST request nameing - Backend render URL changed from `/render/dashboard/solo` `render/dashboard-solo/` (in order to have consistent dashboard url `/dashboard/:type/:slug`) - Search HTTP API response has changed (simplified), tags list moved to seperate HTTP resource URI +- Datasource HTTP api breaking change, ADD datasource is now POST /api/datasources/, update is now PUT /api/datasources/:id # 2.0.3 (unreleased - 2.0.x branch) diff --git a/pkg/api/api.go b/pkg/api/api.go index f5da406a8a5..6ecaa51652e 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -107,10 +107,9 @@ func Register(r *macaron.Macaron) { // Data sources r.Group("/datasources", func() { - r.Combo("/"). - Get(GetDataSources). - Put(bind(m.AddDataSourceCommand{}), AddDataSource). - Post(bind(m.UpdateDataSourceCommand{}), UpdateDataSource) + r.Get("/", GetDataSources) + r.Post("/", bind(m.AddDataSourceCommand{}), AddDataSource) + r.Put("/:id", bind(m.UpdateDataSourceCommand{}), UpdateDataSource) r.Delete("/:id", DeleteDataSource) r.Get("/:id", GetDataSourceById) r.Get("/plugins", GetDataSourcePlugins) diff --git a/pkg/api/datasources.go b/pkg/api/datasources.go index 76a9bddd253..e0253df3cdb 100644 --- a/pkg/api/datasources.go +++ b/pkg/api/datasources.go @@ -6,6 +6,7 @@ import ( "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/plugins" + "github.com/grafana/grafana/pkg/util" ) func GetDataSources(c *middleware.Context) { @@ -94,11 +95,12 @@ func AddDataSource(c *middleware.Context, cmd m.AddDataSourceCommand) { return } - c.JsonOK("Datasource added") + c.JSON(200, util.DynMap{"message": "Datasource added", "id": cmd.Result.Id}) } func UpdateDataSource(c *middleware.Context, cmd m.UpdateDataSourceCommand) { cmd.OrgId = c.OrgId + cmd.Id = c.ParamsInt64(":id") err := bus.Dispatch(&cmd) if err != nil { diff --git a/pkg/models/datasource.go b/pkg/models/datasource.go index 2ba236cd56b..c756faaba59 100644 --- a/pkg/models/datasource.go +++ b/pkg/models/datasource.go @@ -69,7 +69,6 @@ type AddDataSourceCommand struct { // Also acts as api DTO type UpdateDataSourceCommand struct { - Id int64 `json:"id" binding:"Required"` Name string `json:"name" binding:"Required"` Type string `json:"type" binding:"Required"` Access DsAccess `json:"access" binding:"Required"` @@ -84,6 +83,7 @@ type UpdateDataSourceCommand struct { JsonData map[string]interface{} `json:"jsonData"` OrgId int64 `json:"-"` + Id int64 `json:"-"` } type DeleteDataSourceCommand struct { diff --git a/public/app/features/org/datasourceEditCtrl.js b/public/app/features/org/datasourceEditCtrl.js index 780aee3e843..12d552c985b 100644 --- a/public/app/features/org/datasourceEditCtrl.js +++ b/public/app/features/org/datasourceEditCtrl.js @@ -25,7 +25,6 @@ function (angular, config) { $scope.loadDatasourceTypes().then(function() { if ($routeParams.id) { - $scope.isNew = false; $scope.getDatasourceById($routeParams.id); } else { $scope.current = angular.copy(defaults); @@ -48,6 +47,7 @@ function (angular, config) { $scope.getDatasourceById = function(id) { backendSrv.get('/api/datasources/' + id).then(function(ds) { + $scope.isNew = false; $scope.current = ds; $scope.typeChanged(); }); @@ -65,26 +65,46 @@ function (angular, config) { }); }; - $scope.update = function() { - if (!$scope.editForm.$valid) { - return; - } + $scope.testDatasource = function() { + $scope.testing = { done: false }; - backendSrv.post('/api/datasources', $scope.current).then(function() { - $scope.updateFrontendSettings(); - $location.path("datasources"); + datasourceSrv.get($scope.current.name).then(function(datasource) { + if (!datasource.testDatasource) { + $scope.testing.message = 'Data source does not support test connection feature.'; + $scope.testing.status = 'warning'; + $scope.testing.title = 'Unknown'; + return; + } + return datasource.testDatasource().then(function(result) { + $scope.testing.message = result.message; + $scope.testing.status = result.status; + $scope.testing.title = result.title; + }); + }).finally(function() { + $scope.testing.done = true; }); }; - $scope.add = function() { + $scope.saveChanges = function(test) { if (!$scope.editForm.$valid) { return; } - backendSrv.put('/api/datasources', $scope.current).then(function() { - $scope.updateFrontendSettings(); - $location.path("datasources"); - }); + if ($scope.current.id) { + return backendSrv.put('/api/datasources/' + $scope.current.id, $scope.current).then(function() { + $scope.updateFrontendSettings(); + if (test) { + $scope.testDatasource(); + } else { + $location.path('datasources'); + } + }); + } else { + return backendSrv.post('/api/datasources', $scope.current).then(function(result) { + $scope.updateFrontendSettings(); + $location.path('datasources/edit/' + result.id); + }); + } }; $scope.init(); diff --git a/public/app/features/org/partials/datasourceEdit.html b/public/app/features/org/partials/datasourceEdit.html index 12b46ee284b..6ea33e5a43c 100644 --- a/public/app/features/org/partials/datasourceEdit.html +++ b/public/app/features/org/partials/datasourceEdit.html @@ -43,11 +43,22 @@
-
-
-
- - + +
+
Testing....
+
Test results
+
+
{{testing.title}}
+
+
+
+ +
+ + + Cancel

diff --git a/public/app/plugins/datasource/graphite/datasource.js b/public/app/plugins/datasource/graphite/datasource.js index 9315b5a5b33..ff06d9f46aa 100644 --- a/public/app/plugins/datasource/graphite/datasource.js +++ b/public/app/plugins/datasource/graphite/datasource.js @@ -196,6 +196,22 @@ function (angular, _, $, config, kbn, moment) { }); }; + GraphiteDatasource.prototype.testDatasource = function() { + return this.metricFindQuery('*').then(function () { + return { status: "success", message: "Data source is working", title: "Success" }; + }, function(err) { + var message, title; + if (err.statusText) { + message = err.statusText; + title = "HTTP Error"; + } else { + message = err; + title = "Unknown error"; + } + return { status: "error", message: message, title: title }; + }); + }; + GraphiteDatasource.prototype.listDashboards = function(query) { return this.doGraphiteRequest({ method: 'GET', url: '/dashboard/find/', params: {query: query || ''} }) .then(function(results) { diff --git a/public/css/less/overrides.less b/public/css/less/overrides.less index 425777f1597..b03cb7f7e6b 100644 --- a/public/css/less/overrides.less +++ b/public/css/less/overrides.less @@ -315,38 +315,37 @@ div.flot-text { position: fixed; right: 20px; top: 56px; +} - .alert { - color: @white; - padding-bottom: 13px; - position: relative; - } +.alert { + color: @white; + padding-bottom: 13px; + position: relative; +} - .alert-close { - position: absolute; - top: -4px; - right: -2px; - width: 19px; - height: 19px; - padding: 0; - background: @grayLighter; - border-radius: 50%; - border: none; - font-size: 1.1rem; - color: @grayDarker; - } +.alert-close { + position: absolute; + top: -4px; + right: -2px; + width: 19px; + height: 19px; + padding: 0; + background: @grayLighter; + border-radius: 50%; + border: none; + font-size: 1.1rem; + color: @grayDarker; +} - .alert-title { - font-weight: bold; - padding-bottom: 2px; - } +.alert-title { + font-weight: bold; + padding-bottom: 2px; } .alert-warning { background-color: @warningBackground; border-color: @warningBorder; - color: @warningText; } /* ===================================================