Commit fe46410c by Torkel Ödegaard

Merge branch 'cloudwatch'

parents f680c152 aef644bd
......@@ -29,6 +29,11 @@
"Rev": "bed164a424e75154a40550c04c313ef51a7bb275"
},
{
"ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/ec2query",
"Comment": "v0.7.3",
"Rev": "bed164a424e75154a40550c04c313ef51a7bb275"
},
{
"ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/query",
"Comment": "v0.7.3",
"Rev": "bed164a424e75154a40550c04c313ef51a7bb275"
......@@ -54,6 +59,11 @@
"Rev": "bed164a424e75154a40550c04c313ef51a7bb275"
},
{
"ImportPath": "github.com/aws/aws-sdk-go/service/ec2",
"Comment": "v0.7.3",
"Rev": "bed164a424e75154a40550c04c313ef51a7bb275"
},
{
"ImportPath": "github.com/davecgh/go-spew/spew",
"Rev": "2df174808ee097f90d259e432cc04442cf60be21"
},
......
// Package ec2query provides serialisation of AWS EC2 requests and responses.
package ec2query
//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/input/ec2.json build_test.go
import (
"net/url"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/internal/protocol/query/queryutil"
)
// Build builds a request for the EC2 protocol.
func Build(r *aws.Request) {
body := url.Values{
"Action": {r.Operation.Name},
"Version": {r.Service.APIVersion},
}
if err := queryutil.Parse(body, r.Params, true); err != nil {
r.Error = awserr.New("SerializationError", "failed encoding EC2 Query request", err)
}
if r.ExpireTime == 0 {
r.HTTPRequest.Method = "POST"
r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
r.SetBufferBody([]byte(body.Encode()))
} else { // This is a pre-signed request
r.HTTPRequest.Method = "GET"
r.HTTPRequest.URL.RawQuery = body.Encode()
}
}
package ec2query
//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/output/ec2.json unmarshal_test.go
import (
"encoding/xml"
"io"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil"
)
// Unmarshal unmarshals a response body for the EC2 protocol.
func Unmarshal(r *aws.Request) {
defer r.HTTPResponse.Body.Close()
if r.DataFilled() {
decoder := xml.NewDecoder(r.HTTPResponse.Body)
err := xmlutil.UnmarshalXML(r.Data, decoder, "")
if err != nil {
r.Error = awserr.New("SerializationError", "failed decoding EC2 Query response", err)
return
}
}
}
// UnmarshalMeta unmarshals response headers for the EC2 protocol.
func UnmarshalMeta(r *aws.Request) {
// TODO implement unmarshaling of request IDs
}
type xmlErrorResponse struct {
XMLName xml.Name `xml:"Response"`
Code string `xml:"Errors>Error>Code"`
Message string `xml:"Errors>Error>Message"`
RequestID string `xml:"RequestId"`
}
// UnmarshalError unmarshals a response error for the EC2 protocol.
func UnmarshalError(r *aws.Request) {
defer r.HTTPResponse.Body.Close()
resp := &xmlErrorResponse{}
err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp)
if err != nil && err != io.EOF {
r.Error = awserr.New("SerializationError", "failed decoding EC2 Query error response", err)
} else {
r.Error = awserr.NewRequestFailure(
awserr.New(resp.Code, resp.Message, nil),
r.HTTPResponse.StatusCode,
resp.RequestID,
)
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
package ec2
import (
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awsutil"
)
func init() {
initRequest = func(r *aws.Request) {
if r.Operation.Name == opCopySnapshot { // fill the PresignedURL parameter
r.Handlers.Build.PushFront(fillPresignedURL)
}
}
}
func fillPresignedURL(r *aws.Request) {
if !r.ParamsFilled() {
return
}
params := r.Params.(*CopySnapshotInput)
// Stop if PresignedURL/DestinationRegion is set
if params.PresignedURL != nil || params.DestinationRegion != nil {
return
}
// First generate a copy of parameters
r.Params = awsutil.CopyOf(r.Params)
params = r.Params.(*CopySnapshotInput)
// Set destination region. Avoids infinite handler loop.
// Also needed to sign sub-request.
params.DestinationRegion = r.Service.Config.Region
// Create a new client pointing at source region.
// We will use this to presign the CopySnapshot request against
// the source region
config := r.Service.Config.Copy().
WithEndpoint("").
WithRegion(*params.SourceRegion)
client := New(config)
// Presign a CopySnapshot request with modified params
req, _ := client.CopySnapshotRequest(params)
url, err := req.Presign(300 * time.Second) // 5 minutes should be enough.
if err != nil { // bubble error back up to original request
r.Error = err
}
// We have our URL, set it on params
params.PresignedURL = &url
}
package ec2_test
import (
"io/ioutil"
"net/url"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/internal/test/unit"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/stretchr/testify/assert"
)
var _ = unit.Imported
func TestCopySnapshotPresignedURL(t *testing.T) {
svc := ec2.New(&aws.Config{Region: aws.String("us-west-2")})
assert.NotPanics(t, func() {
// Doesn't panic on nil input
req, _ := svc.CopySnapshotRequest(nil)
req.Sign()
})
req, _ := svc.CopySnapshotRequest(&ec2.CopySnapshotInput{
SourceRegion: aws.String("us-west-1"),
SourceSnapshotID: aws.String("snap-id"),
})
req.Sign()
b, _ := ioutil.ReadAll(req.HTTPRequest.Body)
q, _ := url.ParseQuery(string(b))
url, _ := url.QueryUnescape(q.Get("PresignedUrl"))
assert.Equal(t, "us-west-2", q.Get("DestinationRegion"))
assert.Regexp(t, `^https://ec2\.us-west-1\.amazon.+&DestinationRegion=us-west-2`, url)
}
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
package ec2iface_test
import (
"testing"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
"github.com/stretchr/testify/assert"
)
func TestInterface(t *testing.T) {
assert.Implements(t, (*ec2iface.EC2API)(nil), ec2.New(nil))
}
This source diff could not be displayed because it is too large. You can view the blob instead.
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
package ec2
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/internal/protocol/ec2query"
"github.com/aws/aws-sdk-go/internal/signer/v4"
)
// Amazon Elastic Compute Cloud (Amazon EC2) provides resizable computing capacity
// in the Amazon Web Services (AWS) cloud. Using Amazon EC2 eliminates your
// need to invest in hardware up front, so you can develop and deploy applications
// faster.
type EC2 struct {
*aws.Service
}
// Used for custom service initialization logic
var initService func(*aws.Service)
// Used for custom request initialization logic
var initRequest func(*aws.Request)
// New returns a new EC2 client.
func New(config *aws.Config) *EC2 {
service := &aws.Service{
Config: aws.DefaultConfig.Merge(config),
ServiceName: "ec2",
APIVersion: "2015-04-15",
}
service.Initialize()
// Handlers
service.Handlers.Sign.PushBack(v4.Sign)
service.Handlers.Build.PushBack(ec2query.Build)
service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
// Run custom service initialization if present
if initService != nil {
initService(service)
}
return &EC2{service}
}
// newRequest creates a new request for a EC2 operation and runs any
// custom request initialization.
func (c *EC2) newRequest(op *aws.Operation, params, data interface{}) *aws.Request {
req := aws.NewRequest(c.Service, op, params, data)
// Run custom request initialization if present
if initRequest != nil {
initRequest(req)
}
return req
}
......@@ -21,7 +21,6 @@
"angular-native-dragdrop": "~1.1.1",
"angular-bindonce": "~0.3.3",
"requirejs": "~2.1.18",
"requirejs-text": "~2.0.14",
"aws-sdk": "~2.1.42"
"requirejs-text": "~2.0.14"
}
}
package cloudwatch
import (
"encoding/json"
"errors"
"io/ioutil"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/cloudwatch"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/grafana/grafana/pkg/middleware"
)
type actionHandler func(*cwRequest, *middleware.Context)
var actionHandlers map[string]actionHandler
type cwRequest struct {
Region string `json:"region"`
Action string `json:"action"`
Body []byte `json:"-"`
}
func init() {
actionHandlers = map[string]actionHandler{
"GetMetricStatistics": handleGetMetricStatistics,
"ListMetrics": handleListMetrics,
"DescribeInstances": handleDescribeInstances,
"__GetRegions": handleGetRegions,
"__GetNamespaces": handleGetNamespaces,
"__GetMetrics": handleGetMetrics,
"__GetDimensions": handleGetDimensions,
}
}
func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) {
svc := cloudwatch.New(&aws.Config{Region: aws.String(req.Region)})
reqParam := &struct {
Parameters struct {
Namespace string `json:"namespace"`
MetricName string `json:"metricName"`
Dimensions []*cloudwatch.Dimension `json:"dimensions"`
Statistics []*string `json:"statistics"`
StartTime int64 `json:"startTime"`
EndTime int64 `json:"endTime"`
Period int64 `json:"period"`
} `json:"parameters"`
}{}
json.Unmarshal(req.Body, reqParam)
params := &cloudwatch.GetMetricStatisticsInput{
Namespace: aws.String(reqParam.Parameters.Namespace),
MetricName: aws.String(reqParam.Parameters.MetricName),
Dimensions: reqParam.Parameters.Dimensions,
Statistics: reqParam.Parameters.Statistics,
StartTime: aws.Time(time.Unix(reqParam.Parameters.StartTime, 0)),
EndTime: aws.Time(time.Unix(reqParam.Parameters.EndTime, 0)),
Period: aws.Int64(reqParam.Parameters.Period),
}
resp, err := svc.GetMetricStatistics(params)
if err != nil {
c.JsonApiErr(500, "Unable to call AWS API", err)
return
}
c.JSON(200, resp)
}
func handleListMetrics(req *cwRequest, c *middleware.Context) {
svc := cloudwatch.New(&aws.Config{Region: aws.String(req.Region)})
reqParam := &struct {
Parameters struct {
Namespace string `json:"namespace"`
MetricName string `json:"metricName"`
Dimensions []*cloudwatch.DimensionFilter `json:"dimensions"`
} `json:"parameters"`
}{}
json.Unmarshal(req.Body, reqParam)
params := &cloudwatch.ListMetricsInput{
Namespace: aws.String(reqParam.Parameters.Namespace),
MetricName: aws.String(reqParam.Parameters.MetricName),
Dimensions: reqParam.Parameters.Dimensions,
}
resp, err := svc.ListMetrics(params)
if err != nil {
c.JsonApiErr(500, "Unable to call AWS API", err)
return
}
c.JSON(200, resp)
}
func handleDescribeInstances(req *cwRequest, c *middleware.Context) {
svc := ec2.New(&aws.Config{Region: aws.String(req.Region)})
reqParam := &struct {
Parameters struct {
Filters []*ec2.Filter `json:"filters"`
InstanceIds []*string `json:"instanceIds"`
} `json:"parameters"`
}{}
json.Unmarshal(req.Body, reqParam)
params := &ec2.DescribeInstancesInput{}
if len(reqParam.Parameters.Filters) > 0 {
params.Filters = reqParam.Parameters.Filters
}
if len(reqParam.Parameters.InstanceIds) > 0 {
params.InstanceIDs = reqParam.Parameters.InstanceIds
}
resp, err := svc.DescribeInstances(params)
if err != nil {
c.JsonApiErr(500, "Unable to call AWS API", err)
return
}
c.JSON(200, resp)
}
func HandleRequest(c *middleware.Context) {
var req cwRequest
req.Body, _ = ioutil.ReadAll(c.Req.Request.Body)
json.Unmarshal(req.Body, &req)
if handler, found := actionHandlers[req.Action]; !found {
c.JsonApiErr(500, "Unexpected AWS Action", errors.New(req.Action))
return
} else {
handler(&req, c)
}
}
package cloudwatch
import (
"encoding/json"
"github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/util"
)
var metricsMap map[string][]string
var dimensionsMap map[string][]string
func init() {
metricsMap = map[string][]string{
"AWS/AutoScaling": []string{"GroupMinSize", "GroupMaxSize", "GroupDesiredCapacity", "GroupInServiceInstances", "GroupPendingInstances", "GroupStandbyInstances", "GroupTerminatingInstances", "GroupTotalInstances"},
"AWS/Billing": []string{"EstimatedCharges"},
"AWS/EC2": []string{"CPUCreditUsage", "CPUCreditBalance", "CPUUtilization", "DiskReadOps", "DiskWriteOps", "DiskReadBytes", "DiskWriteBytes", "NetworkIn", "NetworkOut", "StatusCheckFailed", "StatusCheckFailed_Instance", "StatusCheckFailed_System"},
"AWS/CloudFront": []string{"Requests", "BytesDownloaded", "BytesUploaded", "TotalErrorRate", "4xxErrorRate", "5xxErrorRate"},
"AWS/CloudSearch": []string{"SuccessfulRequests", "SearchableDocuments", "IndexUtilization", "Partitions"},
"AWS/DynamoDB": []string{"ConditionalCheckFailedRequests", "ConsumedReadCapacityUnits", "ConsumedWriteCapacityUnits", "OnlineIndexConsumedWriteCapacity", "OnlineIndexPercentageProgress", "OnlineIndexThrottleEvents", "ProvisionedReadCapacityUnits", "ProvisionedWriteCapacityUnits", "ReadThrottleEvents", "ReturnedItemCount", "SuccessfulRequestLatency", "SystemErrors", "ThrottledRequests", "UserErrors", "WriteThrottleEvents"},
"AWS/ElastiCache": []string{
"CPUUtilization", "SwapUsage", "FreeableMemory", "NetworkBytesIn", "NetworkBytesOut",
"BytesUsedForCacheItems", "BytesReadIntoMemcached", "BytesWrittenOutFromMemcached", "CasBadval", "CasHits", "CasMisses", "CmdFlush", "CmdGet", "CmdSet", "CurrConnections", "CurrItems", "DecrHits", "DecrMisses", "DeleteHits", "DeleteMisses", "Evictions", "GetHits", "GetMisses", "IncrHits", "IncrMisses", "Reclaimed",
"CurrConnections", "Evictions", "Reclaimed", "NewConnections", "BytesUsedForCache", "CacheHits", "CacheMisses", "ReplicationLag", "GetTypeCmds", "SetTypeCmds", "KeyBasedCmds", "StringBasedCmds", "HashBasedCmds", "ListBasedCmds", "SetBasedCmds", "SortedSetBasedCmds", "CurrItems",
},
"AWS/EBS": []string{"VolumeReadBytes", "VolumeWriteBytes", "VolumeReadOps", "VolumeWriteOps", "VolumeTotalReadTime", "VolumeTotalWriteTime", "VolumeIdleTime", "VolumeQueueLength", "VolumeThroughputPercentage", "VolumeConsumedReadWriteOps"},
"AWS/ELB": []string{"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/ElasticMapReduce": []string{"CoreNodesPending", "CoreNodesRunning", "HBaseBackupFailed", "HBaseMostRecentBackupDuration", "HBaseTimeSinceLastSuccessfulBackup", "HDFSBytesRead", "HDFSBytesWritten", "HDFSUtilization", "IsIdle", "JobsFailed", "JobsRunning", "LiveDataNodes", "LiveTaskTrackers", "MapSlotsOpen", "MissingBlocks", "ReduceSlotsOpen", "RemainingMapTasks", "RemainingMapTasksPerSlot", "RemainingReduceTasks", "RunningMapTasks", "RunningReduceTasks", "S3BytesRead", "S3BytesWritten", "TaskNodesPending", "TaskNodesRunning", "TotalLoad"},
"AWS/Kinesis": []string{"PutRecord.Bytes", "PutRecord.Latency", "PutRecord.Success", "PutRecords.Bytes", "PutRecords.Latency", "PutRecords.Records", "PutRecords.Success", "IncomingBytes", "IncomingRecords", "GetRecords.Bytes", "GetRecords.IteratorAgeMilliseconds", "GetRecords.Latency", "GetRecords.Success"},
"AWS/ML": []string{"PredictCount", "PredictFailureCount"},
"AWS/OpsWorks": []string{"cpu_idle", "cpu_nice", "cpu_system", "cpu_user", "cpu_waitio", "load_1", "load_5", "load_15", "memory_buffers", "memory_cached", "memory_free", "memory_swap", "memory_total", "memory_used", "procs"},
"AWS/Redshift": []string{"CPUUtilization", "DatabaseConnections", "HealthStatus", "MaintenanceMode", "NetworkReceiveThroughput", "NetworkTransmitThroughput", "PercentageDiskSpaceUsed", "ReadIOPS", "ReadLatency", "ReadThroughput", "WriteIOPS", "WriteLatency", "WriteThroughput"},
"AWS/RDS": []string{"BinLogDiskUsage", "CPUUtilization", "DatabaseConnections", "DiskQueueDepth", "FreeableMemory", "FreeStorageSpace", "ReplicaLag", "SwapUsage", "ReadIOPS", "WriteIOPS", "ReadLatency", "WriteLatency", "ReadThroughput", "WriteThroughput", "NetworkReceiveThroughput", "NetworkTransmitThroughput"},
"AWS/Route53": []string{"HealthCheckStatus", "HealthCheckPercentageHealthy"},
"AWS/SNS": []string{"NumberOfMessagesPublished", "PublishSize", "NumberOfNotificationsDelivered", "NumberOfNotificationsFailed"},
"AWS/SQS": []string{"NumberOfMessagesSent", "SentMessageSize", "NumberOfMessagesReceived", "NumberOfEmptyReceives", "NumberOfMessagesDeleted", "ApproximateNumberOfMessagesDelayed", "ApproximateNumberOfMessagesVisible", "ApproximateNumberOfMessagesNotVisible"},
"AWS/S3": []string{"BucketSizeBytes", "NumberOfObjects"},
"AWS/SWF": []string{"DecisionTaskScheduleToStartTime", "DecisionTaskStartToCloseTime", "DecisionTasksCompleted", "StartedDecisionTasksTimedOutOnClose", "WorkflowStartToCloseTime", "WorkflowsCanceled", "WorkflowsCompleted", "WorkflowsContinuedAsNew", "WorkflowsFailed", "WorkflowsTerminated", "WorkflowsTimedOut"},
"AWS/StorageGateway": []string{"CacheHitPercent", "CachePercentUsed", "CachePercentDirty", "CloudBytesDownloaded", "CloudDownloadLatency", "CloudBytesUploaded", "UploadBufferFree", "UploadBufferPercentUsed", "UploadBufferUsed", "QueuedWrites", "ReadBytes", "ReadTime", "TotalCacheSize", "WriteBytes", "WriteTime", "WorkingStorageFree", "WorkingStoragePercentUsed", "WorkingStorageUsed", "CacheHitPercent", "CachePercentUsed", "CachePercentDirty", "ReadBytes", "ReadTime", "WriteBytes", "WriteTime", "QueuedWrites"},
"AWS/WorkSpaces": []string{"Available", "Unhealthy", "ConnectionAttempt", "ConnectionSuccess", "ConnectionFailure", "SessionLaunchTime", "InSessionLatency", "SessionDisconnect"},
}
dimensionsMap = map[string][]string{
"AWS/AutoScaling": []string{"AutoScalingGroupName"},
"AWS/Billing": []string{"ServiceName", "LinkedAccount", "Currency"},
"AWS/CloudFront": []string{"DistributionId", "Region"},
"AWS/CloudSearch": []string{},
"AWS/DynamoDB": []string{"TableName", "GlobalSecondaryIndexName", "Operation"},
"AWS/ElastiCache": []string{"CacheClusterId", "CacheNodeId"},
"AWS/EBS": []string{"VolumeId"},
"AWS/EC2": []string{"AutoScalingGroupName", "ImageId", "InstanceId", "InstanceType"},
"AWS/ELB": []string{"LoadBalancerName", "AvailabilityZone"},
"AWS/ElasticMapReduce": []string{"ClusterId", "JobId"},
"AWS/Kinesis": []string{"StreamName"},
"AWS/ML": []string{"MLModelId", "RequestMode"},
"AWS/OpsWorks": []string{"StackId", "LayerId", "InstanceId"},
"AWS/Redshift": []string{"NodeID", "ClusterIdentifier"},
"AWS/RDS": []string{"DBInstanceIdentifier", "DatabaseClass", "EngineName"},
"AWS/Route53": []string{"HealthCheckId"},
"AWS/SNS": []string{"Application", "Platform", "TopicName"},
"AWS/SQS": []string{"QueueName"},
"AWS/S3": []string{"BucketName", "StorageType"},
"AWS/SWF": []string{"Domain", "ActivityTypeName", "ActivityTypeVersion"},
"AWS/StorageGateway": []string{"GatewayId", "GatewayName", "VolumeId"},
"AWS/WorkSpaces": []string{"DirectoryId", "WorkspaceId"},
}
}
func handleGetRegions(req *cwRequest, c *middleware.Context) {
regions := []string{
"us-west-2", "us-west-1", "eu-west-1", "eu-central-1", "ap-southeast-1",
"ap-southeast-2", "ap-northeast-1", "sa-east-1",
}
result := []interface{}{}
for _, region := range regions {
result = append(result, util.DynMap{"text": region, "value": region})
}
c.JSON(200, result)
}
func handleGetNamespaces(req *cwRequest, c *middleware.Context) {
result := []interface{}{}
for key, _ := range metricsMap {
result = append(result, util.DynMap{"text": key, "value": key})
}
c.JSON(200, result)
}
func handleGetMetrics(req *cwRequest, c *middleware.Context) {
reqParam := &struct {
Parameters struct {
Namespace string `json:"namespace"`
} `json:"parameters"`
}{}
json.Unmarshal(req.Body, reqParam)
namespaceMetrics, exists := metricsMap[reqParam.Parameters.Namespace]
if !exists {
c.JsonApiErr(404, "Unable to find namespace "+reqParam.Parameters.Namespace, nil)
return
}
result := []interface{}{}
for _, name := range namespaceMetrics {
result = append(result, util.DynMap{"text": name, "value": name})
}
c.JSON(200, result)
}
func handleGetDimensions(req *cwRequest, c *middleware.Context) {
reqParam := &struct {
Parameters struct {
Namespace string `json:"namespace"`
} `json:"parameters"`
}{}
json.Unmarshal(req.Body, reqParam)
dimensionValues, exists := dimensionsMap[reqParam.Parameters.Namespace]
if !exists {
c.JsonApiErr(404, "Unable to find dimension "+reqParam.Parameters.Namespace, nil)
return
}
result := []interface{}{}
for _, name := range dimensionValues {
result = append(result, util.DynMap{"text": name, "value": name})
}
c.JSON(200, result)
}
......@@ -8,6 +8,7 @@ import (
"net/url"
"time"
"github.com/grafana/grafana/pkg/api/cloudwatch"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/middleware"
m "github.com/grafana/grafana/pkg/models"
......@@ -83,7 +84,7 @@ func ProxyDataSourceRequest(c *middleware.Context) {
}
if query.Result.Type == m.DS_CLOUDWATCH {
ProxyCloudWatchDataSourceRequest(c)
cloudwatch.HandleRequest(c)
} else {
proxyPath := c.Params("*")
proxy := NewReverseProxy(&ds, proxyPath, targetUrl)
......
package api
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/cloudwatch"
"github.com/grafana/grafana/pkg/middleware"
)
func ProxyCloudWatchDataSourceRequest(c *middleware.Context) {
body, _ := ioutil.ReadAll(c.Req.Request.Body)
reqInfo := &struct {
Region string `json:"region"`
Service string `json:"service"`
Action string `json:"action"`
}{}
json.Unmarshal([]byte(body), reqInfo)
svc := cloudwatch.New(&aws.Config{Region: aws.String(reqInfo.Region)})
switch reqInfo.Action {
case "GetMetricStatistics":
reqParam := &struct {
Parameters struct {
Namespace string `json:"Namespace"`
MetricName string `json:"MetricName"`
Dimensions []map[string]string `json:"Dimensions"`
Statistics []string `json:"Statistics"`
StartTime int64 `json:"StartTime"`
EndTime int64 `json:"EndTime"`
Period int64 `json:"Period"`
} `json:"parameters"`
}{}
json.Unmarshal([]byte(body), reqParam)
statistics := make([]*string, 0)
for k := range reqParam.Parameters.Statistics {
statistics = append(statistics, &reqParam.Parameters.Statistics[k])
}
dimensions := make([]*cloudwatch.Dimension, 0)
for _, d := range reqParam.Parameters.Dimensions {
dimensions = append(dimensions, &cloudwatch.Dimension{
Name: aws.String(d["Name"]),
Value: aws.String(d["Value"]),
})
}
params := &cloudwatch.GetMetricStatisticsInput{
Namespace: aws.String(reqParam.Parameters.Namespace),
MetricName: aws.String(reqParam.Parameters.MetricName),
Dimensions: dimensions,
Statistics: statistics,
StartTime: aws.Time(time.Unix(reqParam.Parameters.StartTime, 0)),
EndTime: aws.Time(time.Unix(reqParam.Parameters.EndTime, 0)),
Period: aws.Int64(reqParam.Parameters.Period),
}
resp, err := svc.GetMetricStatistics(params)
if err != nil {
c.JsonApiErr(500, "Unable to call AWS API", err)
return
}
respJson, _ := json.Marshal(resp)
fmt.Fprint(c.RW(), string(respJson))
case "ListMetrics":
reqParam := &struct {
Parameters struct {
Namespace string `json:"Namespace"`
MetricName string `json:"MetricName"`
Dimensions []map[string]string `json:"Dimensions"`
} `json:"parameters"`
}{}
json.Unmarshal([]byte(body), reqParam)
dimensions := make([]*cloudwatch.DimensionFilter, 0)
for _, d := range reqParam.Parameters.Dimensions {
dimensions = append(dimensions, &cloudwatch.DimensionFilter{
Name: aws.String(d["Name"]),
Value: aws.String(d["Value"]),
})
}
params := &cloudwatch.ListMetricsInput{
Namespace: aws.String(reqParam.Parameters.Namespace),
MetricName: aws.String(reqParam.Parameters.MetricName),
Dimensions: dimensions,
}
resp, err := svc.ListMetrics(params)
if err != nil {
c.JsonApiErr(500, "Unable to call AWS API", err)
return
}
respJson, _ := json.Marshal(resp)
fmt.Fprint(c.RW(), string(respJson))
default:
c.JsonApiErr(500, "Unexpected CloudWatch action", errors.New(reqInfo.Action))
}
}
......@@ -64,7 +64,7 @@ function (angular, $, config) {
$scope.appEvent("dashboard-loaded", $scope.dashboard);
}).catch(function(err) {
console.log('Failed to initialize dashboard', err);
if (err.data && err.data.message) { err.message = err.data.message; }
$scope.appEvent("alert-error", ['Dashboard init failed', 'Template variables could not be initialized: ' + err.message]);
});
};
......
......@@ -7,7 +7,7 @@ function (angular, _) {
var module = angular.module('grafana.controllers');
module.controller('TemplateEditorCtrl', function($scope, datasourceSrv, templateSrv, templateValuesSrv, alertSrv) {
module.controller('TemplateEditorCtrl', function($scope, datasourceSrv, templateSrv, templateValuesSrv) {
var replacementDefaults = {
type: 'query',
......@@ -78,9 +78,9 @@ function (angular, _) {
};
$scope.runQuery = function() {
return templateValuesSrv.updateOptions($scope.current).then(function() {
}, function(err) {
alertSrv.set('Templating', 'Failed to run query for variable values: ' + err.message, 'error');
return templateValuesSrv.updateOptions($scope.current).then(null, function(err) {
if (err.data && err.data.message) { err.message = err.data.message; }
$scope.appEvent("alert-error", ['Templating', 'Template variables could not be initialized: ' + err.message]);
});
};
......
......@@ -9,46 +9,53 @@
<input type="text" class="tight-form-input input-xlarge" ng-model='current.jsonData.defaultRegion' placeholder="" required></input>
</li>
</ul>
<ul class="tight-form-list">
<li class="tight-form-item">
Access <tip>Direct = url is used directly from browser, Proxy = Grafana backend will proxy the request</label>
</li>
<li>
<select class="input-small tight-form-input" ng-model="current.jsonData.access" ng-options="f for f in ['direct', 'proxy']" ng-init="current.jsonData.access = current.jsonData.access || 'direct'"></select>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form" ng-show="current.jsonData.access === 'direct'">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 160px">
Access Key Id
</li>
<li>
<input type="text" class="tight-form-input input-xlarge" ng-model='current.jsonData.accessKeyId' placeholder="" ng-required="current.jsonData.access === 'direct'"></input>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 160px">
Secret Access Key
</li>
<li>
<input type="password" class="tight-form-input input-xlarge" ng-model='current.jsonData.secretAccessKey' placeholder="" ng-required="current.jsonData.access === 'direct'"></input>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form last">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 160px">
Custom Metric Attributes
</li>
<li>
<input type="text" class="tight-form-input input-xlarge" ng-model='current.jsonData.customMetricsAttributes[0]' ng-init="current.jsonData.customMetricsAttributes = current.jsonData.customMetricsAttributes || []" placeholder="JSON url" bs-tooltip="'Set JSON url of the result, \'aws cloudwatch list-metrics --output json\''"></input>
</li>
</ul>
<div class="clearfix"></div>
</div>
<!-- <div class="tight&#45;form" ng&#45;show="current.jsonData.access === 'direct'"> -->
<!-- <ul class="tight&#45;form&#45;list"> -->
<!-- <li class="tight&#45;form&#45;item" style="width: 160px"> -->
<!-- </li> -->
<!-- <li> -->
<!-- <input type="text" class="tight&#45;form&#45;input input&#45;xlarge" ng&#45;model='current.jsonData.accessKeyId' placeholder=""></input> -->
<!-- </li> -->
<!-- </ul> -->
<!-- <div class="clearfix"></div> -->
<!-- </div> -->
<!-- <div class="tight&#45;form" ng&#45;show="current.jsonData.access === 'direct'"> -->
<!-- <ul class="tight&#45;form&#45;list"> -->
<!-- <li class="tight&#45;form&#45;item" style="width: 160px"> -->
<!-- Access Key Id -->
<!-- </li> -->
<!-- <li> -->
<!-- <input type="text" class="tight&#45;form&#45;input input&#45;xlarge" ng&#45;model='current.jsonData.accessKeyId' placeholder=""></input> -->
<!-- </li> -->
<!-- </ul> -->
<!-- <div class="clearfix"></div> -->
<!-- </div> -->
<!-- <div class="tight&#45;form" ng&#45;show="current.jsonData.access === 'direct'"> -->
<!-- <ul class="tight&#45;form&#45;list"> -->
<!-- <li class="tight&#45;form&#45;item" style="width: 160px"> -->
<!-- Secret Access Key -->
<!-- </li> -->
<!-- <li> -->
<!-- <input type="password" class="tight&#45;form&#45;input input&#45;xlarge" ng&#45;model='current.jsonData.secretAccessKey' placeholder=""></input> -->
<!-- </li> -->
<!-- </ul> -->
<!-- <div class="clearfix"></div> -->
<!-- </div> -->
<!-- <div class="tight&#45;form last"> -->
<!-- <ul class="tight&#45;form&#45;list"> -->
<!-- <li class="tight&#45;form&#45;item" style="width: 160px"> -->
<!-- Custom Metric Attributes -->
<!-- </li> -->
<!-- <li> -->
<!-- <input type="text" class="tight&#45;form&#45;input input&#45;xlarge" -->
<!-- ng&#45;model='current.jsonData.customMetricsAttributes[0]' -->
<!-- ng&#45;init="current.jsonData.customMetricsAttributes = current.jsonData.customMetricsAttributes || []" placeholder="JSON url" bs&#45;tooltip="'Set JSON url of the result, \'aws cloudwatch list&#45;metrics &#45;&#45;output json\''"> -->
<!-- </input> -->
<!-- </li> -->
<!-- </ul> -->
<!-- <div class="clearfix"></div> -->
<!-- </div> -->
......@@ -33,17 +33,23 @@
</ul>
<ul class="tight-form-list" role="menu">
<li class="tight-form-item" style="width: 100px">
<li class="tight-form-item query-keyword" style="width: 100px">
Metric
</li>
<li>
<metric-segment segment="regionSegment" get-alt-segments="getRegions()" on-value-changed="regionChanged()"></metric-segment>
<metric-segment segment="regionSegment" get-options="getRegions()" on-change="regionChanged()"></metric-segment>
</li>
<li>
<metric-segment segment="namespaceSegment" get-alt-segments="getNamespaces()" on-value-changed="namespaceChanged()"></metric-segment>
<metric-segment segment="namespaceSegment" get-options="getNamespaces()" on-change="namespaceChanged()"></metric-segment>
</li>
<li>
<metric-segment segment="metricSegment" get-alt-segments="getMetrics()" on-value-changed="metricChanged()"></metric-segment>
<metric-segment segment="metricSegment" get-options="getMetrics()" on-change="metricChanged()"></metric-segment>
</li>
<li class="tight-form-item query-keyword">
Stats
</li>
<li ng-repeat="segment in statSegments">
<metric-segment segment="segment" get-options="getStatSegments(segment, $index)" on-change="statSegmentChanged(segment, $index)"></metric-segment>
</li>
</ul>
......@@ -52,40 +58,11 @@
<div class="tight-form">
<ul class="tight-form-list" role="menu">
<li class="tight-form-item tight-form-align" style="width: 100px">
<li class="tight-form-item query-keyword tight-form-align" style="width: 100px">
Dimensions
</li>
<li ng-repeat="(key, value) in target.escapedDimensions track by $index" class="tight-form-item">
{{key}}&nbsp;=&nbsp;{{value}}
<a ng-click="removeDimension(key)">
<i class="fa fa-remove"></i>
</a>
</li>
<li class="tight-form-item" ng-hide="addDimensionMode">
<a ng-click="addDimension()">
<i class="fa fa-plus"></i>
</a>
</li>
<li ng-show="addDimensionMode">
<input type="text"
class="input-small tight-form-input"
spellcheck='false'
bs-typeahead="suggestDimensionKeys"
data-min-length=0 data-items=100
ng-model="target.currentDimensionKey"
placeholder="key">
<input type="text"
class="input-small tight-form-input"
spellcheck='false'
bs-typeahead="suggestDimensionValues"
data-min-length=0 data-items=100
ng-model="target.currentDimensionValue"
placeholder="value">
<a ng-click="addDimension()">
add dimension
</a>
<li ng-repeat="segment in dimSegments">
<metric-segment segment="segment" get-options="getDimSegments(segment, $index)" on-change="dimSegmentChanged(segment, $index)"></metric-segment>
</li>
</ul>
......@@ -94,58 +71,20 @@
<div class="tight-form">
<ul class="tight-form-list" role="menu">
<li class="tight-form-item tight-form-align" style="width: 100px">
Statistics
<li class="tight-form-item query-keyword tight-form-align" style="width: 100px">
Alias
<tip>{{metric}} {{stat}} {{namespace}} {{region}} {{<dimension name>}}</tip>
</li>
<li class="tight-form-item">
<editor-checkbox text="Min" model="target.statistics.Minimum" change="statisticsOptionChanged()"></editor-checkbox>
<editor-checkbox text="Max" model="target.statistics.Maximum" change="statisticsOptionChanged()"></editor-checkbox>
<editor-checkbox text="Avg" model="target.statistics.Average" change="statisticsOptionChanged()"></editor-checkbox>
<editor-checkbox text="Sum" model="target.statistics.Sum" change="statisticsOptionChanged()"></editor-checkbox>
<editor-checkbox text="SampleCount" model="target.statistics.SampleCount" change="statisticsOptionChanged()"></editor-checkbox>
<li>
<input type="text" class="input-xlarge tight-form-input" ng-model="target.alias" spellcheck='false' ng-model-onblur ng-change="refreshMetricData()">
</li>
<li class="tight-form-item">
<li class="tight-form-item query-keyword">
Period
</li>
<li>
<input type="text"
class="input-mini tight-form-input"
ng-model="target.period"
data-placement="right"
spellcheck='false'
placeholder="period"
data-min-length=0 data-items=100
ng-model-onblur
ng-change="refreshMetricData()"
/>
<a bs-tooltip="target.errors.period"
style="color: rgb(229, 189, 28)"
ng-show="target.errors.period">
<i class="fa fa-warning"></i>
</a>
<input type="text" class="input-mini tight-form-input" ng-model="target.period" spellcheck='false' placeholder="period" ng-model-onblur ng-change="refreshMetricData()" />
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form">
<ul class="tight-form-list" role="menu">
<li class="tight-form-item tight-form-align" style="width: 100px">
Alias Pattern
</li>
<li>
<input type="text"
class="input-xxlarge tight-form-input"
ng-model="target.legendFormat"
spellcheck='false'
placeholder="Syntax: {{Region}} {{Namespace}} {{MetricName}} {{Statistics}} {{Dimensions[N].Name}} {{Dimensions[N].Value}}"
data-min-length=0 data-items=100
ng-model-onblur
ng-change="refreshMetricData()"
>
<tip>Syntax: {{Region}} {{Namespace}} {{MetricName}} {{Statistics}} {{Dimensions[N].Name}} {{Dimensions[N].Value}}</tip>
</li>
</ul>
<div class="clearfix"></div>
......
define([
'angular',
'lodash',
],
function (angular, _) {
'use strict';
var module = angular.module('grafana.controllers');
module.controller('CloudWatchQueryCtrl', function($scope, templateSrv, uiSegmentSrv) {
$scope.init = function() {
$scope.target.namespace = $scope.target.namespace || '';
$scope.target.metricName = $scope.target.metricName || '';
$scope.target.dimensions = $scope.target.dimensions || {};
$scope.target.escapedDimensions = this.escapeDimensions($scope.target.dimensions);
$scope.target.statistics = $scope.target.statistics || {};
$scope.target.period = $scope.target.period || 60;
$scope.target.region = $scope.target.region || $scope.datasource.getDefaultRegion();
$scope.target.errors = validateTarget();
$scope.regionSegment = uiSegmentSrv.getSegmentForValue($scope.target.region, 'select region');
$scope.namespaceSegment = uiSegmentSrv.getSegmentForValue($scope.target.namespace, 'select namespace');
$scope.metricSegment = uiSegmentSrv.getSegmentForValue($scope.target.metricName, 'select metric');
};
$scope.getRegions = function() {
return $scope.datasource.metricFindQuery('region()')
.then($scope.transformToSegments(true));
};
$scope.getNamespaces = function() {
return $scope.datasource.metricFindQuery('namespace()')
.then($scope.transformToSegments(true));
};
$scope.getMetrics = function() {
return $scope.datasource.metricFindQuery('metrics(' + $scope.target.namespace + ')')
.then($scope.transformToSegments(true));
};
$scope.regionChanged = function() {
$scope.target.region = $scope.regionSegment.value;
$scope.get_data();
};
$scope.namespaceChanged = function() {
$scope.target.namespace = $scope.namespaceSegment.value;
$scope.get_data();
};
$scope.metricChanged = function() {
$scope.target.metricName = $scope.metricSegment.value;
$scope.get_data();
};
$scope.transformToSegments = function(addTemplateVars) {
return function(results) {
var segments = _.map(results, function(segment) {
return uiSegmentSrv.newSegment({ value: segment.text, expandable: segment.expandable });
});
if (addTemplateVars) {
_.each(templateSrv.variables, function(variable) {
segments.unshift(uiSegmentSrv.newSegment({ type: 'template', value: '$' + variable.name, expandable: true }));
});
}
return segments;
};
};
$scope.refreshMetricData = function() {
$scope.target.errors = validateTarget($scope.target);
// this does not work so good
if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
$scope.oldTarget = angular.copy($scope.target);
$scope.get_data();
}
};
$scope.suggestDimensionKeys = function(query, callback) { // jshint unused:false
return _.union($scope.datasource.performSuggestDimensionKeys($scope.target.namespace), $scope.datasource.getTemplateVariableNames());
};
$scope.suggestDimensionValues = function(query, callback) {
if (!$scope.target.namespace || !$scope.target.metricName) {
return callback([]);
}
$scope.datasource.performSuggestDimensionValues(
$scope.target.region,
$scope.target.namespace,
$scope.target.metricName,
$scope.target.dimensions
)
.then(function(result) {
var suggestData = _.chain(result)
.flatten(true)
.filter(function(dimension) {
return dimension.Name === templateSrv.replace($scope.target.currentDimensionKey);
})
.pluck('Value')
.uniq()
.value();
suggestData = _.union(suggestData, $scope.datasource.getTemplateVariableNames());
callback(suggestData);
}, function() {
callback([]);
});
};
$scope.addDimension = function() {
if (!$scope.addDimensionMode) {
$scope.addDimensionMode = true;
return;
}
if (!$scope.target.dimensions) {
$scope.target.dimensions = {};
}
$scope.target.dimensions[$scope.target.currentDimensionKey] = $scope.target.currentDimensionValue;
$scope.target.escapedDimensions = this.escapeDimensions($scope.target.dimensions);
$scope.target.currentDimensionKey = '';
$scope.target.currentDimensionValue = '';
$scope.refreshMetricData();
$scope.addDimensionMode = false;
};
$scope.removeDimension = function(key) {
key = key.replace(/\\\$/g, '$');
delete $scope.target.dimensions[key];
$scope.target.escapedDimensions = this.escapeDimensions($scope.target.dimensions);
$scope.refreshMetricData();
};
$scope.escapeDimensions = function(d) {
var result = {};
_.chain(d)
.keys(d)
.each(function(k) {
var v = d[k];
result[k.replace(/\$/g, '\uFF04')] = v.replace(/\$/g, '\$');
});
return result;
};
$scope.statisticsOptionChanged = function() {
$scope.refreshMetricData();
};
// TODO: validate target
function validateTarget() {
var errs = {};
if ($scope.target.period < 60 || ($scope.target.period % 60) !== 0) {
errs.period = 'Period must be at least 60 seconds and must be a multiple of 60';
}
return errs;
}
$scope.init();
});
});
define([
'angular',
'lodash',
],
function (angular, _) {
'use strict';
var module = angular.module('grafana.controllers');
module.controller('CloudWatchQueryCtrl', function($scope, templateSrv, uiSegmentSrv, $q) {
$scope.init = function() {
var target = $scope.target;
target.namespace = target.namespace || '';
target.metricName = target.metricName || '';
target.statistics = target.statistics || ['Average'];
target.dimensions = target.dimensions || {};
target.period = target.period || 60;
target.region = target.region || $scope.datasource.getDefaultRegion();
$scope.aliasSyntax = '{{metric}} {{stat}} {{namespace}} {{region}} {{<dimension name>}}';
$scope.regionSegment = uiSegmentSrv.getSegmentForValue($scope.target.region, 'select region');
$scope.namespaceSegment = uiSegmentSrv.getSegmentForValue($scope.target.namespace, 'select namespace');
$scope.metricSegment = uiSegmentSrv.getSegmentForValue($scope.target.metricName, 'select metric');
$scope.dimSegments = _.reduce($scope.target.dimensions, function(memo, value, key) {
memo.push(uiSegmentSrv.newKey(key));
memo.push(uiSegmentSrv.newOperator("="));
memo.push(uiSegmentSrv.newKeyValue(value));
return memo;
}, []);
$scope.statSegments = _.map($scope.target.statistics, function(stat) {
return uiSegmentSrv.getSegmentForValue(stat);
});
$scope.ensurePlusButton($scope.statSegments);
$scope.ensurePlusButton($scope.dimSegments);
$scope.removeDimSegment = uiSegmentSrv.newSegment({fake: true, value: '-- remove dimension --'});
$scope.removeStatSegment = uiSegmentSrv.newSegment({fake: true, value: '-- remove stat --'});
};
$scope.getStatSegments = function() {
return $q.when([
angular.copy($scope.removeStatSegment),
uiSegmentSrv.getSegmentForValue('Average'),
uiSegmentSrv.getSegmentForValue('Maximum'),
uiSegmentSrv.getSegmentForValue('Minimum'),
uiSegmentSrv.getSegmentForValue('Sum'),
uiSegmentSrv.getSegmentForValue('SampleCount'),
]);
};
$scope.statSegmentChanged = function(segment, index) {
if (segment.value === $scope.removeStatSegment.value) {
$scope.statSegments.splice(index, 1);
} else {
segment.type = 'value';
}
$scope.target.statistics = _.reduce($scope.statSegments, function(memo, seg) {
if (!seg.fake) { memo.push(seg.value); } return memo;
}, []);
$scope.ensurePlusButton($scope.statSegments);
$scope.get_data();
};
$scope.ensurePlusButton = function(segments) {
var count = segments.length;
var lastSegment = segments[Math.max(count-1, 0)];
if (!lastSegment || lastSegment.type !== 'plus-button') {
segments.push(uiSegmentSrv.newPlusButton());
}
};
$scope.getDimSegments = function(segment) {
if (segment.type === 'operator') { return $q.when([]); }
var target = $scope.target;
var query = $q.when([]);
if (segment.type === 'key' || segment.type === 'plus-button') {
query = $scope.datasource.getDimensionKeys($scope.target.namespace);
} else if (segment.type === 'value') {
query = $scope.datasource.getDimensionValues(target.region, target.namespace, target.metricName, {});
}
return query.then($scope.transformToSegments(true)).then(function(results) {
if (segment.type === 'key') {
results.splice(0, 0, angular.copy($scope.removeDimSegment));
}
return results;
});
};
$scope.dimSegmentChanged = function(segment, index) {
$scope.dimSegments[index] = segment;
if (segment.value === $scope.removeDimSegment.value) {
$scope.dimSegments.splice(index, 3);
}
else if (segment.type === 'plus-button') {
$scope.dimSegments.push(uiSegmentSrv.newOperator('='));
$scope.dimSegments.push(uiSegmentSrv.newFake('select dimension value', 'value', 'query-segment-value'));
segment.type = 'key';
segment.cssClass = 'query-segment-key';
}
$scope.syncDimSegmentsWithModel();
$scope.ensurePlusButton($scope.dimSegments);
$scope.get_data();
};
$scope.syncDimSegmentsWithModel = function() {
var dims = {};
var length = $scope.dimSegments.length;
for (var i = 0; i < length - 2; i += 3) {
var keySegment = $scope.dimSegments[i];
var valueSegment = $scope.dimSegments[i + 2];
if (!valueSegment.fake) {
dims[keySegment.value] = valueSegment.value;
}
}
$scope.target.dimensions = dims;
};
$scope.getRegions = function() {
return $scope.datasource.metricFindQuery('regions()')
.then($scope.transformToSegments(true));
};
$scope.getNamespaces = function() {
return $scope.datasource.metricFindQuery('namespaces()')
.then($scope.transformToSegments(true));
};
$scope.getMetrics = function() {
return $scope.datasource.metricFindQuery('metrics(' + $scope.target.namespace + ')')
.then($scope.transformToSegments(true));
};
$scope.regionChanged = function() {
$scope.target.region = $scope.regionSegment.value;
$scope.get_data();
};
$scope.namespaceChanged = function() {
$scope.target.namespace = $scope.namespaceSegment.value;
$scope.get_data();
};
$scope.metricChanged = function() {
$scope.target.metricName = $scope.metricSegment.value;
$scope.get_data();
};
$scope.transformToSegments = function(addTemplateVars) {
return function(results) {
var segments = _.map(results, function(segment) {
return uiSegmentSrv.newSegment({ value: segment.text, expandable: segment.expandable });
});
if (addTemplateVars) {
_.each(templateSrv.variables, function(variable) {
segments.unshift(uiSegmentSrv.newSegment({ type: 'template', value: '$' + variable.name, expandable: true }));
});
}
return segments;
};
};
$scope.refreshMetricData = function() {
if (!_.isEqual($scope.oldTarget, $scope.target)) {
$scope.oldTarget = angular.copy($scope.target);
$scope.get_data();
}
};
$scope.init();
});
});
///<amd-dependency path="app/plugins/datasource/cloudwatch/datasource" />
///<amd-dependency path="test/specs/helpers" name="helpers" />
import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/common';
declare var helpers: any;
describe('CloudWatchDatasource', function() {
var ctx = new helpers.ServiceTestContext();
beforeEach(angularMocks.module('grafana.services'));
beforeEach(angularMocks.module('grafana.controllers'));
beforeEach(ctx.providePhase(['templateSrv', 'backendSrv']));
beforeEach(ctx.createService('CloudWatchDatasource'));
beforeEach(function() {
ctx.ds = new ctx.service({
jsonData: {
defaultRegion: 'us-east-1',
access: 'proxy'
}
});
});
describe('When performing CloudWatch query', function() {
var requestParams;
var query = {
range: { from: 'now-1h', to: 'now' },
targets: [
{
region: 'us-east-1',
namespace: 'AWS/EC2',
metricName: 'CPUUtilization',
dimensions: {
InstanceId: 'i-12345678'
},
statistics: ['Average'],
period: 300
}
]
};
var response = {
Datapoints: [
{
Average: 1,
Timestamp: 'Wed Dec 31 1969 16:00:00 GMT-0800 (PST)'
}
],
Label: 'CPUUtilization'
};
beforeEach(function() {
ctx.backendSrv.datasourceRequest = function(params) {
requestParams = params;
return ctx.$q.when({data: response});
};
});
it('should generate the correct query', function(done) {
ctx.ds.query(query).then(function() {
var params = requestParams.data.parameters;
expect(params.namespace).to.be(query.targets[0].namespace);
expect(params.metricName).to.be(query.targets[0].metricName);
expect(params.dimensions[0].Name).to.be(Object.keys(query.targets[0].dimensions)[0]);
expect(params.dimensions[0].Value).to.be(query.targets[0].dimensions[Object.keys(query.targets[0].dimensions)[0]]);
expect(params.statistics).to.eql(query.targets[0].statistics);
expect(params.period).to.be(query.targets[0].period);
done();
});
ctx.$rootScope.$apply();
});
it('should return series list', function(done) {
ctx.ds.query(query).then(function(result) {
expect(result.data[0].target).to.be('CPUUtilization_Average');
expect(result.data[0].datapoints[0][0]).to.be(response.Datapoints[0]['Average']);
done();
});
ctx.$rootScope.$apply();
});
});
function describeMetricFindQuery(query, func) {
describe('metricFindQuery ' + query, () => {
let scenario: any = {};
scenario.setup = setupCallback => {
beforeEach(() => {
setupCallback();
ctx.backendSrv.datasourceRequest = args => {
scenario.request = args;
return ctx.$q.when({data: scenario.requestResponse });
};
ctx.ds.metricFindQuery(query).then(args => {
scenario.result = args;
});
ctx.$rootScope.$apply();
});
};
func(scenario);
});
}
describeMetricFindQuery('regions()', scenario => {
scenario.setup(() => {
scenario.requestResponse = [{text: 'us-east-1'}];
});
it('should call __GetRegions and return result', () => {
expect(scenario.result[0].text).to.contain('us-east-1');
expect(scenario.request.data.action).to.be('__GetRegions');
});
});
describeMetricFindQuery('namespaces()', scenario => {
scenario.setup(() => {
scenario.requestResponse = [{text: 'AWS/EC2'}];
});
it('should call __GetNamespaces and return result', () => {
expect(scenario.result[0].text).to.contain('AWS/EC2');
expect(scenario.request.data.action).to.be('__GetNamespaces');
});
});
describeMetricFindQuery('metrics(AWS/EC2)', scenario => {
scenario.setup(() => {
scenario.requestResponse = [{text: 'CPUUtilization'}];
});
it('should call __GetMetrics and return result', () => {
expect(scenario.result[0].text).to.be('CPUUtilization');
expect(scenario.request.data.action).to.be('__GetMetrics');
});
});
describeMetricFindQuery('dimension_keys(AWS/EC2)', scenario => {
scenario.setup(() => {
scenario.requestResponse = [{text: 'InstanceId'}];
});
it('should call __GetDimensions and return result', () => {
expect(scenario.result[0].text).to.be('InstanceId');
expect(scenario.request.data.action).to.be('__GetDimensions');
});
});
describeMetricFindQuery('dimension_values(us-east-1,AWS/EC2,CPUUtilization)', scenario => {
scenario.setup(() => {
scenario.requestResponse = {
Metrics: [
{
Namespace: 'AWS/EC2',
MetricName: 'CPUUtilization',
Dimensions: [
{
Name: 'InstanceId',
Value: 'i-12345678'
}
]
}
]
};
});
it('should call __ListMetrics and return result', () => {
expect(scenario.result[0].text).to.be('i-12345678');
expect(scenario.request.data.action).to.be('ListMetrics');
});
});
});
// define([
// './helpers',
// 'app/plugins/datasource/cloudwatch/datasource',
// 'aws-sdk',
// ], function(helpers) {
// 'use strict';
//
// describe('CloudWatchDatasource', function() {
// var ctx = new helpers.ServiceTestContext();
//
// beforeEach(module('grafana.services'));
// beforeEach(module('grafana.controllers'));
// beforeEach(ctx.providePhase(['templateSrv']));
// beforeEach(ctx.createService('CloudWatchDatasource'));
// beforeEach(function() {
// ctx.ds = new ctx.service({
// jsonData: {
// defaultRegion: 'us-east-1',
// access: 'proxy'
// }
// });
// });
//
// describe('When performing CloudWatch query', function() {
// var requestParams;
//
// var query = {
// range: { from: 'now-1h', to: 'now' },
// targets: [
// {
// region: 'us-east-1',
// namespace: 'AWS/EC2',
// metricName: 'CPUUtilization',
// dimensions: {
// InstanceId: 'i-12345678'
// },
// statistics: {
// Average: true
// },
// period: 300
// }
// ]
// };
//
// var response = {
// Datapoints: [
// {
// Average: 1,
// Timestamp: 'Wed Dec 31 1969 16:00:00 GMT-0800 (PST)'
// }
// ],
// Label: 'CPUUtilization'
// };
//
// beforeEach(function() {
// ctx.ds.getCloudWatchClient = function() {
// return {
// getMetricStatistics: function(params, callback) {
// setTimeout(function() {
// requestParams = params;
// callback(null, response);
// }, 0);
// }
// };
// };
// });
//
// it('should generate the correct query', function() {
// ctx.ds.query(query).then(function() {
// expect(requestParams.Namespace).to.be(query.targets[0].namespace);
// expect(requestParams.MetricName).to.be(query.targets[0].metricName);
// expect(requestParams.Dimensions[0].Name).to.be(Object.keys(query.targets[0].dimensions)[0]);
// expect(requestParams.Dimensions[0].Value).to.be(query.targets[0].dimensions[Object.keys(query.targets[0].dimensions)[0]]);
// expect(requestParams.Statistics).to.eql(Object.keys(query.targets[0].statistics));
// expect(requestParams.Period).to.be(query.targets[0].period);
// });
// });
//
// it('should return series list', function() {
// ctx.ds.query(query).then(function(result) {
// var s = Object.keys(query.targets[0].statistics)[0];
// expect(result.data[0].target).to.be(response.Label + s);
// expect(result.data[0].datapoints[0][0]).to.be(response.Datapoints[0][s]);
// });
// });
// });
//
// describe('When performing CloudWatch metricFindQuery', function() {
// var requestParams;
//
// var response = {
// Metrics: [
// {
// Namespace: 'AWS/EC2',
// MetricName: 'CPUUtilization',
// Dimensions: [
// {
// Name: 'InstanceId',
// Value: 'i-12345678'
// }
// ]
// }
// ]
// };
//
// beforeEach(function() {
// ctx.ds.getCloudWatchClient = function() {
// return {
// listMetrics: function(params, callback) {
// setTimeout(function() {
// requestParams = params;
// callback(null, response);
// }, 0);
// }
// };
// };
// });
//
// it('should return suggest list for region()', function() {
// var query = 'region()';
// ctx.ds.metricFindQuery(query).then(function(result) {
// expect(result).to.contain('us-east-1');
// });
// });
//
// it('should return suggest list for namespace()', function() {
// var query = 'namespace()';
// ctx.ds.metricFindQuery(query).then(function(result) {
// expect(result).to.contain('AWS/EC2');
// });
// });
//
// it('should return suggest list for metrics()', function() {
// var query = 'metrics(AWS/EC2)';
// ctx.ds.metricFindQuery(query).then(function(result) {
// expect(result).to.contain('CPUUtilization');
// });
// });
//
// it('should return suggest list for dimension_keys()', function() {
// var query = 'dimension_keys(AWS/EC2)';
// ctx.ds.metricFindQuery(query).then(function(result) {
// expect(result).to.contain('InstanceId');
// });
// });
//
// it('should return suggest list for dimension_values()', function() {
// var query = 'dimension_values(us-east-1,AWS/EC2,CPUUtilization)';
// ctx.ds.metricFindQuery(query).then(function(result) {
// expect(result).to.contain('InstanceId');
// });
// });
// });
// });
// });
{
"name": "aws-sdk",
"ignore": [
"apis",
"doc-src",
"dist-tools",
"eslint-rules",
"features",
"lib",
"scripts",
"tasks",
"test",
"Gemfile*",
"configuration*",
"Rakefile",
"package.json",
"testem.json",
".*",
"index.js"
],
"main": "dist/aws-sdk.js",
"homepage": "https://github.com/aws/aws-sdk-js",
"version": "2.1.42",
"_release": "2.1.42",
"_resolution": {
"type": "version",
"tag": "v2.1.42",
"commit": "6ad65d3e09a3a4531c84d12b980e6fb9af136a0a"
},
"_source": "git://github.com/aws/aws-sdk-js.git",
"_target": "~2.1.41",
"_originalSource": "aws-sdk"
}
\ No newline at end of file
# Contributing to the AWS SDK for JavaScript
We work hard to provide a high-quality and useful SDK, and we greatly value
feedback and contributions from our community. Whether it's a bug report,
new feature, correction, or additional documentation, we welcome your issues
and pull requests. Please read through this document before submitting any
issues or pull requests to ensure we have all the necessary information to
effectively respond to your bug report or contribution.
## Filing Bug Reports
You can file bug reports against the SDK on the [GitHub issues][issues] page.
If you are filing a report for a bug or regression in the SDK, it's extremely
helpful to provide as much information as possible when opening the original
issue. This helps us reproduce and investigate the possible bug without having
to wait for this extra information to be provided. Please read the following
guidelines prior to filing a bug report.
1. Search through existing [issues][] to ensure that your specific issue has
not yet been reported. If it is a common issue, it is likely there is
already a bug report for your problem.
2. Ensure that you have tested the latest version of the SDK. Although you
may have an issue against an older version of the SDK, we cannot provide
bug fixes for old versions. It's also possible that the bug may have been
fixed in the latest release.
3. Provide as much information about your environment, SDK version, and
relevant dependencies as possible. For example, let us know what version
of Node.js you are using, or if it's a browser issue, which browser you
are using. If the issue only occurs with a specific dependency loaded,
please provide that dependency name and version.
4. Provide a minimal test case that reproduces your issue or any error
information you related to your problem. We can provide feedback much
more quickly if we know what operations you are calling in the SDK. If
you cannot provide a full test case, provide as much code as you can
to help us diagnose the problem. Any relevant information should be provided
as well, like whether this is a persistent issue, or if it only occurs
some of the time.
## Submitting Pull Requests
We are always happy to receive code and documentation contributions to the SDK.
Please be aware of the following notes prior to opening a pull request:
1. The SDK is released under the [Apache license][license]. Any code you submit
will be released under that license. For substantial contributions, we may
ask you to sign a [Contributor License Agreement (CLA)][cla].
2. If you would like to implement support for a significant feature that is not
yet available in the SDK, please talk to us beforehand to avoid any
duplication of effort.
### Testing
To run the tests locally, install `phantomjs`. You can do so using [Homebrew][homebrew]:
```
brew install phantomjs
```
Then, to run all tests:
```
npm test
```
To run a particular test subset e.g. just the unit tests:
```
npm run-script unit
```
See the implementation of the `test` script in `package.json` for more options.
[issues]: https://github.com/aws/aws-sdk-js/issues
[pr]: https://github.com/aws/aws-sdk-js/pulls
[license]: http://aws.amazon.com/apache2.0/
[cla]: http://en.wikipedia.org/wiki/Contributor_License_Agreement
[homebrew]: http://brew.sh/
AWS SDK for JavaScript
Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
This product includes software developed at
Amazon Web Services, Inc. (http://aws.amazon.com/).
# AWS SDK for JavaScript
[![NPM](https://nodei.co/npm/aws-sdk.svg?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/aws-sdk/)
[![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.svg)](https://gitter.im/aws/aws-sdk-js)
[![Version](https://badge.fury.io/js/aws-sdk.svg)](http://badge.fury.io/js/aws-sdk) [![Build Status](https://travis-ci.org/aws/aws-sdk-js.svg?branch=master)](https://travis-ci.org/aws/aws-sdk-js) [![Coverage Status](https://coveralls.io/repos/aws/aws-sdk-js/badge.svg?branch=master)](https://coveralls.io/r/aws/aws-sdk-js?branch=master)
The official AWS SDK for JavaScript, available for browsers and mobile devices,
or Node.js backends
Release notes can be found at http://aws.amazon.com/releasenotes/SDK/JavaScript
<p class="note">
If you are upgrading from 1.x to 2.0 of the SDK, please see
the {file:UPGRADING.md} notes for information on how to migrate existing code
to work with the new major version.
</p>
## Installing
### In the Browser
To use the SDK in the browser, simply add the following script tag to your
HTML pages:
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.1.42.min.js"></script>
The AWS SDK is also compatible with [browserify](http://browserify.org).
### In Node.js
The preferred way to install the AWS SDK for Node.js is to use the
[npm](http://npmjs.org) package manager for Node.js. Simply type the following
into a terminal window:
```sh
npm install aws-sdk
```
### Using Bower
You can also use [Bower](http://bower.io) to install the SDK by typing the
following into a terminal window:
```sh
bower install aws-sdk-js
```
## Usage and Getting Started
You can find a getting started guide at:
http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/
## Supported Services
<p class="note"><strong>Note</strong>:
Although all services are supported in the browser version of the SDK,
not all of the services are available in the default hosted build (using the
script tag provided above). A list of services in the hosted build are provided
in the "<a href="http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/browser-services.html">Working With Services</a>"
section of the browser SDK guide, including instructions on how to build a
custom version of the SDK with extra services.
</p>
The SDK currently supports the following services:
<table>
<thead>
<th>Service Name</th>
<th>Class Name</th>
<th>API Version</th>
</thead>
<tbody>
<tr><td>Amazon CloudFront</td><td>AWS.CloudFront</td><td>2014-10-21</td></tr>
<tr><td>Amazon CloudSearch</td><td>AWS.CloudSearch</td><td>2013-01-01</td></tr>
<tr><td>Amazon CloudSearch Domain</td><td>AWS.CloudSearchDomain</td><td>2013-01-01</td></tr>
<tr><td>Amazon CloudWatch</td><td>AWS.CloudWatch</td><td>2010-08-01</td></tr>
<tr><td>Amazon CloudWatch Logs</td><td>AWS.CloudWatchLogs</td><td>2014-03-28</td></tr>
<tr><td>Amazon Cognito Identity</td><td>AWS.CognitoIdentity</td><td>2014-06-30</td></tr>
<tr><td>Amazon Cognito Sync</td><td>AWS.CognitoSync</td><td>2014-06-30</td></tr>
<tr><td>Amazon DynamoDB</td><td>AWS.DynamoDB</td><td>2012-08-10</td></tr>
<tr><td>Amazon Elastic Compute Cloud</td><td>AWS.EC2</td><td>2014-10-01</td></tr>
<tr><td>Amazon Elastic MapReduce</td><td>AWS.EMR</td><td>2009-03-31</td></tr>
<tr><td>Amazon Elastic Transcoder</td><td>AWS.ElasticTranscoder</td><td>2012-09-25</td></tr>
<tr><td>Amazon ElastiCache</td><td>AWS.ElastiCache</td><td>2014-09-30</td></tr>
<tr><td>Amazon Glacier</td><td>AWS.Glacier</td><td>2012-06-01</td></tr>
<tr><td>Amazon Kinesis</td><td>AWS.Kinesis</td><td>2013-12-02</td></tr>
<tr><td>Amazon Redshift</td><td>AWS.Redshift</td><td>2012-12-01</td></tr>
<tr><td>Amazon Relational Database Service</td><td>AWS.RDS</td><td>2014-09-01</td></tr>
<tr><td>Amazon Route 53</td><td>AWS.Route53</td><td>2013-04-01</td></tr>
<tr><td>Amazon Route 53 Domains</td><td>AWS.Route53Domains</td><td>2014-05-15</td></tr>
<tr><td>Amazon Simple Email Service</td><td>AWS.SES</td><td>2010-12-01</td></tr>
<tr><td>Amazon Simple Notification Service</td><td>AWS.SNS</td><td>2010-03-31</td></tr>
<tr><td>Amazon Simple Queue Service</td><td>AWS.SQS</td><td>2012-11-05</td></tr>
<tr><td>Amazon Simple Storage Service</td><td>AWS.S3</td><td>2006-03-01</td></tr>
<tr><td>Amazon Simple Workflow Service</td><td>AWS.SWF</td><td>2012-01-25</td></tr>
<tr><td>Amazon SimpleDB</td><td>AWS.SimpleDB</td><td>2009-04-15</td></tr>
<tr><td>Auto Scaling</td><td>AWS.AutoScaling</td><td>2011-01-01</td></tr>
<tr><td>AWS CloudFormation</td><td>AWS.CloudFormation</td><td>2010-05-15</td></tr>
<tr><td>AWS CloudTrail</td><td>AWS.CloudTrail</td><td>2013-11-01</td></tr>
<tr><td>AWS CodeDeploy</td><td>AWS.CodeDeploy</td><td>2014-10-06</td></tr>
<tr><td>AWS Config</td><td>AWS.ConfigService</td><td>2014-11-12</td></tr>
<tr><td>AWS Data Pipeline</td><td>AWS.DataPipeline</td><td>2012-10-29</td></tr>
<tr><td>AWS Direct Connect</td><td>AWS.DirectConnect</td><td>2012-10-25</td></tr>
<tr><td>AWS Elastic Beanstalk</td><td>AWS.ElasticBeanstalk</td><td>2010-12-01</td></tr>
<tr><td>AWS Identity and Access Management</td><td>AWS.IAM</td><td>2010-05-08</td></tr>
<tr><td>AWS Import/Export</td><td>AWS.ImportExport</td><td>2010-06-01</td></tr>
<tr><td>AWS Key Management Service</td><td>AWS.KMS</td><td>2014-11-01</td></tr>
<tr><td>AWS Lambda</td><td>AWS.Lambda</td><td>2014-11-11</td></tr>
<tr><td>AWS OpsWorks</td><td>AWS.OpsWorks</td><td>2013-02-18</td></tr>
<tr><td>AWS Security Token Service</td><td>AWS.STS</td><td>2011-06-15</td></tr>
<tr><td>AWS Storage Gateway</td><td>AWS.StorageGateway</td><td>2013-06-30</td></tr>
<tr><td>AWS Support</td><td>AWS.Support</td><td>2013-04-15</td></tr>
<tr><td>Elastic Load Balancing</td><td>AWS.ELB</td><td>2012-06-01</td></tr>
</tbody>
</table>
## License
This SDK is distributed under the
[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0),
see LICENSE.txt and NOTICE.txt for more information.
# @!title Upgrading Notes (1.x to 2.0)
# Upgrading Notes (1.x to 2.0)
This document captures breaking changes from 1.x versions to the first
stable 2.x (non-RC) release of the AWS SDK for JavaScript.
## 1. Automatic Conversion of Base64 and Timestamp Types on Input/Output
The SDK will now automatically encode and decode base64-encoded values, as well
as timestamp values, on the user's behalf. This change affects any operation
where Base64 or Timestamp values were sent by a request or returned in a
response, i.e., `AWS.DynamoDB` and `AWS.SQS`, which allow for Base64
encoded values.
User code that previously did base64 conversion no longer requires this.
Furthermore, values encoded as base64 are now returned as Buffer objects
from server responses (and can also be passed as Buffer input). For
example, the following 1.x `SQS.sendMessage()` parameters:
```javascript
var params = {
MessageBody: 'Some Message',
MessageAttributes: {
attrName: {
DataType: 'Binary',
BinaryValue: new Buffer('example text').toString('base64')
}
}
};
```
Can be rewritten as:
```javascript
var params = {
MessageBody: 'Some Message',
MessageAttributes: {
attrName: {
DataType: 'Binary',
BinaryValue: 'example text'
}
}
};
```
And the message will be read as:
```javascript
sqs.receiveMessage(params, function(err, data) {
// buf is <Buffer 65 78 61 6d 70 6c 65 20 74 65 78 74>
var buf = data.Messages[0].MessageAttributes.attrName.BinaryValue;
console.log(buf.toString()); // "example text"
});
```
## 2. Moved response.data.RequestId to response.requestId
The SDK now stores request IDs for all services in a consistent place on the
response object, rather than inside the response.data property. This is to
improve consistency across services that expose request IDs in different ways.
Note that this is also a breaking change that renames the
`response.data.RequestId` property to `response.requestId`
(or `this.requestId` inside of a callback).
To migrate your code, change:
```javascript
svc.operation(params, function (err, data) {
console.log('Request ID:', data.RequestId);
});
```
To the following:
```javascript
svc.operation(params, function () {
console.log('Request ID:', this.requestId);
});
```
## 3. Exposed Wrapper Elements
If you use {AWS.ElastiCache}, {AWS.RDS}, or {AWS.Redshift}, you must now access
the response through the top-level output property in the response for certain
operations. This change corrects the SDK to behave according to documentation
output, which was previously listing this wrapper element.
Example:
`RDS.describeEngineDefaultParameters()` used to return:
```javascript
{ Parameters: [ ... ] }
```
This operation now returns:
```javascript
{ EngineDefaults: { Parameters: [ ... ] } }
```
The full list of affected operations for each service are:
**AWS.ElastiCache**: authorizeCacheSecurityGroupIngress, createCacheCluster,
createCacheParameterGroup, createCacheSecurityGroup, createCacheSubnetGroup,
createReplicationGroup, deleteCacheCluster, deleteReplicationGroup,
describeEngineDefaultParameters, modifyCacheCluster, modifyCacheSubnetGroup,
modifyReplicationGroup, purchaseReservedCacheNodesOffering, rebootCacheCluster,
revokeCacheSecurityGroupIngress
**AWS.RDS**: addSourceIdentifierToSubscription, authorizeDBSecurityGroupIngress,
copyDBSnapshot, createDBInstance, createDBInstanceReadReplica,
createDBParameterGroup, createDBSecurityGroup, createDBSnapshot,
createDBSubnetGroup, createEventSubscription, createOptionGroup,
deleteDBInstance, deleteDBSnapshot, deleteEventSubscription,
describeEngineDefaultParameters, modifyDBInstance, modifyDBSubnetGroup,
modifyEventSubscription, modifyOptionGroup, promoteReadReplica,
purchaseReservedDBInstancesOffering, rebootDBInstance,
removeSourceIdentifierFromSubscription, restoreDBInstanceFromDBSnapshot,
restoreDBInstanceToPointInTime, revokeDBSecurityGroupIngress
**AWS.Redshift**: authorizeClusterSecurityGroupIngress, authorizeSnapshotAccess,
copyClusterSnapshot, createCluster, createClusterParameterGroup,
createClusterSecurityGroup, createClusterSnapshot, createClusterSubnetGroup,
createEventSubscription, createHsmClientCertificate, createHsmConfiguration,
deleteCluster, deleteClusterSnapshot, describeDefaultClusterParameters,
disableSnapshotCopy, enableSnapshotCopy, modifyCluster,
modifyClusterSubnetGroup, modifyEventSubscription,
modifySnapshotCopyRetentionPeriod, purchaseReservedNodeOffering, rebootCluster,
restoreFromClusterSnapshot, revokeClusterSecurityGroupIngress,
revokeSnapshotAccess, rotateEncryptionKey
## 4. Dropped `.Client` and `.client` Properties
The `.Client` and `.client` properties have been removed from Service objects.
If you are using the `.Client` property on a Service class or a `.client`
property on an instance of the service, remove these properties from your code.
Upgrading example:
The following 1.x code:
```
var sts = new AWS.STS.Client();
// or
var sts = new AWS.STS();
sts.client.operation(...);
```
Should be changed to the following:
```
var sts = new AWS.STS();
sts.operation(...)
```
{
"name": "aws-sdk",
"ignore": [
"apis", "doc-src", "dist-tools", "eslint-rules", "features", "lib",
"scripts", "tasks", "test", "Gemfile*", "configuration*",
"Rakefile", "package.json", "testem.json", ".*", "index.js"
],
"main": "dist/aws-sdk.js"
}
The bundled package of the AWS SDK for JavaScript is available under the
Apache License, Version 2.0:
Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"). You
may not use this file except in compliance with the License. A copy of
the License is located at
http://aws.amazon.com/apache2.0/
or in the "license" file accompanying this file. This file is
distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License.
This product bundles browserify, which is available under a
"3-clause BSD" license:
Copyright Joyent, Inc. and other Node contributors.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
This product bundles crypto-browserify, which is available under
the MIT license:
Copyright (c) 2013 Dominic Tarr
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This product bundles MD5, SHA-1, and SHA-256 hashing algorithm components,
which are available under a BSD license:
Copyright (c) 1998 - 2009, Paul Johnston & Contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyrightnotice,
this list of conditions and the following disclaimer. Redistributions
in binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of the author nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
module.exports = function(config) {
'use strict';
return {
css: {
files: [ '<%= srcDir %>/less/**/*.less' ],
tasks: ['css'],
options: {
spawn: false
}
},
// css: {
// files: [ '<%= srcDir %>/less#<{(||)}>#*.less' ],
// tasks: ['css'],
// options: {
// spawn: false
// }
// },
copy_to_gen: {
files: ['<%= srcDir %>/**/*', '!<%= srcDir %>/**/*.less'],
tasks: ['copy:public_to_gen'],
files: ['<%= srcDir %>/**/*'],
tasks: [
'clean:gen',
'copy:public_to_gen',
'css',
'typescript:build',
'jshint',
'jscs',
'tslint',
'karma:test'
],
options: {
spawn: false
}
},
typescript: {
files: ['<%= srcDir %>/app/**/*.ts', '<%= srcDir %>/test/**/*.ts'],
tasks: ['tslint', 'typescript:build'],
options: {
spawn: false
}
}
// typescript: {
// files: ['<%= srcDir %>/app#<{(||)}>#*.ts', '<%= srcDir %>/test#<{(||)}>#*.ts'],
// tasks: ['tslint', 'typescript:build'],
// options: {
// spawn: false
// }
// }
};
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment