diff --git a/docs/Makefile b/docs/Makefile index 9fd8cd6399f..f24a63065b3 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -44,7 +44,7 @@ docs-test: docs-build $(DOCKER_RUN_DOCS) "$(DOCKER_DOCS_IMAGE)" ./test.sh docs-build: - git fetch https://github.com/grafana/grafana.git docs-2.1 && git diff --name-status FETCH_HEAD...HEAD -- . > changed-files + git fetch https://github.com/grafana/grafana.git docs-2.5 && git diff --name-status FETCH_HEAD...HEAD -- . > changed-files echo "$(GIT_BRANCH)" > GIT_BRANCH echo "$(GITCOMMIT)" > GITCOMMIT docker build -t "$(DOCKER_DOCS_IMAGE)" . diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 7bca7e2f01f..e4c3dd91b79 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -62,6 +62,7 @@ pages: - ['reference/templating.md', 'Reference', 'Templating'] - ['reference/scripting.md', 'Reference', 'Scripting'] - ['reference/playlist.md', 'Reference', 'Playlist'] +- ['reference/plugins.md', 'Reference', 'Plugins'] - ['reference/export_import.md', 'Reference', 'Import & Export'] - ['reference/admin.md', 'Reference', 'Administration'] - ['reference/http_api.md', 'Reference', 'HTTP API'] diff --git a/docs/sources/project/building_from_source.md b/docs/sources/project/building_from_source.md index 71e94b088fb..9535d4d0247 100644 --- a/docs/sources/project/building_from_source.md +++ b/docs/sources/project/building_from_source.md @@ -11,7 +11,7 @@ dev environment. Grafana ships with its own required backend server; also comple ## Dependencies -- [Go 1.4](https://golang.org/dl/) +- [Go 1.5](https://golang.org/dl/) - [NodeJS](https://nodejs.org/download/) ## Get Code @@ -54,7 +54,7 @@ bra run ## Running Grafana Locally You can run a local instance of Grafana by running: ``` -./bin/grafana-server +./bin/grafana-server ``` If you built the binary with `go run build.go build`, run `./bin/grafana-server` @@ -63,7 +63,7 @@ If you built it with `go build .`, run `./grafana` Open grafana in your browser (default [http://localhost:3000](http://localhost:3000)) and login with admin user (default user/pass = admin/admin). ## Developing for Grafana -To add features, customize your config, etc, you'll need to rebuild on source change (requires that you executed [godep restore](#build-the-backend), as outlined above). +To add features, customize your config, etc, you'll need to rebuild on source change (requires that you executed [godep restore](#build-the-backend), as outlined above). ``` go get github.com/Unknwon/bra bra run @@ -88,7 +88,7 @@ You only need to add the options you want to override. Config files are applied Learn more about Grafana config options in the [Configuration section](/installation/configuration/) ## Create a pull requests -Please contribute to the Grafana project and submit a pull request! Build new features, write or update documentation, fix bugs and generally make Grafana even more awesome. +Please contribute to the Grafana project and submit a pull request! Build new features, write or update documentation, fix bugs and generally make Grafana even more awesome. Before or after you create a pull request, sign the [contributor license agreement](/project/cla.html). -Together we can build amazing software faster. \ No newline at end of file +Together we can build amazing software faster. diff --git a/docs/sources/reference/plugins.md b/docs/sources/reference/plugins.md new file mode 100644 index 00000000000..8ed4e30853d --- /dev/null +++ b/docs/sources/reference/plugins.md @@ -0,0 +1,50 @@ +--- +page_title: Plugin guide +page_description: Plugin guide for Grafana +page_keywords: grafana, plugins, documentation +--- + +# Plugins + +!Plugin support for panels is only available in nightly! + +Adding support for all datasources and suggested panels would bloat grafana and make it impossible to maintain. That's why we implemented a plugin system that makes it possible for anyone to develop support for a datasource or custom panel without adding it to Grafana itself. + +## Installing plugins + +Installing a plugin is very simple. Just download it and place it in the Grafana plugins folder and restart grafana. + +The default plugin folder is configurable under paths.plugins + +It's also possible to add one specific plugin by linking to its folder. + +``` +[plugin.mirror] +path = /home/evil-queen/datasource-plugin-mirror +``` + +## Plugin implementation ## + +Each plugin is defined in plugin.json file in the plugin folder. + +Instead of massive documentation about how it works we created a reference implementation of a plugin. +You can find each reference implementation further down on this page. + +## Datasource plugins + +Datasource have three responsibilities. + + * UI for configuring its settings + * Datasource object that can send queries, metricqueries and healthcheck the datasource + * Query editor within panels + +https://github.com/grafana/datasource-plugin-genericdatasource + +## Panel plugins + +Panel plugins are responsible for + + * UI for Panel options. + * Creating a directive that can render something based on datasource data. + +We currently dont have a reference implementation for panel plugins but you can checkout https://github.com/grafana/panel-plugin-piechart diff --git a/pkg/api/cloudwatch/cloudwatch.go b/pkg/api/cloudwatch/cloudwatch.go index 0995c88da4b..babcf9fddb0 100644 --- a/pkg/api/cloudwatch/cloudwatch.go +++ b/pkg/api/cloudwatch/cloudwatch.go @@ -43,18 +43,29 @@ func init() { } } -func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) { +var awsCredentials map[string]*credentials.Credentials = make(map[string]*credentials.Credentials) + +func getCredentials(profile string) *credentials.Credentials { + if _, ok := awsCredentials[profile]; ok { + return awsCredentials[profile] + } + sess := session.New() creds := credentials.NewChainCredentials( []credentials.Provider{ &credentials.EnvProvider{}, - &credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database}, + &credentials.SharedCredentialsProvider{Filename: "", Profile: profile}, &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute}, }) + awsCredentials[profile] = creds + return creds +} + +func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) { cfg := &aws.Config{ Region: aws.String(req.Region), - Credentials: creds, + Credentials: getCredentials(req.DataSource.Database), } svc := cloudwatch.New(session.New(cfg), cfg) @@ -92,17 +103,9 @@ func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) { } func handleListMetrics(req *cwRequest, c *middleware.Context) { - sess := session.New() - creds := credentials.NewChainCredentials( - []credentials.Provider{ - &credentials.EnvProvider{}, - &credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database}, - &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute}, - }) - cfg := &aws.Config{ Region: aws.String(req.Region), - Credentials: creds, + Credentials: getCredentials(req.DataSource.Database), } svc := cloudwatch.New(session.New(cfg), cfg) @@ -140,17 +143,9 @@ func handleListMetrics(req *cwRequest, c *middleware.Context) { } func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) { - sess := session.New() - creds := credentials.NewChainCredentials( - []credentials.Provider{ - &credentials.EnvProvider{}, - &credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database}, - &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute}, - }) - cfg := &aws.Config{ Region: aws.String(req.Region), - Credentials: creds, + Credentials: getCredentials(req.DataSource.Database), } svc := cloudwatch.New(session.New(cfg), cfg) @@ -188,17 +183,9 @@ func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) { } func handleDescribeAlarmHistory(req *cwRequest, c *middleware.Context) { - sess := session.New() - creds := credentials.NewChainCredentials( - []credentials.Provider{ - &credentials.EnvProvider{}, - &credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database}, - &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute}, - }) - cfg := &aws.Config{ Region: aws.String(req.Region), - Credentials: creds, + Credentials: getCredentials(req.DataSource.Database), } svc := cloudwatch.New(session.New(cfg), cfg) @@ -232,17 +219,9 @@ func handleDescribeAlarmHistory(req *cwRequest, c *middleware.Context) { } func handleDescribeInstances(req *cwRequest, c *middleware.Context) { - sess := session.New() - creds := credentials.NewChainCredentials( - []credentials.Provider{ - &credentials.EnvProvider{}, - &credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database}, - &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute}, - }) - cfg := &aws.Config{ Region: aws.String(req.Region), - Credentials: creds, + Credentials: getCredentials(req.DataSource.Database), } svc := ec2.New(session.New(cfg), cfg) diff --git a/public/app/core/controllers/sidemenu_ctrl.js b/public/app/core/controllers/sidemenu_ctrl.js index e53b555466e..368d275a3df 100644 --- a/public/app/core/controllers/sidemenu_ctrl.js +++ b/public/app/core/controllers/sidemenu_ctrl.js @@ -24,26 +24,32 @@ function (angular, _, $, coreModule, config) { }); }; - $scope.loadOrgs = function() { - $scope.orgMenu = []; + $scope.openUserDropdown = function() { + $scope.orgMenu = [ + {section: 'You', cssClass: 'dropdown-menu-title'}, + {text: 'Profile', url: $scope.getUrl('/profile')}, + ]; if (contextSrv.hasRole('Admin')) { + $scope.orgMenu.push({section: contextSrv.user.orgName, cssClass: 'dropdown-menu-title'}); $scope.orgMenu.push({ - text: "Organization settings", - href: $scope.getUrl("/org"), + text: "Settings", + url: $scope.getUrl("/org"), }); $scope.orgMenu.push({ text: "Users", - href: $scope.getUrl("/org/users"), + url: $scope.getUrl("/org/users"), }); $scope.orgMenu.push({ text: "API Keys", - href: $scope.getUrl("/org/apikeys"), + url: $scope.getUrl("/org/apikeys"), }); } - if ($scope.orgMenu.length > 0) { - $scope.orgMenu.push({ cssClass: 'divider' }); + $scope.orgMenu.push({cssClass: "divider"}); + + if (config.allowOrgCreate) { + $scope.orgMenu.push({text: "New organization", icon: "fa fa-fw fa-plus", url: $scope.getUrl('/org/new')}); } backendSrv.get('/api/user/orgs').then(function(orgs) { @@ -61,12 +67,12 @@ function (angular, _, $, coreModule, config) { }); }); - if (config.allowOrgCreate) { - $scope.orgMenu.push({ - text: "New Organization", - icon: "fa fa-fw fa-plus", - href: $scope.getUrl('/org/new') - }); + $scope.orgMenu.push({cssClass: "divider"}); + if (contextSrv.isGrafanaAdmin) { + $scope.orgMenu.push({text: "Server admin", url: $scope.getUrl("/admin/settings")}); + } + if (contextSrv.isSignedIn) { + $scope.orgMenu.push({text: "Sign out", url: $scope.getUrl("/logout"), target: "_self"}); } }); }; diff --git a/public/app/features/annotations/partials/editor.html b/public/app/features/annotations/partials/editor.html index 851db4b4f01..0f244998c17 100644 --- a/public/app/features/annotations/partials/editor.html +++ b/public/app/features/annotations/partials/editor.html @@ -44,7 +44,7 @@
| - + {{annotation.name}} | diff --git a/public/app/features/org/all.js b/public/app/features/org/all.js index 7f300064e5a..d03d270709d 100644 --- a/public/app/features/org/all.js +++ b/public/app/features/org/all.js @@ -6,8 +6,4 @@ define([ './userInviteCtrl', './orgApiKeysCtrl', './orgDetailsCtrl', - './app_list_ctrl', - './app_edit_ctrl', - './app_srv', - './app_directive', ], function () {}); diff --git a/public/app/partials/sidemenu.html b/public/app/partials/sidemenu.html index b8cbdd84bc3..bf75b465be8 100644 --- a/public/app/partials/sidemenu.html +++ b/public/app/partials/sidemenu.html @@ -8,6 +8,32 @@ + |