Просмотр исходного кода

Merge branch 'master' into influxdb_stop_hidden_queries

bergquist 9 лет назад
Родитель
Сommit
b47a307106
34 измененных файлов с 201 добавлено и 72 удалено
  1. 13 2
      CHANGELOG.md
  2. 3 0
      conf/defaults.ini
  3. 1 1
      docs/VERSION
  4. 10 3
      docs/sources/installation/debian.md
  5. 20 2
      docs/sources/installation/rpm.md
  6. 9 1
      docs/sources/reference/export_import.md
  7. 1 0
      docs/sources/versions.html_fragment
  8. 2 2
      package.json
  9. 8 8
      packaging/publish/publish.sh
  10. 19 15
      pkg/api/cloudwatch/metrics.go
  11. 1 0
      pkg/api/login.go
  12. 11 0
      pkg/cmd/grafana-cli/commands/command_line.go
  13. 8 0
      pkg/cmd/grafana-cli/commands/commandstest/fake_commandLine.go
  14. 4 4
      pkg/cmd/grafana-cli/commands/install_command.go
  15. 1 1
      pkg/cmd/grafana-cli/commands/listremote_command.go
  16. 1 1
      pkg/cmd/grafana-cli/commands/ls_command.go
  17. 10 8
      pkg/cmd/grafana-cli/commands/remove_command.go
  18. 1 1
      pkg/cmd/grafana-cli/commands/upgrade_all_command.go
  19. 2 2
      pkg/cmd/grafana-cli/commands/upgrade_command.go
  20. 10 3
      pkg/cmd/grafana-cli/services/services.go
  21. 0 2
      pkg/middleware/middleware_test.go
  22. 2 0
      pkg/setting/setting.go
  23. 1 0
      public/app/core/controllers/login_ctrl.js
  24. 0 4
      public/app/core/services/alert_srv.ts
  25. 1 1
      public/app/core/services/backend_srv.ts
  26. 6 0
      public/app/core/utils/kbn.js
  27. 4 4
      public/app/partials/login.html
  28. 1 1
      public/app/plugins/datasource/prometheus/datasource.ts
  29. 1 1
      public/app/plugins/panel/graph/series_overrides_ctrl.js
  30. 4 1
      public/app/plugins/panel/singlestat/editor.html
  31. 18 4
      public/app/plugins/panel/singlestat/module.ts
  32. 16 0
      public/app/plugins/panel/singlestat/specs/singlestat-specs.ts
  33. 7 0
      public/sass/_old_responsive.scss
  34. 5 0
      public/sass/components/_gf-form.scss

+ 13 - 2
CHANGELOG.md

@@ -1,4 +1,16 @@
-# 3.1.0 (unreleased)
+# 3.2.0-pre (unreleased)
+
+### Enhancements
+* **Login**: Adds option to disable username/password logins, closes [#4674](https://github.com/grafana/grafana/issues/4674)
+* **SingleStat**: Add seriename as option in singlestat panel, closes [#4740](https://github.com/grafana/grafana/issues/4740)
+
+
+# 3.1.0 stable (unreleased)
+
+### Bugfixes
+* **User Alert Notices**: Backend error alert popups did not show properly, fixes [#5435](https://github.com/grafana/grafana/issues/5435)
+
+# 3.1.0-beta1 (2016-06-23)
 
 ### Enhancements
 * **Dashboard Export/Import**: Dashboard export now templetize data sources and constant variables, users pick these on import, closes [#5084](https://github.com/grafana/grafana/issues/5084)
@@ -11,7 +23,6 @@
 * **InfluxDB**: Add spread function, closes [#5211](https://github.com/grafana/grafana/issues/5211)
 * **Scripts**: Use restart instead of start for deb package script, closes [#5282](https://github.com/grafana/grafana/pull/5282)
 * **Logging**: Moved to structured logging lib, and moved to component specific level filters via config file, closes [#4590](https://github.com/grafana/grafana/issues/4590)
-* **Search**: Add search limit query parameter, closes [#5292](https://github.com/grafana/grafana/pull/5292)
 * **OpenTSDB**: Support nested template variables in tag_values function, closes [#4398](https://github.com/grafana/grafana/issues/4398)
 * **Datasource**: Pending data source requests are cancelled before new ones are issues (Graphite & Prometheus), closes [#5321](https://github.com/grafana/grafana/issues/5321)
 

+ 3 - 0
conf/defaults.ini

@@ -178,6 +178,9 @@ login_hint = email or username
 # Default UI theme ("dark" or "light")
 default_theme = dark
 
+# Allow users to sign in using username and password
+allow_user_pass_login = true
+
 #################################### Anonymous Auth ##########################
 [auth.anonymous]
 # enable anonymous access

+ 1 - 1
docs/VERSION

@@ -1 +1 @@
-3.0.0
+3.1.0

+ 10 - 3
docs/sources/installation/debian.md

@@ -10,7 +10,8 @@ page_keywords: grafana, installation, debian, ubuntu, guide
 
 Description | Download
 ------------ | -------------
-Stable .deb for Debian-based Linux | [grafana_3.0.4-1464167696.deb](https://grafanarel.s3.amazonaws.com/builds/grafana_3.0.4-1464167696_amd64.deb)
+Stable .deb for Debian-based Linux | [3.0.4](https://grafanarel.s3.amazonaws.com/builds/grafana_3.0.4-1464167696_amd64.deb)
+Beta .deb for Debian-based Linux | [3.1.0-beta1](https://grafanarel.s3.amazonaws.com/builds/grafana_3.1.0-1466666977beta1_amd64.deb)
 
 ## Install Stable
 
@@ -18,17 +19,23 @@ Stable .deb for Debian-based Linux | [grafana_3.0.4-1464167696.deb](https://graf
     $ sudo apt-get install -y adduser libfontconfig
     $ sudo dpkg -i grafana_3.0.4-1464167696_amd64.deb
 
+## Install 3.1 beta
+
+    $ wget https://grafanarel.s3.amazonaws.com/builds/grafana_3.1.0-1466666977beta1_amd64.deb
+    $ sudo apt-get install -y adduser libfontconfig
+    $ sudo dpkg -i grafana_3.1.0-1466666977beta1_amd64.deb
+
 ## APT Repository
 
 Add the following line to your `/etc/apt/sources.list` file.
 
-    deb https://packagecloud.io/grafana/stable/debian/ wheezy main
+    deb https://packagecloud.io/grafana/stable/debian/ jessie main
 
 Use the above line even if you are on Ubuntu or another Debian version.
 There is also a testing repository if you want beta or release
 candidates.
 
-    deb https://packagecloud.io/grafana/testing/debian/ wheezy main
+    deb https://packagecloud.io/grafana/testing/debian/ jessie main
 
 Then add the [Package Cloud](https://packagecloud.io/grafana) key. This
 allows you to install signed packages.

+ 20 - 2
docs/sources/installation/rpm.md

@@ -10,9 +10,10 @@ page_keywords: grafana, installation, centos, fedora, opensuse, redhat, guide
 
 Description | Download
 ------------ | -------------
-Stable .RPM for CentOS / Fedora / OpenSuse / Redhat Linux | [grafana-3.0.4-1464167696.x86_64.rpm](https://grafanarel.s3.amazonaws.com/builds/grafana-3.0.4-1464167696.x86_64.rpm)
+Stable .RPM for CentOS / Fedora / OpenSuse / Redhat Linux | [3.0.4 (x86-64 rpm)](https://grafanarel.s3.amazonaws.com/builds/grafana-3.0.4-1464167696.x86_64.rpm)
+Beta .RPM for CentOS / Fedora / OpenSuse / Redhat Linux | [3.1.0-beta1 (x86-64 rpm)](https://grafanarel.s3.amazonaws.com/builds/grafana-3.1.0-1466666977beta1.x86_64.rpm)
 
-## Install Stable Release from package file
+## Install Latest Stable
 
 You can install Grafana using Yum directly.
 
@@ -29,6 +30,23 @@ Or install manually using `rpm`.
 
     $ sudo rpm -i --nodeps grafana-3.0.4-1464167696.x86_64.rpm
 
+## Install 3.1 Beta
+
+You can install Grafana using Yum directly.
+
+    $ sudo yum install https://grafanarel.s3.amazonaws.com/builds/grafana-3.1.0-1466666977beta1.x86_64.rpm
+
+Or install manually using `rpm`.
+
+#### On CentOS / Fedora / Redhat:
+
+    $ sudo yum install initscripts fontconfig
+    $ sudo rpm -Uvh https://grafanarel.s3.amazonaws.com/builds/grafana-3.1.0-1466666977beta1.x86_64.rpm
+
+#### On OpenSuse:
+
+    $ sudo rpm -i --nodeps https://grafanarel.s3.amazonaws.com/builds/grafana-3.1.0-1466666977beta1.x86_64.rpm
+
 ## Install via YUM Repository
 
 Add the following to a new file at `/etc/yum.repos.d/grafana.repo`

+ 9 - 1
docs/sources/reference/export_import.md

@@ -14,9 +14,17 @@ The export feature is accessed from the share menu.
 
 <img src="/img/v31/export_menu.png">
 
+### Making a dashboard portable
+
+If you want to export a dashboard for others to use then it could be a good idea to
+add template variables for things like a metric prefix (use contant variable) and server name.
+
+A template varible of the type `Constant` will automatically be hidden in
+the dashboard, and will also be added as an required input when the dashboard is imported.
+
 ## Importing a dashboard
 
-To import a dasbhoard open dashboard search and then hit the import button.
+To import a dashboard open dashboard search and then hit the import button.
 
 <img src="/img/v31/import_step1.png">
 

+ 1 - 0
docs/sources/versions.html_fragment

@@ -1,3 +1,4 @@
+<li><a class='version' href='/v3.1'>Version v3.1</a></li>
 <li><a class='version' href='/v3.0'>Version v3.0</a></li>
 <li><a class='version' href='/v2.6'>Version v2.6</a></li>
 <li><a class='version' href='/v2.5'>Version v2.5</a></li>

+ 2 - 2
package.json

@@ -4,7 +4,7 @@
     "company": "Coding Instinct AB"
   },
   "name": "grafana",
-  "version": "3.1.0",
+  "version": "3.2.0-pre1",
   "repository": {
     "type": "git",
     "url": "http://github.com/grafana/grafana.git"
@@ -57,7 +57,7 @@
     "systemjs": "0.19.24"
   },
   "engines": {
-    "node": "0.4.x",
+    "node": "4.x",
     "npm": "2.14.x"
   },
   "scripts": {

+ 8 - 8
packaging/publish/publish.sh

@@ -1,20 +1,20 @@
 #! /usr/bin/env bash
 
-deb_ver=3.0.4-1464167696
-rpm_ver=3.0.4-1464167696
+deb_ver=3.1.0-1466666977beta1
+rpm_ver=3.1.0-1466666977beta1
 
-wget https://grafanarel.s3.amazonaws.com/builds/grafana_${deb_ver}_amd64.deb
+# wget https://grafanarel.s3.amazonaws.com/builds/grafana_${deb_ver}_amd64.deb
 
-package_cloud push grafana/stable/debian/jessie grafana_${deb_ver}_amd64.deb
-package_cloud push grafana/stable/debian/wheezy grafana_${deb_ver}_amd64.deb
+# package_cloud push grafana/stable/debian/jessie grafana_${deb_ver}_amd64.deb
+# package_cloud push grafana/stable/debian/wheezy grafana_${deb_ver}_amd64.deb
 
 package_cloud push grafana/testing/debian/jessie grafana_${deb_ver}_amd64.deb
 package_cloud push grafana/testing/debian/wheezy grafana_${deb_ver}_amd64.deb
 
-wget https://grafanarel.s3.amazonaws.com/builds/grafana-${rpm_ver}.x86_64.rpm
+# wget https://grafanarel.s3.amazonaws.com/builds/grafana-${rpm_ver}.x86_64.rpm
 
 package_cloud push grafana/testing/el/6 grafana-${rpm_ver}.x86_64.rpm
 package_cloud push grafana/testing/el/7 grafana-${rpm_ver}.x86_64.rpm
 
-package_cloud push grafana/stable/el/7 grafana-${rpm_ver}.x86_64.rpm
-package_cloud push grafana/stable/el/6 grafana-${rpm_ver}.x86_64.rpm
+# package_cloud push grafana/stable/el/7 grafana-${rpm_ver}.x86_64.rpm
+# package_cloud push grafana/stable/el/6 grafana-${rpm_ver}.x86_64.rpm

+ 19 - 15
pkg/api/cloudwatch/metrics.go

@@ -32,8 +32,13 @@ func init() {
 		"AWS/Billing":     {"EstimatedCharges"},
 		"AWS/CloudFront":  {"Requests", "BytesDownloaded", "BytesUploaded", "TotalErrorRate", "4xxErrorRate", "5xxErrorRate"},
 		"AWS/CloudSearch": {"SuccessfulRequests", "SearchableDocuments", "IndexUtilization", "Partitions"},
-		"AWS/DynamoDB":    {"ConditionalCheckFailedRequests", "ConsumedReadCapacityUnits", "ConsumedWriteCapacityUnits", "OnlineIndexConsumedWriteCapacity", "OnlineIndexPercentageProgress", "OnlineIndexThrottleEvents", "ProvisionedReadCapacityUnits", "ProvisionedWriteCapacityUnits", "ReadThrottleEvents", "ReturnedItemCount", "SuccessfulRequestLatency", "SystemErrors", "ThrottledRequests", "UserErrors", "WriteThrottleEvents"},
-		"AWS/ECS":         {"CPUUtilization", "MemoryUtilization"},
+		"AWS/DynamoDB":    {"ConditionalCheckFailedRequests", "ConsumedReadCapacityUnits", "ConsumedWriteCapacityUnits", "OnlineIndexConsumedWriteCapacity", "OnlineIndexPercentageProgress", "OnlineIndexThrottleEvents", "ProvisionedReadCapacityUnits", "ProvisionedWriteCapacityUnits", "ReadThrottleEvents", "ReturnedBytes", "ReturnedItemCount", "ReturnedRecordsCount", "SuccessfulRequestLatency", "SystemErrors", "ThrottledRequests", "UserErrors", "WriteThrottleEvents"},
+		"AWS/EBS":         {"VolumeReadBytes", "VolumeWriteBytes", "VolumeReadOps", "VolumeWriteOps", "VolumeTotalReadTime", "VolumeTotalWriteTime", "VolumeIdleTime", "VolumeQueueLength", "VolumeThroughputPercentage", "VolumeConsumedReadWriteOps", "BurstBalance"},
+		"AWS/EC2":         {"CPUCreditUsage", "CPUCreditBalance", "CPUUtilization", "DiskReadOps", "DiskWriteOps", "DiskReadBytes", "DiskWriteBytes", "NetworkIn", "NetworkOut", "NetworkPacketsIn", "NetworkPacketsOut", "StatusCheckFailed", "StatusCheckFailed_Instance", "StatusCheckFailed_System"},
+		"AWS/EC2Spot":     {"AvailableInstancePoolsCount", "BidsSubmittedForCapacity", "EligibleInstancePoolCount", "FulfilledCapacity", "MaxPercentCapacityAllocation", "PendingCapacity", "PercentCapacityAllocation", "TargetCapacity", "TerminatingCapacity"},
+		"AWS/ECS":         {"CPUReservation", "MemoryReservation", "CPUUtilization", "MemoryUtilization"},
+		"AWS/EFS":         {"BurstCreditBalance", "ClientConnections", "DataReadIOBytes", "DataWriteIOBytes", "MetadataIOBytes", "TotalIOBytes", "PermittedThroughput", "PercentIOLimit"},
+		"AWS/ELB":         {"HealthyHostCount", "UnHealthyHostCount", "RequestCount", "Latency", "HTTPCode_ELB_4XX", "HTTPCode_ELB_5XX", "HTTPCode_Backend_2XX", "HTTPCode_Backend_3XX", "HTTPCode_Backend_4XX", "HTTPCode_Backend_5XX", "BackendConnectionErrors", "SurgeQueueLength", "SpilloverCount"},
 		"AWS/ElastiCache": {
 			"CPUUtilization", "FreeableMemory", "NetworkBytesIn", "NetworkBytesOut", "SwapUsage",
 			"BytesUsedForCacheItems", "BytesReadIntoMemcached", "BytesWrittenOutFromMemcached", "CasBadval", "CasHits", "CasMisses", "CmdFlush", "CmdGet", "CmdSet", "CurrConnections", "CurrItems", "DecrHits", "DecrMisses", "DeleteHits", "DeleteMisses", "Evictions", "GetHits", "GetMisses", "IncrHits", "IncrMisses", "Reclaimed",
@@ -42,9 +47,6 @@ func init() {
 			"BytesUsedForCache", "CacheHits", "CacheMisses", "CurrConnections", "Evictions", "HyperLogLogBasedCmds", "NewConnections", "Reclaimed", "ReplicationBytes", "ReplicationLag", "SaveInProgress",
 			"CurrItems", "GetTypeCmds", "HashBasedCmds", "KeyBasedCmds", "ListBasedCmds", "SetBasedCmds", "SetTypeCmds", "SortedSetBasedCmds", "StringBasedCmds",
 		},
-		"AWS/EBS": {"VolumeReadBytes", "VolumeWriteBytes", "VolumeReadOps", "VolumeWriteOps", "VolumeTotalReadTime", "VolumeTotalWriteTime", "VolumeIdleTime", "VolumeQueueLength", "VolumeThroughputPercentage", "VolumeConsumedReadWriteOps"},
-		"AWS/EC2": {"CPUCreditUsage", "CPUCreditBalance", "CPUUtilization", "DiskReadOps", "DiskWriteOps", "DiskReadBytes", "DiskWriteBytes", "NetworkIn", "NetworkOut", "StatusCheckFailed", "StatusCheckFailed_Instance", "StatusCheckFailed_System"},
-		"AWS/ELB": {"HealthyHostCount", "UnHealthyHostCount", "RequestCount", "Latency", "HTTPCode_ELB_4XX", "HTTPCode_ELB_5XX", "HTTPCode_Backend_2XX", "HTTPCode_Backend_3XX", "HTTPCode_Backend_4XX", "HTTPCode_Backend_5XX", "BackendConnectionErrors", "SurgeQueueLength", "SpilloverCount"},
 		"AWS/ElasticBeanstalk": {
 			"EnvironmentHealth",
 			"ApplicationLatencyP10", "ApplicationLatencyP50", "ApplicationLatencyP75", "ApplicationLatencyP85", "ApplicationLatencyP90", "ApplicationLatencyP95", "ApplicationLatencyP99", "ApplicationLatencyP99.9",
@@ -73,13 +75,13 @@ func init() {
 		"AWS/Redshift": {"CPUUtilization", "DatabaseConnections", "HealthStatus", "MaintenanceMode", "NetworkReceiveThroughput", "NetworkTransmitThroughput", "PercentageDiskSpaceUsed", "ReadIOPS", "ReadLatency", "ReadThroughput", "WriteIOPS", "WriteLatency", "WriteThroughput"},
 		"AWS/RDS":      {"BinLogDiskUsage", "CPUUtilization", "CPUCreditUsage", "CPUCreditBalance", "DatabaseConnections", "DiskQueueDepth", "FreeableMemory", "FreeStorageSpace", "ReplicaLag", "SwapUsage", "ReadIOPS", "WriteIOPS", "ReadLatency", "WriteLatency", "ReadThroughput", "WriteThroughput", "NetworkReceiveThroughput", "NetworkTransmitThroughput"},
 		"AWS/Route53":  {"HealthCheckStatus", "HealthCheckPercentageHealthy", "ConnectionTime", "SSLHandshakeTime", "TimeToFirstByte"},
+		"AWS/S3":       {"BucketSizeBytes", "NumberOfObjects"},
 		"AWS/SNS":      {"NumberOfMessagesPublished", "PublishSize", "NumberOfNotificationsDelivered", "NumberOfNotificationsFailed"},
 		"AWS/SQS":      {"NumberOfMessagesSent", "SentMessageSize", "NumberOfMessagesReceived", "NumberOfEmptyReceives", "NumberOfMessagesDeleted", "ApproximateNumberOfMessagesDelayed", "ApproximateNumberOfMessagesVisible", "ApproximateNumberOfMessagesNotVisible"},
-		"AWS/S3":       {"BucketSizeBytes", "NumberOfObjects"},
-		"AWS/SWF": {"DecisionTaskScheduleToStartTime", "DecisionTaskStartToCloseTime", "DecisionTasksCompleted", "StartedDecisionTasksTimedOutOnClose", "WorkflowStartToCloseTime", "WorkflowsCanceled", "WorkflowsCompleted", "WorkflowsContinuedAsNew", "WorkflowsFailed", "WorkflowsTerminated", "WorkflowsTimedOut",
-			"ActivityTaskScheduleToCloseTime", "ActivityTaskScheduleToStartTime", "ActivityTaskStartToCloseTime", "ActivityTasksCanceled", "ActivityTasksCompleted", "ActivityTasksFailed", "ScheduledActivityTasksTimedOutOnClose", "ScheduledActivityTasksTimedOutOnStart", "StartedActivityTasksTimedOutOnClose", "StartedActivityTasksTimedOutOnHeartbeat"},
 		"AWS/StorageGateway": {"CacheHitPercent", "CachePercentUsed", "CachePercentDirty", "CloudBytesDownloaded", "CloudDownloadLatency", "CloudBytesUploaded", "UploadBufferFree", "UploadBufferPercentUsed", "UploadBufferUsed", "QueuedWrites", "ReadBytes", "ReadTime", "TotalCacheSize", "WriteBytes", "WriteTime", "TimeSinceLastRecoveryPoint", "WorkingStorageFree", "WorkingStoragePercentUsed", "WorkingStorageUsed",
 			"CacheHitPercent", "CachePercentUsed", "CachePercentDirty", "ReadBytes", "ReadTime", "WriteBytes", "WriteTime", "QueuedWrites"},
+		"AWS/SWF": {"DecisionTaskScheduleToStartTime", "DecisionTaskStartToCloseTime", "DecisionTasksCompleted", "StartedDecisionTasksTimedOutOnClose", "WorkflowStartToCloseTime", "WorkflowsCanceled", "WorkflowsCompleted", "WorkflowsContinuedAsNew", "WorkflowsFailed", "WorkflowsTerminated", "WorkflowsTimedOut",
+			"ActivityTaskScheduleToCloseTime", "ActivityTaskScheduleToStartTime", "ActivityTaskStartToCloseTime", "ActivityTasksCanceled", "ActivityTasksCompleted", "ActivityTasksFailed", "ScheduledActivityTasksTimedOutOnClose", "ScheduledActivityTasksTimedOutOnStart", "StartedActivityTasksTimedOutOnClose", "StartedActivityTasksTimedOutOnHeartbeat"},
 		"AWS/WAF":        {"AllowedRequests", "BlockedRequests", "CountedRequests"},
 		"AWS/WorkSpaces": {"Available", "Unhealthy", "ConnectionAttempt", "ConnectionSuccess", "ConnectionFailure", "SessionLaunchTime", "InSessionLatency", "SessionDisconnect"},
 	}
@@ -88,29 +90,31 @@ func init() {
 		"AWS/Billing":          {"ServiceName", "LinkedAccount", "Currency"},
 		"AWS/CloudFront":       {"DistributionId", "Region"},
 		"AWS/CloudSearch":      {},
-		"AWS/DynamoDB":         {"TableName", "GlobalSecondaryIndexName", "Operation"},
-		"AWS/ECS":              {"ClusterName", "ServiceName"},
-		"AWS/ElastiCache":      {"CacheClusterId", "CacheNodeId"},
+		"AWS/DynamoDB":         {"TableName", "GlobalSecondaryIndexName", "Operation", "StreamLabel"},
 		"AWS/EBS":              {"VolumeId"},
 		"AWS/EC2":              {"AutoScalingGroupName", "ImageId", "InstanceId", "InstanceType"},
+		"AWS/EC2Spot":          {"AvailabilityZone", "FleetRequestId", "InstanceType"},
+		"AWS/ECS":              {"ClusterName", "ServiceName"},
+		"AWS/EFS":              {"FileSystemId"},
 		"AWS/ELB":              {"LoadBalancerName", "AvailabilityZone"},
+		"AWS/ElastiCache":      {"CacheClusterId", "CacheNodeId"},
 		"AWS/ElasticBeanstalk": {"EnvironmentName", "InstanceId"},
 		"AWS/ElasticMapReduce": {"ClusterId", "JobFlowId", "JobId"},
 		"AWS/ES":               {"ClientId", "DomainName"},
 		"AWS/Events":           {"RuleName"},
 		"AWS/Kinesis":          {"StreamName", "ShardID"},
-		"AWS/Lambda":           {"FunctionName"},
+		"AWS/Lambda":           {"FunctionName", "Resource", "Version", "Alias"},
 		"AWS/Logs":             {"LogGroupName", "DestinationType", "FilterName"},
 		"AWS/ML":               {"MLModelId", "RequestMode"},
 		"AWS/OpsWorks":         {"StackId", "LayerId", "InstanceId"},
 		"AWS/Redshift":         {"NodeID", "ClusterIdentifier"},
-		"AWS/RDS":              {"DBInstanceIdentifier", "DatabaseClass", "EngineName"},
+		"AWS/RDS":              {"DBInstanceIdentifier", "DBClusterIdentifier", "DatabaseClass", "EngineName"},
 		"AWS/Route53":          {"HealthCheckId"},
+		"AWS/S3":               {"BucketName", "StorageType"},
 		"AWS/SNS":              {"Application", "Platform", "TopicName"},
 		"AWS/SQS":              {"QueueName"},
-		"AWS/S3":               {"BucketName", "StorageType"},
-		"AWS/SWF":              {"Domain", "WorkflowTypeName", "WorkflowTypeVersion", "ActivityTypeName", "ActivityTypeVersion"},
 		"AWS/StorageGateway":   {"GatewayId", "GatewayName", "VolumeId"},
+		"AWS/SWF":              {"Domain", "WorkflowTypeName", "WorkflowTypeVersion", "ActivityTypeName", "ActivityTypeVersion"},
 		"AWS/WAF":              {"Rule", "WebACL"},
 		"AWS/WorkSpaces":       {"DirectoryId", "WorkspaceId"},
 	}

+ 1 - 0
pkg/api/login.go

@@ -29,6 +29,7 @@ func LoginView(c *middleware.Context) {
 	viewData.Settings["githubAuthEnabled"] = setting.OAuthService.GitHub
 	viewData.Settings["disableUserSignUp"] = !setting.AllowUserSignUp
 	viewData.Settings["loginHint"] = setting.LoginHint
+	viewData.Settings["allowUserPassLogin"] = setting.AllowUserPassLogin
 
 	if !tryLoginUsingRememberCookie(c) {
 		c.HTML(200, VIEW_INDEX, viewData)

+ 11 - 0
pkg/cmd/grafana-cli/commands/command_line.go

@@ -16,6 +16,9 @@ type CommandLine interface {
 	GlobalString(name string) string
 	FlagNames() (names []string)
 	Generic(name string) interface{}
+
+	PluginDirectory() string
+	RepoDirectory() string
 }
 
 type contextCommandLine struct {
@@ -33,3 +36,11 @@ func (c *contextCommandLine) ShowVersion() {
 func (c *contextCommandLine) Application() *cli.App {
 	return c.App
 }
+
+func (c *contextCommandLine) PluginDirectory() string {
+	return c.GlobalString("pluginsDir")
+}
+
+func (c *contextCommandLine) RepoDirectory() string {
+	return c.GlobalString("repo")
+}

+ 8 - 0
pkg/cmd/grafana-cli/commands/commandstest/fake_commandLine.go

@@ -93,3 +93,11 @@ func (fcli *FakeCommandLine) Args() cli.Args {
 func (fcli *FakeCommandLine) ShowVersion() {
 	fcli.VersionShown = true
 }
+
+func (fcli *FakeCommandLine) RepoDirectory() string {
+	return fcli.GlobalString("repo")
+}
+
+func (fcli *FakeCommandLine) PluginDirectory() string {
+	return fcli.GlobalString("pluginsDir")
+}

+ 4 - 4
pkg/cmd/grafana-cli/commands/install_command.go

@@ -25,7 +25,7 @@ func validateInput(c CommandLine, pluginFolder string) error {
 		return errors.New("please specify plugin to install")
 	}
 
-	pluginsDir := c.GlobalString("pluginsDir")
+	pluginsDir := c.PluginDirectory()
 	if pluginsDir == "" {
 		return errors.New("missing pluginsDir flag")
 	}
@@ -46,7 +46,7 @@ func validateInput(c CommandLine, pluginFolder string) error {
 }
 
 func installCommand(c CommandLine) error {
-	pluginFolder := c.GlobalString("pluginsDir")
+	pluginFolder := c.PluginDirectory()
 	if err := validateInput(c, pluginFolder); err != nil {
 		return err
 	}
@@ -58,8 +58,8 @@ func installCommand(c CommandLine) error {
 }
 
 func InstallPlugin(pluginName, version string, c CommandLine) error {
-	plugin, err := s.GetPlugin(pluginName, c.GlobalString("repo"))
-	pluginFolder := c.GlobalString("pluginsDir")
+	plugin, err := s.GetPlugin(pluginName, c.RepoDirectory())
+	pluginFolder := c.PluginDirectory()
 	if err != nil {
 		return err
 	}

+ 1 - 1
pkg/cmd/grafana-cli/commands/listremote_command.go

@@ -6,7 +6,7 @@ import (
 )
 
 func listremoteCommand(c CommandLine) error {
-	plugin, err := s.ListAllPlugins(c.GlobalString("repo"))
+	plugin, err := s.ListAllPlugins(c.RepoDirectory())
 
 	if err != nil {
 		return err

+ 1 - 1
pkg/cmd/grafana-cli/commands/ls_command.go

@@ -32,7 +32,7 @@ var validateLsCommand = func(pluginDir string) error {
 }
 
 func lsCommand(c CommandLine) error {
-	pluginDir := c.GlobalString("pluginsDir")
+	pluginDir := c.PluginDirectory()
 	if err := validateLsCommand(pluginDir); err != nil {
 		return err
 	}

+ 10 - 8
pkg/cmd/grafana-cli/commands/remove_command.go

@@ -2,30 +2,32 @@ package commands
 
 import (
 	"errors"
-
 	"fmt"
 	m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
 	services "github.com/grafana/grafana/pkg/cmd/grafana-cli/services"
+	"strings"
 )
 
 var getPluginss func(path string) []m.InstalledPlugin = services.GetLocalPlugins
 var removePlugin func(pluginPath, id string) error = services.RemoveInstalledPlugin
 
 func removeCommand(c CommandLine) error {
-	pluginPath := c.GlobalString("pluginsDir")
-	localPlugins := getPluginss(pluginPath)
+	pluginPath := c.PluginDirectory()
 
 	plugin := c.Args().First()
 	if plugin == "" {
 		return errors.New("Missing plugin parameter")
 	}
 
-	for _, p := range localPlugins {
-		if p.Id == c.Args().First() {
-			removePlugin(pluginPath, p.Id)
-			return nil
+	err := removePlugin(pluginPath, plugin)
+
+	if err != nil {
+		if strings.Contains(err.Error(), "no such file or directory") {
+			return fmt.Errorf("Plugin does not exist")
 		}
+
+		return err
 	}
 
-	return fmt.Errorf("Could not find plugin named %s", c.Args().First())
+	return nil
 }

+ 1 - 1
pkg/cmd/grafana-cli/commands/upgrade_all_command.go

@@ -28,7 +28,7 @@ func ShouldUpgrade(installed string, remote m.Plugin) bool {
 }
 
 func upgradeAllCommand(c CommandLine) error {
-	pluginsDir := c.GlobalString("pluginsDir")
+	pluginsDir := c.PluginDirectory()
 
 	localPlugins := s.GetLocalPlugins(pluginsDir)
 

+ 2 - 2
pkg/cmd/grafana-cli/commands/upgrade_command.go

@@ -7,7 +7,7 @@ import (
 )
 
 func upgradeCommand(c CommandLine) error {
-	pluginsDir := c.GlobalString("pluginsDir")
+	pluginsDir := c.PluginDirectory()
 	pluginName := c.Args().First()
 
 	localPlugin, err := s.ReadPlugin(pluginsDir, pluginName)
@@ -16,7 +16,7 @@ func upgradeCommand(c CommandLine) error {
 		return err
 	}
 
-	v, err2 := s.GetPlugin(localPlugin.Id, c.GlobalString("repo"))
+	v, err2 := s.GetPlugin(localPlugin.Id, c.RepoDirectory())
 
 	if err2 != nil {
 		return err2

+ 10 - 3
pkg/cmd/grafana-cli/services/services.go

@@ -75,9 +75,16 @@ func GetLocalPlugins(pluginDir string) []m.InstalledPlugin {
 	return result
 }
 
-func RemoveInstalledPlugin(pluginPath, id string) error {
-	logger.Infof("Removing plugin: %v\n", id)
-	return IoHelper.RemoveAll(path.Join(pluginPath, id))
+func RemoveInstalledPlugin(pluginPath, pluginName string) error {
+	logger.Infof("Removing plugin: %v\n", pluginName)
+	pluginDir := path.Join(pluginPath, pluginName)
+
+	_, err := IoHelper.Stat(pluginDir)
+	if err != nil {
+		return err
+	}
+
+	return IoHelper.RemoveAll(pluginDir)
 }
 
 func GetPlugin(pluginId, repoUrl string) (m.Plugin, error) {

+ 0 - 2
pkg/middleware/middleware_test.go

@@ -191,9 +191,7 @@ func TestMiddlewareContext(t *testing.T) {
 				}
 			})
 
-			var createUserCmd *m.CreateUserCommand
 			bus.AddHandler("test", func(cmd *m.CreateUserCommand) error {
-				createUserCmd = cmd
 				cmd.Result = m.User{Id: 33}
 				return nil
 			})

+ 2 - 0
pkg/setting/setting.go

@@ -89,6 +89,7 @@ var (
 	VerifyEmailEnabled bool
 	LoginHint          string
 	DefaultTheme       string
+	AllowUserPassLogin bool
 
 	// Http auth
 	AdminUser     string
@@ -485,6 +486,7 @@ func NewConfigContext(args *CommandLineArgs) error {
 	VerifyEmailEnabled = users.Key("verify_email_enabled").MustBool(false)
 	LoginHint = users.Key("login_hint").String()
 	DefaultTheme = users.Key("default_theme").String()
+	AllowUserPassLogin = users.Key("allow_user_pass_login").MustBool(true)
 
 	// anonymous access
 	AnonymousEnabled = Cfg.Section("auth.anonymous").Key("enabled").MustBool(false)

+ 1 - 0
public/app/core/controllers/login_ctrl.js

@@ -18,6 +18,7 @@ function (angular, coreModule, config) {
     $scope.googleAuthEnabled = config.googleAuthEnabled;
     $scope.githubAuthEnabled = config.githubAuthEnabled;
     $scope.oauthEnabled = config.githubAuthEnabled || config.googleAuthEnabled;
+    $scope.allowUserPassLogin = config.allowUserPassLogin;
     $scope.disableUserSignUp = config.disableUserSignUp;
     $scope.loginHint     = config.loginHint;
 

+ 0 - 4
public/app/core/services/alert_srv.ts

@@ -28,10 +28,6 @@ export class AlertSrv {
     }, this.$rootScope);
 
     appEvents.on('confirm-modal', this.showConfirmModal.bind(this));
-
-    this.$rootScope.onAppEvent('confirm-modal', (e, data) => {
-      this.showConfirmModal(data);
-    }, this.$rootScope);
   }
 
   set(title, text, severity, timeout) {

+ 1 - 1
public/app/core/services/backend_srv.ts

@@ -87,7 +87,7 @@ export class BackendSrv {
         });
       }
 
-      this.$timeout(this.requestErrorHandler.bind(this), 50);
+      this.$timeout(this.requestErrorHandler.bind(this, err), 50);
       throw err;
     });
   };

+ 6 - 0
public/app/core/utils/kbn.js

@@ -397,6 +397,9 @@ function($, _, moment) {
   kbn.valueFormats.rps  = kbn.formatBuilders.simpleCountUnit('rps');
   kbn.valueFormats.wps  = kbn.formatBuilders.simpleCountUnit('wps');
   kbn.valueFormats.iops = kbn.formatBuilders.simpleCountUnit('iops');
+  kbn.valueFormats.opm = kbn.formatBuilders.simpleCountUnit('opm');
+  kbn.valueFormats.rpm = kbn.formatBuilders.simpleCountUnit('rpm');
+  kbn.valueFormats.wpm = kbn.formatBuilders.simpleCountUnit('wpm');
 
   // Energy
   kbn.valueFormats.watt         = kbn.formatBuilders.decimalSIPrefix('W');
@@ -664,6 +667,9 @@ function($, _, moment) {
           {text: 'reads/sec (rps)',     value: 'rps' },
           {text: 'writes/sec (wps)',    value: 'wps' },
           {text: 'I/O ops/sec (iops)',  value: 'iops'},
+          {text: 'ops/min (opm)',       value: 'opm' },
+          {text: 'reads/min (rpm)',     value: 'rpm' },
+          {text: 'writes/min (wpm)',    value: 'wpm' },
         ]
       },
       {

+ 4 - 4
public/app/partials/login.html

@@ -17,7 +17,7 @@
 				</button>
 			</div>
 
-      <form name="loginForm" class="login-form gf-form-group">
+      <form name="loginForm" class="login-form gf-form-group" ng-show="allowUserPassLogin">
 				<div class="gf-form" ng-if="loginMode">
 					<span class="gf-form-label width-7">User</span>
 					<input type="text" name="username" class="gf-form-input max-width-14" required ng-model='formModel.user' placeholder={{loginHint}}>
@@ -40,7 +40,7 @@
 			</form>
 
 			<div ng-if="loginMode">
-				<div class="text-center login-divider" ng-if="oauthEnabled">
+				<div class="text-center login-divider" ng-show="oauthEnabled && allowUserPassLogin">
 					<div class="login-divider-line">
 						<span class="login-divider-text">
 							Or login with
@@ -50,7 +50,7 @@
 
 				<div class="clearfix"></div>
 
-				<div class="login-oauth text-center" ng-if="oauthEnabled">
+				<div class="login-oauth text-center" ng-show="oauthEnabled">
 					<a class="btn btn-large btn-google" href="login/google" target="_self" ng-if="googleAuthEnabled">
 						<i class="fa fa-google"></i>
 						with Google
@@ -64,7 +64,7 @@
 
 			<div class="clearfix"></div>
 
-			<div class="text-center password-recovery">
+			<div class="text-center password-recovery" ng-show="allowUserPassLogin">
 				<div class="text-center">
 					<a href="user/password/send-reset-email">
 						Forgot your password?

+ 1 - 1
public/app/plugins/datasource/prometheus/datasource.ts

@@ -77,7 +77,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
 
       var query: any = {};
       query.expr = templateSrv.replace(target.expr, options.scopedVars, self.interpolateQueryExpr);
-      query.requestId = target.expr;
+      query.requestId = options.panelId + target.refId;
 
       var interval = target.interval || options.interval;
       var intervalFactor = target.intervalFactor || 1;

+ 1 - 1
public/app/plugins/panel/graph/series_overrides_ctrl.js

@@ -105,7 +105,7 @@ define([
     $scope.addOverrideOption('Stack', 'stack', [true, false, 'A', 'B', 'C', 'D']);
     $scope.addOverrideOption('Color', 'color', ['change']);
     $scope.addOverrideOption('Y-axis', 'yaxis', [1, 2]);
-    $scope.addOverrideOption('Z-index', 'zindex', [-1,-2,-3,0,1,2,3]);
+    $scope.addOverrideOption('Z-index', 'zindex', [-3,-2,-1,0,1,2,3]);
     $scope.addOverrideOption('Transform', 'transform', ['negative-Y']);
     $scope.addOverrideOption('Legend', 'legend', [true, false]);
     $scope.updateCurrentOverrides();

+ 4 - 1
public/app/plugins/panel/singlestat/editor.html

@@ -16,7 +16,10 @@
 					Value
 				</li>
 				<li>
-					<select class="input-small tight-form-input" ng-model="ctrl.panel.valueName" ng-options="f for f in ['min','max','avg', 'current', 'total']" ng-change="ctrl.render()"></select>
+					<select class="input-small tight-form-input"
+            ng-model="ctrl.panel.valueName"
+            ng-options="f for f in ctrl.valueNameOptions"
+            ng-change="ctrl.render()"></select>
 				</li>
 				<li class="tight-form-item">
 					Postfix

+ 18 - 4
public/app/plugins/panel/singlestat/module.ts

@@ -19,6 +19,9 @@ class SingleStatCtrl extends MetricsPanelCtrl {
   fontSizes: any[];
   unitFormats: any[];
   invalidGaugeRange: boolean;
+  panel: any;
+  events: any;
+  valueNameOptions: any[] = ['min','max','avg', 'current', 'total', 'name'];
 
   // Set and populate defaults
   panelDefaults = {
@@ -186,9 +189,13 @@ class SingleStatCtrl extends MetricsPanelCtrl {
       var lastPoint = _.last(this.series[0].datapoints);
       var lastValue = _.isArray(lastPoint) ? lastPoint[0] : null;
 
-      if (_.isString(lastValue)) {
+      if (this.panel.valueName === 'name') {
         data.value = 0;
-        data.valueFormated = lastValue;
+        data.valueRounded = 0;
+        data.valueFormated = this.series[0].alias;
+      } else if (_.isString(lastValue)) {
+        data.value = 0;
+        data.valueFormated = _.escape(lastValue);
         data.valueRounded = 0;
       } else {
         data.value = this.series[0].stats[this.panel.valueName];
@@ -199,6 +206,13 @@ class SingleStatCtrl extends MetricsPanelCtrl {
         data.valueFormated = formatFunc(data.value, decimalInfo.decimals, decimalInfo.scaledDecimals);
         data.valueRounded = kbn.roundValue(data.value, decimalInfo.decimals);
       }
+
+      // Add $__name variable for using in prefix or postfix
+      data.scopedVars = {
+        __name: {
+          value: this.series[0].label
+        }
+      };
     }
 
     // check value to text mappings if its enabled
@@ -296,7 +310,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
     }
 
     function getSpan(className, fontSize, value)  {
-      value = templateSrv.replace(value);
+      value = templateSrv.replace(value, data.scopedVars);
       return '<span class="' + className + '" style="font-size:' + fontSize + '">' +
         value + '</span>';
     }
@@ -395,7 +409,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
             value: {
               color: panel.colorValue ? getColorForValue(data, data.valueRounded) : null,
               formatter: function() { return getValueText(); },
-              font: { size: fontSize, family: 'Helvetica Neue", Helvetica, Arial, sans-serif' }
+              font: { size: fontSize, family: '"Helvetica Neue", Helvetica, Arial, sans-serif' }
             },
             show: true
           }

+ 16 - 0
public/app/plugins/panel/singlestat/specs/singlestat-specs.ts

@@ -51,6 +51,22 @@ describe('SingleStatCtrl', function() {
     });
   });
 
+  singleStatScenario('showing serie name instead of value', function(ctx) {
+    ctx.setup(function() {
+      ctx.datapoints = [[10,1], [20,2]];
+      ctx.ctrl.panel.valueName = 'name';
+    });
+
+    it('Should use series avg as default main value', function() {
+      expect(ctx.data.value).to.be(0);
+      expect(ctx.data.valueRounded).to.be(0);
+    });
+
+    it('should set formated falue', function() {
+      expect(ctx.data.valueFormated).to.be('test.cpu1');
+    });
+  });
+
   singleStatScenario('MainValue should use same number for decimals as displayed when checking thresholds', function(ctx) {
     ctx.setup(function() {
       ctx.datapoints = [[99.999,1], [99.99999,2]];

+ 7 - 0
public/sass/_old_responsive.scss

@@ -5,6 +5,7 @@
 
 // Media queries
 // ---------------------
+
 @include media-breakpoint-down(sm) {
   div.panel {
     width: 100% !important;
@@ -33,6 +34,12 @@
   }
 }
 
+@include media-breakpoint-down(xs) {
+  .page-dashboard .navbar-page-btn {
+    max-width: 150px;
+  }
+}
+
 // form styles
 @include media-breakpoint-up(md) {
   .page-dashboard .navbar-page-btn {

+ 5 - 0
public/sass/components/_gf-form.scss

@@ -102,6 +102,11 @@ $gf-form-margin: 0.25rem;
     display: none;
   }
 
+  &.gf-input-small {
+    padding: $input-padding-y/3 $input-padding-x/3;
+    font-size: $font-size-xs;
+  }
+
   // Customize the `:focus` state to imitate native WebKit styles.
   @include form-control-focus();