Merge branch 'master' into alerting_definitions
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"url": "https://floobits.com/raintank/grafana"
|
"url": "https://floobits.com/raintank/grafana"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -5,7 +5,11 @@
|
|||||||
* **Graph**: Adds sort order options for graph tooltip, closes [#1189](https://github.com/grafana/grafana/issues/1189)
|
* **Graph**: Adds sort order options for graph tooltip, closes [#1189](https://github.com/grafana/grafana/issues/1189)
|
||||||
* **Theme**: Add default theme to config file [#5011](https://github.com/grafana/grafana/pull/5011)
|
* **Theme**: Add default theme to config file [#5011](https://github.com/grafana/grafana/pull/5011)
|
||||||
|
|
||||||
# 3.0.2 Stable (2016-05-16)
|
# 3.0.3 Patch release (unreleased)
|
||||||
|
* **Time picker**: Fixed issue timepicker and UTC when reading time from URL, fixes [#5078](https://github.com/grafana/grafana/issues/5078)
|
||||||
|
* **CloudWatch**: Support for Multiple Account by AssumeRole, closes [#3522](https://github.com/grafana/grafana/issues/3522)
|
||||||
|
|
||||||
|
# 3.0.2 Patch release (2016-05-16)
|
||||||
|
|
||||||
* **Templating**: Fixed issue mixing row repeat and panel repeats, fixes [#4988](https://github.com/grafana/grafana/issues/4988)
|
* **Templating**: Fixed issue mixing row repeat and panel repeats, fixes [#4988](https://github.com/grafana/grafana/issues/4988)
|
||||||
* **Templating**: Fixed issue detecting dependencies in nested variables, fixes [#4987](https://github.com/grafana/grafana/issues/4987), fixes [#4986](https://github.com/grafana/grafana/issues/4986)
|
* **Templating**: Fixed issue detecting dependencies in nested variables, fixes [#4987](https://github.com/grafana/grafana/issues/4987), fixes [#4986](https://github.com/grafana/grafana/issues/4986)
|
||||||
|
|||||||
Generated
+5
@@ -124,6 +124,11 @@
|
|||||||
"Comment": "v1.0.0",
|
"Comment": "v1.0.0",
|
||||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/aws/aws-sdk-go/service/sts",
|
||||||
|
"Comment": "v1.0.0",
|
||||||
|
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/bmizerany/assert",
|
"ImportPath": "github.com/bmizerany/assert",
|
||||||
"Comment": "release.r60-6-ge17e998",
|
"Comment": "release.r60-6-ge17e998",
|
||||||
|
|||||||
+1127
File diff suppressed because it is too large
Load Diff
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package sts
|
||||||
|
|
||||||
|
import "github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
initRequest = func(r *request.Request) {
|
||||||
|
switch r.Operation.Name {
|
||||||
|
case opAssumeRoleWithSAML, opAssumeRoleWithWebIdentity:
|
||||||
|
r.Handlers.Sign.Clear() // these operations are unsigned
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
Vendored
+39
@@ -0,0 +1,39 @@
|
|||||||
|
package sts_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||||
|
"github.com/aws/aws-sdk-go/service/sts"
|
||||||
|
)
|
||||||
|
|
||||||
|
var svc = sts.New(unit.Session, &aws.Config{
|
||||||
|
Region: aws.String("mock-region"),
|
||||||
|
})
|
||||||
|
|
||||||
|
func TestUnsignedRequest_AssumeRoleWithSAML(t *testing.T) {
|
||||||
|
req, _ := svc.AssumeRoleWithSAMLRequest(&sts.AssumeRoleWithSAMLInput{
|
||||||
|
PrincipalArn: aws.String("ARN01234567890123456789"),
|
||||||
|
RoleArn: aws.String("ARN01234567890123456789"),
|
||||||
|
SAMLAssertion: aws.String("ASSERT"),
|
||||||
|
})
|
||||||
|
|
||||||
|
err := req.Sign()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "", req.HTTPRequest.Header.Get("Authorization"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnsignedRequest_AssumeRoleWithWebIdentity(t *testing.T) {
|
||||||
|
req, _ := svc.AssumeRoleWithWebIdentityRequest(&sts.AssumeRoleWithWebIdentityInput{
|
||||||
|
RoleArn: aws.String("ARN01234567890123456789"),
|
||||||
|
RoleSessionName: aws.String("SESSION"),
|
||||||
|
WebIdentityToken: aws.String("TOKEN"),
|
||||||
|
})
|
||||||
|
|
||||||
|
err := req.Sign()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "", req.HTTPRequest.Header.Get("Authorization"))
|
||||||
|
}
|
||||||
+149
@@ -0,0 +1,149 @@
|
|||||||
|
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||||
|
|
||||||
|
package sts_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
|
"github.com/aws/aws-sdk-go/service/sts"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ time.Duration
|
||||||
|
var _ bytes.Buffer
|
||||||
|
|
||||||
|
func ExampleSTS_AssumeRole() {
|
||||||
|
svc := sts.New(session.New())
|
||||||
|
|
||||||
|
params := &sts.AssumeRoleInput{
|
||||||
|
RoleArn: aws.String("arnType"), // Required
|
||||||
|
RoleSessionName: aws.String("roleSessionNameType"), // Required
|
||||||
|
DurationSeconds: aws.Int64(1),
|
||||||
|
ExternalId: aws.String("externalIdType"),
|
||||||
|
Policy: aws.String("sessionPolicyDocumentType"),
|
||||||
|
SerialNumber: aws.String("serialNumberType"),
|
||||||
|
TokenCode: aws.String("tokenCodeType"),
|
||||||
|
}
|
||||||
|
resp, err := svc.AssumeRole(params)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// Print the error, cast err to awserr.Error to get the Code and
|
||||||
|
// Message from an error.
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pretty-print the response data.
|
||||||
|
fmt.Println(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleSTS_AssumeRoleWithSAML() {
|
||||||
|
svc := sts.New(session.New())
|
||||||
|
|
||||||
|
params := &sts.AssumeRoleWithSAMLInput{
|
||||||
|
PrincipalArn: aws.String("arnType"), // Required
|
||||||
|
RoleArn: aws.String("arnType"), // Required
|
||||||
|
SAMLAssertion: aws.String("SAMLAssertionType"), // Required
|
||||||
|
DurationSeconds: aws.Int64(1),
|
||||||
|
Policy: aws.String("sessionPolicyDocumentType"),
|
||||||
|
}
|
||||||
|
resp, err := svc.AssumeRoleWithSAML(params)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// Print the error, cast err to awserr.Error to get the Code and
|
||||||
|
// Message from an error.
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pretty-print the response data.
|
||||||
|
fmt.Println(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleSTS_AssumeRoleWithWebIdentity() {
|
||||||
|
svc := sts.New(session.New())
|
||||||
|
|
||||||
|
params := &sts.AssumeRoleWithWebIdentityInput{
|
||||||
|
RoleArn: aws.String("arnType"), // Required
|
||||||
|
RoleSessionName: aws.String("roleSessionNameType"), // Required
|
||||||
|
WebIdentityToken: aws.String("clientTokenType"), // Required
|
||||||
|
DurationSeconds: aws.Int64(1),
|
||||||
|
Policy: aws.String("sessionPolicyDocumentType"),
|
||||||
|
ProviderId: aws.String("urlType"),
|
||||||
|
}
|
||||||
|
resp, err := svc.AssumeRoleWithWebIdentity(params)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// Print the error, cast err to awserr.Error to get the Code and
|
||||||
|
// Message from an error.
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pretty-print the response data.
|
||||||
|
fmt.Println(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleSTS_DecodeAuthorizationMessage() {
|
||||||
|
svc := sts.New(session.New())
|
||||||
|
|
||||||
|
params := &sts.DecodeAuthorizationMessageInput{
|
||||||
|
EncodedMessage: aws.String("encodedMessageType"), // Required
|
||||||
|
}
|
||||||
|
resp, err := svc.DecodeAuthorizationMessage(params)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// Print the error, cast err to awserr.Error to get the Code and
|
||||||
|
// Message from an error.
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pretty-print the response data.
|
||||||
|
fmt.Println(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleSTS_GetFederationToken() {
|
||||||
|
svc := sts.New(session.New())
|
||||||
|
|
||||||
|
params := &sts.GetFederationTokenInput{
|
||||||
|
Name: aws.String("userNameType"), // Required
|
||||||
|
DurationSeconds: aws.Int64(1),
|
||||||
|
Policy: aws.String("sessionPolicyDocumentType"),
|
||||||
|
}
|
||||||
|
resp, err := svc.GetFederationToken(params)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// Print the error, cast err to awserr.Error to get the Code and
|
||||||
|
// Message from an error.
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pretty-print the response data.
|
||||||
|
fmt.Println(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleSTS_GetSessionToken() {
|
||||||
|
svc := sts.New(session.New())
|
||||||
|
|
||||||
|
params := &sts.GetSessionTokenInput{
|
||||||
|
DurationSeconds: aws.Int64(1),
|
||||||
|
SerialNumber: aws.String("serialNumberType"),
|
||||||
|
TokenCode: aws.String("tokenCodeType"),
|
||||||
|
}
|
||||||
|
resp, err := svc.GetSessionToken(params)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// Print the error, cast err to awserr.Error to get the Code and
|
||||||
|
// Message from an error.
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pretty-print the response data.
|
||||||
|
fmt.Println(resp)
|
||||||
|
}
|
||||||
+130
@@ -0,0 +1,130 @@
|
|||||||
|
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||||
|
|
||||||
|
package sts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/client"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/client/metadata"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
"github.com/aws/aws-sdk-go/private/protocol/query"
|
||||||
|
"github.com/aws/aws-sdk-go/private/signer/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The AWS Security Token Service (STS) is a web service that enables you to
|
||||||
|
// request temporary, limited-privilege credentials for AWS Identity and Access
|
||||||
|
// Management (IAM) users or for users that you authenticate (federated users).
|
||||||
|
// This guide provides descriptions of the STS API. For more detailed information
|
||||||
|
// about using this service, go to Temporary Security Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html).
|
||||||
|
//
|
||||||
|
// As an alternative to using the API, you can use one of the AWS SDKs, which
|
||||||
|
// consist of libraries and sample code for various programming languages and
|
||||||
|
// platforms (Java, Ruby, .NET, iOS, Android, etc.). The SDKs provide a convenient
|
||||||
|
// way to create programmatic access to STS. For example, the SDKs take care
|
||||||
|
// of cryptographically signing requests, managing errors, and retrying requests
|
||||||
|
// automatically. For information about the AWS SDKs, including how to download
|
||||||
|
// and install them, see the Tools for Amazon Web Services page (http://aws.amazon.com/tools/).
|
||||||
|
// For information about setting up signatures and authorization through the
|
||||||
|
// API, go to Signing AWS API Requests (http://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html"
|
||||||
|
// target="_blank) in the AWS General Reference. For general information about
|
||||||
|
// the Query API, go to Making Query Requests (http://docs.aws.amazon.com/IAM/latest/UserGuide/IAM_UsingQueryAPI.html"
|
||||||
|
// target="_blank) in Using IAM. For information about using security tokens
|
||||||
|
// with other AWS products, go to AWS Services That Work with IAM (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html)
|
||||||
|
// in the Using IAM.
|
||||||
|
//
|
||||||
|
// If you're new to AWS and need additional technical information about a specific
|
||||||
|
// AWS product, you can find the product's technical documentation at http://aws.amazon.com/documentation/
|
||||||
|
// (http://aws.amazon.com/documentation/" target="_blank).
|
||||||
|
//
|
||||||
|
// Endpoints
|
||||||
|
//
|
||||||
|
// The AWS Security Token Service (STS) has a default endpoint of https://sts.amazonaws.com
|
||||||
|
// that maps to the US East (N. Virginia) region. Additional regions are available,
|
||||||
|
// but must first be activated in the AWS Management Console before you can
|
||||||
|
// use a different region's endpoint. For more information about activating
|
||||||
|
// a region for STS see Activating STS in a New Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
|
||||||
|
// in the Using IAM.
|
||||||
|
//
|
||||||
|
// For information about STS endpoints, see Regions and Endpoints (http://docs.aws.amazon.com/general/latest/gr/rande.html#sts_region)
|
||||||
|
// in the AWS General Reference.
|
||||||
|
//
|
||||||
|
// Recording API requests
|
||||||
|
//
|
||||||
|
// STS supports AWS CloudTrail, which is a service that records AWS calls for
|
||||||
|
// your AWS account and delivers log files to an Amazon S3 bucket. By using
|
||||||
|
// information collected by CloudTrail, you can determine what requests were
|
||||||
|
// successfully made to STS, who made the request, when it was made, and so
|
||||||
|
// on. To learn more about CloudTrail, including how to turn it on and find
|
||||||
|
// your log files, see the AWS CloudTrail User Guide (http://docs.aws.amazon.com/awscloudtrail/latest/userguide/what_is_cloud_trail_top_level.html).
|
||||||
|
//The service client's operations are safe to be used concurrently.
|
||||||
|
// It is not safe to mutate any of the client's properties though.
|
||||||
|
type STS struct {
|
||||||
|
*client.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for custom client initialization logic
|
||||||
|
var initClient func(*client.Client)
|
||||||
|
|
||||||
|
// Used for custom request initialization logic
|
||||||
|
var initRequest func(*request.Request)
|
||||||
|
|
||||||
|
// A ServiceName is the name of the service the client will make API calls to.
|
||||||
|
const ServiceName = "sts"
|
||||||
|
|
||||||
|
// New creates a new instance of the STS client with a session.
|
||||||
|
// If additional configuration is needed for the client instance use the optional
|
||||||
|
// aws.Config parameter to add your extra config.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// // Create a STS client from just a session.
|
||||||
|
// svc := sts.New(mySession)
|
||||||
|
//
|
||||||
|
// // Create a STS client with additional configuration
|
||||||
|
// svc := sts.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
|
||||||
|
func New(p client.ConfigProvider, cfgs ...*aws.Config) *STS {
|
||||||
|
c := p.ClientConfig(ServiceName, cfgs...)
|
||||||
|
return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
|
||||||
|
}
|
||||||
|
|
||||||
|
// newClient creates, initializes and returns a new service client instance.
|
||||||
|
func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *STS {
|
||||||
|
svc := &STS{
|
||||||
|
Client: client.New(
|
||||||
|
cfg,
|
||||||
|
metadata.ClientInfo{
|
||||||
|
ServiceName: ServiceName,
|
||||||
|
SigningRegion: signingRegion,
|
||||||
|
Endpoint: endpoint,
|
||||||
|
APIVersion: "2011-06-15",
|
||||||
|
},
|
||||||
|
handlers,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handlers
|
||||||
|
svc.Handlers.Sign.PushBack(v4.Sign)
|
||||||
|
svc.Handlers.Build.PushBack(query.Build)
|
||||||
|
svc.Handlers.Unmarshal.PushBack(query.Unmarshal)
|
||||||
|
svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta)
|
||||||
|
svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError)
|
||||||
|
|
||||||
|
// Run custom client initialization if present
|
||||||
|
if initClient != nil {
|
||||||
|
initClient(svc.Client)
|
||||||
|
}
|
||||||
|
|
||||||
|
return svc
|
||||||
|
}
|
||||||
|
|
||||||
|
// newRequest creates a new request for a STS operation and runs any
|
||||||
|
// custom request initialization.
|
||||||
|
func (c *STS) newRequest(op *request.Operation, params, data interface{}) *request.Request {
|
||||||
|
req := c.NewRequest(op, params, data)
|
||||||
|
|
||||||
|
// Run custom request initialization if present
|
||||||
|
if initRequest != nil {
|
||||||
|
initRequest(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
return req
|
||||||
|
}
|
||||||
Generated
Vendored
+38
@@ -0,0 +1,38 @@
|
|||||||
|
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||||
|
|
||||||
|
// Package stsiface provides an interface for the AWS Security Token Service.
|
||||||
|
package stsiface
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
"github.com/aws/aws-sdk-go/service/sts"
|
||||||
|
)
|
||||||
|
|
||||||
|
// STSAPI is the interface type for sts.STS.
|
||||||
|
type STSAPI interface {
|
||||||
|
AssumeRoleRequest(*sts.AssumeRoleInput) (*request.Request, *sts.AssumeRoleOutput)
|
||||||
|
|
||||||
|
AssumeRole(*sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error)
|
||||||
|
|
||||||
|
AssumeRoleWithSAMLRequest(*sts.AssumeRoleWithSAMLInput) (*request.Request, *sts.AssumeRoleWithSAMLOutput)
|
||||||
|
|
||||||
|
AssumeRoleWithSAML(*sts.AssumeRoleWithSAMLInput) (*sts.AssumeRoleWithSAMLOutput, error)
|
||||||
|
|
||||||
|
AssumeRoleWithWebIdentityRequest(*sts.AssumeRoleWithWebIdentityInput) (*request.Request, *sts.AssumeRoleWithWebIdentityOutput)
|
||||||
|
|
||||||
|
AssumeRoleWithWebIdentity(*sts.AssumeRoleWithWebIdentityInput) (*sts.AssumeRoleWithWebIdentityOutput, error)
|
||||||
|
|
||||||
|
DecodeAuthorizationMessageRequest(*sts.DecodeAuthorizationMessageInput) (*request.Request, *sts.DecodeAuthorizationMessageOutput)
|
||||||
|
|
||||||
|
DecodeAuthorizationMessage(*sts.DecodeAuthorizationMessageInput) (*sts.DecodeAuthorizationMessageOutput, error)
|
||||||
|
|
||||||
|
GetFederationTokenRequest(*sts.GetFederationTokenInput) (*request.Request, *sts.GetFederationTokenOutput)
|
||||||
|
|
||||||
|
GetFederationToken(*sts.GetFederationTokenInput) (*sts.GetFederationTokenOutput, error)
|
||||||
|
|
||||||
|
GetSessionTokenRequest(*sts.GetSessionTokenInput) (*request.Request, *sts.GetSessionTokenOutput)
|
||||||
|
|
||||||
|
GetSessionToken(*sts.GetSessionTokenInput) (*sts.GetSessionTokenOutput, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ STSAPI = (*sts.STS)(nil)
|
||||||
@@ -8,7 +8,7 @@ graphite:
|
|||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
- /etc/timezone:/etc/timezone:ro
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
|
||||||
fake-data-gen:
|
fake-graphite-data:
|
||||||
image: grafana/fake-data-gen
|
image: grafana/fake-data-gen
|
||||||
net: bridge
|
net: bridge
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -4,3 +4,11 @@ influxdb:
|
|||||||
- "2004:2004"
|
- "2004:2004"
|
||||||
- "8083:8083"
|
- "8083:8083"
|
||||||
- "8086:8086"
|
- "8086:8086"
|
||||||
|
|
||||||
|
fake-influxdb-data:
|
||||||
|
image: grafana/fake-data-gen
|
||||||
|
net: bridge
|
||||||
|
environment:
|
||||||
|
FD_DATASOURCE: influxdb
|
||||||
|
FD_PORT: 8086
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ opentsdb:
|
|||||||
ports:
|
ports:
|
||||||
- "4242:4242"
|
- "4242:4242"
|
||||||
|
|
||||||
fake-data-gen:
|
fake-opentsdb-data:
|
||||||
image: grafana/fake-data-gen
|
image: grafana/fake-data-gen
|
||||||
net: bridge
|
net: bridge
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -1,6 +1,16 @@
|
|||||||
prometheus:
|
prometheus:
|
||||||
build: blocks/prometheus
|
build: blocks/prometheus
|
||||||
|
net: bridge
|
||||||
ports:
|
ports:
|
||||||
- "9090:9090"
|
- "9090:9090"
|
||||||
volumes:
|
volumes:
|
||||||
- /var/docker/prometheus:/prometheus-data
|
- /var/docker/prometheus:/prometheus-data
|
||||||
|
|
||||||
|
fake-prometheus-data:
|
||||||
|
image: grafana/fake-data-gen
|
||||||
|
net: bridge
|
||||||
|
ports:
|
||||||
|
- "9091:9091"
|
||||||
|
environment:
|
||||||
|
FD_DATASOURCE: prom
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ Name | The data source name, important that this is the same as in Grafana v1.x
|
|||||||
Default | Default data source means that it will be pre-selected for new panels.
|
Default | Default data source means that it will be pre-selected for new panels.
|
||||||
Credentials profile name | Specify the name of the profile to use (if you use `~/aws/credentials` file), leave blank for default. This option was introduced in Grafana 2.5.1
|
Credentials profile name | Specify the name of the profile to use (if you use `~/aws/credentials` file), leave blank for default. This option was introduced in Grafana 2.5.1
|
||||||
Default Region | Used in query editor to set region (can be changed on per query basis)
|
Default Region | Used in query editor to set region (can be changed on per query basis)
|
||||||
|
Custom Metrics namespace | Specify the CloudWatch namespace of Custom metrics
|
||||||
|
Assume Role Arn | Specify the ARN of the role to assume
|
||||||
|
|
||||||
## Authentication
|
## Authentication
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ page_keywords: grafana, opentsdb, documentation
|
|||||||
# OpenTSDB Guide
|
# OpenTSDB Guide
|
||||||
The newest release of Grafana adds additional functionality when using an OpenTSDB Data source.
|
The newest release of Grafana adds additional functionality when using an OpenTSDB Data source.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
1. Open the side menu by clicking the the Grafana icon in the top header.
|
1. Open the side menu by clicking the the Grafana icon in the top header.
|
||||||
2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`.
|
2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`.
|
||||||
|
|
||||||
> NOTE: If this link is missing in the side menu it means that your current user does not have the `Admin` role for the current organization.
|
> NOTE: If this link is missing in the side menu it means that your current user does not have the `Admin` role for the current organization.
|
||||||
|
|
||||||
|
|||||||
@@ -18,4 +18,5 @@ dashboards, creating users and updating data sources.
|
|||||||
* [User API](/http_api/user/)
|
* [User API](/http_api/user/)
|
||||||
* [Admin API](/http_api/admin/)
|
* [Admin API](/http_api/admin/)
|
||||||
* [Snapshot API](/http_api/snapshot/)
|
* [Snapshot API](/http_api/snapshot/)
|
||||||
|
* [Preferences API](/http_api/preferences/)
|
||||||
* [Other API](/http_api/other/)
|
* [Other API](/http_api/other/)
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
----
|
||||||
|
page_title: Preferences API
|
||||||
|
page_description: Grafana Preferences API Reference
|
||||||
|
page_keywords: grafana, preferences, http, api, documentation
|
||||||
|
---
|
||||||
|
|
||||||
|
# User and Org Preferences API
|
||||||
|
|
||||||
|
Keys:
|
||||||
|
|
||||||
|
- **theme** - One of: ``light``, ``dark``, or an empty string for the default theme
|
||||||
|
- **homeDashboardId** - The numerical ``:id`` of a favorited dashboard, default: ``0``
|
||||||
|
- **timezone** - One of: ``utc``, ``browser``, or an empty string for the default
|
||||||
|
|
||||||
|
Omitting a key will cause the current value to be replaced with the
|
||||||
|
system default value.
|
||||||
|
|
||||||
|
## Get Current User Prefs
|
||||||
|
|
||||||
|
`GET /api/user/preferences`
|
||||||
|
|
||||||
|
**Example Request**:
|
||||||
|
|
||||||
|
GET /api/user/preferences HTTP/1.1
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||||
|
|
||||||
|
**Example Response**:
|
||||||
|
|
||||||
|
HTTP/1.1 200
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{"theme":"","homeDashboardId":0,"timezone":""}
|
||||||
|
|
||||||
|
## Update Current User Prefs
|
||||||
|
|
||||||
|
`PUT /api/user/preferences`
|
||||||
|
|
||||||
|
**Example Request**:
|
||||||
|
|
||||||
|
PUT /api/user/preferences HTTP/1.1
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||||
|
|
||||||
|
{
|
||||||
|
"theme": "",
|
||||||
|
"homeDashboardId":0,
|
||||||
|
"timezone":"utc"
|
||||||
|
}
|
||||||
|
|
||||||
|
**Example Response**:
|
||||||
|
|
||||||
|
HTTP/1.1 200
|
||||||
|
Content-Type: text/plain; charset=utf-8
|
||||||
|
|
||||||
|
{"message":"Preferences updated"}
|
||||||
|
|
||||||
|
## Get Current Org Prefs
|
||||||
|
|
||||||
|
`GET /api/org/preferences`
|
||||||
|
|
||||||
|
**Example Request**:
|
||||||
|
|
||||||
|
GET /api/org/preferences HTTP/1.1
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||||
|
|
||||||
|
**Example Response**:
|
||||||
|
|
||||||
|
HTTP/1.1 200
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{"theme":"","homeDashboardId":0,"timezone":""}
|
||||||
|
|
||||||
|
## Update Current Org Prefs
|
||||||
|
|
||||||
|
`PUT /api/org/preferences`
|
||||||
|
|
||||||
|
**Example Request**:
|
||||||
|
|
||||||
|
PUT /api/org/preferences HTTP/1.1
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||||
|
|
||||||
|
{
|
||||||
|
"theme": "",
|
||||||
|
"homeDashboardId":0,
|
||||||
|
"timezone":"utc"
|
||||||
|
}
|
||||||
|
|
||||||
|
**Example Response**:
|
||||||
|
|
||||||
|
HTTP/1.1 200
|
||||||
|
Content-Type: text/plain; charset=utf-8
|
||||||
|
|
||||||
|
{"message":"Preferences updated"}
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"stable": "3.0.1",
|
"stable": "3.0.2",
|
||||||
"testing": "3.0.1"
|
"testing": "3.0.2"
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@
|
|||||||
"zone.js": "^0.6.6",
|
"zone.js": "^0.6.6",
|
||||||
"autoprefixer": "^6.3.3",
|
"autoprefixer": "^6.3.3",
|
||||||
"es6-promise": "^3.0.2",
|
"es6-promise": "^3.0.2",
|
||||||
"es6-shim": "^0.35.0",
|
"es6-shim": "^0.35.1",
|
||||||
"expect.js": "~0.2.0",
|
"expect.js": "~0.2.0",
|
||||||
"glob": "~3.2.7",
|
"glob": "~3.2.7",
|
||||||
"grunt": "~0.4.0",
|
"grunt": "~0.4.0",
|
||||||
|
|||||||
@@ -14,6 +14,6 @@ CONF_DIR=/etc/grafana
|
|||||||
|
|
||||||
CONF_FILE=/etc/grafana/grafana.ini
|
CONF_FILE=/etc/grafana/grafana.ini
|
||||||
|
|
||||||
RESTART_ON_UPGRADE=true
|
RESTART_ON_UPGRADE=false
|
||||||
|
|
||||||
PLUGINS_DIR=/var/lib/grafana/plugins
|
PLUGINS_DIR=/var/lib/grafana/plugins
|
||||||
|
|||||||
@@ -14,6 +14,6 @@ CONF_DIR=/etc/grafana
|
|||||||
|
|
||||||
CONF_FILE=/etc/grafana/grafana.ini
|
CONF_FILE=/etc/grafana/grafana.ini
|
||||||
|
|
||||||
RESTART_ON_UPGRADE=true
|
RESTART_ON_UPGRADE=false
|
||||||
|
|
||||||
PLUGINS_DIR=/var/lib/grafana/plugins
|
PLUGINS_DIR=/var/lib/grafana/plugins
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
@@ -14,6 +16,8 @@ import (
|
|||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
"github.com/aws/aws-sdk-go/service/cloudwatch"
|
"github.com/aws/aws-sdk-go/service/cloudwatch"
|
||||||
"github.com/aws/aws-sdk-go/service/ec2"
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
|
"github.com/aws/aws-sdk-go/service/sts"
|
||||||
|
"github.com/grafana/grafana/pkg/log"
|
||||||
"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"
|
||||||
)
|
)
|
||||||
@@ -44,31 +48,96 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var awsCredentials map[string]*credentials.Credentials = make(map[string]*credentials.Credentials)
|
type cache struct {
|
||||||
|
credential *credentials.Credentials
|
||||||
|
expiration *time.Time
|
||||||
|
}
|
||||||
|
|
||||||
func getCredentials(profile string) *credentials.Credentials {
|
var awsCredentialCache map[string]cache = make(map[string]cache)
|
||||||
if _, ok := awsCredentials[profile]; ok {
|
var credentialCacheLock sync.RWMutex
|
||||||
return awsCredentials[profile]
|
|
||||||
|
func getCredentials(profile string, region string, assumeRoleArn string) *credentials.Credentials {
|
||||||
|
credentialCacheLock.RLock()
|
||||||
|
if _, ok := awsCredentialCache[profile]; ok {
|
||||||
|
if awsCredentialCache[profile].expiration != nil &&
|
||||||
|
(*awsCredentialCache[profile].expiration).After(time.Now().UTC()) {
|
||||||
|
result := awsCredentialCache[profile].credential
|
||||||
|
credentialCacheLock.RUnlock()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
credentialCacheLock.RUnlock()
|
||||||
|
|
||||||
|
accessKeyId := ""
|
||||||
|
secretAccessKey := ""
|
||||||
|
sessionToken := ""
|
||||||
|
var expiration *time.Time
|
||||||
|
expiration = nil
|
||||||
|
if strings.Index(assumeRoleArn, "arn:aws:iam:") == 0 {
|
||||||
|
params := &sts.AssumeRoleInput{
|
||||||
|
RoleArn: aws.String(assumeRoleArn),
|
||||||
|
RoleSessionName: aws.String("GrafanaSession"),
|
||||||
|
DurationSeconds: aws.Int64(900),
|
||||||
|
}
|
||||||
|
|
||||||
|
stsSess := session.New()
|
||||||
|
stsCreds := credentials.NewChainCredentials(
|
||||||
|
[]credentials.Provider{
|
||||||
|
&credentials.EnvProvider{},
|
||||||
|
&credentials.SharedCredentialsProvider{Filename: "", Profile: profile},
|
||||||
|
&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(stsSess), ExpiryWindow: 5 * time.Minute},
|
||||||
|
})
|
||||||
|
stsConfig := &aws.Config{
|
||||||
|
Region: aws.String(region),
|
||||||
|
Credentials: stsCreds,
|
||||||
|
}
|
||||||
|
svc := sts.New(session.New(stsConfig), stsConfig)
|
||||||
|
resp, err := svc.AssumeRole(params)
|
||||||
|
if err != nil {
|
||||||
|
// ignore
|
||||||
|
log.Error(3, "CloudWatch: Failed to assume role", err)
|
||||||
|
}
|
||||||
|
if resp.Credentials != nil {
|
||||||
|
accessKeyId = *resp.Credentials.AccessKeyId
|
||||||
|
secretAccessKey = *resp.Credentials.SecretAccessKey
|
||||||
|
sessionToken = *resp.Credentials.SessionToken
|
||||||
|
expiration = resp.Credentials.Expiration
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sess := session.New()
|
sess := session.New()
|
||||||
creds := credentials.NewChainCredentials(
|
creds := credentials.NewChainCredentials(
|
||||||
[]credentials.Provider{
|
[]credentials.Provider{
|
||||||
|
&credentials.StaticProvider{Value: credentials.Value{
|
||||||
|
AccessKeyID: accessKeyId,
|
||||||
|
SecretAccessKey: secretAccessKey,
|
||||||
|
SessionToken: sessionToken,
|
||||||
|
}},
|
||||||
&credentials.EnvProvider{},
|
&credentials.EnvProvider{},
|
||||||
&credentials.SharedCredentialsProvider{Filename: "", Profile: profile},
|
&credentials.SharedCredentialsProvider{Filename: "", Profile: profile},
|
||||||
&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute},
|
&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute},
|
||||||
})
|
})
|
||||||
awsCredentials[profile] = creds
|
credentialCacheLock.Lock()
|
||||||
|
awsCredentialCache[profile] = cache{
|
||||||
|
credential: creds,
|
||||||
|
expiration: expiration,
|
||||||
|
}
|
||||||
|
credentialCacheLock.Unlock()
|
||||||
|
|
||||||
return creds
|
return creds
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) {
|
func getAwsConfig(req *cwRequest) *aws.Config {
|
||||||
|
assumeRoleArn := req.DataSource.JsonData.Get("assumeRoleArn").MustString()
|
||||||
cfg := &aws.Config{
|
cfg := &aws.Config{
|
||||||
Region: aws.String(req.Region),
|
Region: aws.String(req.Region),
|
||||||
Credentials: getCredentials(req.DataSource.Database),
|
Credentials: getCredentials(req.DataSource.Database, req.Region, assumeRoleArn),
|
||||||
}
|
}
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) {
|
||||||
|
cfg := getAwsConfig(req)
|
||||||
svc := cloudwatch.New(session.New(cfg), cfg)
|
svc := cloudwatch.New(session.New(cfg), cfg)
|
||||||
|
|
||||||
reqParam := &struct {
|
reqParam := &struct {
|
||||||
@@ -104,11 +173,7 @@ func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleListMetrics(req *cwRequest, c *middleware.Context) {
|
func handleListMetrics(req *cwRequest, c *middleware.Context) {
|
||||||
cfg := &aws.Config{
|
cfg := getAwsConfig(req)
|
||||||
Region: aws.String(req.Region),
|
|
||||||
Credentials: getCredentials(req.DataSource.Database),
|
|
||||||
}
|
|
||||||
|
|
||||||
svc := cloudwatch.New(session.New(cfg), cfg)
|
svc := cloudwatch.New(session.New(cfg), cfg)
|
||||||
|
|
||||||
reqParam := &struct {
|
reqParam := &struct {
|
||||||
@@ -144,11 +209,7 @@ func handleListMetrics(req *cwRequest, c *middleware.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleDescribeAlarms(req *cwRequest, c *middleware.Context) {
|
func handleDescribeAlarms(req *cwRequest, c *middleware.Context) {
|
||||||
cfg := &aws.Config{
|
cfg := getAwsConfig(req)
|
||||||
Region: aws.String(req.Region),
|
|
||||||
Credentials: getCredentials(req.DataSource.Database),
|
|
||||||
}
|
|
||||||
|
|
||||||
svc := cloudwatch.New(session.New(cfg), cfg)
|
svc := cloudwatch.New(session.New(cfg), cfg)
|
||||||
|
|
||||||
reqParam := &struct {
|
reqParam := &struct {
|
||||||
@@ -187,11 +248,7 @@ func handleDescribeAlarms(req *cwRequest, c *middleware.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) {
|
func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) {
|
||||||
cfg := &aws.Config{
|
cfg := getAwsConfig(req)
|
||||||
Region: aws.String(req.Region),
|
|
||||||
Credentials: getCredentials(req.DataSource.Database),
|
|
||||||
}
|
|
||||||
|
|
||||||
svc := cloudwatch.New(session.New(cfg), cfg)
|
svc := cloudwatch.New(session.New(cfg), cfg)
|
||||||
|
|
||||||
reqParam := &struct {
|
reqParam := &struct {
|
||||||
@@ -227,11 +284,7 @@ func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleDescribeAlarmHistory(req *cwRequest, c *middleware.Context) {
|
func handleDescribeAlarmHistory(req *cwRequest, c *middleware.Context) {
|
||||||
cfg := &aws.Config{
|
cfg := getAwsConfig(req)
|
||||||
Region: aws.String(req.Region),
|
|
||||||
Credentials: getCredentials(req.DataSource.Database),
|
|
||||||
}
|
|
||||||
|
|
||||||
svc := cloudwatch.New(session.New(cfg), cfg)
|
svc := cloudwatch.New(session.New(cfg), cfg)
|
||||||
|
|
||||||
reqParam := &struct {
|
reqParam := &struct {
|
||||||
@@ -263,11 +316,7 @@ func handleDescribeAlarmHistory(req *cwRequest, c *middleware.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleDescribeInstances(req *cwRequest, c *middleware.Context) {
|
func handleDescribeInstances(req *cwRequest, c *middleware.Context) {
|
||||||
cfg := &aws.Config{
|
cfg := getAwsConfig(req)
|
||||||
Region: aws.String(req.Region),
|
|
||||||
Credentials: getCredentials(req.DataSource.Database),
|
|
||||||
}
|
|
||||||
|
|
||||||
svc := ec2.New(session.New(cfg), cfg)
|
svc := ec2.New(session.New(cfg), cfg)
|
||||||
|
|
||||||
reqParam := &struct {
|
reqParam := &struct {
|
||||||
|
|||||||
@@ -166,7 +166,8 @@ func handleGetMetrics(req *cwRequest, c *middleware.Context) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var err error
|
var err error
|
||||||
if namespaceMetrics, err = getMetricsForCustomMetrics(req.Region, reqParam.Parameters.Namespace, req.DataSource.Database, getAllMetrics); err != nil {
|
assumeRoleArn := req.DataSource.JsonData.Get("assumeRoleArn").MustString()
|
||||||
|
if namespaceMetrics, err = getMetricsForCustomMetrics(req.Region, reqParam.Parameters.Namespace, req.DataSource.Database, assumeRoleArn, getAllMetrics); err != nil {
|
||||||
c.JsonApiErr(500, "Unable to call AWS API", err)
|
c.JsonApiErr(500, "Unable to call AWS API", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -199,7 +200,8 @@ func handleGetDimensions(req *cwRequest, c *middleware.Context) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var err error
|
var err error
|
||||||
if dimensionValues, err = getDimensionsForCustomMetrics(req.Region, reqParam.Parameters.Namespace, req.DataSource.Database, getAllMetrics); err != nil {
|
assumeRoleArn := req.DataSource.JsonData.Get("assumeRoleArn").MustString()
|
||||||
|
if dimensionValues, err = getDimensionsForCustomMetrics(req.Region, reqParam.Parameters.Namespace, req.DataSource.Database, assumeRoleArn, getAllMetrics); err != nil {
|
||||||
c.JsonApiErr(500, "Unable to call AWS API", err)
|
c.JsonApiErr(500, "Unable to call AWS API", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -214,10 +216,10 @@ func handleGetDimensions(req *cwRequest, c *middleware.Context) {
|
|||||||
c.JSON(200, result)
|
c.JSON(200, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllMetrics(region string, namespace string, database string) (cloudwatch.ListMetricsOutput, error) {
|
func getAllMetrics(region string, namespace string, database string, assumeRoleArn string) (cloudwatch.ListMetricsOutput, error) {
|
||||||
cfg := &aws.Config{
|
cfg := &aws.Config{
|
||||||
Region: aws.String(region),
|
Region: aws.String(region),
|
||||||
Credentials: getCredentials(database),
|
Credentials: getCredentials(database, region, assumeRoleArn),
|
||||||
}
|
}
|
||||||
|
|
||||||
svc := cloudwatch.New(session.New(cfg), cfg)
|
svc := cloudwatch.New(session.New(cfg), cfg)
|
||||||
@@ -244,8 +246,8 @@ func getAllMetrics(region string, namespace string, database string) (cloudwatch
|
|||||||
|
|
||||||
var metricsCacheLock sync.Mutex
|
var metricsCacheLock sync.Mutex
|
||||||
|
|
||||||
func getMetricsForCustomMetrics(region string, namespace string, database string, getAllMetrics func(string, string, string) (cloudwatch.ListMetricsOutput, error)) ([]string, error) {
|
func getMetricsForCustomMetrics(region string, namespace string, database string, assumeRoleArn string, getAllMetrics func(string, string, string, string) (cloudwatch.ListMetricsOutput, error)) ([]string, error) {
|
||||||
result, err := getAllMetrics(region, namespace, database)
|
result, err := getAllMetrics(region, namespace, database, assumeRoleArn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []string{}, err
|
return []string{}, err
|
||||||
}
|
}
|
||||||
@@ -282,8 +284,8 @@ func getMetricsForCustomMetrics(region string, namespace string, database string
|
|||||||
|
|
||||||
var dimensionsCacheLock sync.Mutex
|
var dimensionsCacheLock sync.Mutex
|
||||||
|
|
||||||
func getDimensionsForCustomMetrics(region string, namespace string, database string, getAllMetrics func(string, string, string) (cloudwatch.ListMetricsOutput, error)) ([]string, error) {
|
func getDimensionsForCustomMetrics(region string, namespace string, database string, assumeRoleArn string, getAllMetrics func(string, string, string, string) (cloudwatch.ListMetricsOutput, error)) ([]string, error) {
|
||||||
result, err := getAllMetrics(region, namespace, database)
|
result, err := getAllMetrics(region, namespace, database, assumeRoleArn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []string{}, err
|
return []string{}, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ func TestCloudWatchMetrics(t *testing.T) {
|
|||||||
region := "us-east-1"
|
region := "us-east-1"
|
||||||
namespace := "Foo"
|
namespace := "Foo"
|
||||||
database := "default"
|
database := "default"
|
||||||
f := func(region string, namespace string, database string) (cloudwatch.ListMetricsOutput, error) {
|
assumeRoleArn := ""
|
||||||
|
f := func(region string, namespace string, database string, assumeRoleArn string) (cloudwatch.ListMetricsOutput, error) {
|
||||||
return cloudwatch.ListMetricsOutput{
|
return cloudwatch.ListMetricsOutput{
|
||||||
Metrics: []*cloudwatch.Metric{
|
Metrics: []*cloudwatch.Metric{
|
||||||
{
|
{
|
||||||
@@ -28,7 +29,7 @@ func TestCloudWatchMetrics(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
metrics, _ := getMetricsForCustomMetrics(region, namespace, database, f)
|
metrics, _ := getMetricsForCustomMetrics(region, namespace, database, assumeRoleArn, f)
|
||||||
|
|
||||||
Convey("Should contain Test_MetricName", func() {
|
Convey("Should contain Test_MetricName", func() {
|
||||||
So(metrics, ShouldContain, "Test_MetricName")
|
So(metrics, ShouldContain, "Test_MetricName")
|
||||||
@@ -39,7 +40,8 @@ func TestCloudWatchMetrics(t *testing.T) {
|
|||||||
region := "us-east-1"
|
region := "us-east-1"
|
||||||
namespace := "Foo"
|
namespace := "Foo"
|
||||||
database := "default"
|
database := "default"
|
||||||
f := func(region string, namespace string, database string) (cloudwatch.ListMetricsOutput, error) {
|
assumeRoleArn := ""
|
||||||
|
f := func(region string, namespace string, database string, assumeRoleArn string) (cloudwatch.ListMetricsOutput, error) {
|
||||||
return cloudwatch.ListMetricsOutput{
|
return cloudwatch.ListMetricsOutput{
|
||||||
Metrics: []*cloudwatch.Metric{
|
Metrics: []*cloudwatch.Metric{
|
||||||
{
|
{
|
||||||
@@ -53,7 +55,7 @@ func TestCloudWatchMetrics(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
dimensionKeys, _ := getDimensionsForCustomMetrics(region, namespace, database, f)
|
dimensionKeys, _ := getDimensionsForCustomMetrics(region, namespace, database, assumeRoleArn, f)
|
||||||
|
|
||||||
Convey("Should contain Test_DimensionName", func() {
|
Convey("Should contain Test_DimensionName", func() {
|
||||||
So(dimensionKeys, ShouldContain, "Test_DimensionName")
|
So(dimensionKeys, ShouldContain, "Test_DimensionName")
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro
|
|||||||
"buildstamp": setting.BuildStamp,
|
"buildstamp": setting.BuildStamp,
|
||||||
"latestVersion": plugins.GrafanaLatestVersion,
|
"latestVersion": plugins.GrafanaLatestVersion,
|
||||||
"hasUpdate": plugins.GrafanaHasUpdate,
|
"hasUpdate": plugins.GrafanaHasUpdate,
|
||||||
|
"env": setting.Env,
|
||||||
},
|
},
|
||||||
"alertingEnabled": setting.AlertingEnabled,
|
"alertingEnabled": setting.AlertingEnabled,
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-1
@@ -24,7 +24,16 @@ func GetPluginSettings(orgId int64) (map[string]*m.PluginSettingInfoDTO, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// default to enabled true
|
// default to enabled true
|
||||||
opt := &m.PluginSettingInfoDTO{Enabled: true}
|
opt := &m.PluginSettingInfoDTO{
|
||||||
|
PluginId: pluginDef.Id,
|
||||||
|
OrgId: orgId,
|
||||||
|
Enabled: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// apps are disabled by default
|
||||||
|
if pluginDef.Type == PluginTypeApp {
|
||||||
|
opt.Enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
// if it's included in app check app settings
|
// if it's included in app check app settings
|
||||||
if pluginDef.IncludedInAppId != "" {
|
if pluginDef.IncludedInAppId != "" {
|
||||||
|
|||||||
+16
-6
@@ -534,6 +534,17 @@ var logLevels = map[string]int{
|
|||||||
"Critical": 5,
|
"Critical": 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getLogLevel(key string, defaultName string) (string, int) {
|
||||||
|
levelName := Cfg.Section(key).Key("level").In(defaultName, []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"})
|
||||||
|
|
||||||
|
level, ok := logLevels[levelName]
|
||||||
|
if !ok {
|
||||||
|
log.Fatal(4, "Unknown log level: %s", levelName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return levelName, level
|
||||||
|
}
|
||||||
|
|
||||||
func initLogging(args *CommandLineArgs) {
|
func initLogging(args *CommandLineArgs) {
|
||||||
//close any existing log handlers.
|
//close any existing log handlers.
|
||||||
log.Close()
|
log.Close()
|
||||||
@@ -541,8 +552,12 @@ func initLogging(args *CommandLineArgs) {
|
|||||||
LogModes = strings.Split(Cfg.Section("log").Key("mode").MustString("console"), ",")
|
LogModes = strings.Split(Cfg.Section("log").Key("mode").MustString("console"), ",")
|
||||||
LogsPath = makeAbsolute(Cfg.Section("paths").Key("logs").String(), HomePath)
|
LogsPath = makeAbsolute(Cfg.Section("paths").Key("logs").String(), HomePath)
|
||||||
|
|
||||||
|
defaultLevelName, _ := getLogLevel("log", "Info")
|
||||||
|
|
||||||
LogConfigs = make([]util.DynMap, len(LogModes))
|
LogConfigs = make([]util.DynMap, len(LogModes))
|
||||||
|
|
||||||
for i, mode := range LogModes {
|
for i, mode := range LogModes {
|
||||||
|
|
||||||
mode = strings.TrimSpace(mode)
|
mode = strings.TrimSpace(mode)
|
||||||
sec, err := Cfg.GetSection("log." + mode)
|
sec, err := Cfg.GetSection("log." + mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -550,12 +565,7 @@ func initLogging(args *CommandLineArgs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Log level.
|
// Log level.
|
||||||
levelName := Cfg.Section("log."+mode).Key("level").In("Trace",
|
_, level := getLogLevel("log."+mode, defaultLevelName)
|
||||||
[]string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"})
|
|
||||||
level, ok := logLevels[levelName]
|
|
||||||
if !ok {
|
|
||||||
log.Fatal(4, "Unknown log level: %s", levelName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate log configuration.
|
// Generate log configuration.
|
||||||
switch mode {
|
switch mode {
|
||||||
|
|||||||
+3
-1
@@ -42,7 +42,9 @@ export class GrafanaApp {
|
|||||||
app.constant('grafanaVersion', "@grafanaVersion@");
|
app.constant('grafanaVersion', "@grafanaVersion@");
|
||||||
|
|
||||||
app.config(($locationProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) => {
|
app.config(($locationProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) => {
|
||||||
//$compileProvider.debugInfoEnabled(false);
|
if (config.buildInfo.env !== 'development') {
|
||||||
|
$compileProvider.debugInfoEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
this.registerFunctions.controller = $controllerProvider.register;
|
this.registerFunctions.controller = $controllerProvider.register;
|
||||||
this.registerFunctions.directive = $compileProvider.directive;
|
this.registerFunctions.directive = $compileProvider.directive;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export function parse(text, roundUp?) {
|
|||||||
mathString = text.substring(index + 2);
|
mathString = text.substring(index + 2);
|
||||||
}
|
}
|
||||||
// We're going to just require ISO8601 timestamps, k?
|
// We're going to just require ISO8601 timestamps, k?
|
||||||
time = moment(parseString);
|
time = moment(parseString, moment.ISO_8601);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mathString.length) {
|
if (!mathString.length) {
|
||||||
|
|||||||
@@ -396,6 +396,7 @@ function($, _) {
|
|||||||
kbn.valueFormats.ev = kbn.formatBuilders.decimalSIPrefix('eV');
|
kbn.valueFormats.ev = kbn.formatBuilders.decimalSIPrefix('eV');
|
||||||
kbn.valueFormats.amp = kbn.formatBuilders.decimalSIPrefix('A');
|
kbn.valueFormats.amp = kbn.formatBuilders.decimalSIPrefix('A');
|
||||||
kbn.valueFormats.volt = kbn.formatBuilders.decimalSIPrefix('V');
|
kbn.valueFormats.volt = kbn.formatBuilders.decimalSIPrefix('V');
|
||||||
|
kbn.valueFormats.dBm = kbn.formatBuilders.decimalSIPrefix('dBm');
|
||||||
|
|
||||||
// Temperature
|
// Temperature
|
||||||
kbn.valueFormats.celsius = kbn.formatBuilders.fixedUnit('°C');
|
kbn.valueFormats.celsius = kbn.formatBuilders.fixedUnit('°C');
|
||||||
@@ -677,6 +678,7 @@ function($, _) {
|
|||||||
{text: 'electron volt (eV)', value: 'ev' },
|
{text: 'electron volt (eV)', value: 'ev' },
|
||||||
{text: 'Ampere (A)', value: 'amp' },
|
{text: 'Ampere (A)', value: 'amp' },
|
||||||
{text: 'Volt (V)', value: 'volt' },
|
{text: 'Volt (V)', value: 'volt' },
|
||||||
|
{text: 'Decibel-milliwatt (dBm)', value: 'dBm' },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,10 +55,11 @@ define([
|
|||||||
}, this);
|
}, this);
|
||||||
});
|
});
|
||||||
|
|
||||||
promiseCached = $q.all(promises)
|
promiseCached = $q.all(promises).then(function() {
|
||||||
.then(function() {
|
return list;
|
||||||
return list;
|
}).catch(function(err) {
|
||||||
});
|
$rootScope.appEvent('alert-error', ['Annotations failed', (err.message || err)]);
|
||||||
|
});
|
||||||
|
|
||||||
return promiseCached;
|
return promiseCached;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ function (angular, $, _, moment) {
|
|||||||
|
|
||||||
// cleans meta data and other non peristent state
|
// cleans meta data and other non peristent state
|
||||||
p.getSaveModelClone = function() {
|
p.getSaveModelClone = function() {
|
||||||
var copy = angular.copy(this);
|
var copy = $.extend(true, {}, this);
|
||||||
delete copy.meta;
|
delete copy.meta;
|
||||||
return copy;
|
return copy;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ define([
|
|||||||
|
|
||||||
if (!isNaN(value)) {
|
if (!isNaN(value)) {
|
||||||
var epoch = parseInt(value);
|
var epoch = parseInt(value);
|
||||||
return moment(epoch);
|
return moment.utc(epoch);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -90,6 +90,15 @@ export class PanelCtrl {
|
|||||||
this.addEditorTab('General', 'public/app/partials/panelgeneral.html');
|
this.addEditorTab('General', 'public/app/partials/panelgeneral.html');
|
||||||
this.editModeInitiated = true;
|
this.editModeInitiated = true;
|
||||||
this.events.emit('init-edit-mode', null);
|
this.events.emit('init-edit-mode', null);
|
||||||
|
|
||||||
|
var route = this.$injector.get('$route');
|
||||||
|
if (route.current.params.editorTab) {
|
||||||
|
this.editorTabs.forEach((tab, i) => {
|
||||||
|
if (tab.title === route.current.params.editorTab) {
|
||||||
|
this.editorTabIndex = i;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addEditorTab(title, directiveFn, index?) {
|
addEditorTab(title, directiveFn, index?) {
|
||||||
|
|||||||
@@ -24,4 +24,11 @@
|
|||||||
Namespaces of Custom Metrics
|
Namespaces of Custom Metrics
|
||||||
</info-popover>
|
</info-popover>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="gf-form">
|
||||||
|
<label class="gf-form-label width-13">Assume Role ARN</label>
|
||||||
|
<input type="text" class="gf-form-input max-width-18" ng-model='ctrl.current.jsonData.assumeRoleArn' placeholder="arn:aws:iam:*"></input>
|
||||||
|
<info-popover mode="right-absolute">
|
||||||
|
ARN of Assume Role
|
||||||
|
</info-popover>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import PrometheusMetricFindQuery from './metric_find_query';
|
|||||||
var durationSplitRegexp = /(\d+)(ms|s|m|h|d|w|M|y)/;
|
var durationSplitRegexp = /(\d+)(ms|s|m|h|d|w|M|y)/;
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateSrv) {
|
export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateSrv, timeSrv) {
|
||||||
this.type = 'prometheus';
|
this.type = 'prometheus';
|
||||||
this.editorSrc = 'app/features/prometheus/partials/query.editor.html';
|
this.editorSrc = 'app/features/prometheus/partials/query.editor.html';
|
||||||
this.name = instanceSettings.name;
|
this.name = instanceSettings.name;
|
||||||
@@ -43,7 +43,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
|
|||||||
return value.replace(/[\\^$*+?.()|[\]{}]/g, '\\\\$&');
|
return value.replace(/[\\^$*+?.()|[\]{}]/g, '\\\\$&');
|
||||||
}
|
}
|
||||||
|
|
||||||
function interpolateQueryExpr(value, variable, defaultFormatFn) {
|
this.interpolateQueryExpr = function(value, variable, defaultFormatFn) {
|
||||||
// if no multi or include all do not regexEscape
|
// if no multi or include all do not regexEscape
|
||||||
if (!variable.multi && !variable.includeAll) {
|
if (!variable.multi && !variable.includeAll) {
|
||||||
return value;
|
return value;
|
||||||
@@ -59,6 +59,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
|
|||||||
|
|
||||||
// Called once per panel (graph)
|
// Called once per panel (graph)
|
||||||
this.query = function(options) {
|
this.query = function(options) {
|
||||||
|
var self = this;
|
||||||
var start = getPrometheusTime(options.range.from, false);
|
var start = getPrometheusTime(options.range.from, false);
|
||||||
var end = getPrometheusTime(options.range.to, true);
|
var end = getPrometheusTime(options.range.to, true);
|
||||||
|
|
||||||
@@ -73,7 +74,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
|
|||||||
activeTargets.push(target);
|
activeTargets.push(target);
|
||||||
|
|
||||||
var query: any = {};
|
var query: any = {};
|
||||||
query.expr = templateSrv.replace(target.expr, options.scopedVars, interpolateQueryExpr);
|
query.expr = templateSrv.replace(target.expr, options.scopedVars, self.interpolateQueryExpr);
|
||||||
|
|
||||||
var interval = target.interval || options.interval;
|
var interval = target.interval || options.interval;
|
||||||
var intervalFactor = target.intervalFactor || 1;
|
var intervalFactor = target.intervalFactor || 1;
|
||||||
@@ -99,7 +100,6 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
|
|||||||
return this.performTimeSeriesQuery(query, start, end);
|
return this.performTimeSeriesQuery(query, start, end);
|
||||||
}, this));
|
}, this));
|
||||||
|
|
||||||
var self = this;
|
|
||||||
return $q.all(allQueryPromise)
|
return $q.all(allQueryPromise)
|
||||||
.then(function(allResponse) {
|
.then(function(allResponse) {
|
||||||
var result = [];
|
var result = [];
|
||||||
@@ -140,12 +140,12 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
|
|||||||
|
|
||||||
var interpolated;
|
var interpolated;
|
||||||
try {
|
try {
|
||||||
interpolated = templateSrv.replace(query);
|
interpolated = templateSrv.replace(query, {}, this.interpolateQueryExpr);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return $q.reject(err);
|
return $q.reject(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
var metricFindQuery = new PrometheusMetricFindQuery(this, interpolated);
|
var metricFindQuery = new PrometheusMetricFindQuery(this, interpolated, timeSrv);
|
||||||
return metricFindQuery.process();
|
return metricFindQuery.process();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -160,7 +160,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
|
|||||||
|
|
||||||
var interpolated;
|
var interpolated;
|
||||||
try {
|
try {
|
||||||
interpolated = templateSrv.replace(expr, {}, interpolateQueryExpr);
|
interpolated = templateSrv.replace(expr, {}, this.interpolateQueryExpr);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return $q.reject(err);
|
return $q.reject(err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
define([
|
define([
|
||||||
'lodash',
|
'lodash'
|
||||||
'moment',
|
|
||||||
],
|
],
|
||||||
function (_, moment) {
|
function (_) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function PrometheusMetricFindQuery(datasource, query) {
|
function PrometheusMetricFindQuery(datasource, query, timeSrv) {
|
||||||
this.datasource = datasource;
|
this.datasource = datasource;
|
||||||
this.query = query;
|
this.query = query;
|
||||||
|
this.range = timeSrv.timeRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
PrometheusMetricFindQuery.prototype.process = function() {
|
PrometheusMetricFindQuery.prototype.process = function() {
|
||||||
@@ -51,7 +51,9 @@ function (_, moment) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
url = '/api/v1/series?match[]=' + encodeURIComponent(metric);
|
url = '/api/v1/series?match[]=' + encodeURIComponent(metric)
|
||||||
|
+ '&start=' + (this.range.from.valueOf() / 1000)
|
||||||
|
+ '&end=' + (this.range.to.valueOf() / 1000);
|
||||||
|
|
||||||
return this.datasource._request('GET', url)
|
return this.datasource._request('GET', url)
|
||||||
.then(function(result) {
|
.then(function(result) {
|
||||||
@@ -86,7 +88,7 @@ function (_, moment) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
PrometheusMetricFindQuery.prototype.queryResultQuery = function(query) {
|
PrometheusMetricFindQuery.prototype.queryResultQuery = function(query) {
|
||||||
var url = '/api/v1/query?query=' + encodeURIComponent(query) + '&time=' + (moment().valueOf() / 1000);
|
var url = '/api/v1/query?query=' + encodeURIComponent(query) + '&time=' + (this.range.to.valueOf() / 1000);
|
||||||
|
|
||||||
return this.datasource._request('GET', url)
|
return this.datasource._request('GET', url)
|
||||||
.then(function(result) {
|
.then(function(result) {
|
||||||
@@ -107,7 +109,9 @@ function (_, moment) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
PrometheusMetricFindQuery.prototype.metricNameAndLabelsQuery = function(query) {
|
PrometheusMetricFindQuery.prototype.metricNameAndLabelsQuery = function(query) {
|
||||||
var url = '/api/v1/series?match[]=' + encodeURIComponent(query);
|
var url = '/api/v1/series?match[]=' + encodeURIComponent(query)
|
||||||
|
+ '&start=' + (this.range.from.valueOf() / 1000)
|
||||||
|
+ '&end=' + (this.range.to.valueOf() / 1000);
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
return this.datasource._request('GET', url)
|
return this.datasource._request('GET', url)
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ class PrometheusQueryCtrl extends QueryCtrl {
|
|||||||
var rangeDiff = Math.ceil((range.to.valueOf() - range.from.valueOf()) / 1000);
|
var rangeDiff = Math.ceil((range.to.valueOf() - range.from.valueOf()) / 1000);
|
||||||
var endTime = range.to.utc().format('YYYY-MM-DD HH:mm');
|
var endTime = range.to.utc().format('YYYY-MM-DD HH:mm');
|
||||||
var expr = {
|
var expr = {
|
||||||
expr: this.templateSrv.replace(this.target.expr, this.panelCtrl.panel.scopedVars),
|
expr: this.templateSrv.replace(this.target.expr, this.panelCtrl.panel.scopedVars, this.datasource.interpolateQueryExpr),
|
||||||
range_input: rangeDiff + 's',
|
range_input: rangeDiff + 's',
|
||||||
end_input: endTime,
|
end_input: endTime,
|
||||||
step_input: '',
|
step_input: '',
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ describe('PrometheusMetricFindQuery', function() {
|
|||||||
data: ["value1", "value2", "value3"]
|
data: ["value1", "value2", "value3"]
|
||||||
};
|
};
|
||||||
ctx.$httpBackend.expect('GET', 'proxied/api/v1/label/resource/values').respond(response);
|
ctx.$httpBackend.expect('GET', 'proxied/api/v1/label/resource/values').respond(response);
|
||||||
var pm = new PrometheusMetricFindQuery(ctx.ds, 'label_values(resource)');
|
var pm = new PrometheusMetricFindQuery(ctx.ds, 'label_values(resource)', ctx.timeSrv);
|
||||||
pm.process().then(function(data) { results = data; });
|
pm.process().then(function(data) { results = data; });
|
||||||
ctx.$httpBackend.flush();
|
ctx.$httpBackend.flush();
|
||||||
ctx.$rootScope.$apply();
|
ctx.$rootScope.$apply();
|
||||||
@@ -43,13 +43,22 @@ describe('PrometheusMetricFindQuery', function() {
|
|||||||
{__name__: "metric", resource: "value3"}
|
{__name__: "metric", resource: "value3"}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
ctx.$httpBackend.expect('GET', 'proxied/api/v1/series?match[]=metric').respond(response);
|
ctx.$httpBackend.expect('GET', /proxied\/api\/v1\/series\?match\[\]=metric&start=.*&end=.*/).respond(response);
|
||||||
var pm = new PrometheusMetricFindQuery(ctx.ds, 'label_values(metric, resource)');
|
var pm = new PrometheusMetricFindQuery(ctx.ds, 'label_values(metric, resource)', ctx.timeSrv);
|
||||||
pm.process().then(function(data) { results = data; });
|
pm.process().then(function(data) { results = data; });
|
||||||
ctx.$httpBackend.flush();
|
ctx.$httpBackend.flush();
|
||||||
ctx.$rootScope.$apply();
|
ctx.$rootScope.$apply();
|
||||||
expect(results.length).to.be(3);
|
expect(results.length).to.be(3);
|
||||||
});
|
});
|
||||||
|
it('label_values(metric, resource) should pass correct time', function() {
|
||||||
|
ctx.timeSrv.setTime({ from: moment.utc('2011-01-01'), to: moment.utc('2015-01-01') });
|
||||||
|
ctx.$httpBackend.expect('GET',
|
||||||
|
/proxied\/api\/v1\/series\?match\[\]=metric&start=1293840000&end=1420070400/).respond(response);
|
||||||
|
var pm = new PrometheusMetricFindQuery(ctx.ds, 'label_values(metric, resource)', ctx.timeSrv);
|
||||||
|
pm.process().then(function(data) { results = data; });
|
||||||
|
ctx.$httpBackend.flush();
|
||||||
|
ctx.$rootScope.$apply();
|
||||||
|
});
|
||||||
it('label_values(metric{label1="foo", label2="bar", label3="baz"}, resource) should generate series query', function() {
|
it('label_values(metric{label1="foo", label2="bar", label3="baz"}, resource) should generate series query', function() {
|
||||||
response = {
|
response = {
|
||||||
status: "success",
|
status: "success",
|
||||||
@@ -59,8 +68,8 @@ describe('PrometheusMetricFindQuery', function() {
|
|||||||
{__name__: "metric", resource: "value3"}
|
{__name__: "metric", resource: "value3"}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
ctx.$httpBackend.expect('GET', 'proxied/api/v1/series?match[]=metric').respond(response);
|
ctx.$httpBackend.expect('GET', /proxied\/api\/v1\/series\?match\[\]=metric&start=.*&end=.*/).respond(response);
|
||||||
var pm = new PrometheusMetricFindQuery(ctx.ds, 'label_values(metric, resource)');
|
var pm = new PrometheusMetricFindQuery(ctx.ds, 'label_values(metric, resource)', ctx.timeSrv);
|
||||||
pm.process().then(function(data) { results = data; });
|
pm.process().then(function(data) { results = data; });
|
||||||
ctx.$httpBackend.flush();
|
ctx.$httpBackend.flush();
|
||||||
ctx.$rootScope.$apply();
|
ctx.$rootScope.$apply();
|
||||||
@@ -72,7 +81,7 @@ describe('PrometheusMetricFindQuery', function() {
|
|||||||
data: ["metric1","metric2","metric3","nomatch"]
|
data: ["metric1","metric2","metric3","nomatch"]
|
||||||
};
|
};
|
||||||
ctx.$httpBackend.expect('GET', 'proxied/api/v1/label/__name__/values').respond(response);
|
ctx.$httpBackend.expect('GET', 'proxied/api/v1/label/__name__/values').respond(response);
|
||||||
var pm = new PrometheusMetricFindQuery(ctx.ds, 'metrics(metric.*)');
|
var pm = new PrometheusMetricFindQuery(ctx.ds, 'metrics(metric.*)', ctx.timeSrv);
|
||||||
pm.process().then(function(data) { results = data; });
|
pm.process().then(function(data) { results = data; });
|
||||||
ctx.$httpBackend.flush();
|
ctx.$httpBackend.flush();
|
||||||
ctx.$rootScope.$apply();
|
ctx.$rootScope.$apply();
|
||||||
@@ -90,7 +99,7 @@ describe('PrometheusMetricFindQuery', function() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
ctx.$httpBackend.expect('GET', /proxied\/api\/v1\/query\?query=metric&time=.*/).respond(response);
|
ctx.$httpBackend.expect('GET', /proxied\/api\/v1\/query\?query=metric&time=.*/).respond(response);
|
||||||
var pm = new PrometheusMetricFindQuery(ctx.ds, 'query_result(metric)');
|
var pm = new PrometheusMetricFindQuery(ctx.ds, 'query_result(metric)', ctx.timeSrv);
|
||||||
pm.process().then(function(data) { results = data; });
|
pm.process().then(function(data) { results = data; });
|
||||||
ctx.$httpBackend.flush();
|
ctx.$httpBackend.flush();
|
||||||
ctx.$rootScope.$apply();
|
ctx.$rootScope.$apply();
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="editor-row" ng-if="ctrl.panel.mappingType==1">
|
<div class="editor-row" ng-if="ctrl.panel.mappingType==1">
|
||||||
<h5 class="page-heading">Set valuea mappings</h5>
|
<h5 class="page-heading">Set value mappings</h5>
|
||||||
<div class="gf-form-group">
|
<div class="gf-form-group">
|
||||||
<div class="gf-form" ng-repeat="map in ctrl.panel.valueMaps">
|
<div class="gf-form" ng-repeat="map in ctrl.panel.valueMaps">
|
||||||
<span class="gf-form-label">
|
<span class="gf-form-label">
|
||||||
|
|||||||
@@ -138,6 +138,10 @@ define([
|
|||||||
this.replace = function(target) {
|
this.replace = function(target) {
|
||||||
return target;
|
return target;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.setTime = function(time) {
|
||||||
|
this.time = time;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContextSrvStub() {
|
function ContextSrvStub() {
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ define([
|
|||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
dash = _dashboardSrv.create({
|
dash = _dashboardSrv.create({
|
||||||
|
refresh: false,
|
||||||
rows: [
|
rows: [
|
||||||
{
|
{
|
||||||
panels: [{ test: "asd", legend: { } }]
|
panels: [{ test: "asd", legend: { } }]
|
||||||
|
|||||||
Reference in New Issue
Block a user