From 163e55c0ebc66f909a0210230c15ccfa67b24d0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 16 May 2016 18:07:42 +0200 Subject: [PATCH 01/26] Update latest.json --- latest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/latest.json b/latest.json index 4afdb750b3f..443a440a529 100644 --- a/latest.json +++ b/latest.json @@ -1,4 +1,4 @@ { - "stable": "3.0.1", - "testing": "3.0.1" + "stable": "3.0.2", + "testing": "3.0.2" } From d443079cf64b21da3efd1c71576fe684e0929d9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 16 May 2016 18:48:13 +0200 Subject: [PATCH 02/26] fix(): fixed sass issue --- .floo | 5 +++-- public/sass/components/_modals.scss | 11 ----------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/.floo b/.floo index 1201c5e93b9..a8fb87025ec 100644 --- a/.floo +++ b/.floo @@ -1,3 +1,4 @@ { - "url": "https://floobits.com/raintank/grafana" -} \ No newline at end of file + "url": "https://floobits.com/raintank/grafana" +} + diff --git a/public/sass/components/_modals.scss b/public/sass/components/_modals.scss index 5f93b4e0592..357840062eb 100644 --- a/public/sass/components/_modals.scss +++ b/public/sass/components/_modals.scss @@ -115,17 +115,6 @@ margin-right: $spacer/2; } } - - .confirm-model-invalid-input { - border: thin solid $input-invalid-border-color; - } - - .modal-content-confirm-text { - margin-bottom: 2rem; - span { - text-align: center; - } - } } .share-modal-body { From 451e917e7de39aa15181e86ac184d1713d501b7b Mon Sep 17 00:00:00 2001 From: hijklmno Date: Mon, 16 May 2016 15:24:31 -0700 Subject: [PATCH 03/26] Add dBm as an option in energy units --- public/app/core/utils/kbn.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/public/app/core/utils/kbn.js b/public/app/core/utils/kbn.js index 11a544d2708..c70973b84b0 100644 --- a/public/app/core/utils/kbn.js +++ b/public/app/core/utils/kbn.js @@ -396,7 +396,8 @@ function($, _) { kbn.valueFormats.ev = kbn.formatBuilders.decimalSIPrefix('eV'); kbn.valueFormats.amp = kbn.formatBuilders.decimalSIPrefix('A'); kbn.valueFormats.volt = kbn.formatBuilders.decimalSIPrefix('V'); - + kbn.valueFormats.dBm = kbn.formatBuilders.decimalSIPrefix('dBm'); + // Temperature kbn.valueFormats.celsius = kbn.formatBuilders.fixedUnit('°C'); kbn.valueFormats.farenheit = kbn.formatBuilders.fixedUnit('°F'); @@ -677,6 +678,7 @@ function($, _) { {text: 'electron volt (eV)', value: 'ev' }, {text: 'Ampere (A)', value: 'amp' }, {text: 'Volt (V)', value: 'volt' }, + {text: 'Decibel-milliwatt (dBm)', value: 'dBm' }, ] }, { From f1b5a265ab762486e445584f3280cd3a883d8a2f Mon Sep 17 00:00:00 2001 From: hijklmno Date: Mon, 16 May 2016 15:35:42 -0700 Subject: [PATCH 04/26] fix trailing whitespace in kbn.js --- public/app/core/utils/kbn.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/core/utils/kbn.js b/public/app/core/utils/kbn.js index c70973b84b0..9d714c34fb3 100644 --- a/public/app/core/utils/kbn.js +++ b/public/app/core/utils/kbn.js @@ -397,7 +397,7 @@ function($, _) { kbn.valueFormats.amp = kbn.formatBuilders.decimalSIPrefix('A'); kbn.valueFormats.volt = kbn.formatBuilders.decimalSIPrefix('V'); kbn.valueFormats.dBm = kbn.formatBuilders.decimalSIPrefix('dBm'); - + // Temperature kbn.valueFormats.celsius = kbn.formatBuilders.fixedUnit('°C'); kbn.valueFormats.farenheit = kbn.formatBuilders.fixedUnit('°F'); From 99db89067ef0e1fb2cef12345c1a05c717dea5a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 17 May 2016 08:34:34 +0200 Subject: [PATCH 05/26] fix(): reverted RESTART_ON_UPGRADE change --- packaging/deb/default/grafana-server | 2 +- packaging/rpm/sysconfig/grafana-server | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/deb/default/grafana-server b/packaging/deb/default/grafana-server index cc5ee866f7d..dd06906b903 100644 --- a/packaging/deb/default/grafana-server +++ b/packaging/deb/default/grafana-server @@ -14,6 +14,6 @@ CONF_DIR=/etc/grafana CONF_FILE=/etc/grafana/grafana.ini -RESTART_ON_UPGRADE=true +RESTART_ON_UPGRADE=false PLUGINS_DIR=/var/lib/grafana/plugins diff --git a/packaging/rpm/sysconfig/grafana-server b/packaging/rpm/sysconfig/grafana-server index cc5ee866f7d..dd06906b903 100644 --- a/packaging/rpm/sysconfig/grafana-server +++ b/packaging/rpm/sysconfig/grafana-server @@ -14,6 +14,6 @@ CONF_DIR=/etc/grafana CONF_FILE=/etc/grafana/grafana.ini -RESTART_ON_UPGRADE=true +RESTART_ON_UPGRADE=false PLUGINS_DIR=/var/lib/grafana/plugins From fb8296524eb9ca646a46a7f9e237d56aa0cfbaa3 Mon Sep 17 00:00:00 2001 From: bergquist Date: Mon, 16 May 2016 17:25:40 +0200 Subject: [PATCH 06/26] tech(docker): add default fake-data-gen for prometheus --- docker/blocks/prometheus/fig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docker/blocks/prometheus/fig b/docker/blocks/prometheus/fig index 0880902c9fd..aa00e1b6272 100644 --- a/docker/blocks/prometheus/fig +++ b/docker/blocks/prometheus/fig @@ -1,6 +1,16 @@ prometheus: build: blocks/prometheus + net: bridge ports: - "9090:9090" volumes: - /var/docker/prometheus:/prometheus-data + +fake-data-gen: + image: grafana/fake-data-gen + net: bridge + ports: + - "9091:9091" + environment: + FD_DATASOURCE: prom + From efe6fd154ba4de50582ddc389bf6168f070662f4 Mon Sep 17 00:00:00 2001 From: bergquist Date: Mon, 16 May 2016 17:39:51 +0200 Subject: [PATCH 07/26] tech(docker): add default writer for influxdb --- docker/blocks/influxdb/fig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docker/blocks/influxdb/fig b/docker/blocks/influxdb/fig index c537a74b003..0dc69cb6b72 100644 --- a/docker/blocks/influxdb/fig +++ b/docker/blocks/influxdb/fig @@ -4,3 +4,11 @@ influxdb: - "2004:2004" - "8083:8083" - "8086:8086" + +fake-data-gen: + image: grafana/fake-data-gen + net: bridge + environment: + FD_DATASOURCE: influxdb + FD_PORT: 8086 + From 83f5080274098821dbc7fadf2849de82ea4c86a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 17 May 2016 15:00:48 +0200 Subject: [PATCH 08/26] feat(angular): disable debug in production for angular compiler --- pkg/api/frontendsettings.go | 1 + public/app/app.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index dd84f7827eb..9fcd5e567fb 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -142,6 +142,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro "buildstamp": setting.BuildStamp, "latestVersion": plugins.GrafanaLatestVersion, "hasUpdate": plugins.GrafanaHasUpdate, + "env": setting.Env, }, } diff --git a/public/app/app.ts b/public/app/app.ts index 3434814d3b6..6de7181f5a1 100644 --- a/public/app/app.ts +++ b/public/app/app.ts @@ -42,7 +42,9 @@ export class GrafanaApp { app.constant('grafanaVersion', "@grafanaVersion@"); app.config(($locationProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) => { - //$compileProvider.debugInfoEnabled(false); + if (config.buildInfo.env !== 'development') { + $compileProvider.debugInfoEnabled(false); + } this.registerFunctions.controller = $controllerProvider.register; this.registerFunctions.directive = $compileProvider.directive; From b5fc12fb80c9c7d481c598033c6ce26eee386232 Mon Sep 17 00:00:00 2001 From: bergquist Date: Tue, 17 May 2016 15:28:25 +0200 Subject: [PATCH 09/26] docs(opentsdb): add working image of add datasource for opentsdb closes #4984 --- docs/sources/datasources/opentsdb.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sources/datasources/opentsdb.md b/docs/sources/datasources/opentsdb.md index 28d90c19b00..6ef930c0cc0 100644 --- a/docs/sources/datasources/opentsdb.md +++ b/docs/sources/datasources/opentsdb.md @@ -7,10 +7,10 @@ page_keywords: grafana, opentsdb, documentation # OpenTSDB Guide The newest release of Grafana adds additional functionality when using an OpenTSDB Data source. -![](/img/v2/add_OpenTSDB.jpg) +![](/img/v2/add_OpenTSDB.png) -1. Open the side menu by clicking the the Grafana icon in the top header. -2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`. +1. Open the side menu by clicking the the Grafana icon in the top header. +2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`. > NOTE: If this link is missing in the side menu it means that your current user does not have the `Admin` role for the current organization. From 958f97232f917c54e02cacbe4dd4206579580c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 17 May 2016 21:51:19 +0200 Subject: [PATCH 10/26] fix(pluginlist): fixed issue with plugin list, fixes #5068 --- pkg/plugins/queries.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pkg/plugins/queries.go b/pkg/plugins/queries.go index b930c9575a3..5ae1825a88f 100644 --- a/pkg/plugins/queries.go +++ b/pkg/plugins/queries.go @@ -24,7 +24,16 @@ func GetPluginSettings(orgId int64) (map[string]*m.PluginSettingInfoDTO, error) } // default to enabled true - opt := &m.PluginSettingInfoDTO{Enabled: true} + opt := &m.PluginSettingInfoDTO{ + PluginId: pluginDef.Id, + OrgId: orgId, + Enabled: true, + } + + // apps are disabled by default + if pluginDef.Type == PluginTypeApp { + opt.Enabled = false + } // if it's included in app check app settings if pluginDef.IncludedInAppId != "" { From 8a9455d901d31c2b16037f91ed7fadd1cf0aac0a Mon Sep 17 00:00:00 2001 From: Utkarsh Bhatnagar Date: Tue, 17 May 2016 22:44:01 -0700 Subject: [PATCH 11/26] Fixed singlestat mapping typo (#5070) --- public/app/plugins/panel/singlestat/mappings.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/plugins/panel/singlestat/mappings.html b/public/app/plugins/panel/singlestat/mappings.html index a1105a159dd..8dd1c94768e 100644 --- a/public/app/plugins/panel/singlestat/mappings.html +++ b/public/app/plugins/panel/singlestat/mappings.html @@ -12,7 +12,7 @@
-
Set valuea mappings
+
Set value mappings
From fc1891320ec54928cbe3fd96fa2dccd5d761e189 Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanda Date: Wed, 18 May 2016 14:49:32 +0900 Subject: [PATCH 12/26] (prometheus) fix prometheus link (#5074) --- public/app/plugins/datasource/prometheus/datasource.ts | 8 ++++---- public/app/plugins/datasource/prometheus/query_ctrl.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/public/app/plugins/datasource/prometheus/datasource.ts b/public/app/plugins/datasource/prometheus/datasource.ts index ca7ef051ba0..d4d4ff8ff83 100644 --- a/public/app/plugins/datasource/prometheus/datasource.ts +++ b/public/app/plugins/datasource/prometheus/datasource.ts @@ -43,7 +43,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS return value.replace(/[\\^$*+?.()|[\]{}]/g, '\\\\$&'); } - function interpolateQueryExpr(value, variable, defaultFormatFn) { + this.interpolateQueryExpr = function(value, variable, defaultFormatFn) { // if no multi or include all do not regexEscape if (!variable.multi && !variable.includeAll) { return value; @@ -59,6 +59,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS // Called once per panel (graph) this.query = function(options) { + var self = this; var start = getPrometheusTime(options.range.from, false); var end = getPrometheusTime(options.range.to, true); @@ -73,7 +74,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS activeTargets.push(target); var query: any = {}; - query.expr = templateSrv.replace(target.expr, options.scopedVars, interpolateQueryExpr); + query.expr = templateSrv.replace(target.expr, options.scopedVars, self.interpolateQueryExpr); var interval = target.interval || options.interval; var intervalFactor = target.intervalFactor || 1; @@ -99,7 +100,6 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS return this.performTimeSeriesQuery(query, start, end); }, this)); - var self = this; return $q.all(allQueryPromise) .then(function(allResponse) { var result = []; @@ -160,7 +160,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS var interpolated; try { - interpolated = templateSrv.replace(expr, {}, interpolateQueryExpr); + interpolated = templateSrv.replace(expr, {}, this.interpolateQueryExpr); } catch (err) { return $q.reject(err); } diff --git a/public/app/plugins/datasource/prometheus/query_ctrl.ts b/public/app/plugins/datasource/prometheus/query_ctrl.ts index 8284268ef39..94340804988 100644 --- a/public/app/plugins/datasource/prometheus/query_ctrl.ts +++ b/public/app/plugins/datasource/prometheus/query_ctrl.ts @@ -61,7 +61,7 @@ class PrometheusQueryCtrl extends QueryCtrl { var rangeDiff = Math.ceil((range.to.valueOf() - range.from.valueOf()) / 1000); var endTime = range.to.utc().format('YYYY-MM-DD HH:mm'); var expr = { - expr: this.templateSrv.replace(this.target.expr, this.panelCtrl.panel.scopedVars), + expr: this.templateSrv.replace(this.target.expr, this.panelCtrl.panel.scopedVars, this.datasource.interpolateQueryExpr), range_input: rangeDiff + 's', end_input: endTime, step_input: '', From 8d2f350ad17d1cc3ce36933ae4b7d0b7e4eb854b Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanda Date: Wed, 18 May 2016 14:00:12 +0900 Subject: [PATCH 13/26] (prometheus) fix prometheus link --- public/app/plugins/datasource/prometheus/datasource.ts | 8 ++++---- public/app/plugins/datasource/prometheus/query_ctrl.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/public/app/plugins/datasource/prometheus/datasource.ts b/public/app/plugins/datasource/prometheus/datasource.ts index ca7ef051ba0..d4d4ff8ff83 100644 --- a/public/app/plugins/datasource/prometheus/datasource.ts +++ b/public/app/plugins/datasource/prometheus/datasource.ts @@ -43,7 +43,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS return value.replace(/[\\^$*+?.()|[\]{}]/g, '\\\\$&'); } - function interpolateQueryExpr(value, variable, defaultFormatFn) { + this.interpolateQueryExpr = function(value, variable, defaultFormatFn) { // if no multi or include all do not regexEscape if (!variable.multi && !variable.includeAll) { return value; @@ -59,6 +59,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS // Called once per panel (graph) this.query = function(options) { + var self = this; var start = getPrometheusTime(options.range.from, false); var end = getPrometheusTime(options.range.to, true); @@ -73,7 +74,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS activeTargets.push(target); var query: any = {}; - query.expr = templateSrv.replace(target.expr, options.scopedVars, interpolateQueryExpr); + query.expr = templateSrv.replace(target.expr, options.scopedVars, self.interpolateQueryExpr); var interval = target.interval || options.interval; var intervalFactor = target.intervalFactor || 1; @@ -99,7 +100,6 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS return this.performTimeSeriesQuery(query, start, end); }, this)); - var self = this; return $q.all(allQueryPromise) .then(function(allResponse) { var result = []; @@ -160,7 +160,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS var interpolated; try { - interpolated = templateSrv.replace(expr, {}, interpolateQueryExpr); + interpolated = templateSrv.replace(expr, {}, this.interpolateQueryExpr); } catch (err) { return $q.reject(err); } diff --git a/public/app/plugins/datasource/prometheus/query_ctrl.ts b/public/app/plugins/datasource/prometheus/query_ctrl.ts index 8284268ef39..94340804988 100644 --- a/public/app/plugins/datasource/prometheus/query_ctrl.ts +++ b/public/app/plugins/datasource/prometheus/query_ctrl.ts @@ -61,7 +61,7 @@ class PrometheusQueryCtrl extends QueryCtrl { var rangeDiff = Math.ceil((range.to.valueOf() - range.from.valueOf()) / 1000); var endTime = range.to.utc().format('YYYY-MM-DD HH:mm'); var expr = { - expr: this.templateSrv.replace(this.target.expr, this.panelCtrl.panel.scopedVars), + expr: this.templateSrv.replace(this.target.expr, this.panelCtrl.panel.scopedVars, this.datasource.interpolateQueryExpr), range_input: rangeDiff + 's', end_input: endTime, step_input: '', From 07d355851efeffc2b6938693bc49d2987f3aec6e Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanda Date: Wed, 18 May 2016 14:54:24 +0900 Subject: [PATCH 14/26] (cloudwatch) assume role support (#5065) * (cloudwatch) assume role support * save godep * (cloudwatch) add assumeRoleArn field * (cloudwatch) set cred provider for sts * (cloudwatch) fix test --- Godeps/Godeps.json | 5 + .../aws/aws-sdk-go/service/sts/api.go | 1127 +++++++++++++++++ .../aws-sdk-go/service/sts/customizations.go | 12 + .../service/sts/customizations_test.go | 39 + .../aws-sdk-go/service/sts/examples_test.go | 149 +++ .../aws/aws-sdk-go/service/sts/service.go | 130 ++ .../service/sts/stsiface/interface.go | 38 + pkg/api/cloudwatch/cloudwatch.go | 113 +- pkg/api/cloudwatch/metrics.go | 18 +- pkg/api/cloudwatch/metrics_test.go | 10 +- .../cloudwatch/partials/config.html | 7 + 11 files changed, 1604 insertions(+), 44 deletions(-) create mode 100644 Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/api.go create mode 100644 Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/customizations.go create mode 100644 Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/customizations_test.go create mode 100644 Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/examples_test.go create mode 100644 Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/service.go create mode 100644 Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/stsiface/interface.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index b48d5189e94..a1bb492e5d2 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -124,6 +124,11 @@ "Comment": "v1.0.0", "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" }, + { + "ImportPath": "github.com/aws/aws-sdk-go/service/sts", + "Comment": "v1.0.0", + "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" + }, { "ImportPath": "github.com/bmizerany/assert", "Comment": "release.r60-6-ge17e998", diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/api.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/api.go new file mode 100644 index 00000000000..52755c9e061 --- /dev/null +++ b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/api.go @@ -0,0 +1,1127 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +// Package sts provides a client for AWS Security Token Service. +package sts + +import ( + "time" + + "github.com/aws/aws-sdk-go/aws/awsutil" + "github.com/aws/aws-sdk-go/aws/request" +) + +const opAssumeRole = "AssumeRole" + +// AssumeRoleRequest generates a request for the AssumeRole operation. +func (c *STS) AssumeRoleRequest(input *AssumeRoleInput) (req *request.Request, output *AssumeRoleOutput) { + op := &request.Operation{ + Name: opAssumeRole, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AssumeRoleInput{} + } + + req = c.newRequest(op, input, output) + output = &AssumeRoleOutput{} + req.Data = output + return +} + +// Returns a set of temporary security credentials (consisting of an access +// key ID, a secret access key, and a security token) that you can use to access +// AWS resources that you might not normally have access to. Typically, you +// use AssumeRole for cross-account access or federation. +// +// Important: You cannot call AssumeRole by using AWS account credentials; +// access will be denied. You must use IAM user credentials or temporary security +// credentials to call AssumeRole. +// +// For cross-account access, imagine that you own multiple accounts and need +// to access resources in each account. You could create long-term credentials +// in each account to access those resources. However, managing all those credentials +// and remembering which one can access which account can be time consuming. +// Instead, you can create one set of long-term credentials in one account and +// then use temporary security credentials to access all the other accounts +// by assuming roles in those accounts. For more information about roles, see +// IAM Roles (Delegation and Federation) (http://docs.aws.amazon.com/IAM/latest/UserGuide/roles-toplevel.html) +// in the Using IAM. +// +// For federation, you can, for example, grant single sign-on access to the +// AWS Management Console. If you already have an identity and authentication +// system in your corporate network, you don't have to recreate user identities +// in AWS in order to grant those user identities access to AWS. Instead, after +// a user has been authenticated, you call AssumeRole (and specify the role +// with the appropriate permissions) to get temporary security credentials for +// that user. With those temporary security credentials, you construct a sign-in +// URL that users can use to access the console. For more information, see Common +// Scenarios for Temporary Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html#sts-introduction) +// in the Using IAM. +// +// The temporary security credentials are valid for the duration that you specified +// when calling AssumeRole, which can be from 900 seconds (15 minutes) to 3600 +// seconds (1 hour). The default is 1 hour. +// +// Optionally, you can pass an IAM access policy to this operation. If you +// choose not to pass a policy, the temporary security credentials that are +// returned by the operation have the permissions that are defined in the access +// policy of the role that is being assumed. If you pass a policy to this operation, +// the temporary security credentials that are returned by the operation have +// the permissions that are allowed by both the access policy of the role that +// is being assumed, and the policy that you pass. This gives you a way to further +// restrict the permissions for the resulting temporary security credentials. +// You cannot use the passed policy to grant permissions that are in excess +// of those allowed by the access policy of the role that is being assumed. +// For more information, see Permissions for AssumeRole, AssumeRoleWithSAML, +// and AssumeRoleWithWebIdentity (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) +// in the Using IAM. +// +// To assume a role, your AWS account must be trusted by the role. The trust +// relationship is defined in the role's trust policy when the role is created. +// You must also have a policy that allows you to call sts:AssumeRole. +// +// Using MFA with AssumeRole +// +// You can optionally include multi-factor authentication (MFA) information +// when you call AssumeRole. This is useful for cross-account scenarios in which +// you want to make sure that the user who is assuming the role has been authenticated +// using an AWS MFA device. In that scenario, the trust policy of the role being +// assumed includes a condition that tests for MFA authentication; if the caller +// does not include valid MFA information, the request to assume the role is +// denied. The condition in a trust policy that tests for MFA authentication +// might look like the following example. +// +// "Condition": {"Bool": {"aws:MultiFactorAuthPresent": true}} +// +// For more information, see Configuring MFA-Protected API Access (http://docs.aws.amazon.com/IAM/latest/UserGuide/MFAProtectedAPI.html) +// in the Using IAM guide. +// +// To use MFA with AssumeRole, you pass values for the SerialNumber and TokenCode +// parameters. The SerialNumber value identifies the user's hardware or virtual +// MFA device. The TokenCode is the time-based one-time password (TOTP) that +// the MFA devices produces. +func (c *STS) AssumeRole(input *AssumeRoleInput) (*AssumeRoleOutput, error) { + req, out := c.AssumeRoleRequest(input) + err := req.Send() + return out, err +} + +const opAssumeRoleWithSAML = "AssumeRoleWithSAML" + +// AssumeRoleWithSAMLRequest generates a request for the AssumeRoleWithSAML operation. +func (c *STS) AssumeRoleWithSAMLRequest(input *AssumeRoleWithSAMLInput) (req *request.Request, output *AssumeRoleWithSAMLOutput) { + op := &request.Operation{ + Name: opAssumeRoleWithSAML, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AssumeRoleWithSAMLInput{} + } + + req = c.newRequest(op, input, output) + output = &AssumeRoleWithSAMLOutput{} + req.Data = output + return +} + +// Returns a set of temporary security credentials for users who have been authenticated +// via a SAML authentication response. This operation provides a mechanism for +// tying an enterprise identity store or directory to role-based AWS access +// without user-specific credentials or configuration. +// +// The temporary security credentials returned by this operation consist of +// an access key ID, a secret access key, and a security token. Applications +// can use these temporary security credentials to sign calls to AWS services. +// The credentials are valid for the duration that you specified when calling +// AssumeRoleWithSAML, which can be up to 3600 seconds (1 hour) or until the +// time specified in the SAML authentication response's SessionNotOnOrAfter +// value, whichever is shorter. +// +// The maximum duration for a session is 1 hour, and the minimum duration is +// 15 minutes, even if values outside this range are specified. Optionally, +// you can pass an IAM access policy to this operation. If you choose not to +// pass a policy, the temporary security credentials that are returned by the +// operation have the permissions that are defined in the access policy of the +// role that is being assumed. If you pass a policy to this operation, the temporary +// security credentials that are returned by the operation have the permissions +// that are allowed by both the access policy of the role that is being assumed, +// and the policy that you pass. This gives you a way to further restrict the +// permissions for the resulting temporary security credentials. You cannot +// use the passed policy to grant permissions that are in excess of those allowed +// by the access policy of the role that is being assumed. For more information, +// see Permissions for AssumeRole, AssumeRoleWithSAML, and AssumeRoleWithWebIdentity +// (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) +// in the Using IAM. +// +// Before your application can call AssumeRoleWithSAML, you must configure +// your SAML identity provider (IdP) to issue the claims required by AWS. Additionally, +// you must use AWS Identity and Access Management (IAM) to create a SAML provider +// entity in your AWS account that represents your identity provider, and create +// an IAM role that specifies this SAML provider in its trust policy. +// +// Calling AssumeRoleWithSAML does not require the use of AWS security credentials. +// The identity of the caller is validated by using keys in the metadata document +// that is uploaded for the SAML provider entity for your identity provider. +// +// For more information, see the following resources: +// +// About SAML 2.0-based Federation (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_saml.html) +// in the Using IAM. Creating SAML Identity Providers (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml.html) +// in the Using IAM. Configuring a Relying Party and Claims (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml_relying-party.html) +// in the Using IAM. Creating a Role for SAML 2.0 Federation (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp_saml.html) +// in the Using IAM. +func (c *STS) AssumeRoleWithSAML(input *AssumeRoleWithSAMLInput) (*AssumeRoleWithSAMLOutput, error) { + req, out := c.AssumeRoleWithSAMLRequest(input) + err := req.Send() + return out, err +} + +const opAssumeRoleWithWebIdentity = "AssumeRoleWithWebIdentity" + +// AssumeRoleWithWebIdentityRequest generates a request for the AssumeRoleWithWebIdentity operation. +func (c *STS) AssumeRoleWithWebIdentityRequest(input *AssumeRoleWithWebIdentityInput) (req *request.Request, output *AssumeRoleWithWebIdentityOutput) { + op := &request.Operation{ + Name: opAssumeRoleWithWebIdentity, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AssumeRoleWithWebIdentityInput{} + } + + req = c.newRequest(op, input, output) + output = &AssumeRoleWithWebIdentityOutput{} + req.Data = output + return +} + +// Returns a set of temporary security credentials for users who have been authenticated +// in a mobile or web application with a web identity provider, such as Amazon +// Cognito, Login with Amazon, Facebook, Google, or any OpenID Connect-compatible +// identity provider. +// +// For mobile applications, we recommend that you use Amazon Cognito. You +// can use Amazon Cognito with the AWS SDK for iOS (http://aws.amazon.com/sdkforios/) +// and the AWS SDK for Android (http://aws.amazon.com/sdkforandroid/) to uniquely +// identify a user and supply the user with a consistent identity throughout +// the lifetime of an application. +// +// To learn more about Amazon Cognito, see Amazon Cognito Overview (http://docs.aws.amazon.com/mobile/sdkforandroid/developerguide/cognito-auth.html#d0e840) +// in the AWS SDK for Android Developer Guide guide and Amazon Cognito Overview +// (http://docs.aws.amazon.com/mobile/sdkforios/developerguide/cognito-auth.html#d0e664) +// in the AWS SDK for iOS Developer Guide. +// +// Calling AssumeRoleWithWebIdentity does not require the use of AWS security +// credentials. Therefore, you can distribute an application (for example, on +// mobile devices) that requests temporary security credentials without including +// long-term AWS credentials in the application, and without deploying server-based +// proxy services that use long-term AWS credentials. Instead, the identity +// of the caller is validated by using a token from the web identity provider. +// +// The temporary security credentials returned by this API consist of an access +// key ID, a secret access key, and a security token. Applications can use these +// temporary security credentials to sign calls to AWS service APIs. The credentials +// are valid for the duration that you specified when calling AssumeRoleWithWebIdentity, +// which can be from 900 seconds (15 minutes) to 3600 seconds (1 hour). By default, +// the temporary security credentials are valid for 1 hour. +// +// Optionally, you can pass an IAM access policy to this operation. If you +// choose not to pass a policy, the temporary security credentials that are +// returned by the operation have the permissions that are defined in the access +// policy of the role that is being assumed. If you pass a policy to this operation, +// the temporary security credentials that are returned by the operation have +// the permissions that are allowed by both the access policy of the role that +// is being assumed, and the policy that you pass. This gives you a way to further +// restrict the permissions for the resulting temporary security credentials. +// You cannot use the passed policy to grant permissions that are in excess +// of those allowed by the access policy of the role that is being assumed. +// For more information, see Permissions for AssumeRole, AssumeRoleWithSAML, +// and AssumeRoleWithWebIdentity (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) +// in the Using IAM. +// +// Before your application can call AssumeRoleWithWebIdentity, you must have +// an identity token from a supported identity provider and create a role that +// the application can assume. The role that your application assumes must trust +// the identity provider that is associated with the identity token. In other +// words, the identity provider must be specified in the role's trust policy. +// +// For more information about how to use web identity federation and the AssumeRoleWithWebIdentity +// API, see the following resources: +// +// Using Web Identity Federation APIs for Mobile Apps (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc_manual) +// and Federation Through a Web-based Identity Provider (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_assumerolewithwebidentity). +// Web Identity Federation Playground (https://web-identity-federation-playground.s3.amazonaws.com/index.html). +// This interactive website lets you walk through the process of authenticating +// via Login with Amazon, Facebook, or Google, getting temporary security credentials, +// and then using those credentials to make a request to AWS. AWS SDK for +// iOS (http://aws.amazon.com/sdkforios/) and AWS SDK for Android (http://aws.amazon.com/sdkforandroid/). +// These toolkits contain sample apps that show how to invoke the identity providers, +// and then how to use the information from these providers to get and use temporary +// security credentials. Web Identity Federation with Mobile Applications +// (http://aws.amazon.com/articles/4617974389850313). This article discusses +// web identity federation and shows an example of how to use web identity federation +// to get access to content in Amazon S3. +func (c *STS) AssumeRoleWithWebIdentity(input *AssumeRoleWithWebIdentityInput) (*AssumeRoleWithWebIdentityOutput, error) { + req, out := c.AssumeRoleWithWebIdentityRequest(input) + err := req.Send() + return out, err +} + +const opDecodeAuthorizationMessage = "DecodeAuthorizationMessage" + +// DecodeAuthorizationMessageRequest generates a request for the DecodeAuthorizationMessage operation. +func (c *STS) DecodeAuthorizationMessageRequest(input *DecodeAuthorizationMessageInput) (req *request.Request, output *DecodeAuthorizationMessageOutput) { + op := &request.Operation{ + Name: opDecodeAuthorizationMessage, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DecodeAuthorizationMessageInput{} + } + + req = c.newRequest(op, input, output) + output = &DecodeAuthorizationMessageOutput{} + req.Data = output + return +} + +// Decodes additional information about the authorization status of a request +// from an encoded message returned in response to an AWS request. +// +// For example, if a user is not authorized to perform an action that he or +// she has requested, the request returns a Client.UnauthorizedOperation response +// (an HTTP 403 response). Some AWS actions additionally return an encoded message +// that can provide details about this authorization failure. +// +// Only certain AWS actions return an encoded authorization message. The documentation +// for an individual action indicates whether that action returns an encoded +// message in addition to returning an HTTP code. The message is encoded because +// the details of the authorization status can constitute privileged information +// that the user who requested the action should not see. To decode an authorization +// status message, a user must be granted permissions via an IAM policy to request +// the DecodeAuthorizationMessage (sts:DecodeAuthorizationMessage) action. +// +// The decoded message includes the following type of information: +// +// Whether the request was denied due to an explicit deny or due to the absence +// of an explicit allow. For more information, see Determining Whether a Request +// is Allowed or Denied (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html#policy-eval-denyallow) +// in the Using IAM. The principal who made the request. The requested action. +// The requested resource. The values of condition keys in the context of the +// user's request. +func (c *STS) DecodeAuthorizationMessage(input *DecodeAuthorizationMessageInput) (*DecodeAuthorizationMessageOutput, error) { + req, out := c.DecodeAuthorizationMessageRequest(input) + err := req.Send() + return out, err +} + +const opGetFederationToken = "GetFederationToken" + +// GetFederationTokenRequest generates a request for the GetFederationToken operation. +func (c *STS) GetFederationTokenRequest(input *GetFederationTokenInput) (req *request.Request, output *GetFederationTokenOutput) { + op := &request.Operation{ + Name: opGetFederationToken, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &GetFederationTokenInput{} + } + + req = c.newRequest(op, input, output) + output = &GetFederationTokenOutput{} + req.Data = output + return +} + +// Returns a set of temporary security credentials (consisting of an access +// key ID, a secret access key, and a security token) for a federated user. +// A typical use is in a proxy application that gets temporary security credentials +// on behalf of distributed applications inside a corporate network. Because +// you must call the GetFederationToken action using the long-term security +// credentials of an IAM user, this call is appropriate in contexts where those +// credentials can be safely stored, usually in a server-based application. +// +// If you are creating a mobile-based or browser-based app that can authenticate +// users using a web identity provider like Login with Amazon, Facebook, Google, +// or an OpenID Connect-compatible identity provider, we recommend that you +// use Amazon Cognito (http://aws.amazon.com/cognito/) or AssumeRoleWithWebIdentity. +// For more information, see Federation Through a Web-based Identity Provider +// (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_assumerolewithwebidentity). +// +// The GetFederationToken action must be called by using the long-term AWS +// security credentials of an IAM user. You can also call GetFederationToken +// using the security credentials of an AWS account (root), but this is not +// recommended. Instead, we recommend that you create an IAM user for the purpose +// of the proxy application and then attach a policy to the IAM user that limits +// federated users to only the actions and resources they need access to. For +// more information, see IAM Best Practices (http://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html) +// in the Using IAM. +// +// The temporary security credentials that are obtained by using the long-term +// credentials of an IAM user are valid for the specified duration, between +// 900 seconds (15 minutes) and 129600 seconds (36 hours). Temporary credentials +// that are obtained by using AWS account (root) credentials have a maximum +// duration of 3600 seconds (1 hour) +// +// Permissions +// +// The permissions for the temporary security credentials returned by GetFederationToken +// are determined by a combination of the following: +// +// The policy or policies that are attached to the IAM user whose credentials +// are used to call GetFederationToken. The policy that is passed as a parameter +// in the call. The passed policy is attached to the temporary security credentials +// that result from the GetFederationToken API call--that is, to the federated +// user. When the federated user makes an AWS request, AWS evaluates the policy +// attached to the federated user in combination with the policy or policies +// attached to the IAM user whose credentials were used to call GetFederationToken. +// AWS allows the federated user's request only when both the federated user +// and the IAM user are explicitly allowed to perform the requested action. +// The passed policy cannot grant more permissions than those that are defined +// in the IAM user policy. +// +// A typical use case is that the permissions of the IAM user whose credentials +// are used to call GetFederationToken are designed to allow access to all the +// actions and resources that any federated user will need. Then, for individual +// users, you pass a policy to the operation that scopes down the permissions +// to a level that's appropriate to that individual user, using a policy that +// allows only a subset of permissions that are granted to the IAM user. +// +// If you do not pass a policy, the resulting temporary security credentials +// have no effective permissions. The only exception is when the temporary security +// credentials are used to access a resource that has a resource-based policy +// that specifically allows the federated user to access the resource. +// +// For more information about how permissions work, see Permissions for GetFederationToken +// (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_getfederationtoken.html). +// For information about using GetFederationToken to create temporary security +// credentials, see GetFederationToken—Federation Through a Custom Identity +// Broker (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_getfederationtoken). +func (c *STS) GetFederationToken(input *GetFederationTokenInput) (*GetFederationTokenOutput, error) { + req, out := c.GetFederationTokenRequest(input) + err := req.Send() + return out, err +} + +const opGetSessionToken = "GetSessionToken" + +// GetSessionTokenRequest generates a request for the GetSessionToken operation. +func (c *STS) GetSessionTokenRequest(input *GetSessionTokenInput) (req *request.Request, output *GetSessionTokenOutput) { + op := &request.Operation{ + Name: opGetSessionToken, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &GetSessionTokenInput{} + } + + req = c.newRequest(op, input, output) + output = &GetSessionTokenOutput{} + req.Data = output + return +} + +// Returns a set of temporary credentials for an AWS account or IAM user. The +// credentials consist of an access key ID, a secret access key, and a security +// token. Typically, you use GetSessionToken if you want to use MFA to protect +// programmatic calls to specific AWS APIs like Amazon EC2 StopInstances. MFA-enabled +// IAM users would need to call GetSessionToken and submit an MFA code that +// is associated with their MFA device. Using the temporary security credentials +// that are returned from the call, IAM users can then make programmatic calls +// to APIs that require MFA authentication. If you do not supply a correct MFA +// code, then the API returns an access denied error. +// +// The GetSessionToken action must be called by using the long-term AWS security +// credentials of the AWS account or an IAM user. Credentials that are created +// by IAM users are valid for the duration that you specify, between 900 seconds +// (15 minutes) and 129600 seconds (36 hours); credentials that are created +// by using account credentials have a maximum duration of 3600 seconds (1 hour). +// +// We recommend that you do not call GetSessionToken with root account credentials. +// Instead, follow our best practices (http://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#create-iam-users) +// by creating one or more IAM users, giving them the necessary permissions, +// and using IAM users for everyday interaction with AWS. +// +// The permissions associated with the temporary security credentials returned +// by GetSessionToken are based on the permissions associated with account or +// IAM user whose credentials are used to call the action. If GetSessionToken +// is called using root account credentials, the temporary credentials have +// root account permissions. Similarly, if GetSessionToken is called using the +// credentials of an IAM user, the temporary credentials have the same permissions +// as the IAM user. +// +// For more information about using GetSessionToken to create temporary credentials, +// go to Temporary Credentials for Users in Untrusted Environments (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_getsessiontoken) +// in the Using IAM. +func (c *STS) GetSessionToken(input *GetSessionTokenInput) (*GetSessionTokenOutput, error) { + req, out := c.GetSessionTokenRequest(input) + err := req.Send() + return out, err +} + +type AssumeRoleInput struct { + // The duration, in seconds, of the role session. The value can range from 900 + // seconds (15 minutes) to 3600 seconds (1 hour). By default, the value is set + // to 3600 seconds. + DurationSeconds *int64 `min:"900" type:"integer"` + + // A unique identifier that is used by third parties when assuming roles in + // their customers' accounts. For each role that the third party can assume, + // they should instruct their customers to ensure the role's trust policy checks + // for the external ID that the third party generated. Each time the third party + // assumes the role, they should pass the customer's external ID. The external + // ID is useful in order to help third parties bind a role to the customer who + // created it. For more information about the external ID, see How to Use an + // External ID When Granting Access to Your AWS Resources to a Third Party (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html) + // in the Using IAM. + ExternalId *string `min:"2" type:"string"` + + // An IAM policy in JSON format. + // + // This parameter is optional. If you pass a policy, the temporary security + // credentials that are returned by the operation have the permissions that + // are allowed by both (the intersection of) the access policy of the role that + // is being assumed, and the policy that you pass. This gives you a way to further + // restrict the permissions for the resulting temporary security credentials. + // You cannot use the passed policy to grant permissions that are in excess + // of those allowed by the access policy of the role that is being assumed. + // For more information, see Permissions for AssumeRole, AssumeRoleWithSAML, + // and AssumeRoleWithWebIdentity (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) + // in the Using IAM. + // + // The policy plain text must be 2048 bytes or shorter. However, an internal + // conversion compresses it into a packed binary format with a separate limit. + // The PackedPolicySize response element indicates by percentage how close to + // the upper size limit the policy is, with 100% equaling the maximum allowed + // size. + Policy *string `min:"1" type:"string"` + + // The Amazon Resource Name (ARN) of the role to assume. + RoleArn *string `min:"20" type:"string" required:"true"` + + // An identifier for the assumed role session. + // + // Use the role session name to uniquely identity a session when the same role + // is assumed by different principals or for different reasons. In cross-account + // scenarios, the role session name is visible to, and can be logged by the + // account that owns the role. The role session name is also used in the ARN + // of the assumed role principal. This means that subsequent cross-account API + // requests using the temporary security credentials will expose the role session + // name to the external account in their CloudTrail logs. + RoleSessionName *string `min:"2" type:"string" required:"true"` + + // The identification number of the MFA device that is associated with the user + // who is making the AssumeRole call. Specify this value if the trust policy + // of the role being assumed includes a condition that requires MFA authentication. + // The value is either the serial number for a hardware device (such as GAHT12345678) + // or an Amazon Resource Name (ARN) for a virtual device (such as arn:aws:iam::123456789012:mfa/user). + SerialNumber *string `min:"9" type:"string"` + + // The value provided by the MFA device, if the trust policy of the role being + // assumed requires MFA (that is, if the policy includes a condition that tests + // for MFA). If the role being assumed requires MFA and if the TokenCode value + // is missing or expired, the AssumeRole call returns an "access denied" error. + TokenCode *string `min:"6" type:"string"` + + metadataAssumeRoleInput `json:"-" xml:"-"` +} + +type metadataAssumeRoleInput struct { + SDKShapeTraits bool `type:"structure"` +} + +// String returns the string representation +func (s AssumeRoleInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleInput) GoString() string { + return s.String() +} + +// Contains the response to a successful AssumeRole request, including temporary +// AWS credentials that can be used to make AWS requests. +type AssumeRoleOutput struct { + // The Amazon Resource Name (ARN) and the assumed role ID, which are identifiers + // that you can use to refer to the resulting temporary security credentials. + // For example, you can reference these credentials as a principal in a resource-based + // policy by using the ARN or assumed role ID. The ARN and ID include the RoleSessionName + // that you specified when you called AssumeRole. + AssumedRoleUser *AssumedRoleUser `type:"structure"` + + // The temporary security credentials, which include an access key ID, a secret + // access key, and a security (or session) token. + Credentials *Credentials `type:"structure"` + + // A percentage value that indicates the size of the policy in packed form. + // The service rejects any policy with a packed size greater than 100 percent, + // which means the policy exceeded the allowed space. + PackedPolicySize *int64 `type:"integer"` + + metadataAssumeRoleOutput `json:"-" xml:"-"` +} + +type metadataAssumeRoleOutput struct { + SDKShapeTraits bool `type:"structure"` +} + +// String returns the string representation +func (s AssumeRoleOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleOutput) GoString() string { + return s.String() +} + +type AssumeRoleWithSAMLInput struct { + // The duration, in seconds, of the role session. The value can range from 900 + // seconds (15 minutes) to 3600 seconds (1 hour). By default, the value is set + // to 3600 seconds. An expiration can also be specified in the SAML authentication + // response's SessionNotOnOrAfter value. The actual expiration time is whichever + // value is shorter. + // + // The maximum duration for a session is 1 hour, and the minimum duration is + // 15 minutes, even if values outside this range are specified. + DurationSeconds *int64 `min:"900" type:"integer"` + + // An IAM policy in JSON format. + // + // The policy parameter is optional. If you pass a policy, the temporary security + // credentials that are returned by the operation have the permissions that + // are allowed by both the access policy of the role that is being assumed, + // and the policy that you pass. This gives you a way to further restrict the + // permissions for the resulting temporary security credentials. You cannot + // use the passed policy to grant permissions that are in excess of those allowed + // by the access policy of the role that is being assumed. For more information, + // Permissions for AssumeRole, AssumeRoleWithSAML, and AssumeRoleWithWebIdentity + // (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) + // in the Using IAM. + // + // The policy plain text must be 2048 bytes or shorter. However, an internal + // conversion compresses it into a packed binary format with a separate limit. + // The PackedPolicySize response element indicates by percentage how close to + // the upper size limit the policy is, with 100% equaling the maximum allowed + // size. + Policy *string `min:"1" type:"string"` + + // The Amazon Resource Name (ARN) of the SAML provider in IAM that describes + // the IdP. + PrincipalArn *string `min:"20" type:"string" required:"true"` + + // The Amazon Resource Name (ARN) of the role that the caller is assuming. + RoleArn *string `min:"20" type:"string" required:"true"` + + // The base-64 encoded SAML authentication response provided by the IdP. + // + // For more information, see Configuring a Relying Party and Adding Claims + // (http://docs.aws.amazon.com/IAM/latest/UserGuide/create-role-saml-IdP-tasks.html) + // in the Using IAM guide. + SAMLAssertion *string `min:"4" type:"string" required:"true"` + + metadataAssumeRoleWithSAMLInput `json:"-" xml:"-"` +} + +type metadataAssumeRoleWithSAMLInput struct { + SDKShapeTraits bool `type:"structure"` +} + +// String returns the string representation +func (s AssumeRoleWithSAMLInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleWithSAMLInput) GoString() string { + return s.String() +} + +// Contains the response to a successful AssumeRoleWithSAML request, including +// temporary AWS credentials that can be used to make AWS requests. +type AssumeRoleWithSAMLOutput struct { + // The identifiers for the temporary security credentials that the operation + // returns. + AssumedRoleUser *AssumedRoleUser `type:"structure"` + + // The value of the Recipient attribute of the SubjectConfirmationData element + // of the SAML assertion. + Audience *string `type:"string"` + + // AWS credentials for API authentication. + Credentials *Credentials `type:"structure"` + + // The value of the Issuer element of the SAML assertion. + Issuer *string `type:"string"` + + // A hash value based on the concatenation of the Issuer response value, the + // AWS account ID, and the friendly name (the last part of the ARN) of the SAML + // provider in IAM. The combination of NameQualifier and Subject can be used + // to uniquely identify a federated user. + // + // The following pseudocode shows how the hash value is calculated: + // + // BASE64 ( SHA1 ( "https://example.com/saml" + "123456789012" + "/MySAMLIdP" + // ) ) + NameQualifier *string `type:"string"` + + // A percentage value that indicates the size of the policy in packed form. + // The service rejects any policy with a packed size greater than 100 percent, + // which means the policy exceeded the allowed space. + PackedPolicySize *int64 `type:"integer"` + + // The value of the NameID element in the Subject element of the SAML assertion. + Subject *string `type:"string"` + + // The format of the name ID, as defined by the Format attribute in the NameID + // element of the SAML assertion. Typical examples of the format are transient + // or persistent. + // + // If the format includes the prefix urn:oasis:names:tc:SAML:2.0:nameid-format, + // that prefix is removed. For example, urn:oasis:names:tc:SAML:2.0:nameid-format:transient + // is returned as transient. If the format includes any other prefix, the format + // is returned with no modifications. + SubjectType *string `type:"string"` + + metadataAssumeRoleWithSAMLOutput `json:"-" xml:"-"` +} + +type metadataAssumeRoleWithSAMLOutput struct { + SDKShapeTraits bool `type:"structure"` +} + +// String returns the string representation +func (s AssumeRoleWithSAMLOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleWithSAMLOutput) GoString() string { + return s.String() +} + +type AssumeRoleWithWebIdentityInput struct { + // The duration, in seconds, of the role session. The value can range from 900 + // seconds (15 minutes) to 3600 seconds (1 hour). By default, the value is set + // to 3600 seconds. + DurationSeconds *int64 `min:"900" type:"integer"` + + // An IAM policy in JSON format. + // + // The policy parameter is optional. If you pass a policy, the temporary security + // credentials that are returned by the operation have the permissions that + // are allowed by both the access policy of the role that is being assumed, + // and the policy that you pass. This gives you a way to further restrict the + // permissions for the resulting temporary security credentials. You cannot + // use the passed policy to grant permissions that are in excess of those allowed + // by the access policy of the role that is being assumed. For more information, + // see Permissions for AssumeRoleWithWebIdentity (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) + // in the Using IAM. + // + // The policy plain text must be 2048 bytes or shorter. However, an internal + // conversion compresses it into a packed binary format with a separate limit. + // The PackedPolicySize response element indicates by percentage how close to + // the upper size limit the policy is, with 100% equaling the maximum allowed + // size. + Policy *string `min:"1" type:"string"` + + // The fully qualified host component of the domain name of the identity provider. + // + // Specify this value only for OAuth 2.0 access tokens. Currently www.amazon.com + // and graph.facebook.com are the only supported identity providers for OAuth + // 2.0 access tokens. Do not include URL schemes and port numbers. + // + // Do not specify this value for OpenID Connect ID tokens. + ProviderId *string `min:"4" type:"string"` + + // The Amazon Resource Name (ARN) of the role that the caller is assuming. + RoleArn *string `min:"20" type:"string" required:"true"` + + // An identifier for the assumed role session. Typically, you pass the name + // or identifier that is associated with the user who is using your application. + // That way, the temporary security credentials that your application will use + // are associated with that user. This session name is included as part of the + // ARN and assumed role ID in the AssumedRoleUser response element. + RoleSessionName *string `min:"2" type:"string" required:"true"` + + // The OAuth 2.0 access token or OpenID Connect ID token that is provided by + // the identity provider. Your application must get this token by authenticating + // the user who is using your application with a web identity provider before + // the application makes an AssumeRoleWithWebIdentity call. + WebIdentityToken *string `min:"4" type:"string" required:"true"` + + metadataAssumeRoleWithWebIdentityInput `json:"-" xml:"-"` +} + +type metadataAssumeRoleWithWebIdentityInput struct { + SDKShapeTraits bool `type:"structure"` +} + +// String returns the string representation +func (s AssumeRoleWithWebIdentityInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleWithWebIdentityInput) GoString() string { + return s.String() +} + +// Contains the response to a successful AssumeRoleWithWebIdentity request, +// including temporary AWS credentials that can be used to make AWS requests. +type AssumeRoleWithWebIdentityOutput struct { + // The Amazon Resource Name (ARN) and the assumed role ID, which are identifiers + // that you can use to refer to the resulting temporary security credentials. + // For example, you can reference these credentials as a principal in a resource-based + // policy by using the ARN or assumed role ID. The ARN and ID include the RoleSessionName + // that you specified when you called AssumeRole. + AssumedRoleUser *AssumedRoleUser `type:"structure"` + + // The intended audience (also known as client ID) of the web identity token. + // This is traditionally the client identifier issued to the application that + // requested the web identity token. + Audience *string `type:"string"` + + // The temporary security credentials, which include an access key ID, a secret + // access key, and a security token. + Credentials *Credentials `type:"structure"` + + // A percentage value that indicates the size of the policy in packed form. + // The service rejects any policy with a packed size greater than 100 percent, + // which means the policy exceeded the allowed space. + PackedPolicySize *int64 `type:"integer"` + + // The issuing authority of the web identity token presented. For OpenID Connect + // ID Tokens this contains the value of the iss field. For OAuth 2.0 access + // tokens, this contains the value of the ProviderId parameter that was passed + // in the AssumeRoleWithWebIdentity request. + Provider *string `type:"string"` + + // The unique user identifier that is returned by the identity provider. This + // identifier is associated with the WebIdentityToken that was submitted with + // the AssumeRoleWithWebIdentity call. The identifier is typically unique to + // the user and the application that acquired the WebIdentityToken (pairwise + // identifier). For OpenID Connect ID tokens, this field contains the value + // returned by the identity provider as the token's sub (Subject) claim. + SubjectFromWebIdentityToken *string `min:"6" type:"string"` + + metadataAssumeRoleWithWebIdentityOutput `json:"-" xml:"-"` +} + +type metadataAssumeRoleWithWebIdentityOutput struct { + SDKShapeTraits bool `type:"structure"` +} + +// String returns the string representation +func (s AssumeRoleWithWebIdentityOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleWithWebIdentityOutput) GoString() string { + return s.String() +} + +// The identifiers for the temporary security credentials that the operation +// returns. +type AssumedRoleUser struct { + // The ARN of the temporary security credentials that are returned from the + // AssumeRole action. For more information about ARNs and how to use them in + // policies, see IAM Identifiers (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html) + // in Using IAM. + Arn *string `min:"20" type:"string" required:"true"` + + // A unique identifier that contains the role ID and the role session name of + // the role that is being assumed. The role ID is generated by AWS when the + // role is created. + AssumedRoleId *string `min:"2" type:"string" required:"true"` + + metadataAssumedRoleUser `json:"-" xml:"-"` +} + +type metadataAssumedRoleUser struct { + SDKShapeTraits bool `type:"structure"` +} + +// String returns the string representation +func (s AssumedRoleUser) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumedRoleUser) GoString() string { + return s.String() +} + +// AWS credentials for API authentication. +type Credentials struct { + // The access key ID that identifies the temporary security credentials. + AccessKeyId *string `min:"16" type:"string" required:"true"` + + // The date on which the current credentials expire. + Expiration *time.Time `type:"timestamp" timestampFormat:"iso8601" required:"true"` + + // The secret access key that can be used to sign requests. + SecretAccessKey *string `type:"string" required:"true"` + + // The token that users must pass to the service API to use the temporary credentials. + SessionToken *string `type:"string" required:"true"` + + metadataCredentials `json:"-" xml:"-"` +} + +type metadataCredentials struct { + SDKShapeTraits bool `type:"structure"` +} + +// String returns the string representation +func (s Credentials) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Credentials) GoString() string { + return s.String() +} + +type DecodeAuthorizationMessageInput struct { + // The encoded message that was returned with the response. + EncodedMessage *string `min:"1" type:"string" required:"true"` + + metadataDecodeAuthorizationMessageInput `json:"-" xml:"-"` +} + +type metadataDecodeAuthorizationMessageInput struct { + SDKShapeTraits bool `type:"structure"` +} + +// String returns the string representation +func (s DecodeAuthorizationMessageInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DecodeAuthorizationMessageInput) GoString() string { + return s.String() +} + +// A document that contains additional information about the authorization status +// of a request from an encoded message that is returned in response to an AWS +// request. +type DecodeAuthorizationMessageOutput struct { + // An XML document that contains the decoded message. For more information, + // see DecodeAuthorizationMessage. + DecodedMessage *string `type:"string"` + + metadataDecodeAuthorizationMessageOutput `json:"-" xml:"-"` +} + +type metadataDecodeAuthorizationMessageOutput struct { + SDKShapeTraits bool `type:"structure"` +} + +// String returns the string representation +func (s DecodeAuthorizationMessageOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DecodeAuthorizationMessageOutput) GoString() string { + return s.String() +} + +// Identifiers for the federated user that is associated with the credentials. +type FederatedUser struct { + // The ARN that specifies the federated user that is associated with the credentials. + // For more information about ARNs and how to use them in policies, see IAM + // Identifiers (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html) + // in Using IAM. + Arn *string `min:"20" type:"string" required:"true"` + + // The string that identifies the federated user associated with the credentials, + // similar to the unique ID of an IAM user. + FederatedUserId *string `min:"2" type:"string" required:"true"` + + metadataFederatedUser `json:"-" xml:"-"` +} + +type metadataFederatedUser struct { + SDKShapeTraits bool `type:"structure"` +} + +// String returns the string representation +func (s FederatedUser) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s FederatedUser) GoString() string { + return s.String() +} + +type GetFederationTokenInput struct { + // The duration, in seconds, that the session should last. Acceptable durations + // for federation sessions range from 900 seconds (15 minutes) to 129600 seconds + // (36 hours), with 43200 seconds (12 hours) as the default. Sessions obtained + // using AWS account (root) credentials are restricted to a maximum of 3600 + // seconds (one hour). If the specified duration is longer than one hour, the + // session obtained by using AWS account (root) credentials defaults to one + // hour. + DurationSeconds *int64 `min:"900" type:"integer"` + + // The name of the federated user. The name is used as an identifier for the + // temporary security credentials (such as Bob). For example, you can reference + // the federated user name in a resource-based policy, such as in an Amazon + // S3 bucket policy. + Name *string `min:"2" type:"string" required:"true"` + + // An IAM policy in JSON format that is passed with the GetFederationToken call + // and evaluated along with the policy or policies that are attached to the + // IAM user whose credentials are used to call GetFederationToken. The passed + // policy is used to scope down the permissions that are available to the IAM + // user, by allowing only a subset of the permissions that are granted to the + // IAM user. The passed policy cannot grant more permissions than those granted + // to the IAM user. The final permissions for the federated user are the most + // restrictive set based on the intersection of the passed policy and the IAM + // user policy. + // + // If you do not pass a policy, the resulting temporary security credentials + // have no effective permissions. The only exception is when the temporary security + // credentials are used to access a resource that has a resource-based policy + // that specifically allows the federated user to access the resource. + // + // The policy plain text must be 2048 bytes or shorter. However, an internal + // conversion compresses it into a packed binary format with a separate limit. + // The PackedPolicySize response element indicates by percentage how close to + // the upper size limit the policy is, with 100% equaling the maximum allowed + // size. For more information about how permissions work, see Permissions for + // GetFederationToken (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_getfederationtoken.html). + Policy *string `min:"1" type:"string"` + + metadataGetFederationTokenInput `json:"-" xml:"-"` +} + +type metadataGetFederationTokenInput struct { + SDKShapeTraits bool `type:"structure"` +} + +// String returns the string representation +func (s GetFederationTokenInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetFederationTokenInput) GoString() string { + return s.String() +} + +// Contains the response to a successful GetFederationToken request, including +// temporary AWS credentials that can be used to make AWS requests. +type GetFederationTokenOutput struct { + // Credentials for the service API authentication. + Credentials *Credentials `type:"structure"` + + // Identifiers for the federated user associated with the credentials (such + // as arn:aws:sts::123456789012:federated-user/Bob or 123456789012:Bob). You + // can use the federated user's ARN in your resource-based policies, such as + // an Amazon S3 bucket policy. + FederatedUser *FederatedUser `type:"structure"` + + // A percentage value indicating the size of the policy in packed form. The + // service rejects policies for which the packed size is greater than 100 percent + // of the allowed value. + PackedPolicySize *int64 `type:"integer"` + + metadataGetFederationTokenOutput `json:"-" xml:"-"` +} + +type metadataGetFederationTokenOutput struct { + SDKShapeTraits bool `type:"structure"` +} + +// String returns the string representation +func (s GetFederationTokenOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetFederationTokenOutput) GoString() string { + return s.String() +} + +type GetSessionTokenInput struct { + // The duration, in seconds, that the credentials should remain valid. Acceptable + // durations for IAM user sessions range from 900 seconds (15 minutes) to 129600 + // seconds (36 hours), with 43200 seconds (12 hours) as the default. Sessions + // for AWS account owners are restricted to a maximum of 3600 seconds (one hour). + // If the duration is longer than one hour, the session for AWS account owners + // defaults to one hour. + DurationSeconds *int64 `min:"900" type:"integer"` + + // The identification number of the MFA device that is associated with the IAM + // user who is making the GetSessionToken call. Specify this value if the IAM + // user has a policy that requires MFA authentication. The value is either the + // serial number for a hardware device (such as GAHT12345678) or an Amazon Resource + // Name (ARN) for a virtual device (such as arn:aws:iam::123456789012:mfa/user). + // You can find the device for an IAM user by going to the AWS Management Console + // and viewing the user's security credentials. + SerialNumber *string `min:"9" type:"string"` + + // The value provided by the MFA device, if MFA is required. If any policy requires + // the IAM user to submit an MFA code, specify this value. If MFA authentication + // is required, and the user does not provide a code when requesting a set of + // temporary security credentials, the user will receive an "access denied" + // response when requesting resources that require MFA authentication. + TokenCode *string `min:"6" type:"string"` + + metadataGetSessionTokenInput `json:"-" xml:"-"` +} + +type metadataGetSessionTokenInput struct { + SDKShapeTraits bool `type:"structure"` +} + +// String returns the string representation +func (s GetSessionTokenInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetSessionTokenInput) GoString() string { + return s.String() +} + +// Contains the response to a successful GetSessionToken request, including +// temporary AWS credentials that can be used to make AWS requests. +type GetSessionTokenOutput struct { + // The session credentials for API authentication. + Credentials *Credentials `type:"structure"` + + metadataGetSessionTokenOutput `json:"-" xml:"-"` +} + +type metadataGetSessionTokenOutput struct { + SDKShapeTraits bool `type:"structure"` +} + +// String returns the string representation +func (s GetSessionTokenOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetSessionTokenOutput) GoString() string { + return s.String() +} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/customizations.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/customizations.go new file mode 100644 index 00000000000..4010cc7fa14 --- /dev/null +++ b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/customizations.go @@ -0,0 +1,12 @@ +package sts + +import "github.com/aws/aws-sdk-go/aws/request" + +func init() { + initRequest = func(r *request.Request) { + switch r.Operation.Name { + case opAssumeRoleWithSAML, opAssumeRoleWithWebIdentity: + r.Handlers.Sign.Clear() // these operations are unsigned + } + } +} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/customizations_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/customizations_test.go new file mode 100644 index 00000000000..6f870d35e27 --- /dev/null +++ b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/customizations_test.go @@ -0,0 +1,39 @@ +package sts_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/awstesting/unit" + "github.com/aws/aws-sdk-go/service/sts" +) + +var svc = sts.New(unit.Session, &aws.Config{ + Region: aws.String("mock-region"), +}) + +func TestUnsignedRequest_AssumeRoleWithSAML(t *testing.T) { + req, _ := svc.AssumeRoleWithSAMLRequest(&sts.AssumeRoleWithSAMLInput{ + PrincipalArn: aws.String("ARN01234567890123456789"), + RoleArn: aws.String("ARN01234567890123456789"), + SAMLAssertion: aws.String("ASSERT"), + }) + + err := req.Sign() + assert.NoError(t, err) + assert.Equal(t, "", req.HTTPRequest.Header.Get("Authorization")) +} + +func TestUnsignedRequest_AssumeRoleWithWebIdentity(t *testing.T) { + req, _ := svc.AssumeRoleWithWebIdentityRequest(&sts.AssumeRoleWithWebIdentityInput{ + RoleArn: aws.String("ARN01234567890123456789"), + RoleSessionName: aws.String("SESSION"), + WebIdentityToken: aws.String("TOKEN"), + }) + + err := req.Sign() + assert.NoError(t, err) + assert.Equal(t, "", req.HTTPRequest.Header.Get("Authorization")) +} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/examples_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/examples_test.go new file mode 100644 index 00000000000..083bcbd6877 --- /dev/null +++ b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/examples_test.go @@ -0,0 +1,149 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +package sts_test + +import ( + "bytes" + "fmt" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/sts" +) + +var _ time.Duration +var _ bytes.Buffer + +func ExampleSTS_AssumeRole() { + svc := sts.New(session.New()) + + params := &sts.AssumeRoleInput{ + RoleArn: aws.String("arnType"), // Required + RoleSessionName: aws.String("roleSessionNameType"), // Required + DurationSeconds: aws.Int64(1), + ExternalId: aws.String("externalIdType"), + Policy: aws.String("sessionPolicyDocumentType"), + SerialNumber: aws.String("serialNumberType"), + TokenCode: aws.String("tokenCodeType"), + } + resp, err := svc.AssumeRole(params) + + if err != nil { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + return + } + + // Pretty-print the response data. + fmt.Println(resp) +} + +func ExampleSTS_AssumeRoleWithSAML() { + svc := sts.New(session.New()) + + params := &sts.AssumeRoleWithSAMLInput{ + PrincipalArn: aws.String("arnType"), // Required + RoleArn: aws.String("arnType"), // Required + SAMLAssertion: aws.String("SAMLAssertionType"), // Required + DurationSeconds: aws.Int64(1), + Policy: aws.String("sessionPolicyDocumentType"), + } + resp, err := svc.AssumeRoleWithSAML(params) + + if err != nil { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + return + } + + // Pretty-print the response data. + fmt.Println(resp) +} + +func ExampleSTS_AssumeRoleWithWebIdentity() { + svc := sts.New(session.New()) + + params := &sts.AssumeRoleWithWebIdentityInput{ + RoleArn: aws.String("arnType"), // Required + RoleSessionName: aws.String("roleSessionNameType"), // Required + WebIdentityToken: aws.String("clientTokenType"), // Required + DurationSeconds: aws.Int64(1), + Policy: aws.String("sessionPolicyDocumentType"), + ProviderId: aws.String("urlType"), + } + resp, err := svc.AssumeRoleWithWebIdentity(params) + + if err != nil { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + return + } + + // Pretty-print the response data. + fmt.Println(resp) +} + +func ExampleSTS_DecodeAuthorizationMessage() { + svc := sts.New(session.New()) + + params := &sts.DecodeAuthorizationMessageInput{ + EncodedMessage: aws.String("encodedMessageType"), // Required + } + resp, err := svc.DecodeAuthorizationMessage(params) + + if err != nil { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + return + } + + // Pretty-print the response data. + fmt.Println(resp) +} + +func ExampleSTS_GetFederationToken() { + svc := sts.New(session.New()) + + params := &sts.GetFederationTokenInput{ + Name: aws.String("userNameType"), // Required + DurationSeconds: aws.Int64(1), + Policy: aws.String("sessionPolicyDocumentType"), + } + resp, err := svc.GetFederationToken(params) + + if err != nil { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + return + } + + // Pretty-print the response data. + fmt.Println(resp) +} + +func ExampleSTS_GetSessionToken() { + svc := sts.New(session.New()) + + params := &sts.GetSessionTokenInput{ + DurationSeconds: aws.Int64(1), + SerialNumber: aws.String("serialNumberType"), + TokenCode: aws.String("tokenCodeType"), + } + resp, err := svc.GetSessionToken(params) + + if err != nil { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + return + } + + // Pretty-print the response data. + fmt.Println(resp) +} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/service.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/service.go new file mode 100644 index 00000000000..33f49001fa1 --- /dev/null +++ b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/service.go @@ -0,0 +1,130 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +package sts + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/query" + "github.com/aws/aws-sdk-go/private/signer/v4" +) + +// The AWS Security Token Service (STS) is a web service that enables you to +// request temporary, limited-privilege credentials for AWS Identity and Access +// Management (IAM) users or for users that you authenticate (federated users). +// This guide provides descriptions of the STS API. For more detailed information +// about using this service, go to Temporary Security Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html). +// +// As an alternative to using the API, you can use one of the AWS SDKs, which +// consist of libraries and sample code for various programming languages and +// platforms (Java, Ruby, .NET, iOS, Android, etc.). The SDKs provide a convenient +// way to create programmatic access to STS. For example, the SDKs take care +// of cryptographically signing requests, managing errors, and retrying requests +// automatically. For information about the AWS SDKs, including how to download +// and install them, see the Tools for Amazon Web Services page (http://aws.amazon.com/tools/). +// For information about setting up signatures and authorization through the +// API, go to Signing AWS API Requests (http://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html" +// target="_blank) in the AWS General Reference. For general information about +// the Query API, go to Making Query Requests (http://docs.aws.amazon.com/IAM/latest/UserGuide/IAM_UsingQueryAPI.html" +// target="_blank) in Using IAM. For information about using security tokens +// with other AWS products, go to AWS Services That Work with IAM (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html) +// in the Using IAM. +// +// If you're new to AWS and need additional technical information about a specific +// AWS product, you can find the product's technical documentation at http://aws.amazon.com/documentation/ +// (http://aws.amazon.com/documentation/" target="_blank). +// +// Endpoints +// +// The AWS Security Token Service (STS) has a default endpoint of https://sts.amazonaws.com +// that maps to the US East (N. Virginia) region. Additional regions are available, +// but must first be activated in the AWS Management Console before you can +// use a different region's endpoint. For more information about activating +// a region for STS see Activating STS in a New Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) +// in the Using IAM. +// +// For information about STS endpoints, see Regions and Endpoints (http://docs.aws.amazon.com/general/latest/gr/rande.html#sts_region) +// in the AWS General Reference. +// +// Recording API requests +// +// STS supports AWS CloudTrail, which is a service that records AWS calls for +// your AWS account and delivers log files to an Amazon S3 bucket. By using +// information collected by CloudTrail, you can determine what requests were +// successfully made to STS, who made the request, when it was made, and so +// on. To learn more about CloudTrail, including how to turn it on and find +// your log files, see the AWS CloudTrail User Guide (http://docs.aws.amazon.com/awscloudtrail/latest/userguide/what_is_cloud_trail_top_level.html). +//The service client's operations are safe to be used concurrently. +// It is not safe to mutate any of the client's properties though. +type STS struct { + *client.Client +} + +// Used for custom client initialization logic +var initClient func(*client.Client) + +// Used for custom request initialization logic +var initRequest func(*request.Request) + +// A ServiceName is the name of the service the client will make API calls to. +const ServiceName = "sts" + +// New creates a new instance of the STS client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a STS client from just a session. +// svc := sts.New(mySession) +// +// // Create a STS client with additional configuration +// svc := sts.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func New(p client.ConfigProvider, cfgs ...*aws.Config) *STS { + c := p.ClientConfig(ServiceName, cfgs...) + return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) +} + +// newClient creates, initializes and returns a new service client instance. +func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *STS { + svc := &STS{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: ServiceName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2011-06-15", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBack(v4.Sign) + svc.Handlers.Build.PushBack(query.Build) + svc.Handlers.Unmarshal.PushBack(query.Unmarshal) + svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) + svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) + + // Run custom client initialization if present + if initClient != nil { + initClient(svc.Client) + } + + return svc +} + +// newRequest creates a new request for a STS operation and runs any +// custom request initialization. +func (c *STS) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + // Run custom request initialization if present + if initRequest != nil { + initRequest(req) + } + + return req +} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/stsiface/interface.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/stsiface/interface.go new file mode 100644 index 00000000000..09dae0c9dc3 --- /dev/null +++ b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/sts/stsiface/interface.go @@ -0,0 +1,38 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +// Package stsiface provides an interface for the AWS Security Token Service. +package stsiface + +import ( + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/service/sts" +) + +// STSAPI is the interface type for sts.STS. +type STSAPI interface { + AssumeRoleRequest(*sts.AssumeRoleInput) (*request.Request, *sts.AssumeRoleOutput) + + AssumeRole(*sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) + + AssumeRoleWithSAMLRequest(*sts.AssumeRoleWithSAMLInput) (*request.Request, *sts.AssumeRoleWithSAMLOutput) + + AssumeRoleWithSAML(*sts.AssumeRoleWithSAMLInput) (*sts.AssumeRoleWithSAMLOutput, error) + + AssumeRoleWithWebIdentityRequest(*sts.AssumeRoleWithWebIdentityInput) (*request.Request, *sts.AssumeRoleWithWebIdentityOutput) + + AssumeRoleWithWebIdentity(*sts.AssumeRoleWithWebIdentityInput) (*sts.AssumeRoleWithWebIdentityOutput, error) + + DecodeAuthorizationMessageRequest(*sts.DecodeAuthorizationMessageInput) (*request.Request, *sts.DecodeAuthorizationMessageOutput) + + DecodeAuthorizationMessage(*sts.DecodeAuthorizationMessageInput) (*sts.DecodeAuthorizationMessageOutput, error) + + GetFederationTokenRequest(*sts.GetFederationTokenInput) (*request.Request, *sts.GetFederationTokenOutput) + + GetFederationToken(*sts.GetFederationTokenInput) (*sts.GetFederationTokenOutput, error) + + GetSessionTokenRequest(*sts.GetSessionTokenInput) (*request.Request, *sts.GetSessionTokenOutput) + + GetSessionToken(*sts.GetSessionTokenInput) (*sts.GetSessionTokenOutput, error) +} + +var _ STSAPI = (*sts.STS)(nil) diff --git a/pkg/api/cloudwatch/cloudwatch.go b/pkg/api/cloudwatch/cloudwatch.go index 88d22800d65..5b4449b5c02 100644 --- a/pkg/api/cloudwatch/cloudwatch.go +++ b/pkg/api/cloudwatch/cloudwatch.go @@ -4,6 +4,8 @@ import ( "encoding/json" "errors" "io/ioutil" + "strings" + "sync" "time" "github.com/aws/aws-sdk-go/aws" @@ -14,6 +16,8 @@ import ( "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/cloudwatch" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/sts" + "github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" ) @@ -44,31 +48,96 @@ func init() { } } -var awsCredentials map[string]*credentials.Credentials = make(map[string]*credentials.Credentials) +type cache struct { + credential *credentials.Credentials + expiration *time.Time +} -func getCredentials(profile string) *credentials.Credentials { - if _, ok := awsCredentials[profile]; ok { - return awsCredentials[profile] +var awsCredentialCache map[string]cache = make(map[string]cache) +var credentialCacheLock sync.RWMutex + +func getCredentials(profile string, region string, assumeRoleArn string) *credentials.Credentials { + credentialCacheLock.RLock() + if _, ok := awsCredentialCache[profile]; ok { + if awsCredentialCache[profile].expiration != nil && + (*awsCredentialCache[profile].expiration).After(time.Now().UTC()) { + result := awsCredentialCache[profile].credential + credentialCacheLock.RUnlock() + return result + } + } + credentialCacheLock.RUnlock() + + accessKeyId := "" + secretAccessKey := "" + sessionToken := "" + var expiration *time.Time + expiration = nil + if strings.Index(assumeRoleArn, "arn:aws:iam:") == 0 { + params := &sts.AssumeRoleInput{ + RoleArn: aws.String(assumeRoleArn), + RoleSessionName: aws.String("GrafanaSession"), + DurationSeconds: aws.Int64(900), + } + + stsSess := session.New() + stsCreds := credentials.NewChainCredentials( + []credentials.Provider{ + &credentials.EnvProvider{}, + &credentials.SharedCredentialsProvider{Filename: "", Profile: profile}, + &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(stsSess), ExpiryWindow: 5 * time.Minute}, + }) + stsConfig := &aws.Config{ + Region: aws.String(region), + Credentials: stsCreds, + } + svc := sts.New(session.New(stsConfig), stsConfig) + resp, err := svc.AssumeRole(params) + if err != nil { + // ignore + log.Error(3, "CloudWatch: Failed to assume role", err) + } + if resp.Credentials != nil { + accessKeyId = *resp.Credentials.AccessKeyId + secretAccessKey = *resp.Credentials.SecretAccessKey + sessionToken = *resp.Credentials.SessionToken + expiration = resp.Credentials.Expiration + } } sess := session.New() creds := credentials.NewChainCredentials( []credentials.Provider{ + &credentials.StaticProvider{Value: credentials.Value{ + AccessKeyID: accessKeyId, + SecretAccessKey: secretAccessKey, + SessionToken: sessionToken, + }}, &credentials.EnvProvider{}, &credentials.SharedCredentialsProvider{Filename: "", Profile: profile}, &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute}, }) - awsCredentials[profile] = creds + credentialCacheLock.Lock() + awsCredentialCache[profile] = cache{ + credential: creds, + expiration: expiration, + } + credentialCacheLock.Unlock() return creds } -func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) { +func getAwsConfig(req *cwRequest) *aws.Config { + assumeRoleArn := req.DataSource.JsonData.Get("assumeRoleArn").MustString() cfg := &aws.Config{ Region: aws.String(req.Region), - Credentials: getCredentials(req.DataSource.Database), + Credentials: getCredentials(req.DataSource.Database, req.Region, assumeRoleArn), } + return cfg +} +func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) { + cfg := getAwsConfig(req) svc := cloudwatch.New(session.New(cfg), cfg) reqParam := &struct { @@ -104,11 +173,7 @@ func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) { } func handleListMetrics(req *cwRequest, c *middleware.Context) { - cfg := &aws.Config{ - Region: aws.String(req.Region), - Credentials: getCredentials(req.DataSource.Database), - } - + cfg := getAwsConfig(req) svc := cloudwatch.New(session.New(cfg), cfg) reqParam := &struct { @@ -144,11 +209,7 @@ func handleListMetrics(req *cwRequest, c *middleware.Context) { } func handleDescribeAlarms(req *cwRequest, c *middleware.Context) { - cfg := &aws.Config{ - Region: aws.String(req.Region), - Credentials: getCredentials(req.DataSource.Database), - } - + cfg := getAwsConfig(req) svc := cloudwatch.New(session.New(cfg), cfg) reqParam := &struct { @@ -187,11 +248,7 @@ func handleDescribeAlarms(req *cwRequest, c *middleware.Context) { } func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) { - cfg := &aws.Config{ - Region: aws.String(req.Region), - Credentials: getCredentials(req.DataSource.Database), - } - + cfg := getAwsConfig(req) svc := cloudwatch.New(session.New(cfg), cfg) reqParam := &struct { @@ -227,11 +284,7 @@ func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) { } func handleDescribeAlarmHistory(req *cwRequest, c *middleware.Context) { - cfg := &aws.Config{ - Region: aws.String(req.Region), - Credentials: getCredentials(req.DataSource.Database), - } - + cfg := getAwsConfig(req) svc := cloudwatch.New(session.New(cfg), cfg) reqParam := &struct { @@ -263,11 +316,7 @@ func handleDescribeAlarmHistory(req *cwRequest, c *middleware.Context) { } func handleDescribeInstances(req *cwRequest, c *middleware.Context) { - cfg := &aws.Config{ - Region: aws.String(req.Region), - Credentials: getCredentials(req.DataSource.Database), - } - + cfg := getAwsConfig(req) svc := ec2.New(session.New(cfg), cfg) reqParam := &struct { diff --git a/pkg/api/cloudwatch/metrics.go b/pkg/api/cloudwatch/metrics.go index 7717ca27099..5bd318ea3c9 100644 --- a/pkg/api/cloudwatch/metrics.go +++ b/pkg/api/cloudwatch/metrics.go @@ -166,7 +166,8 @@ func handleGetMetrics(req *cwRequest, c *middleware.Context) { } } else { var err error - if namespaceMetrics, err = getMetricsForCustomMetrics(req.Region, reqParam.Parameters.Namespace, req.DataSource.Database, getAllMetrics); err != nil { + assumeRoleArn := req.DataSource.JsonData.Get("assumeRoleArn").MustString() + if namespaceMetrics, err = getMetricsForCustomMetrics(req.Region, reqParam.Parameters.Namespace, req.DataSource.Database, assumeRoleArn, getAllMetrics); err != nil { c.JsonApiErr(500, "Unable to call AWS API", err) return } @@ -199,7 +200,8 @@ func handleGetDimensions(req *cwRequest, c *middleware.Context) { } } else { var err error - if dimensionValues, err = getDimensionsForCustomMetrics(req.Region, reqParam.Parameters.Namespace, req.DataSource.Database, getAllMetrics); err != nil { + assumeRoleArn := req.DataSource.JsonData.Get("assumeRoleArn").MustString() + if dimensionValues, err = getDimensionsForCustomMetrics(req.Region, reqParam.Parameters.Namespace, req.DataSource.Database, assumeRoleArn, getAllMetrics); err != nil { c.JsonApiErr(500, "Unable to call AWS API", err) return } @@ -214,10 +216,10 @@ func handleGetDimensions(req *cwRequest, c *middleware.Context) { c.JSON(200, result) } -func getAllMetrics(region string, namespace string, database string) (cloudwatch.ListMetricsOutput, error) { +func getAllMetrics(region string, namespace string, database string, assumeRoleArn string) (cloudwatch.ListMetricsOutput, error) { cfg := &aws.Config{ Region: aws.String(region), - Credentials: getCredentials(database), + Credentials: getCredentials(database, region, assumeRoleArn), } svc := cloudwatch.New(session.New(cfg), cfg) @@ -244,8 +246,8 @@ func getAllMetrics(region string, namespace string, database string) (cloudwatch var metricsCacheLock sync.Mutex -func getMetricsForCustomMetrics(region string, namespace string, database string, getAllMetrics func(string, string, string) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { - result, err := getAllMetrics(region, namespace, database) +func getMetricsForCustomMetrics(region string, namespace string, database string, assumeRoleArn string, getAllMetrics func(string, string, string, string) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { + result, err := getAllMetrics(region, namespace, database, assumeRoleArn) if err != nil { return []string{}, err } @@ -282,8 +284,8 @@ func getMetricsForCustomMetrics(region string, namespace string, database string var dimensionsCacheLock sync.Mutex -func getDimensionsForCustomMetrics(region string, namespace string, database string, getAllMetrics func(string, string, string) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { - result, err := getAllMetrics(region, namespace, database) +func getDimensionsForCustomMetrics(region string, namespace string, database string, assumeRoleArn string, getAllMetrics func(string, string, string, string) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { + result, err := getAllMetrics(region, namespace, database, assumeRoleArn) if err != nil { return []string{}, err } diff --git a/pkg/api/cloudwatch/metrics_test.go b/pkg/api/cloudwatch/metrics_test.go index ec39452e116..6dd68037613 100644 --- a/pkg/api/cloudwatch/metrics_test.go +++ b/pkg/api/cloudwatch/metrics_test.go @@ -14,7 +14,8 @@ func TestCloudWatchMetrics(t *testing.T) { region := "us-east-1" namespace := "Foo" database := "default" - f := func(region string, namespace string, database string) (cloudwatch.ListMetricsOutput, error) { + assumeRoleArn := "" + f := func(region string, namespace string, database string, assumeRoleArn string) (cloudwatch.ListMetricsOutput, error) { return cloudwatch.ListMetricsOutput{ Metrics: []*cloudwatch.Metric{ { @@ -28,7 +29,7 @@ func TestCloudWatchMetrics(t *testing.T) { }, }, nil } - metrics, _ := getMetricsForCustomMetrics(region, namespace, database, f) + metrics, _ := getMetricsForCustomMetrics(region, namespace, database, assumeRoleArn, f) Convey("Should contain Test_MetricName", func() { So(metrics, ShouldContain, "Test_MetricName") @@ -39,7 +40,8 @@ func TestCloudWatchMetrics(t *testing.T) { region := "us-east-1" namespace := "Foo" database := "default" - f := func(region string, namespace string, database string) (cloudwatch.ListMetricsOutput, error) { + assumeRoleArn := "" + f := func(region string, namespace string, database string, assumeRoleArn string) (cloudwatch.ListMetricsOutput, error) { return cloudwatch.ListMetricsOutput{ Metrics: []*cloudwatch.Metric{ { @@ -53,7 +55,7 @@ func TestCloudWatchMetrics(t *testing.T) { }, }, nil } - dimensionKeys, _ := getDimensionsForCustomMetrics(region, namespace, database, f) + dimensionKeys, _ := getDimensionsForCustomMetrics(region, namespace, database, assumeRoleArn, f) Convey("Should contain Test_DimensionName", func() { So(dimensionKeys, ShouldContain, "Test_DimensionName") diff --git a/public/app/plugins/datasource/cloudwatch/partials/config.html b/public/app/plugins/datasource/cloudwatch/partials/config.html index ede6baaa525..fb34a9fb92b 100644 --- a/public/app/plugins/datasource/cloudwatch/partials/config.html +++ b/public/app/plugins/datasource/cloudwatch/partials/config.html @@ -24,4 +24,11 @@ Namespaces of Custom Metrics
+
+ + + + ARN of Assume Role + +
From 66bcae353c7d8d3a71cc0db06dee245ab6562b63 Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanda Date: Wed, 18 May 2016 14:56:23 +0900 Subject: [PATCH 15/26] (prometheus) pass dashboard time range to template query (#5007) * (prometheus) pass dashboard time range to template query * (prometheus) add passing time test of templating --- .../datasource/prometheus/datasource.ts | 4 ++-- .../prometheus/metric_find_query.js | 18 +++++++++------ .../specs/metric_find_query_specs.ts | 23 +++++++++++++------ public/test/specs/helpers.js | 4 ++++ 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/public/app/plugins/datasource/prometheus/datasource.ts b/public/app/plugins/datasource/prometheus/datasource.ts index ca7ef051ba0..978fee3e427 100644 --- a/public/app/plugins/datasource/prometheus/datasource.ts +++ b/public/app/plugins/datasource/prometheus/datasource.ts @@ -10,7 +10,7 @@ import PrometheusMetricFindQuery from './metric_find_query'; var durationSplitRegexp = /(\d+)(ms|s|m|h|d|w|M|y)/; /** @ngInject */ -export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateSrv) { +export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateSrv, timeSrv) { this.type = 'prometheus'; this.editorSrc = 'app/features/prometheus/partials/query.editor.html'; this.name = instanceSettings.name; @@ -145,7 +145,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS return $q.reject(err); } - var metricFindQuery = new PrometheusMetricFindQuery(this, interpolated); + var metricFindQuery = new PrometheusMetricFindQuery(this, interpolated, timeSrv); return metricFindQuery.process(); }; diff --git a/public/app/plugins/datasource/prometheus/metric_find_query.js b/public/app/plugins/datasource/prometheus/metric_find_query.js index 25704df1e2c..f449978be81 100644 --- a/public/app/plugins/datasource/prometheus/metric_find_query.js +++ b/public/app/plugins/datasource/prometheus/metric_find_query.js @@ -1,13 +1,13 @@ define([ - 'lodash', - 'moment', + 'lodash' ], -function (_, moment) { +function (_) { 'use strict'; - function PrometheusMetricFindQuery(datasource, query) { + function PrometheusMetricFindQuery(datasource, query, timeSrv) { this.datasource = datasource; this.query = query; + this.range = timeSrv.timeRange(); } PrometheusMetricFindQuery.prototype.process = function() { @@ -51,7 +51,9 @@ function (_, moment) { }); }); } else { - url = '/api/v1/series?match[]=' + encodeURIComponent(metric); + url = '/api/v1/series?match[]=' + encodeURIComponent(metric) + + '&start=' + (this.range.from.valueOf() / 1000) + + '&end=' + (this.range.to.valueOf() / 1000); return this.datasource._request('GET', url) .then(function(result) { @@ -86,7 +88,7 @@ function (_, moment) { }; PrometheusMetricFindQuery.prototype.queryResultQuery = function(query) { - var url = '/api/v1/query?query=' + encodeURIComponent(query) + '&time=' + (moment().valueOf() / 1000); + var url = '/api/v1/query?query=' + encodeURIComponent(query) + '&time=' + (this.range.to.valueOf() / 1000); return this.datasource._request('GET', url) .then(function(result) { @@ -107,7 +109,9 @@ function (_, moment) { }; PrometheusMetricFindQuery.prototype.metricNameAndLabelsQuery = function(query) { - var url = '/api/v1/series?match[]=' + encodeURIComponent(query); + var url = '/api/v1/series?match[]=' + encodeURIComponent(query) + + '&start=' + (this.range.from.valueOf() / 1000) + + '&end=' + (this.range.to.valueOf() / 1000); var self = this; return this.datasource._request('GET', url) diff --git a/public/app/plugins/datasource/prometheus/specs/metric_find_query_specs.ts b/public/app/plugins/datasource/prometheus/specs/metric_find_query_specs.ts index d328f4cb25b..38b50d2ce79 100644 --- a/public/app/plugins/datasource/prometheus/specs/metric_find_query_specs.ts +++ b/public/app/plugins/datasource/prometheus/specs/metric_find_query_specs.ts @@ -28,7 +28,7 @@ describe('PrometheusMetricFindQuery', function() { data: ["value1", "value2", "value3"] }; ctx.$httpBackend.expect('GET', 'proxied/api/v1/label/resource/values').respond(response); - var pm = new PrometheusMetricFindQuery(ctx.ds, 'label_values(resource)'); + var pm = new PrometheusMetricFindQuery(ctx.ds, 'label_values(resource)', ctx.timeSrv); pm.process().then(function(data) { results = data; }); ctx.$httpBackend.flush(); ctx.$rootScope.$apply(); @@ -43,13 +43,22 @@ describe('PrometheusMetricFindQuery', function() { {__name__: "metric", resource: "value3"} ] }; - ctx.$httpBackend.expect('GET', 'proxied/api/v1/series?match[]=metric').respond(response); - var pm = new PrometheusMetricFindQuery(ctx.ds, 'label_values(metric, resource)'); + ctx.$httpBackend.expect('GET', /proxied\/api\/v1\/series\?match\[\]=metric&start=.*&end=.*/).respond(response); + var pm = new PrometheusMetricFindQuery(ctx.ds, 'label_values(metric, resource)', ctx.timeSrv); pm.process().then(function(data) { results = data; }); ctx.$httpBackend.flush(); ctx.$rootScope.$apply(); expect(results.length).to.be(3); }); + it('label_values(metric, resource) should pass correct time', function() { + ctx.timeSrv.setTime({ from: moment.utc('2011-01-01'), to: moment.utc('2015-01-01') }); + ctx.$httpBackend.expect('GET', + /proxied\/api\/v1\/series\?match\[\]=metric&start=1293840000&end=1420070400/).respond(response); + var pm = new PrometheusMetricFindQuery(ctx.ds, 'label_values(metric, resource)', ctx.timeSrv); + pm.process().then(function(data) { results = data; }); + ctx.$httpBackend.flush(); + ctx.$rootScope.$apply(); + }); it('label_values(metric{label1="foo", label2="bar", label3="baz"}, resource) should generate series query', function() { response = { status: "success", @@ -59,8 +68,8 @@ describe('PrometheusMetricFindQuery', function() { {__name__: "metric", resource: "value3"} ] }; - ctx.$httpBackend.expect('GET', 'proxied/api/v1/series?match[]=metric').respond(response); - var pm = new PrometheusMetricFindQuery(ctx.ds, 'label_values(metric, resource)'); + ctx.$httpBackend.expect('GET', /proxied\/api\/v1\/series\?match\[\]=metric&start=.*&end=.*/).respond(response); + var pm = new PrometheusMetricFindQuery(ctx.ds, 'label_values(metric, resource)', ctx.timeSrv); pm.process().then(function(data) { results = data; }); ctx.$httpBackend.flush(); ctx.$rootScope.$apply(); @@ -72,7 +81,7 @@ describe('PrometheusMetricFindQuery', function() { data: ["metric1","metric2","metric3","nomatch"] }; ctx.$httpBackend.expect('GET', 'proxied/api/v1/label/__name__/values').respond(response); - var pm = new PrometheusMetricFindQuery(ctx.ds, 'metrics(metric.*)'); + var pm = new PrometheusMetricFindQuery(ctx.ds, 'metrics(metric.*)', ctx.timeSrv); pm.process().then(function(data) { results = data; }); ctx.$httpBackend.flush(); ctx.$rootScope.$apply(); @@ -90,7 +99,7 @@ describe('PrometheusMetricFindQuery', function() { } }; ctx.$httpBackend.expect('GET', /proxied\/api\/v1\/query\?query=metric&time=.*/).respond(response); - var pm = new PrometheusMetricFindQuery(ctx.ds, 'query_result(metric)'); + var pm = new PrometheusMetricFindQuery(ctx.ds, 'query_result(metric)', ctx.timeSrv); pm.process().then(function(data) { results = data; }); ctx.$httpBackend.flush(); ctx.$rootScope.$apply(); diff --git a/public/test/specs/helpers.js b/public/test/specs/helpers.js index ba75a4ebf51..7b64e18175d 100644 --- a/public/test/specs/helpers.js +++ b/public/test/specs/helpers.js @@ -138,6 +138,10 @@ define([ this.replace = function(target) { return target; }; + + this.setTime = function(time) { + this.time = time; + }; } function ContextSrvStub() { From a86d2188912f6dd1772d346fb3dc75af1d6b08d0 Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanda Date: Wed, 18 May 2016 16:36:57 +0900 Subject: [PATCH 16/26] (prometheus) fix metric find query --- public/app/plugins/datasource/prometheus/datasource.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/plugins/datasource/prometheus/datasource.ts b/public/app/plugins/datasource/prometheus/datasource.ts index d4d4ff8ff83..be1f54f7a86 100644 --- a/public/app/plugins/datasource/prometheus/datasource.ts +++ b/public/app/plugins/datasource/prometheus/datasource.ts @@ -140,7 +140,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS var interpolated; try { - interpolated = templateSrv.replace(query); + interpolated = templateSrv.replace(query, {}, this.interpolateQueryExpr); } catch (err) { return $q.reject(err); } From 0cd2e150d51cbdb00aa97a641c602bbbfc624f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 18 May 2016 11:50:40 +0200 Subject: [PATCH 17/26] feat(snapshots): performance improvements to deep clone, makes snapshot's a lot quicker for big dashboards with a lot of panels and data --- package.json | 2 +- public/app/features/dashboard/dashboardSrv.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e4bb7adaba0..9dbff96c2b8 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "zone.js": "^0.6.6", "autoprefixer": "^6.3.3", "es6-promise": "^3.0.2", - "es6-shim": "^0.35.0", + "es6-shim": "^0.35.1", "expect.js": "~0.2.0", "glob": "~3.2.7", "grunt": "~0.4.0", diff --git a/public/app/features/dashboard/dashboardSrv.js b/public/app/features/dashboard/dashboardSrv.js index 2e1cd1acbf0..a4ae7b31468 100644 --- a/public/app/features/dashboard/dashboardSrv.js +++ b/public/app/features/dashboard/dashboardSrv.js @@ -65,7 +65,7 @@ function (angular, $, _, moment) { // cleans meta data and other non peristent state p.getSaveModelClone = function() { - var copy = angular.copy(this); + var copy = $.extend(true, {}, this); delete copy.meta; return copy; }; From cd80884b76ed5467d0bdbb88107fde03d855f3d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 18 May 2016 12:01:11 +0200 Subject: [PATCH 18/26] fix(dashboard timepicker): fixed issue with time picker and UTC when reading time from url, fixes #5078 --- public/app/features/dashboard/timeSrv.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/features/dashboard/timeSrv.js b/public/app/features/dashboard/timeSrv.js index 13f5ad07bab..cd52155ff5f 100644 --- a/public/app/features/dashboard/timeSrv.js +++ b/public/app/features/dashboard/timeSrv.js @@ -50,7 +50,7 @@ define([ if (!isNaN(value)) { var epoch = parseInt(value); - return moment(epoch); + return moment.utc(epoch); } return null; From c41e3dcb916f16554271df0aaa223e17f4b81a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 18 May 2016 12:04:37 +0200 Subject: [PATCH 19/26] updated changelog --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d37e5ba9e1e..5321c2cd552 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,10 @@ * **Graph**: Adds sort order options for graph tooltip, closes [#1189](https://github.com/grafana/grafana/issues/1189) * **Theme**: Add default theme to config file [#5011](https://github.com/grafana/grafana/pull/5011) -# 3.0.2 Stable (2016-05-16) +# 3.0.3 Patch release (unreleased) +* **Time picker**: Fixed issue timepicker and UTC when reading time from URL, fixes [#5078](https://github.com/grafana/grafana/issues/5078) + +# 3.0.2 Patch release (2016-05-16) * **Templating**: Fixed issue mixing row repeat and panel repeats, fixes [#4988](https://github.com/grafana/grafana/issues/4988) * **Templating**: Fixed issue detecting dependencies in nested variables, fixes [#4987](https://github.com/grafana/grafana/issues/4987), fixes [#4986](https://github.com/grafana/grafana/issues/4986) From 92ac3704155bb70a8557186864f8c64bd6094fbc Mon Sep 17 00:00:00 2001 From: bergquist Date: Wed, 18 May 2016 12:28:45 +0200 Subject: [PATCH 20/26] tech(docker): rename fake data writers --- docker/blocks/graphite/fig | 2 +- docker/blocks/influxdb/fig | 2 +- docker/blocks/opentsdb/fig | 2 +- docker/blocks/prometheus/fig | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docker/blocks/graphite/fig b/docker/blocks/graphite/fig index 4268641d32f..60acb8c1131 100644 --- a/docker/blocks/graphite/fig +++ b/docker/blocks/graphite/fig @@ -8,7 +8,7 @@ graphite: - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro -fake-data-gen: +fake-graphite-data: image: grafana/fake-data-gen net: bridge environment: diff --git a/docker/blocks/influxdb/fig b/docker/blocks/influxdb/fig index 0dc69cb6b72..bdb4a274634 100644 --- a/docker/blocks/influxdb/fig +++ b/docker/blocks/influxdb/fig @@ -5,7 +5,7 @@ influxdb: - "8083:8083" - "8086:8086" -fake-data-gen: +fake-influxdb-data: image: grafana/fake-data-gen net: bridge environment: diff --git a/docker/blocks/opentsdb/fig b/docker/blocks/opentsdb/fig index 705d746a864..c346475e9a3 100644 --- a/docker/blocks/opentsdb/fig +++ b/docker/blocks/opentsdb/fig @@ -3,7 +3,7 @@ opentsdb: ports: - "4242:4242" -fake-data-gen: +fake-opentsdb-data: image: grafana/fake-data-gen net: bridge environment: diff --git a/docker/blocks/prometheus/fig b/docker/blocks/prometheus/fig index aa00e1b6272..ecfcf395d26 100644 --- a/docker/blocks/prometheus/fig +++ b/docker/blocks/prometheus/fig @@ -6,7 +6,7 @@ prometheus: volumes: - /var/docker/prometheus:/prometheus-data -fake-data-gen: +fake-prometheus-data: image: grafana/fake-data-gen net: bridge ports: From 392cb2a7148d12ef24d404d6e7b1f3e82769a29e Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanda Date: Wed, 18 May 2016 20:27:19 +0900 Subject: [PATCH 21/26] (cloudwatch) update changelog (#5080) * update cloudwatch.md * update changelog --- CHANGELOG.md | 1 + docs/sources/datasources/cloudwatch.md | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5321c2cd552..bf074487057 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ # 3.0.3 Patch release (unreleased) * **Time picker**: Fixed issue timepicker and UTC when reading time from URL, fixes [#5078](https://github.com/grafana/grafana/issues/5078) +* **CloudWatch**: Support for Multiple Account by AssumeRole, closes [#3522](https://github.com/grafana/grafana/issues/3522) # 3.0.2 Patch release (2016-05-16) diff --git a/docs/sources/datasources/cloudwatch.md b/docs/sources/datasources/cloudwatch.md index c69d3579784..a3b6a3ba61f 100644 --- a/docs/sources/datasources/cloudwatch.md +++ b/docs/sources/datasources/cloudwatch.md @@ -26,6 +26,8 @@ Name | The data source name, important that this is the same as in Grafana v1.x Default | Default data source means that it will be pre-selected for new panels. Credentials profile name | Specify the name of the profile to use (if you use `~/aws/credentials` file), leave blank for default. This option was introduced in Grafana 2.5.1 Default Region | Used in query editor to set region (can be changed on per query basis) +Custom Metrics namespace | Specify the CloudWatch namespace of Custom metrics +Assume Role Arn | Specify the ARN of the role to assume ## Authentication From d474eba53a4766e8992abc223f9ffad7452950d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 18 May 2016 14:18:08 +0200 Subject: [PATCH 22/26] fix(logging): fixed reading config level from config file, fixes #5079 --- pkg/setting/setting.go | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 2d1bad945eb..8494b8112b7 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -526,6 +526,17 @@ var logLevels = map[string]int{ "Critical": 5, } +func getLogLevel(key string, defaultName string) (string, int) { + levelName := Cfg.Section(key).Key("level").In(defaultName, []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"}) + + level, ok := logLevels[levelName] + if !ok { + log.Fatal(4, "Unknown log level: %s", levelName) + } + + return levelName, level +} + func initLogging(args *CommandLineArgs) { //close any existing log handlers. log.Close() @@ -533,8 +544,12 @@ func initLogging(args *CommandLineArgs) { LogModes = strings.Split(Cfg.Section("log").Key("mode").MustString("console"), ",") LogsPath = makeAbsolute(Cfg.Section("paths").Key("logs").String(), HomePath) + defaultLevelName, _ := getLogLevel("log", "Info") + LogConfigs = make([]util.DynMap, len(LogModes)) + for i, mode := range LogModes { + mode = strings.TrimSpace(mode) sec, err := Cfg.GetSection("log." + mode) if err != nil { @@ -542,12 +557,7 @@ func initLogging(args *CommandLineArgs) { } // Log level. - levelName := Cfg.Section("log."+mode).Key("level").In("Trace", - []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"}) - level, ok := logLevels[levelName] - if !ok { - log.Fatal(4, "Unknown log level: %s", levelName) - } + _, level := getLogLevel("log."+mode, defaultLevelName) // Generate log configuration. switch mode { From 10339090b80b80fc07f2670971efae13ea71c794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 18 May 2016 15:22:40 +0200 Subject: [PATCH 23/26] fix(annotations): fixed annotation error handling, fixes #5077 --- public/app/features/annotations/annotations_srv.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/public/app/features/annotations/annotations_srv.js b/public/app/features/annotations/annotations_srv.js index b0022135ef5..a693dd602c8 100644 --- a/public/app/features/annotations/annotations_srv.js +++ b/public/app/features/annotations/annotations_srv.js @@ -55,10 +55,11 @@ define([ }, this); }); - promiseCached = $q.all(promises) - .then(function() { - return list; - }); + promiseCached = $q.all(promises).then(function() { + return list; + }).catch(function(err) { + $rootScope.appEvent('alert-error', ['Annotations failed', (err.message || err)]); + }); return promiseCached; }; From 24a410ae8f441fcf0310a9ce7a190451d2698bfd Mon Sep 17 00:00:00 2001 From: Tim Bielawa Date: Wed, 18 May 2016 12:31:59 -0400 Subject: [PATCH 24/26] docs(preferences): Document user and org preferences (#5087) closes #5069 --- docs/sources/http_api/overview.md | 1 + docs/sources/http_api/preferences.md | 100 +++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 docs/sources/http_api/preferences.md diff --git a/docs/sources/http_api/overview.md b/docs/sources/http_api/overview.md index 8e7e2d60ad3..7f5a3ecfac8 100644 --- a/docs/sources/http_api/overview.md +++ b/docs/sources/http_api/overview.md @@ -18,4 +18,5 @@ dashboards, creating users and updating data sources. * [User API](/http_api/user/) * [Admin API](/http_api/admin/) * [Snapshot API](/http_api/snapshot/) +* [Preferences API](/http_api/preferences/) * [Other API](/http_api/other/) diff --git a/docs/sources/http_api/preferences.md b/docs/sources/http_api/preferences.md new file mode 100644 index 00000000000..6bb00ed8132 --- /dev/null +++ b/docs/sources/http_api/preferences.md @@ -0,0 +1,100 @@ +---- +page_title: Preferences API +page_description: Grafana Preferences API Reference +page_keywords: grafana, preferences, http, api, documentation +--- + +# User and Org Preferences API + +Keys: + +- **theme** - One of: ``light``, ``dark``, or an empty string for the default theme +- **homeDashboardId** - The numerical ``:id`` of a favorited dashboard, default: ``0`` +- **timezone** - One of: ``utc``, ``browser``, or an empty string for the default + +Omitting a key will cause the current value to be replaced with the +system default value. + +## Get Current User Prefs + +`GET /api/user/preferences` + +**Example Request**: + + GET /api/user/preferences HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + +**Example Response**: + + HTTP/1.1 200 + Content-Type: application/json + + {"theme":"","homeDashboardId":0,"timezone":""} + +## Update Current User Prefs + +`PUT /api/user/preferences` + +**Example Request**: + + PUT /api/user/preferences HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + + { + "theme": "", + "homeDashboardId":0, + "timezone":"utc" + } + +**Example Response**: + + HTTP/1.1 200 + Content-Type: text/plain; charset=utf-8 + + {"message":"Preferences updated"} + +## Get Current Org Prefs + +`GET /api/org/preferences` + +**Example Request**: + + GET /api/org/preferences HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + +**Example Response**: + + HTTP/1.1 200 + Content-Type: application/json + + {"theme":"","homeDashboardId":0,"timezone":""} + +## Update Current Org Prefs + +`PUT /api/org/preferences` + +**Example Request**: + + PUT /api/org/preferences HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + + { + "theme": "", + "homeDashboardId":0, + "timezone":"utc" + } + +**Example Response**: + + HTTP/1.1 200 + Content-Type: text/plain; charset=utf-8 + + {"message":"Preferences updated"} From 1bb4ca22e7542d0e2600de9464d7b5020ba85e32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 19 May 2016 07:58:44 +0200 Subject: [PATCH 25/26] fix(test): fixed failing unsaved changes test --- public/app/core/utils/datemath.ts | 2 +- public/test/specs/unsavedChangesSrv-specs.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/public/app/core/utils/datemath.ts b/public/app/core/utils/datemath.ts index b66325c71a8..467d3750c9a 100644 --- a/public/app/core/utils/datemath.ts +++ b/public/app/core/utils/datemath.ts @@ -28,7 +28,7 @@ export function parse(text, roundUp?) { mathString = text.substring(index + 2); } // We're going to just require ISO8601 timestamps, k? - time = moment(parseString); + time = moment(parseString, moment.ISO_8601); } if (!mathString.length) { diff --git a/public/test/specs/unsavedChangesSrv-specs.js b/public/test/specs/unsavedChangesSrv-specs.js index af88ff77ea6..ddbbb557055 100644 --- a/public/test/specs/unsavedChangesSrv-specs.js +++ b/public/test/specs/unsavedChangesSrv-specs.js @@ -29,6 +29,7 @@ define([ beforeEach(function() { dash = _dashboardSrv.create({ + refresh: false, rows: [ { panels: [{ test: "asd", legend: { } }] From 2b06ceda711fd61ccbbc61201bd49ec0a7aea113 Mon Sep 17 00:00:00 2001 From: bergquist Date: Thu, 19 May 2016 08:00:48 +0200 Subject: [PATCH 26/26] feat(panels): adds queryparameter for choose active tab in edit mode --- public/app/features/panel/panel_ctrl.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/public/app/features/panel/panel_ctrl.ts b/public/app/features/panel/panel_ctrl.ts index 82e19f8681b..94de0166f61 100644 --- a/public/app/features/panel/panel_ctrl.ts +++ b/public/app/features/panel/panel_ctrl.ts @@ -90,6 +90,15 @@ export class PanelCtrl { this.addEditorTab('General', 'public/app/partials/panelgeneral.html'); this.editModeInitiated = true; this.events.emit('init-edit-mode', null); + + var route = this.$injector.get('$route'); + if (route.current.params.editorTab) { + this.editorTabs.forEach((tab, i) => { + if (tab.title === route.current.params.editorTab) { + this.editorTabIndex = i; + } + }); + } } addEditorTab(title, directiveFn, index?) {