Bläddra i källkod

add CloudWatch datasource

Mitsuhiro Tanda 10 år sedan
förälder
incheckning
88ce05976e

+ 2 - 1
bower.json

@@ -21,6 +21,7 @@
     "angular-native-dragdrop": "~1.1.0",
     "angular-bindonce": "~0.3.3",
     "requirejs": "~2.1.18",
-    "requirejs-text": "~2.0.14"
+    "requirejs-text": "~2.0.14",
+    "aws-sdk": "~2.1.42"
   }
 }

+ 1 - 0
public/app/components/require.config.js

@@ -44,6 +44,7 @@ require.config({
     modernizr:                '../vendor/modernizr-2.6.1',
 
     'bootstrap-tagsinput':    '../vendor/tagsinput/bootstrap-tagsinput',
+    'aws-sdk':                '../vendor/aws-sdk/dist/aws-sdk.min',
   },
   shim: {
 

+ 154 - 0
public/app/plugins/datasource/cloudwatch/datasource.js

@@ -0,0 +1,154 @@
+/* global AWS */
+define([
+  'angular',
+  'lodash',
+  'kbn',
+  'moment',
+  './queryCtrl',
+  'aws-sdk',
+],
+function (angular, _, kbn) {
+  'use strict';
+
+  var module = angular.module('grafana.services');
+
+  module.factory('CloudWatchDatasource', function($q, $http, templateSrv) {
+
+    function CloudWatchDatasource(datasource) {
+      this.type = 'cloudwatch';
+      this.name = datasource.name;
+      this.supportMetrics = true;
+
+      AWS.config.update({ region: datasource.jsonData.region });
+      this.cloudwatch = new AWS.CloudWatch({
+        accessKeyId: datasource.jsonData.accessKeyId,
+        secretAccessKey: datasource.jsonData.secretAccessKey,
+      });
+    }
+
+    // Called once per panel (graph)
+    CloudWatchDatasource.prototype.query = function(options) {
+      var start = convertToCloudWatchTime(options.range.from);
+      var end = convertToCloudWatchTime(options.range.to);
+
+      var queries = [];
+      _.each(options.targets, _.bind(function(target) {
+        if (!target.namespace || !target.metricName || _.isEmpty(target.dimensions) || _.isEmpty(target.statistics)) {
+          return;
+        }
+
+        var query = {};
+        query.namespace = templateSrv.replace(target.namespace, options.scopedVars);
+        query.metricName = templateSrv.replace(target.metricName, options.scopedVars);
+        query.dimensions = _.map(_.keys(target.dimensions), function(key) {
+          return {
+            Name: key,
+            Value: target.dimensions[key]
+          };
+        });
+        query.statistics = _.keys(target.statistics);
+        query.period = target.period;
+
+        var range = (end.getTime() - start.getTime()) / 1000;
+        // CloudWatch limit datapoints up to 1440
+        if (range / query.period >= 1440) {
+          query.period = Math.floor(range / 1440 / 60) * 60;
+        }
+
+        queries.push(query);
+      }, this));
+
+      // No valid targets, return the empty result to save a round trip.
+      if (_.isEmpty(queries)) {
+        var d = $q.defer();
+        d.resolve({ data: [] });
+        return d.promise;
+      }
+
+      var allQueryPromise = _.map(queries, _.bind(function(query) {
+        return this.performTimeSeriesQuery(query, start, end);
+      }, this));
+
+      return $q.all(allQueryPromise)
+        .then(function(allResponse) {
+          var result = [];
+
+          _.each(allResponse, function(response, index) {
+            var metrics = transformMetricData(response, options.targets[index]);
+            _.each(metrics, function(m) {
+              result.push(m);
+            });
+          });
+
+          return { data: result };
+        });
+    };
+
+    CloudWatchDatasource.prototype.performTimeSeriesQuery = function(query, start, end) {
+      var params = {
+        Namespace: query.namespace,
+        MetricName: query.metricName,
+        Dimensions: query.dimensions,
+        Statistics: query.statistics,
+        StartTime: start,
+        EndTime: end,
+        Period: query.period
+      };
+
+      var d = $q.defer();
+      this.cloudwatch.getMetricStatistics(params, function(err, data) {
+        if (err) {
+          return d.reject(err);
+        }
+        return d.resolve(data);
+      });
+
+      return d.promise;
+    };
+
+    CloudWatchDatasource.prototype.performSuggestQuery = function(params) {
+      var d = $q.defer();
+
+      this.cloudwatch.listMetrics(params, function(err, data) {
+        if (err) {
+          return d.reject(err);
+        }
+
+        return d.resolve(data);
+      });
+
+      return d.promise;
+    };
+
+    CloudWatchDatasource.prototype.testDatasource = function() {
+      return this.performSuggestQuery({}).then(function () {
+        return { status: 'success', message: 'Data source is working', title: 'Success' };
+      });
+    };
+
+    function transformMetricData(md, options) {
+      var result = [];
+
+      var dimensionPart = JSON.stringify(options.dimensions);
+      _.each(_.keys(options.statistics), function(s) {
+        var metricLabel = md.Label + '_' + s + dimensionPart;
+
+        var dps = _.map(md.Datapoints, function(value) {
+          return [value[s], new Date(value.Timestamp).getTime()];
+        });
+        dps = _.sortBy(dps, function(dp) { return dp[1]; });
+
+        result.push({ target: metricLabel, datapoints: dps });
+      });
+
+      return result;
+    }
+
+    function convertToCloudWatchTime(date) {
+      return kbn.parseDate(date);
+    }
+
+    return CloudWatchDatasource;
+  });
+
+});

+ 30 - 0
public/app/plugins/datasource/cloudwatch/partials/config.html

@@ -0,0 +1,30 @@
+<h5>CloudWatch details</h5>
+
+<div class="tight-form">
+  <ul class="tight-form-list">
+    <li class="tight-form-item" style="width: 80px">
+      Region
+    </li>
+    <li>
+      <input type="text" class="tight-form-input input-large" ng-model='current.jsonData.region' placeholder="" required></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: 80px">
+      Access Key Id
+    </li>
+    <li>
+      <input type="text" class="tight-form-input input-large" ng-model='current.jsonData.accessKeyId' placeholder="" required></input>
+    </li>
+    <li class="tight-form-item">
+      Secret Access Key
+    </li>
+    <li>
+      <input type="password" class="tight-form-input input-large" ng-model='current.jsonData.secretAccessKey' placeholder="" required></input>
+    </li>
+  </ul>
+  <div class="clearfix"></div>
+</div>

+ 212 - 0
public/app/plugins/datasource/cloudwatch/partials/query.editor.html

@@ -0,0 +1,212 @@
+<div class="editor-row" style="margin-top: 10px;">
+
+  <div ng-repeat="target in panel.targets"
+       style="margin-bottom: 10px;"
+       ng-class="{'tight-form-disabled': target.hide}"
+       ng-controller="CloudWatchQueryCtrl"
+       ng-init="init()">
+
+    <div class="tight-form">
+      <ul class="tight-form-list pull-right">
+        <li class="tight-form-item">
+          <div class="dropdown">
+            <a class="pointer dropdown-toggle"
+              data-toggle="dropdown"
+              tabindex="1">
+              <i class="fa fa-bars"></i>
+            </a>
+            <ul class="dropdown-menu pull-right" role="menu">
+              <li role="menuitem">
+                <a tabindex="1"
+                   ng-click="duplicate()">
+                  Duplicate
+                </a>
+              </li>
+              <li role="menuitem">
+                <a tabindex="1"
+                   ng-click="moveMetricQuery($index, $index-1)">
+                  Move up
+                </a>
+              </li>
+              <li role="menuitem">
+                <a tabindex="1"
+                   ng-click="moveMetricQuery($index, $index+1)">
+                  Move down
+                </a>
+              </li>
+            </ul>
+          </div>
+        </li>
+        <li class="tight-form-item last">
+          <a class="pointer" tabindex="1" ng-click="removeDataQuery(target)">
+            <i class="fa fa-remove"></i>
+          </a>
+        </li>
+      </ul>
+
+      <ul class="tight-form-list">
+        <li>
+          <a class="tight-form-item"
+             ng-click="target.hide = !target.hide; get_data();"
+             role="menuitem">
+            <i class="fa fa-eye"></i>
+          </a>
+        </li>
+      </ul>
+
+      <ul class="tight-form-list" role="menu">
+        <li class="tight-form-item" style="width: 100px">
+          Namespace
+        </li>
+        <li>
+          <input type="text"
+                 class="input-medium tight-form-input"
+                 ng-model="target.namespace"
+                 spellcheck='false'
+                 bs-typeahead="suggestNamespace"
+                 placeholder="namespace"
+                 data-min-length=0 data-items=100
+                 ng-change="refreshMetricData()"
+                 >
+        </li>
+        <li class="tight-form-item">
+          Metric
+        </li>
+        <li>
+          <input type="text"
+                 class="input-medium tight-form-input"
+                 ng-model="target.metricName"
+                 spellcheck='false'
+                 bs-typeahead="suggestMetrics"
+                 placeholder="metric name"
+                 data-min-length=0 data-items=100
+                 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">
+          <i class="fa fa-eye invisible"></i>
+        </li>
+
+        <li class="tight-form-item" style="width: 86px">
+          Dimensions
+        </li>
+        <li ng-repeat="(key, value) in target.dimensions 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>
+      </ul>
+
+      <div class="clearfix"></div>
+    </div>
+
+    <div class="tight-form">
+      <ul class="tight-form-list" role="menu">
+        <li class="tight-form-item">
+          <i class="fa fa-eye invisible"></i>
+        </li>
+
+        <li class="tight-form-item" style="width: 86px">
+          Statistics
+        </li>
+        <li class="tight-form-item">
+          Min&nbsp;
+          <input class="cr1" id="target.statistics.Minimum" type="checkbox"
+                     ng-model="target.statistics.Minimum" ng-checked="target.statistics.Minimum" ng-change="statisticsOptionChanged()">
+          <label for="target.statistics.Minimum" class="cr1"></label>
+        </li>
+        <li class="tight-form-item">
+          Max&nbsp;
+          <input class="cr1" id="target.statistics.Maximum" type="checkbox"
+                     ng-model="target.statistics.Maximum" ng-checked="target.statistics.Maximum" ng-change="statisticsOptionChanged()">
+          <label for="target.statistics.Maximum" class="cr1"></label>
+        </li>
+        <li class="tight-form-item">
+          Avg&nbsp;
+          <input class="cr1" id="target.statistics.Average" type="checkbox"
+                     ng-model="target.statistics.Average" ng-checked="target.statistics.Average" ng-change="statisticsOptionChanged()">
+          <label for="target.statistics.Average" class="cr1"></label>
+        </li>
+        <li class="tight-form-item">
+          Sum&nbsp;
+          <input class="cr1" id="target.statistics.Sum" type="checkbox"
+                   ng-model="target.statistics.Sum" ng-checked="target.statistics.Sum" ng-change="statisticsOptionChanged()">
+          <label for="target.statistics.Sum" class="cr1"></label>
+        </li>
+        <li class="tight-form-item last">
+          SampleCount&nbsp;
+          <input class="cr1" id="target.statistics.SampleCount" type="checkbox"
+                       ng-model="target.statistics.SampleCount" ng-checked="target.statistics.SampleCount" ng-change="statisticsOptionChanged()">
+          <label for="target.statistics.SampleCount" class="cr1"></label>
+        </li>
+      </ul>
+
+      <div class="clearfix"></div>
+    </div>
+
+    <div class="tight-form">
+      <ul class="tight-form-list" role="menu">
+        <li class="tight-form-item">
+          <i class="fa fa-eye invisible"></i>
+        </li>
+
+        <li class="tight-form-item" style="width: 100px">
+          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-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>
+        </li>
+      </ul>
+
+      <div class="clearfix"></div>
+    </div>
+
+  </div>
+</div>

+ 16 - 0
public/app/plugins/datasource/cloudwatch/plugin.json

@@ -0,0 +1,16 @@
+{
+  "pluginType": "datasource",
+  "name": "CloudWatch",
+
+  "type": "cloudwatch",
+  "serviceName": "CloudWatchDatasource",
+
+  "module": "plugins/datasource/cloudwatch/datasource",
+
+  "partials": {
+    "config": "app/plugins/datasource/cloudwatch/partials/config.html",
+    "query": "app/plugins/datasource/cloudwatch/partials/query.editor.html"
+  },
+
+  "metrics": true
+}

+ 271 - 0
public/app/plugins/datasource/cloudwatch/queryCtrl.js

@@ -0,0 +1,271 @@
+define([
+  'angular',
+  'lodash',
+  'kbn',
+],
+function (angular, _, kbn) {
+  'use strict';
+
+  var module = angular.module('grafana.controllers');
+
+  var supportedMetrics = {
+    "AWS/AutoScaling": [
+      "GroupMinSize", "GroupMaxSize", "GroupDesiredCapacity", "GroupInServiceInstances", "GroupPendingInstances", "GroupStandbyInstances", "GroupTerminatingInstances", "GroupTotalInstances"
+    ],
+    "AWS/Billing": [
+      "EstimatedCharges"
+    ],
+    "AWS/CloudFront": [
+      "Requests", "BytesDownloaded", "BytesUploaded", "TotalErrorRate", "4xxErrorRate", "5xxErrorRate"
+    ],
+    "AWS/CloudSearch": [
+      "SuccessfulRequests", "SearchableDocuments", "IndexUtilization", "Partitions"
+    ],
+    "AWS/DynamoDB": [
+      "ConditionalCheckFailedRequests", "ConsumedReadCapacityUnits", "ConsumedWriteCapacityUnits", "OnlineIndexConsumedWriteCapacity", "OnlineIndexPercentageProgress", "OnlineIndexThrottleEvents", "ProvisionedReadCapacityUnits", "ProvisionedWriteCapacityUnits", "ReadThrottleEvents", "ReturnedItemCount", "SuccessfulRequestLatency", "SystemErrors", "ThrottledRequests", "UserErrors", "WriteThrottleEvents"
+    ],
+    "AWS/ElastiCache": [
+      "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": [
+      "VolumeReadBytes", "VolumeWriteBytes", "VolumeReadOps", "VolumeWriteOps", "VolumeTotalReadTime", "VolumeTotalWriteTime", "VolumeIdleTime", "VolumeQueueLength", "VolumeThroughputPercentage", "VolumeConsumedReadWriteOps",
+    ],
+    "AWS/EC2": [
+      "CPUCreditUsage", "CPUCreditBalance", "CPUUtilization", "DiskReadOps", "DiskWriteOps", "DiskReadBytes", "DiskWriteBytes", "NetworkIn", "NetworkOut", "StatusCheckFailed", "StatusCheckFailed_Instance", "StatusCheckFailed_System"
+    ],
+    "AWS/ELB": [
+      "HealthyHostCount", "UnHealthyHostCount", "RequestCount", "Latency", "HTTPCode_ELB_4XX", "HTTPCode_ELB_5XX", "HTTPCode_Backend_2XX", "HTTPCode_Backend_3XX", "HTTPCode_Backend_4XX", "HTTPCode_Backend_5XX", "BackendConnectionErrors", "SurgeQueueLength", "SpilloverCount"
+    ],
+    "AWS/ElasticMapReduce": [
+      "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": [
+      "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": [
+      "PredictCount", "PredictFailureCount"
+    ],
+    "AWS/OpsWorks": [
+      "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": [
+      "CPUUtilization", "DatabaseConnections", "HealthStatus", "MaintenanceMode", "NetworkReceiveThroughput", "NetworkTransmitThroughput", "PercentageDiskSpaceUsed", "ReadIOPS", "ReadLatency", "ReadThroughput", "WriteIOPS", "WriteLatency", "WriteThroughput"
+    ],
+    "AWS/RDS": [
+      "BinLogDiskUsage", "CPUUtilization", "DatabaseConnections", "DiskQueueDepth", "FreeableMemory", "FreeStorageSpace", "ReplicaLag", "SwapUsage", "ReadIOPS", "WriteIOPS", "ReadLatency", "WriteLatency", "ReadThroughput", "WriteThroughput", "NetworkReceiveThroughput", "NetworkTransmitThroughput"
+    ],
+    "AWS/Route53": [
+      "HealthCheckStatus", "HealthCheckPercentageHealthy"
+    ],
+    "AWS/SNS": [
+      "NumberOfMessagesPublished", "PublishSize", "NumberOfNotificationsDelivered", "NumberOfNotificationsFailed"
+    ],
+    "AWS/SQS": [
+      "NumberOfMessagesSent", "SentMessageSize", "NumberOfMessagesReceived", "NumberOfEmptyReceives", "NumberOfMessagesDeleted", "ApproximateNumberOfMessagesDelayed", "ApproximateNumberOfMessagesVisible", "ApproximateNumberOfMessagesNotVisible"
+    ],
+    "AWS/S3": [
+      "BucketSizeBytes", "NumberOfObjects"
+    ],
+    "AWS/SWF": [
+      "DecisionTaskScheduleToStartTime", "DecisionTaskStartToCloseTime", "DecisionTasksCompleted", "StartedDecisionTasksTimedOutOnClose", "WorkflowStartToCloseTime", "WorkflowsCanceled", "WorkflowsCompleted", "WorkflowsContinuedAsNew", "WorkflowsFailed", "WorkflowsTerminated", "WorkflowsTimedOut"
+    ],
+    "AWS/StorageGateway": [
+      "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": [
+      "Available", "Unhealthy", "ConnectionAttempt", "ConnectionSuccess", "ConnectionFailure", "SessionLaunchTime", "InSessionLatency", "SessionDisconnect"
+    ],
+  };
+
+  var supportedDimensions = {
+    "AWS/AutoScaling": [
+      "AutoScalingGroupName"
+    ],
+    "AWS/Billing": [
+      "ServiceName", "LinkedAccount", "Currency"
+    ],
+    "AWS/CloudFront": [
+      "DistributionId", "Region"
+    ],
+    "AWS/CloudSearch": [
+
+    ],
+    "AWS/DynamoDB": [
+      "TableName", "GlobalSecondaryIndexName", "Operation"
+    ],
+    "AWS/ElastiCache": [
+      "CacheClusterId", "CacheNodeId"
+    ],
+    "AWS/EBS": [
+      "VolumeId"
+    ],
+    "AWS/EC2": [
+      "AutoScalingGroupName", "ImageId", "InstanceId", "InstanceType"
+    ],
+    "AWS/ELB": [
+      "LoadBalancerName", "AvailabilityZone"
+    ],
+    "AWS/ElasticMapReduce": [
+      "ClusterId", "JobId"
+    ],
+    "AWS/Kinesis": [
+      "StreamName"
+    ],
+    "AWS/ML": [
+      "MLModelId", "RequestMode"
+    ],
+    "AWS/OpsWorks": [
+      "StackId", "LayerId", "InstanceId"
+    ],
+    "AWS/Redshift": [
+      "NodeID", "ClusterIdentifier"
+    ],
+    "AWS/RDS": [
+      "DBInstanceIdentifier", "DatabaseClass", "EngineName"
+    ],
+    "AWS/Route53": [
+      "HealthCheckId"
+    ],
+    "AWS/SNS": [
+      "Application", "Platform", "TopicName"
+    ],
+    "AWS/SQS": [
+      "QueueName"
+    ],
+    "AWS/S3": [
+      "BucketName", "StorageType"
+    ],
+    "AWS/SWF": [
+      "Domain", "ActivityTypeName", "ActivityTypeVersion"
+    ],
+    "AWS/StorageGateway": [
+      "GatewayId", "GatewayName", "VolumeId"
+    ],
+    "AWS/WorkSpaces": [
+      "DirectoryId", "WorkspaceId"
+    ],
+  };
+
+  module.controller('CloudWatchQueryCtrl', function($scope) {
+
+    $scope.init = function() {
+      $scope.target.namespace = $scope.target.namespace || '';
+      $scope.target.metricName = $scope.target.metricName || '';
+      $scope.target.dimensions = $scope.target.dimensions || {};
+      $scope.target.statistics = $scope.target.statistics || {};
+      $scope.target.period = $scope.target.period || 60;
+
+      $scope.target.errors = validateTarget();
+    };
+
+    $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.moveMetricQuery = function(fromIndex, toIndex) {
+      _.move($scope.panel.targets, fromIndex, toIndex);
+    };
+
+    $scope.duplicate = function() {
+      var clone = angular.copy($scope.target);
+      $scope.panel.targets.push(clone);
+    };
+
+    $scope.suggestNamespace = function(query, callback) {
+      return _.keys(supportedMetrics);
+    };
+
+    $scope.suggestMetrics = function(query, callback) {
+      return supportedMetrics[$scope.target.namespace] || [];
+    };
+
+    $scope.suggestDimensionKeys = function(query, callback) {
+      return supportedDimensions[$scope.target.namespace] || [];
+    };
+
+    $scope.suggestDimensionValues = function(query, callback) {
+      if (!$scope.target.namespace || !$scope.target.metricName) {
+        return callback([]);
+      }
+
+      var params = {
+        Namespace: $scope.target.namespace,
+        MetricName: $scope.target.metricName
+      };
+      if (!_.isEmpty($scope.target.dimensions)) {
+        params.Dimensions = $scope.target.dimensions;
+      }
+
+      $scope.datasource
+        .performSuggestQuery(params)
+        .then(function(result) {
+          var suggestData = _.chain(result.Metrics)
+          .map(function(metric) {
+            return metric.Dimensions;
+          })
+          .flatten(true)
+          .filter(function(dimension) {
+            return dimension.Name === $scope.target.currentDimensionKey;
+          })
+          .map(function(metric) {
+            return metric;
+          })
+          .pluck('Value')
+          .uniq()
+          .value();
+
+          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.currentDimensionKey = '';
+      $scope.target.currentDimensionValue = '';
+      $scope.refreshMetricData();
+
+      $scope.addDimensionMode = false;
+    };
+
+    $scope.removeDimension = function(key) {
+      delete $scope.target.dimensions[key];
+      $scope.refreshMetricData();
+    };
+
+    $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;
+    }
+
+  });
+
+});

+ 33 - 0
public/vendor/aws-sdk/.bower.json

@@ -0,0 +1,33 @@
+{
+  "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"
+}

+ 84 - 0
public/vendor/aws-sdk/CONTRIBUTING.md

@@ -0,0 +1,84 @@
+# 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/

+ 201 - 0
public/vendor/aws-sdk/LICENSE.txt

@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright 2012-2015 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.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License 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.

+ 5 - 0
public/vendor/aws-sdk/NOTICE.txt

@@ -0,0 +1,5 @@
+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/).

+ 124 - 0
public/vendor/aws-sdk/README.md

@@ -0,0 +1,124 @@
+# 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.

+ 157 - 0
public/vendor/aws-sdk/UPGRADING.md

@@ -0,0 +1,157 @@
+# @!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(...)
+```

+ 9 - 0
public/vendor/aws-sdk/bower.json

@@ -0,0 +1,9 @@
+{
+  "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"
+}

+ 96 - 0
public/vendor/aws-sdk/dist/BUNDLE_LICENSE.txt

@@ -0,0 +1,96 @@
+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.

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 22 - 0
public/vendor/aws-sdk/dist/aws-sdk.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 3 - 0
public/vendor/aws-sdk/dist/aws-sdk.min.js


Vissa filer visades inte eftersom för många filer har ändrats