diff --git a/src/app/controllers/dashLoader.js b/src/app/controllers/dashLoader.js index dc29006bcdc..9349c5cf00b 100644 --- a/src/app/controllers/dashLoader.js +++ b/src/app/controllers/dashLoader.js @@ -2,16 +2,18 @@ define([ 'angular', 'underscore', 'moment', + 'config', 'filesaver' ], -function (angular, _, moment) { +function (angular, _, moment, config) { 'use strict'; var module = angular.module('grafana.controllers'); - module.controller('dashLoader', function($scope, $rootScope, $http, alertSrv, $location, playlistSrv, elastic) { + module.controller('dashLoader', function($scope, $rootScope, $http, alertSrv, $location, playlistSrv, datasourceSrv) { $scope.init = function() { + $scope.db = datasourceSrv.getGrafanaDB(); $scope.onAppEvent('save-dashboard', function() { $scope.saveDashboard(); }); @@ -19,7 +21,6 @@ function (angular, _, moment) { $scope.onAppEvent('zoom-out', function() { $scope.zoom(2); }); - }; $scope.exitFullscreen = function() { @@ -38,6 +39,9 @@ function (angular, _, moment) { if(type === 'save') { return (_l.save_elasticsearch); } + if(type === 'share') { + return (_l.save_temp); + } return false; }; @@ -52,7 +56,7 @@ function (angular, _, moment) { }; $scope.saveForSharing = function() { - elastic.saveForSharing($scope.dashboard) + $scope.db.saveDashboardTemp($scope.dashboard) .then(function(result) { $scope.share = { url: result.url, title: result.title }; @@ -62,10 +66,32 @@ function (angular, _, moment) { }); }; + $scope.passwordCache = function(pwd) { + if (!window.sessionStorage) { return null; } + if (!pwd) { return window.sessionStorage["grafanaAdminPassword"]; } + window.sessionStorage["grafanaAdminPassword"] = pwd; + }; + + $scope.isAdmin = function() { + if (!config.admin || !config.admin.password) { return true; } + if (this.passwordCache() === config.admin.password) { return true; } + + var password = window.prompt("Admin password", ""); + this.passwordCache(password); + + if (password === config.admin.password) { return true; } + + alertSrv.set('Save failed', 'Password incorrect', 'error'); + + return false; + }; + $scope.saveDashboard = function() { - elastic.saveDashboard($scope.dashboard, $scope.dashboard.title) + if (!this.isAdmin()) { return false; } + + $scope.db.saveDashboard($scope.dashboard, $scope.dashboard.title) .then(function(result) { - alertSrv.set('Dashboard Saved', 'Dashboard has been saved to Elasticsearch as "' + result.title + '"','success', 5000); + alertSrv.set('Dashboard Saved', 'Dashboard has been saved as "' + result.title + '"','success', 5000); $location.path(result.url); @@ -81,7 +107,9 @@ function (angular, _, moment) { return; } - elastic.deleteDashboard(id).then(function(id) { + if (!this.isAdmin()) { return false; } + + $scope.db.deleteDashboard(id).then(function(id) { alertSrv.set('Dashboard Deleted', id + ' has been deleted', 'success', 5000); }, function() { alertSrv.set('Dashboard Not Deleted', 'An error occurred deleting the dashboard', 'error', 5000); diff --git a/src/app/controllers/graphiteImport.js b/src/app/controllers/graphiteImport.js index de30ef64711..bb38eaffb45 100644 --- a/src/app/controllers/graphiteImport.js +++ b/src/app/controllers/graphiteImport.js @@ -11,8 +11,7 @@ function (angular, app, _) { module.controller('GraphiteImportCtrl', function($scope, $rootScope, $timeout, datasourceSrv) { $scope.init = function() { - console.log('hej!'); - $scope.datasources = datasourceSrv.listOptions(); + $scope.datasources = datasourceSrv.getMetricSources(); $scope.setDatasource(null); }; @@ -96,7 +95,8 @@ function (angular, app, _) { currentRow.panels.push(panel); }); - $scope.dashboard.dash_load(newDashboard); + $scope.emitAppEvent('setup-dashboard', newDashboard); + $scope.dismiss(); } }); diff --git a/src/app/controllers/search.js b/src/app/controllers/search.js index f88e9e0c079..1ecd544b289 100644 --- a/src/app/controllers/search.js +++ b/src/app/controllers/search.js @@ -9,13 +9,14 @@ function (angular, _, config, $) { var module = angular.module('grafana.controllers'); - module.controller('SearchCtrl', function($scope, $rootScope, $element, $location, elastic) { + module.controller('SearchCtrl', function($scope, $rootScope, $element, $location, datasourceSrv) { $scope.init = function() { $scope.giveSearchFocus = 0; $scope.selectedIndex = -1; $scope.results = {dashboards: [], tags: [], metrics: []}; $scope.query = { query: 'title:' }; + $scope.db = datasourceSrv.getGrafanaDB(); $scope.onAppEvent('open-search', $scope.openSearch); }; @@ -57,40 +58,12 @@ function (angular, _, config, $) { }; }; - $scope.searchDasboards = function(queryString) { - var tagsOnly = queryString.indexOf('tags!:') === 0; - if (tagsOnly) { - var tagsQuery = queryString.substring(6, queryString.length); - queryString = 'tags:' + tagsQuery + '*'; - } - else { - if (queryString.length === 0) { - queryString = 'title:'; - } - - if (queryString[queryString.length - 1] !== '*') { - queryString += '*'; - } - } - - var query = { - query: { query_string: { query: queryString } }, - facets: { tags: { terms: { field: "tags", order: "term", size: 50 } } }, - size: 20, - sort: ["_uid"] - }; - - return elastic.post('/dashboard/_search', query) + $scope.searchDashboards = function(queryString) { + return $scope.db.searchDashboards(queryString) .then(function(results) { - if(_.isUndefined(results.hits)) { - $scope.results.dashboards = []; - $scope.results.tags = []; - return; - } - - $scope.tagsOnly = tagsOnly; - $scope.results.dashboards = results.hits.hits; - $scope.results.tags = results.facets.tags.terms; + $scope.tagsOnly = results.dashboards.length === 0 && results.tags.length > 0; + $scope.results.dashboards = results.dashboards; + $scope.results.tags = results.tags; }); }; @@ -118,12 +91,9 @@ function (angular, _, config, $) { $scope.selectedIndex = -1; var queryStr = $scope.query.query.toLowerCase(); + queryStr = queryStr.replace(' and ', ' AND '); - if (queryStr.indexOf('m:') !== 0) { - queryStr = queryStr.replace(' and ', ' AND '); - $scope.searchDasboards(queryStr); - return; - } + $scope.searchDashboards(queryStr); }; $scope.openSearch = function (evt) { @@ -177,4 +147,4 @@ function (angular, _, config, $) { }; }); -}); \ No newline at end of file +}); diff --git a/src/app/partials/dashLoader.html b/src/app/partials/dashLoader.html index 6544924f90e..c13227b07fe 100644 --- a/src/app/partials/dashLoader.html +++ b/src/app/partials/dashLoader.html @@ -47,8 +47,11 @@
  • Export dashboard
  • -
  • Share temp copy
  • - +
  • + + Share temp copy + +
  • diff --git a/src/app/partials/dasheditor.html b/src/app/partials/dasheditor.html index db6343470d0..50284aac4b4 100644 --- a/src/app/partials/dasheditor.html +++ b/src/app/partials/dasheditor.html @@ -2,7 +2,7 @@
    Dashboard settings
    -
    +
    @@ -111,11 +111,7 @@
    -
    - -
    - -
    +
    diff --git a/src/app/routes/dashboard-from-es.js b/src/app/routes/dashboard-from-es.js index 280776efa3b..f2d8ce85fb5 100644 --- a/src/app/routes/dashboard-from-es.js +++ b/src/app/routes/dashboard-from-es.js @@ -1,9 +1,7 @@ define([ 'angular', - 'jquery', - 'config' ], -function (angular, $, config) { +function (angular) { "use strict"; var module = angular.module('grafana.routes'); @@ -20,37 +18,15 @@ function (angular, $, config) { }); }); - module.controller('DashFromElasticProvider', function($scope, $rootScope, elastic, $routeParams, alertSrv) { + module.controller('DashFromElasticProvider', function($scope, $rootScope, datasourceSrv, $routeParams, alertSrv) { - var elasticsearch_load = function(id) { - var url = '/dashboard/' + id; - - // hack to check if it is a temp dashboard - if (window.location.href.indexOf('dashboard/temp') > 0) { - url = '/temp/' + id; - } - - return elastic.get(url) - .then(function(result) { - if (result._source && result._source.dashboard) { - return angular.fromJson(result._source.dashboard); - } else { - return false; - } - }, function(data, status) { - if(status === 0) { - alertSrv.set('Error',"Could not contact Elasticsearch at " + - config.elasticsearch + ". Please ensure that Elasticsearch is reachable from your browser.",'error'); - } else { - alertSrv.set('Error',"Could not find dashboard " + id, 'error'); - } - return false; - }); - }; - - elasticsearch_load($routeParams.id).then(function(dashboard) { - $scope.emitAppEvent('setup-dashboard', dashboard); - }); + var db = datasourceSrv.getGrafanaDB(); + db.getDashboard($routeParams.id) + .then(function(dashboard) { + $scope.emitAppEvent('setup-dashboard', dashboard); + }).then(null, function(error) { + alertSrv.set('Error', error, 'error'); + }); }); diff --git a/src/app/services/all.js b/src/app/services/all.js index b426088bd11..7f00219dbca 100644 --- a/src/app/services/all.js +++ b/src/app/services/all.js @@ -8,8 +8,7 @@ define([ './annotationsSrv', './playlistSrv', './unsavedChangesSrv', - './elasticsearch/es-client', './dashboard/dashboardKeyBindings', './dashboard/dashboardModel', ], -function () {}); \ No newline at end of file +function () {}); diff --git a/src/app/services/datasourceSrv.js b/src/app/services/datasourceSrv.js index 705230515f8..97cf10cb6f9 100644 --- a/src/app/services/datasourceSrv.js +++ b/src/app/services/datasourceSrv.js @@ -16,6 +16,7 @@ function (angular, _, config) { var datasources = {}; var metricSources = []; var annotationSources = []; + var grafanaDB = {}; this.init = function() { _.each(config.datasources, function(value, key) { @@ -44,6 +45,9 @@ function (angular, _, config) { editorSrc: value.annotationEditorSrc, }); } + if (value.grafanaDB) { + grafanaDB = value; + } }); }; @@ -82,6 +86,10 @@ function (angular, _, config) { return metricSources; }; + this.getGrafanaDB = function() { + return grafanaDB; + }; + this.init(); }); }); diff --git a/src/app/services/elasticsearch/es-client.js b/src/app/services/elasticsearch/es-client.js deleted file mode 100644 index 5898bf8743f..00000000000 --- a/src/app/services/elasticsearch/es-client.js +++ /dev/null @@ -1,116 +0,0 @@ -define([ - 'angular', - 'config' -], -function(angular, config) { - "use strict"; - - var module = angular.module('grafana.services'); - - module.service('elastic', function($http, $q) { - - this._request = function(method, url, data) { - var options = { - url: config.elasticsearch + "/" + config.grafana_index + url, - method: method, - data: data - }; - - if (config.elasticsearchBasicAuth) { - options.headers = { - "Authorization": "Basic " + config.elasticsearchBasicAuth - }; - } - - return $http(options); - }; - - this.get = function(url) { - return this._request('GET', url) - .then(function(results) { - return results.data; - }); - }; - - this.post = function(url, data) { - return this._request('POST', url, data) - .then(function(results) { - return results.data; - }); - }; - - this.deleteDashboard = function(id) { - if (!this.isAdmin()) { return $q.reject("Invalid admin password"); } - - return this._request('DELETE', '/dashboard/' + id) - .then(function(result) { - return result.data._id; - }, function(err) { - throw err.data; - }); - }; - - this.saveForSharing = function(dashboard) { - var data = { - user: 'guest', - group: 'guest', - title: dashboard.title, - tags: dashboard.tags, - dashboard: angular.toJson(dashboard) - }; - - var ttl = dashboard.loader.save_temp_ttl; - - return this._request('POST', '/temp/?ttl=' + ttl, data) - .then(function(result) { - - var baseUrl = window.location.href.replace(window.location.hash,''); - var url = baseUrl + "#dashboard/temp/" + result.data._id; - - return { title: dashboard.title, url: url }; - - }, function(err) { - throw "Failed to save to temp dashboard to elasticsearch " + err.data; - }); - }; - - this.passwordCache = function(pwd) { - if (!window.sessionStorage) { return null; } - if (!pwd) { return window.sessionStorage["grafanaAdminPassword"]; } - window.sessionStorage["grafanaAdminPassword"] = pwd; - }; - - this.isAdmin = function() { - if (!config.admin || !config.admin.password) { return true; } - if (this.passwordCache() === config.admin.password) { return true; } - - var password = window.prompt("Admin password", ""); - this.passwordCache(password); - - return password === config.admin.password; - }; - - this.saveDashboard = function(dashboard, title) { - if (!this.isAdmin()) { return $q.reject("Invalid admin password"); } - - var dashboardClone = angular.copy(dashboard); - title = dashboardClone.title = title ? title : dashboard.title; - - var data = { - user: 'guest', - group: 'guest', - title: title, - tags: dashboardClone.tags, - dashboard: angular.toJson(dashboardClone) - }; - - return this._request('PUT', '/dashboard/' + encodeURIComponent(title), data) - .then(function() { - return { title: title, url: '/dashboard/elasticsearch/' + title }; - }, function(err) { - throw 'Failed to save to elasticsearch ' + err.data; - }); - }; - - }); -}); diff --git a/src/app/services/elasticsearch/es-datasource.js b/src/app/services/elasticsearch/es-datasource.js index 29291e029f3..1303bdd042e 100644 --- a/src/app/services/elasticsearch/es-datasource.js +++ b/src/app/services/elasticsearch/es-datasource.js @@ -21,16 +21,17 @@ function (angular, _, $, config, kbn, moment) { this.supportAnnotations = true; this.supportMetrics = false; this.index = datasource.index; + this.grafanaDB = datasource.grafanaDB; this.annotationEditorSrc = 'app/partials/elasticsearch/annotation_editor.html'; } - ElasticDatasource.prototype._request = function(method, url, data) { + ElasticDatasource.prototype._request = function(method, url, index, data) { var options = { - url: this.url + "/" + this.index + url, + url: this.url + "/" + index + url, method: method, data: data }; - + // TODO: fix basic auth if (config.elasticsearchBasicAuth) { options.headers = { "Authorization": "Basic " + config.elasticsearchBasicAuth @@ -41,14 +42,14 @@ function (angular, _, $, config, kbn, moment) { }; ElasticDatasource.prototype._get = function(url) { - return this._request('GET', url) + return this._request('GET', url, this.index) .then(function(results) { return results.data; }); }; ElasticDatasource.prototype._post = function(url, data) { - return this._request('POST', url, data) + return this._request('POST', url, this.index, data) .then(function(results) { return results.data; }); @@ -71,9 +72,7 @@ function (angular, _, $, config, kbn, moment) { var query = { "bool": { "should": [{ "query_string": { "query": queryString } }] } }; var data = { "query" : { "filtered": { "query" : query, "filter": filter } }, "size": 100 }; - this.index = annotation.index; - - return this._request('POST', '/_search', data).then(function(results) { + return this._request('POST', '/_search', annotation.index, data).then(function(results) { var list = []; var hits = results.data.hits.hits; @@ -103,6 +102,116 @@ function (angular, _, $, config, kbn, moment) { }); }; + ElasticDatasource.prototype.getDashboard = function(id) { + var url = '/dashboard/' + id; + + // hack to check if it is a temp dashboard + if (window.location.href.indexOf('dashboard/temp') > 0) { + url = '/temp/' + id; + } + + return this._get(url) + .then(function(result) { + if (result._source && result._source.dashboard) { + return angular.fromJson(result._source.dashboard); + } else { + return false; + } + }, function(data, status) { + if(status === 0) { + throw "Could not contact Elasticsearch. Please ensure that Elasticsearch is reachable from your browser."; + } else { + throw "Could not find dashboard " + id; + } + }); + }; + + ElasticDatasource.prototype.saveDashboard = function(dashboard, title) { + var dashboardClone = angular.copy(dashboard); + title = dashboardClone.title = title ? title : dashboard.title; + + var data = { + user: 'guest', + group: 'guest', + title: title, + tags: dashboardClone.tags, + dashboard: angular.toJson(dashboardClone) + }; + + return this._request('PUT', '/dashboard/' + encodeURIComponent(title), this.index, data) + .then(function() { + return { title: title, url: '/dashboard/elasticsearch/' + title }; + }, function(err) { + throw 'Failed to save to elasticsearch ' + err.data; + }); + }; + + ElasticDatasource.prototype.saveDashboardTemp = function(dashboard) { + var data = { + user: 'guest', + group: 'guest', + title: dashboard.title, + tags: dashboard.tags, + dashboard: angular.toJson(dashboard) + }; + + var ttl = dashboard.loader.save_temp_ttl; + + return this._request('POST', '/temp/?ttl=' + ttl, this.index, data) + .then(function(result) { + + var baseUrl = window.location.href.replace(window.location.hash,''); + var url = baseUrl + "#dashboard/temp/" + result.data._id; + + return { title: dashboard.title, url: url }; + + }, function(err) { + throw "Failed to save to temp dashboard to elasticsearch " + err.data; + }); + }; + + ElasticDatasource.prototype.deleteDashboard = function(id) { + return this._request('DELETE', '/dashboard/' + id, this.index) + .then(function(result) { + return result.data._id; + }, function(err) { + throw err.data; + }); + }; + + ElasticDatasource.prototype.searchDashboards = function(queryString) { + var tagsOnly = queryString.indexOf('tags!:') === 0; + if (tagsOnly) { + var tagsQuery = queryString.substring(6, queryString.length); + queryString = 'tags:' + tagsQuery + '*'; + } + else { + if (queryString.length === 0) { + queryString = 'title:'; + } + + if (queryString[queryString.length - 1] !== '*') { + queryString += '*'; + } + } + + var query = { + query: { query_string: { query: queryString } }, + facets: { tags: { terms: { field: "tags", order: "term", size: 50 } } }, + size: 20, + sort: ["_uid"] + }; + + return this._post('/dashboard/_search', query) + .then(function(results) { + if(_.isUndefined(results.hits)) { + return { dashboards: [], tags: [] }; + } + + return { dashboards: results.hits.hits, tags: results.facets.terms }; + }); + }; + return ElasticDatasource; });