mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'master' into getting-started-panel
This commit is contained in:
commit
2233938ba7
11
.github/ISSUE_TEMPLATE.md
vendored
11
.github/ISSUE_TEMPLATE.md
vendored
@ -1,7 +1,5 @@
|
||||
* **I'm submitting a ...**
|
||||
- [ ] Bug report
|
||||
- [ ] Feature request
|
||||
- [ ] Question / Support request: **Please do not** open a github issue. [Support Options](http://grafana.org/support/)
|
||||
Please prefix your title with [Bug] or [Feature request]
|
||||
For question please check [Support Options](http://grafana.org/support/). **Do not** open a github issue
|
||||
|
||||
Please include this information:
|
||||
- What Grafana version are you using?
|
||||
@ -11,7 +9,10 @@ Please include this information:
|
||||
- What was the expected result?
|
||||
- What happened instead?
|
||||
|
||||
**IMPORTANT** If it relates to metric data viz:
|
||||
**IMPORTANT**
|
||||
If it relates to *metric data viz*:
|
||||
- An image or text representation of your metric query
|
||||
- The raw query and response for the network request (check this in chrome dev tools network tab, here you can see metric requests and other request, please include the request body and request response)
|
||||
|
||||
If it relates to *alerting*
|
||||
- An image of the test execution data fully expanded.
|
||||
|
10
CHANGELOG.md
10
CHANGELOG.md
@ -1,9 +1,17 @@
|
||||
# 4.0-beta2 (unrelased)
|
||||
# 4.0-stable (unrelased)
|
||||
|
||||
### Bugfixes
|
||||
* **Server-side rendering**: Fixed address used when rendering panel via phantomjs and using non default http_addr config [#6660](https://github.com/grafana/grafana/issues/6660)
|
||||
* **Graph panel**: Fixed graph panel tooltip sort order issue [#6648](https://github.com/grafana/grafana/issues/6648)
|
||||
* **Unsaved changes**: You now navigate to the intended page after saving in the unsaved changes dialog [#6675](https://github.com/grafana/grafana/issues/6675)
|
||||
|
||||
# 4.0-beta2 (2016-11-21)
|
||||
|
||||
### Bugfixes
|
||||
* **Graph Panel**: Log base scale on right Y-axis had no effect, max value calc was not applied, [#6534](https://github.com/grafana/grafana/issues/6534)
|
||||
* **Graph Panel**: Bar width if bars was only used in series override, [#6528](https://github.com/grafana/grafana/issues/6528)
|
||||
* **UI/Browser**: Fixed issue with page/view header gradient border not showing in Safari, [#6530](https://github.com/grafana/grafana/issues/6530)
|
||||
* **Cloudwatch**: Fixed cloudwatch datasource requesting to many datapoints, [#6544](https://github.com/grafana/grafana/issues/6544)
|
||||
* **UX**: Panel Drop zone visible after duplicating panel, and when entering fullscreen/edit view, [#6598](https://github.com/grafana/grafana/issues/6598)
|
||||
* **Templating**: Newly added variable was not visible directly only after dashboard reload, [#6622](https://github.com/grafana/grafana/issues/6622)
|
||||
|
||||
|
@ -17,6 +17,7 @@ Graphite, Elasticsearch, OpenTSDB, Prometheus and InfluxDB.
|
||||
- [What's New in Grafana 2.1](http://docs.grafana.org/guides/whats-new-in-v2-1/)
|
||||
- [What's New in Grafana 2.5](http://docs.grafana.org/guides/whats-new-in-v2-5/)
|
||||
- [What's New in Grafana 3.0](http://docs.grafana.org/guides/whats-new-in-v3/)
|
||||
- [What's New in Grafana 4.0 Beta](http://docs.grafana.org/guides/whats-new-in-v4/)
|
||||
|
||||
## Features
|
||||
### Graphite Target Editor
|
||||
|
@ -116,7 +116,7 @@ the hosts variable only show hosts from the current selected region with a query
|
||||
SHOW TAG VALUES WITH KEY = "hostname" WHERE region =~ /$region/
|
||||
```
|
||||
|
||||
> Always you `regex values` or `regex wildcard` for All format or multi select format.
|
||||
> Always use `regex values` or `regex wildcard` for All format or multi select format.
|
||||
|
||||

|
||||
|
||||
|
@ -29,7 +29,7 @@ Each Organization can have one or more Data Sources.
|
||||
|
||||
All Dashboards are owned by a particular Organization.
|
||||
|
||||
> Note: It is important to remember that most metric databases to not provide any sort of per-user series authentication. Therefore, in Grafana, Data Sources and Dashboards are available to all Users in a particular Organization.
|
||||
> Note: It is important to remember that most metric databases do not provide any sort of per-user series authentication. Therefore, in Grafana, Data Sources and Dashboards are available to all Users in a particular Organization.
|
||||
|
||||
For more details on the user model for Grafana, please refer to [Admin](/reference/admin/)
|
||||
|
||||
|
@ -1,8 +1,13 @@
|
||||
----
|
||||
page_title: Admin APIs
|
||||
page_description: Grafana Admin API Reference
|
||||
page_keywords: grafana, admin, http, api, documentation
|
||||
---
|
||||
+++
|
||||
title = "Admin HTTP API "
|
||||
description = "Grafana Admin HTTP API"
|
||||
keywords = ["grafana", "http", "documentation", "api", "admin"]
|
||||
aliases = ["/http_api/admin/"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Admin"
|
||||
parent = "http_api"
|
||||
+++
|
||||
|
||||
# Admin API
|
||||
|
||||
|
@ -1,8 +1,13 @@
|
||||
----
|
||||
page_title: Authentication API
|
||||
page_description: Grafana HTTP API Reference
|
||||
page_keywords: grafana, admin, http, api, documentation
|
||||
---
|
||||
+++
|
||||
title = "Authentication HTTP API "
|
||||
description = "Grafana Authentication HTTP API"
|
||||
keywords = ["grafana", "http", "documentation", "api", "authentication"]
|
||||
aliases = ["/http_api/authentication/"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Authentication"
|
||||
parent = "http_api"
|
||||
+++
|
||||
|
||||
# Authentication API
|
||||
|
||||
|
@ -1,8 +1,13 @@
|
||||
----
|
||||
page_title: Dashboard API
|
||||
page_description: Grafana Dashboard API Reference
|
||||
page_keywords: grafana, admin, http, api, documentation, dashboard
|
||||
---
|
||||
+++
|
||||
title = "Dashboard HTTP API "
|
||||
description = "Grafana Dashboard HTTP API"
|
||||
keywords = ["grafana", "http", "documentation", "api", "dashboard"]
|
||||
aliases = ["/http_api/dashboard/"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Dashboard"
|
||||
parent = "http_api"
|
||||
+++
|
||||
|
||||
# Dashboard API
|
||||
|
||||
|
@ -1,8 +1,14 @@
|
||||
----
|
||||
page_title: Data source API
|
||||
page_description: Grafana Data source API Reference
|
||||
page_keywords: grafana, admin, http, api, documentation, datasource
|
||||
---
|
||||
+++
|
||||
title = "Data source HTTP API "
|
||||
description = "Grafana Data source HTTP API"
|
||||
keywords = ["grafana", "http", "documentation", "api", "data source"]
|
||||
aliases = ["/http_api/datasource/"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Data source"
|
||||
parent = "http_api"
|
||||
+++
|
||||
|
||||
|
||||
# Data source API
|
||||
|
||||
|
@ -1,8 +1,14 @@
|
||||
----
|
||||
page_title: Organisation API
|
||||
page_description: Grafana Organisation API Reference
|
||||
page_keywords: grafana, admin, http, api, documentation, orgs, organisation
|
||||
---
|
||||
+++
|
||||
title = "Organisation HTTP API "
|
||||
description = "Grafana Organisation HTTP API"
|
||||
keywords = ["grafana", "http", "documentation", "api", "organisation"]
|
||||
aliases = ["/http_api/organisation/"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Organisation"
|
||||
parent = "http_api"
|
||||
+++
|
||||
|
||||
|
||||
# Organisation API
|
||||
|
||||
|
@ -1,8 +1,14 @@
|
||||
----
|
||||
page_title: Other APIs
|
||||
page_description: Grafana Other API Reference
|
||||
page_keywords: grafana, admin, http, api, documentation, dashboards
|
||||
---
|
||||
+++
|
||||
title = "Other HTTP API "
|
||||
description = "Grafana Other HTTP API"
|
||||
keywords = ["grafana", "http", "documentation", "api", "other"]
|
||||
aliases = ["/http_api/other/"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Other"
|
||||
parent = "http_api"
|
||||
+++
|
||||
|
||||
|
||||
# Frontend Settings API
|
||||
|
||||
|
@ -1,15 +1,21 @@
|
||||
----
|
||||
page_title: HTTP API
|
||||
page_description: Grafana HTTP API Reference
|
||||
page_keywords: grafana, admin, http, api, documentation
|
||||
---
|
||||
+++
|
||||
title = "HTTP API "
|
||||
description = "Grafana HTTP API"
|
||||
keywords = ["grafana", "http", "documentation", "api", "overview"]
|
||||
aliases = ["/http_api/overview/"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Overview"
|
||||
parent = "http_api"
|
||||
+++
|
||||
|
||||
|
||||
# HTTP API Reference
|
||||
|
||||
The Grafana backend exposes an HTTP API, the same API is used by the frontend to do everything from saving
|
||||
dashboards, creating users and updating data sources.
|
||||
|
||||
###Supported HTTP APIs:
|
||||
## Supported HTTP APIs:
|
||||
|
||||
* [Authentication API](/http_api/auth/)
|
||||
* [Dashboard API](/http_api/dashboard/)
|
||||
|
@ -1,8 +1,13 @@
|
||||
----
|
||||
page_title: Preferences API
|
||||
page_description: Grafana Preferences API Reference
|
||||
page_keywords: grafana, preferences, http, api, documentation
|
||||
---
|
||||
+++
|
||||
title = "HTTP Preferences API "
|
||||
description = "Grafana HTTP API"
|
||||
keywords = ["grafana", "http", "documentation", "api", "preferences"]
|
||||
aliases = ["/http_api/preferences/"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Preferences"
|
||||
parent = "http_api"
|
||||
+++
|
||||
|
||||
# User and Org Preferences API
|
||||
|
||||
|
@ -1,8 +1,13 @@
|
||||
----
|
||||
page_title: Snapshot API
|
||||
page_description: Grafana Snapshot API Reference
|
||||
page_keywords: grafana, admin, http, api, documentation, snapshot, dashboard
|
||||
---
|
||||
+++
|
||||
title = "HTTP Snapshot API "
|
||||
description = "Grafana HTTP API"
|
||||
keywords = ["grafana", "http", "documentation", "api", "snapshot"]
|
||||
aliases = ["/http_api/snapshot/"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Snapshot"
|
||||
parent = "http_api"
|
||||
+++
|
||||
|
||||
# Snapshot API
|
||||
|
||||
|
@ -15,7 +15,7 @@ weight = 1
|
||||
Description | Download
|
||||
------------ | -------------
|
||||
Stable for Debian-based Linux | [3.1.1 (x86-64 deb)](https://grafanarel.s3.amazonaws.com/builds/grafana_3.1.1-1470047149_amd64.deb)
|
||||
Latest Beta for Debian-based Linux | [4.0.0-beta1 (x86-64 deb)](https://grafanarel.s3.amazonaws.com/builds/grafana_4.0.0-1478693311beta1_amd64.deb)
|
||||
Latest Beta for Debian-based Linux | [4.0.0-beta2 (x86-64 deb)](https://grafanarel.s3.amazonaws.com/builds/grafana_4.0.0-1479719016beta2_amd64.deb)
|
||||
|
||||
## Install Stable
|
||||
|
||||
@ -27,9 +27,9 @@ $ sudo dpkg -i grafana_3.1.1-1470047149_amd64.deb
|
||||
|
||||
## Install Latest Beta
|
||||
|
||||
$ wget https://grafanarel.s3.amazonaws.com/builds/grafana_4.0.0-1478693311beta1_amd64.deb
|
||||
$ wget https://grafanarel.s3.amazonaws.com/builds/grafana_4.0.0-1479719016beta2_amd64.deb
|
||||
$ sudo apt-get install -y adduser libfontconfig
|
||||
$ sudo dpkg -i grafana_4.0.0-1478693311beta1_amd64.deb
|
||||
$ sudo dpkg -i grafana_4.0.0-1479719016beta2_amd64.deb
|
||||
|
||||
## APT Repository
|
||||
|
||||
@ -139,5 +139,3 @@ To configure Grafana add a configuration file named `custom.ini` to the
|
||||
Start Grafana by executing `./bin/grafana-server web`. The `grafana-server`
|
||||
binary needs the working directory to be the root install directory (where the
|
||||
binary and the `public` folder is located).
|
||||
|
||||
|
||||
|
@ -15,7 +15,7 @@ weight = 2
|
||||
Description | Download
|
||||
------------ | -------------
|
||||
Stable for CentOS / Fedora / OpenSuse / Redhat Linux | [3.1.1 (x86-64 rpm)](https://grafanarel.s3.amazonaws.com/builds/grafana-3.1.1-1470047149.x86_64.rpm)
|
||||
Latest Beta for CentOS / Fedora / OpenSuse / Redhat Linux | [4.0.0-beta1 (x86-64 rpm)](https://grafanarel.s3.amazonaws.com/builds/grafana-4.0.0-1478693311beta1.x86_64.rpm)
|
||||
Latest Beta for CentOS / Fedora / OpenSuse / Redhat Linux | [4.0.0-beta2 (x86-64 rpm)](https://grafanarel.s3.amazonaws.com/builds/grafana-4.0.0-1479719016beta2.x86_64.rpm)
|
||||
|
||||
## Install Stable
|
||||
|
||||
@ -36,18 +36,18 @@ Or install manually using `rpm`.
|
||||
|
||||
## Or Install Latest Beta
|
||||
|
||||
$ sudo yum install https://grafanarel.s3.amazonaws.com/builds/grafana-4.0.0-1478693311beta1.x86_64.rpm
|
||||
$ sudo yum install https://grafanarel.s3.amazonaws.com/builds/grafana-4.0.0-1479719016beta2.x86_64.rpm
|
||||
|
||||
Or install manually using `rpm`.
|
||||
|
||||
#### On CentOS / Fedora / Redhat:
|
||||
|
||||
$ sudo yum install initscripts fontconfig
|
||||
$ sudo rpm -Uvh grafana-4.0.0-1478693311beta1.x86_64.rpm
|
||||
$ sudo rpm -Uvh grafana-4.0.0-1479719016beta2.x86_64.rpm
|
||||
|
||||
#### On OpenSuse:
|
||||
|
||||
$ sudo rpm -i --nodeps grafana-4.0.0-1478693311beta1.x86_64.rpm
|
||||
$ sudo rpm -i --nodeps grafana-4.0.0-1479719016beta2.x86_64.rpm
|
||||
|
||||
## Install via YUM Repository
|
||||
|
||||
|
@ -13,8 +13,8 @@ weight = 3
|
||||
|
||||
Description | Download
|
||||
------------ | -------------
|
||||
Latest stable package for Windows | [grafana.3.1.1.windows-x64.zip](https://grafanarel.s3.amazonaws.com/winbuilds/dist/grafana-3.1.1.windows-x64.zip)
|
||||
Latest beta package for Windows | [grafana.4.0.0-beta1.windows-x64.zip](https://grafanarel.s3.amazonaws.com/builds/grafana-4.0.0-beta1.windows-x64.zip)
|
||||
Latest stable package for Windows | [grafana.3.1.1.windows-x64.zip](https://grafanarel.s3.amazonaws.com/builds/grafana-3.1.1.windows-x64.zip)
|
||||
Latest beta package for Windows | [grafana.4.0.0-beta2.windows-x64.zip](https://grafanarel.s3.amazonaws.com/builds/grafana-4.0.0-beta2.windows-x64.zip)
|
||||
|
||||
|
||||
## Configure
|
||||
|
@ -4,7 +4,7 @@
|
||||
"company": "Coding Instinct AB"
|
||||
},
|
||||
"name": "grafana",
|
||||
"version": "4.0.0-beta1",
|
||||
"version": "4.0.0-beta2",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/grafana/grafana.git"
|
||||
|
@ -103,6 +103,10 @@ func GetAlerts(c *middleware.Context) Response {
|
||||
|
||||
// POST /api/alerts/test
|
||||
func AlertTest(c *middleware.Context, dto dtos.AlertTestCommand) Response {
|
||||
if _, idErr := dto.Dashboard.Get("id").Int64(); idErr != nil {
|
||||
return ApiError(400, "The dashboard needs to be saved at least once before you can test an alert rule", nil)
|
||||
}
|
||||
|
||||
backendCmd := alerting.AlertTestCommand{
|
||||
OrgId: c.OrgId,
|
||||
Dashboard: dto.Dashboard,
|
||||
|
@ -131,6 +131,16 @@ func PostDashboard(c *middleware.Context, cmd m.SaveDashboardCommand) Response {
|
||||
}
|
||||
}
|
||||
|
||||
validateAlertsCmd := alerting.ValidateDashboardAlertsCommand{
|
||||
OrgId: c.OrgId,
|
||||
UserId: c.UserId,
|
||||
Dashboard: dash,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&validateAlertsCmd); err != nil {
|
||||
return ApiError(500, "Invalid alert data. Cannot save dashboard", err)
|
||||
}
|
||||
|
||||
err := bus.Dispatch(&cmd)
|
||||
if err != nil {
|
||||
if err == m.ErrDashboardWithSameNameExists {
|
||||
|
@ -38,6 +38,9 @@ func addOrgUserHelper(cmd m.AddOrgUserCommand) Response {
|
||||
cmd.UserId = userToAdd.Id
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if err == m.ErrOrgUserAlreadyAdded {
|
||||
return ApiError(409, "User is already member of this organization", nil)
|
||||
}
|
||||
return ApiError(500, "Could not add user to organization", err)
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,12 @@ func RenderToPng(params *RenderOpts) (string, error) {
|
||||
executable = executable + ".exe"
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s://localhost:%s/%s", setting.Protocol, setting.HttpPort, params.Path)
|
||||
localAddress := "localhost"
|
||||
if setting.HttpAddr != setting.DEFAULT_HTTP_ADDR {
|
||||
localAddress = setting.HttpAddr
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s://%s:%s/%s", setting.Protocol, localAddress, setting.HttpPort, params.Path)
|
||||
|
||||
binPath, _ := filepath.Abs(filepath.Join(setting.PhantomDir, executable))
|
||||
scriptPath, _ := filepath.Abs(filepath.Join(setting.PhantomDir, "render.js"))
|
||||
|
@ -11,8 +11,25 @@ type UpdateDashboardAlertsCommand struct {
|
||||
Dashboard *m.Dashboard
|
||||
}
|
||||
|
||||
type ValidateDashboardAlertsCommand struct {
|
||||
UserId int64
|
||||
OrgId int64
|
||||
Dashboard *m.Dashboard
|
||||
}
|
||||
|
||||
func init() {
|
||||
bus.AddHandler("alerting", updateDashboardAlerts)
|
||||
bus.AddHandler("alerting", validateDashboardAlerts)
|
||||
}
|
||||
|
||||
func validateDashboardAlerts(cmd *ValidateDashboardAlertsCommand) error {
|
||||
extractor := NewDashAlertExtractor(cmd.Dashboard, cmd.OrgId)
|
||||
|
||||
if _, err := extractor.GetAlerts(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateDashboardAlerts(cmd *UpdateDashboardAlertsCommand) error {
|
||||
|
@ -3,6 +3,8 @@ package conditions
|
||||
import (
|
||||
"math"
|
||||
|
||||
"sort"
|
||||
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
"gopkg.in/guregu/null.v3"
|
||||
)
|
||||
@ -71,6 +73,24 @@ func (s *SimpleReducer) Reduce(series *tsdb.TimeSeries) null.Float {
|
||||
break
|
||||
}
|
||||
}
|
||||
case "median":
|
||||
var values []float64
|
||||
for _, v := range series.Points {
|
||||
if v[0].Valid {
|
||||
allNull = false
|
||||
values = append(values, v[0].Float64)
|
||||
}
|
||||
}
|
||||
if len(values) >= 1 {
|
||||
sort.Float64s(values)
|
||||
length := len(values)
|
||||
if length%2 == 1 {
|
||||
value = values[(length-1)/2]
|
||||
} else {
|
||||
value = (values[(length/2)-1] + values[length/2]) / 2
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if allNull {
|
||||
|
@ -41,6 +41,20 @@ func TestSimpleReducer(t *testing.T) {
|
||||
So(result, ShouldEqual, float64(3000))
|
||||
})
|
||||
|
||||
Convey("median odd amount of numbers", func() {
|
||||
result := testReducer("median", 1, 2, 3000)
|
||||
So(result, ShouldEqual, float64(2))
|
||||
})
|
||||
|
||||
Convey("median even amount of numbers", func() {
|
||||
result := testReducer("median", 1, 2, 4, 3000)
|
||||
So(result, ShouldEqual, float64(3))
|
||||
})
|
||||
|
||||
Convey("median with one values", func() {
|
||||
result := testReducer("median", 1)
|
||||
So(result, ShouldEqual, float64(1))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ func NewEvalHandler() *DefaultEvalHandler {
|
||||
|
||||
func (e *DefaultEvalHandler) Eval(context *EvalContext) {
|
||||
firing := true
|
||||
noDataFound := true
|
||||
conditionEvals := ""
|
||||
|
||||
for i := 0; i < len(context.Rule.Conditions); i++ {
|
||||
@ -40,8 +41,10 @@ func (e *DefaultEvalHandler) Eval(context *EvalContext) {
|
||||
// calculating Firing based on operator
|
||||
if cr.Operator == "or" {
|
||||
firing = firing || cr.Firing
|
||||
noDataFound = noDataFound || cr.NoDataFound
|
||||
} else {
|
||||
firing = firing && cr.Firing
|
||||
noDataFound = noDataFound && cr.NoDataFound
|
||||
}
|
||||
|
||||
if i > 0 {
|
||||
@ -55,6 +58,7 @@ func (e *DefaultEvalHandler) Eval(context *EvalContext) {
|
||||
|
||||
context.ConditionEvals = conditionEvals + " = " + strconv.FormatBool(firing)
|
||||
context.Firing = firing
|
||||
context.NoDataFound = noDataFound
|
||||
context.EndTime = time.Now()
|
||||
elapsedTime := context.EndTime.Sub(context.StartTime) / time.Millisecond
|
||||
metrics.M_Alerting_Exeuction_Time.Update(elapsedTime)
|
||||
|
@ -11,10 +11,11 @@ type conditionStub struct {
|
||||
firing bool
|
||||
operator string
|
||||
matches []*EvalMatch
|
||||
noData bool
|
||||
}
|
||||
|
||||
func (c *conditionStub) Eval(context *EvalContext) (*ConditionResult, error) {
|
||||
return &ConditionResult{Firing: c.firing, EvalMatches: c.matches, Operator: c.operator}, nil
|
||||
return &ConditionResult{Firing: c.firing, EvalMatches: c.matches, Operator: c.operator, NoDataFound: c.noData}, nil
|
||||
}
|
||||
|
||||
func TestAlertingExecutor(t *testing.T) {
|
||||
@ -127,5 +128,41 @@ func TestAlertingExecutor(t *testing.T) {
|
||||
So(context.Firing, ShouldEqual, true)
|
||||
So(context.ConditionEvals, ShouldEqual, "[[true OR false] OR true] = true")
|
||||
})
|
||||
|
||||
Convey("Should return no data if one condition has nodata", func() {
|
||||
context := NewEvalContext(context.TODO(), &Rule{
|
||||
Conditions: []Condition{
|
||||
&conditionStub{operator: "and", noData: true},
|
||||
},
|
||||
})
|
||||
|
||||
handler.Eval(context)
|
||||
So(context.Firing, ShouldEqual, false)
|
||||
So(context.NoDataFound, ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("Should return no data if both conditions have no data and using AND", func() {
|
||||
context := NewEvalContext(context.TODO(), &Rule{
|
||||
Conditions: []Condition{
|
||||
&conditionStub{operator: "and", noData: true},
|
||||
&conditionStub{operator: "and", noData: false},
|
||||
},
|
||||
})
|
||||
|
||||
handler.Eval(context)
|
||||
So(context.NoDataFound, ShouldBeFalse)
|
||||
})
|
||||
|
||||
Convey("Should not return no data if both conditions have no data and using OR", func() {
|
||||
context := NewEvalContext(context.TODO(), &Rule{
|
||||
Conditions: []Condition{
|
||||
&conditionStub{operator: "or", noData: true},
|
||||
&conditionStub{operator: "or", noData: false},
|
||||
},
|
||||
})
|
||||
|
||||
handler.Eval(context)
|
||||
So(context.NoDataFound, ShouldBeTrue)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -55,10 +55,8 @@ func (n *RootNotifier) Notify(context *EvalContext) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = n.uploadImage(context)
|
||||
if err != nil {
|
||||
n.log.Error("Failed to upload alert panel image", "error", err)
|
||||
return err
|
||||
if err = n.uploadImage(context); err != nil {
|
||||
n.log.Error("Failed to upload alert panel image.", "error", err)
|
||||
}
|
||||
|
||||
return n.sendNotifications(context, notifiers)
|
||||
|
@ -24,8 +24,9 @@ import (
|
||||
type Scheme string
|
||||
|
||||
const (
|
||||
HTTP Scheme = "http"
|
||||
HTTPS Scheme = "https"
|
||||
HTTP Scheme = "http"
|
||||
HTTPS Scheme = "https"
|
||||
DEFAULT_HTTP_ADDR string = "0.0.0.0"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -474,7 +475,7 @@ func NewConfigContext(args *CommandLineArgs) error {
|
||||
}
|
||||
|
||||
Domain = server.Key("domain").MustString("localhost")
|
||||
HttpAddr = server.Key("http_addr").MustString("0.0.0.0")
|
||||
HttpAddr = server.Key("http_addr").MustString(DEFAULT_HTTP_ADDR)
|
||||
HttpPort = server.Key("http_port").MustString("3000")
|
||||
RouterLogging = server.Key("router_logging").MustBool(false)
|
||||
EnableGzip = server.Key("enable_gzip").MustBool(false)
|
||||
|
@ -40,6 +40,7 @@ var reducerTypes = [
|
||||
{text: 'sum()' , value: 'sum'},
|
||||
{text: 'count()', value: 'count'},
|
||||
{text: 'last()', value: 'last'},
|
||||
{text: 'median()', value: 'median'},
|
||||
];
|
||||
|
||||
var noDataModes = [
|
||||
|
@ -42,7 +42,7 @@
|
||||
<span class="gf-form-label query-keyword width-5" ng-if="$index===0">WHEN</span>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<query-part-editor class="gf-form-label query-part width-5" part="conditionModel.reducerPart" handle-event="ctrl.handleReducerPartEvent(conditionModel, $event)">
|
||||
<query-part-editor class="gf-form-label query-part width-6" part="conditionModel.reducerPart" handle-event="ctrl.handleReducerPartEvent(conditionModel, $event)">
|
||||
</query-part-editor>
|
||||
<span class="gf-form-label query-keyword">OF</span>
|
||||
</div>
|
||||
|
@ -493,8 +493,6 @@ export class DashboardModel {
|
||||
templateVariable.hide = 2;
|
||||
} else if (templateVariable.hideLabel) {
|
||||
templateVariable.hide = 1;
|
||||
} else {
|
||||
templateVariable.hide = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ export class SubmenuCtrl {
|
||||
private $location) {
|
||||
this.annotations = this.dashboard.templating.list;
|
||||
this.variables = this.variableSrv.variables;
|
||||
console.log(this.variables);
|
||||
}
|
||||
|
||||
annotationStateChanged() {
|
||||
|
@ -143,7 +143,14 @@ function(angular, _) {
|
||||
};
|
||||
|
||||
modalScope.save = function() {
|
||||
tracker.scope.$emit('save-dashboard');
|
||||
var cancel = $rootScope.$on('dashboard-saved', function() {
|
||||
cancel();
|
||||
$timeout(function() {
|
||||
tracker.goto_next();
|
||||
});
|
||||
});
|
||||
|
||||
$rootScope.$emit('save-dashboard');
|
||||
};
|
||||
|
||||
$rootScope.appEvent('show-modal', {
|
||||
|
@ -252,6 +252,7 @@ class MetricsPanelCtrl extends PanelCtrl {
|
||||
},
|
||||
complete: () => {
|
||||
console.log('panel: observer got complete');
|
||||
this.dataStream = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ export class VariableEditorCtrl {
|
||||
};
|
||||
|
||||
$scope.duplicate = function(variable) {
|
||||
var clone = _.cloneDeep(variable.getModel());
|
||||
var clone = _.cloneDeep(variable.getSaveModel());
|
||||
$scope.current = variableSrv.createVariableFromModel(clone);
|
||||
$scope.variables.push($scope.current);
|
||||
$scope.current.name = 'copy_of_'+variable.name;
|
||||
|
@ -22,7 +22,7 @@ function ($) {
|
||||
var len = series.datapoints.points.length;
|
||||
for (var j = initial; j < len; j += ps) {
|
||||
// Special case of a non stepped line, highlight the very last point just before a null point
|
||||
if ((series.datapoints.points[initial] != null && series.datapoints.points[j] == null && ! series.lines.steps)
|
||||
if ((!series.lines.steps && series.datapoints.points[initial] != null && series.datapoints.points[j] == null)
|
||||
//normal case
|
||||
|| series.datapoints.points[j] > posX) {
|
||||
return Math.max(j - ps, 0)/ps;
|
||||
@ -41,15 +41,17 @@ function ($) {
|
||||
return j - 1;
|
||||
};
|
||||
|
||||
this.showTooltip = function(absoluteTime, innerHtml, pos) {
|
||||
var body = '<div class="graph-tooltip-time">'+ absoluteTime + '</div>';
|
||||
body += innerHtml + '</div>';
|
||||
$tooltip.html(body).place_tt(pos.pageX + 20, pos.pageY);
|
||||
this.showTooltip = function(absoluteTime, innerHtml, pos, xMode) {
|
||||
if (xMode === 'time') {
|
||||
innerHtml = '<div class="graph-tooltip-time">'+ absoluteTime + '</div>' + innerHtml;
|
||||
}
|
||||
$tooltip.html(innerHtml).place_tt(pos.pageX + 20, pos.pageY);
|
||||
};
|
||||
|
||||
this.getMultiSeriesPlotHoverInfo = function(seriesList, pos) {
|
||||
var value, i, series, hoverIndex, hoverDistance, pointTime, yaxis;
|
||||
var results = [];
|
||||
// 3 sub-arrays, 1st for hidden series, 2nd for left yaxis, 3rd for right yaxis.
|
||||
var results = [[],[],[]];
|
||||
|
||||
//now we know the current X (j) position for X and Y values
|
||||
var last_value = 0; //needed for stacked values
|
||||
@ -60,14 +62,14 @@ function ($) {
|
||||
series = seriesList[i];
|
||||
|
||||
if (!series.data.length || (panel.legend.hideEmpty && series.allIsNull)) {
|
||||
// Init value & yaxis so that it does not brake series sorting
|
||||
results.push({ hidden: true, value: 0, yaxis: 0 });
|
||||
// Init value so that it does not brake series sorting
|
||||
results[0].push({ hidden: true, value: 0 });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!series.data.length || (panel.legend.hideZero && series.allIsZero)) {
|
||||
// Init value & yaxis so that it does not brake series sorting
|
||||
results.push({ hidden: true, value: 0, yaxis: 0 });
|
||||
// Init value so that it does not brake series sorting
|
||||
results[0].push({ hidden: true, value: 0 });
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -110,18 +112,20 @@ function ($) {
|
||||
yaxis = series.yaxis.n;
|
||||
}
|
||||
|
||||
results.push({
|
||||
results[yaxis].push({
|
||||
value: value,
|
||||
hoverIndex: hoverIndex,
|
||||
color: series.color,
|
||||
label: series.label,
|
||||
time: pointTime,
|
||||
distance: hoverDistance,
|
||||
yaxis: yaxis,
|
||||
index: i
|
||||
});
|
||||
}
|
||||
|
||||
// Contat the 3 sub-arrays
|
||||
results = results[0].concat(results[1],results[2]);
|
||||
|
||||
// Time of the point closer to pointer
|
||||
results.time = minTime;
|
||||
|
||||
@ -145,6 +149,8 @@ function ($) {
|
||||
elem.bind("plothover", function (event, pos, item) {
|
||||
var plot = elem.data().plot;
|
||||
var plotData = plot.getData();
|
||||
var xAxes = plot.getXAxes();
|
||||
var xMode = xAxes[0].options.mode;
|
||||
var seriesList = getSeriesFn();
|
||||
var group, value, absoluteTime, hoverInfo, i, series, seriesHtml, tooltipFormat;
|
||||
|
||||
@ -172,7 +178,7 @@ function ($) {
|
||||
absoluteTime = dashboard.formatDate(seriesHoverInfo.time, tooltipFormat);
|
||||
|
||||
// Dynamically reorder the hovercard for the current time point if the
|
||||
// option is enabled, sort by yaxis by default.
|
||||
// option is enabled.
|
||||
if (panel.tooltip.sort === 2) {
|
||||
seriesHoverInfo.sort(function(a, b) {
|
||||
return b.value - a.value;
|
||||
@ -181,10 +187,6 @@ function ($) {
|
||||
seriesHoverInfo.sort(function(a, b) {
|
||||
return a.value - b.value;
|
||||
});
|
||||
} else {
|
||||
seriesHoverInfo.sort(function(a, b) {
|
||||
return a.yaxis - b.yaxis;
|
||||
});
|
||||
}
|
||||
|
||||
for (i = 0; i < seriesHoverInfo.length; i++) {
|
||||
@ -209,7 +211,7 @@ function ($) {
|
||||
plot.highlight(hoverInfo.index, hoverInfo.hoverIndex);
|
||||
}
|
||||
|
||||
self.showTooltip(absoluteTime, seriesHtml, pos);
|
||||
self.showTooltip(absoluteTime, seriesHtml, pos, xMode);
|
||||
}
|
||||
// single series tooltip
|
||||
else if (item) {
|
||||
@ -230,7 +232,7 @@ function ($) {
|
||||
|
||||
group += '<div class="graph-tooltip-value">' + value + '</div>';
|
||||
|
||||
self.showTooltip(absoluteTime, group, pos);
|
||||
self.showTooltip(absoluteTime, group, pos, xMode);
|
||||
}
|
||||
// no hit
|
||||
else {
|
||||
|
@ -25,8 +25,10 @@ var ARGS;
|
||||
// Intialize a skeleton with nothing but a rows array and service object
|
||||
dashboard = {
|
||||
rows : [],
|
||||
schemaVersion: 13,
|
||||
};
|
||||
|
||||
|
||||
// Set a title
|
||||
dashboard.title = 'Scripted and templated dash';
|
||||
|
||||
@ -39,23 +41,22 @@ dashboard.time = {
|
||||
};
|
||||
|
||||
dashboard.templating = {
|
||||
enable: true,
|
||||
list: [
|
||||
{
|
||||
name: 'test',
|
||||
query: 'apps.backend.*',
|
||||
refresh: true,
|
||||
options: [],
|
||||
current: null,
|
||||
type: 'custom'
|
||||
refresh: 1,
|
||||
type: 'query',
|
||||
datasource: null,
|
||||
hide: 2,
|
||||
},
|
||||
{
|
||||
name: 'test2',
|
||||
query: '*',
|
||||
refresh: true,
|
||||
options: [],
|
||||
current: null,
|
||||
type: 'custom'
|
||||
refresh: 1,
|
||||
type: 'query',
|
||||
datasource: null,
|
||||
hide: 2,
|
||||
}
|
||||
]
|
||||
};
|
||||
|
105
public/vendor/flot/jquery.flot.stack.js
vendored
105
public/vendor/flot/jquery.flot.stack.js
vendored
@ -72,52 +72,49 @@ charts or filled areas).
|
||||
horizontal = s.bars.horizontal,
|
||||
withbottom = ps > 2 && (horizontal ? datapoints.format[2].x : datapoints.format[2].y),
|
||||
withsteps = withlines && s.lines.steps,
|
||||
fromgap = true,
|
||||
keyOffset = horizontal ? 1 : 0,
|
||||
accumulateOffset = horizontal ? 0 : 1,
|
||||
i = 0, j = 0, l, m;
|
||||
|
||||
while (true) {
|
||||
// browse all points from the current series and from the previous series
|
||||
if (i >= points.length && j >= otherpoints.length)
|
||||
break;
|
||||
|
||||
// newpoints will replace current series with
|
||||
// as many points as different timestamps we have in the 2 (current & previous) series
|
||||
l = newpoints.length;
|
||||
px = points[i + keyOffset];
|
||||
py = points[i + accumulateOffset];
|
||||
qx = otherpoints[j + keyOffset];
|
||||
qy = otherpoints[j + accumulateOffset];
|
||||
bottom = 0;
|
||||
|
||||
if (i < points.length && px == null) {
|
||||
// let's ignore null points from current series, nothing to do with them
|
||||
i += ps;
|
||||
}
|
||||
else if (j < otherpoints.length && qx == null) {
|
||||
// let's ignore null points from previous series, nothing to do with them
|
||||
j += otherps;
|
||||
}
|
||||
else if (i >= points.length) {
|
||||
// no more points in the current series, simply take the remaining points
|
||||
// from the previous series so that next series will correctly stack
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(otherpoints[j + m]);
|
||||
bottom = qy;
|
||||
j += otherps;
|
||||
}
|
||||
else if (j >= otherpoints.length) {
|
||||
// no more points in the previous series, of course let's take
|
||||
// the remaining points from the current series
|
||||
if (i < points.length && points[i] == null) {
|
||||
// copy gaps
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
i += ps;
|
||||
}
|
||||
else if (i >= points.length) {
|
||||
// take the remaining points from the previous series
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(otherpoints[j + m]);
|
||||
if (withbottom)
|
||||
newpoints[l + 2] = otherpoints[j + accumulateOffset];
|
||||
j += otherps;
|
||||
}
|
||||
else if (j >= otherpoints.length) {
|
||||
// take the remaining points from the current series
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
i += ps;
|
||||
}
|
||||
else if (j < otherpoints.length && otherpoints[j] == null) {
|
||||
// ignore point
|
||||
j += otherps;
|
||||
}
|
||||
else {
|
||||
// next available points from current and previous series have the same timestamp
|
||||
// cases where we actually got two points
|
||||
px = points[i + keyOffset];
|
||||
py = points[i + accumulateOffset];
|
||||
qx = otherpoints[j + keyOffset];
|
||||
qy = otherpoints[j + accumulateOffset];
|
||||
bottom = 0;
|
||||
|
||||
if (px == qx) {
|
||||
// so take the point from the current series and skip the previous' one
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
|
||||
@ -127,23 +124,27 @@ charts or filled areas).
|
||||
i += ps;
|
||||
j += otherps;
|
||||
}
|
||||
// next available point with the smallest timestamp is from the previous series
|
||||
else if (px > qx) {
|
||||
// so take the point from the previous series so that next series will correctly stack
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(otherpoints[j + m]);
|
||||
|
||||
// we might be able to interpolate
|
||||
if (i > 0 && points[i - ps] != null)
|
||||
newpoints[l + accumulateOffset] += py + (points[i - ps + accumulateOffset] - py) * (qx - px) / (points[i - ps + keyOffset] - px);
|
||||
|
||||
bottom = qy;
|
||||
// take the point from the previous series so that next series will correctly stack
|
||||
if (i == 0) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(otherpoints[j + m]);
|
||||
bottom = qy;
|
||||
}
|
||||
// we got past point below, might need to
|
||||
// insert interpolated extra point
|
||||
if (i > 0 && points[i - ps] != null) {
|
||||
intery = py + (points[i - ps + accumulateOffset] - py) * (qx - px) / (points[i - ps + keyOffset] - px);
|
||||
newpoints.push(qx);
|
||||
newpoints.push(intery + qy);
|
||||
for (m = 2; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
bottom = qy;
|
||||
}
|
||||
|
||||
j += otherps;
|
||||
}
|
||||
// (px < qx) next available point with the smallest timestamp is from the current series
|
||||
else {
|
||||
// so of course let's take the point from the current series
|
||||
else { // px < qx
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
|
||||
@ -156,10 +157,22 @@ charts or filled areas).
|
||||
|
||||
i += ps;
|
||||
}
|
||||
}
|
||||
|
||||
if (l != newpoints.length && withbottom)
|
||||
newpoints[l + 2] = bottom;
|
||||
fromgap = false;
|
||||
|
||||
if (l != newpoints.length && withbottom)
|
||||
newpoints[l + 2] = bottom;
|
||||
}
|
||||
|
||||
// maintain the line steps invariant
|
||||
if (withsteps && l != newpoints.length && l > 0
|
||||
&& newpoints[l] != null
|
||||
&& newpoints[l] != newpoints[l - ps]
|
||||
&& newpoints[l + 1] != newpoints[l - ps + 1]) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints[l + ps + m] = newpoints[l + m];
|
||||
newpoints[l + 1] = newpoints[l - ps + 1];
|
||||
}
|
||||
}
|
||||
|
||||
datapoints.points = newpoints;
|
||||
|
11
vendor/github.com/aws/aws-sdk-go/.gitignore
generated
vendored
11
vendor/github.com/aws/aws-sdk-go/.gitignore
generated
vendored
@ -1,11 +0,0 @@
|
||||
dist
|
||||
/doc
|
||||
/doc-staging
|
||||
.yardoc
|
||||
Gemfile.lock
|
||||
awstesting/integration/smoke/**/importmarker__.go
|
||||
awstesting/integration/smoke/_test/
|
||||
/vendor/bin/
|
||||
/vendor/pkg/
|
||||
/vendor/src/
|
||||
/private/model/cli/gen-api/gen-api
|
14
vendor/github.com/aws/aws-sdk-go/.godoc_config
generated
vendored
14
vendor/github.com/aws/aws-sdk-go/.godoc_config
generated
vendored
@ -1,14 +0,0 @@
|
||||
{
|
||||
"PkgHandler": {
|
||||
"Pattern": "/sdk-for-go/api/",
|
||||
"StripPrefix": "/sdk-for-go/api",
|
||||
"Include": ["/src/github.com/aws/aws-sdk-go/aws", "/src/github.com/aws/aws-sdk-go/service"],
|
||||
"Exclude": ["/src/cmd", "/src/github.com/aws/aws-sdk-go/awstesting", "/src/github.com/aws/aws-sdk-go/awsmigrate"],
|
||||
"IgnoredSuffixes": ["iface"]
|
||||
},
|
||||
"Github": {
|
||||
"Tag": "master",
|
||||
"Repo": "/aws/aws-sdk-go",
|
||||
"UseGithub": true
|
||||
}
|
||||
}
|
23
vendor/github.com/aws/aws-sdk-go/.travis.yml
generated
vendored
23
vendor/github.com/aws/aws-sdk-go/.travis.yml
generated
vendored
@ -1,23 +0,0 @@
|
||||
language: go
|
||||
|
||||
sudo: false
|
||||
|
||||
go:
|
||||
- 1.4
|
||||
- 1.5
|
||||
- 1.6
|
||||
- tip
|
||||
|
||||
# Use Go 1.5's vendoring experiment for 1.5 tests. 1.4 tests will use the tip of the dependencies repo.
|
||||
env:
|
||||
- GO15VENDOREXPERIMENT=1
|
||||
|
||||
install:
|
||||
- make get-deps
|
||||
|
||||
script:
|
||||
- make unit-with-race-cover
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
7
vendor/github.com/aws/aws-sdk-go/.yardopts
generated
vendored
7
vendor/github.com/aws/aws-sdk-go/.yardopts
generated
vendored
@ -1,7 +0,0 @@
|
||||
--plugin go
|
||||
-e doc-src/plugin/plugin.rb
|
||||
-m markdown
|
||||
-o doc/api
|
||||
--title "AWS SDK for Go"
|
||||
aws/**/*.go
|
||||
service/**/*.go
|
204
vendor/github.com/aws/aws-sdk-go/CHANGELOG.md
generated
vendored
Normal file
204
vendor/github.com/aws/aws-sdk-go/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,204 @@
|
||||
Release v1.5.8 (2016-11-18)
|
||||
===
|
||||
|
||||
Service Client Updates
|
||||
---
|
||||
`service/application-autoscaling`: Updates service API and documentation
|
||||
`service/elasticmapreduce`: Updates service API and documentation
|
||||
`service/elastictranscoder`: Updates service API, documentation, and examples
|
||||
`service/gamelift`: Updates service API and documentation
|
||||
`service/lambda`: Updates service API and documentation
|
||||
|
||||
Release v1.5.7 (2016-11-18)
|
||||
===
|
||||
|
||||
Service Client Updates
|
||||
---
|
||||
`service/apigateway`: Updates service API and documentation
|
||||
`service/meteringmarketplace`: Updates service API and documentation
|
||||
`service/monitoring`: Updates service API and documentation
|
||||
`service/sqs`: Updates service API, documentation, and examples
|
||||
|
||||
Release v1.5.6 (2016-11-16)
|
||||
===
|
||||
|
||||
Service Client Updates
|
||||
---
|
||||
`service/route53`: Updates service API and documentation
|
||||
`service/servicecatalog`: Updates service API and documentation
|
||||
|
||||
Release v1.5.5 (2016-11-15)
|
||||
===
|
||||
|
||||
Service Client Updates
|
||||
---
|
||||
`service/ds`: Updates service API and documentation
|
||||
`service/elasticache`: Updates service API and documentation
|
||||
`service/kinesis`: Updates service API and documentation
|
||||
|
||||
Release v1.5.4 (2016-11-15)
|
||||
===
|
||||
|
||||
Service Client Updates
|
||||
---
|
||||
`service/cognito-idp`: Updates service API and documentation
|
||||
|
||||
Release v1.5.3 (2016-11-11)
|
||||
===
|
||||
|
||||
Service Client Updates
|
||||
---
|
||||
`service/cloudformation`: Updates service documentation and examples
|
||||
`service/logs`: Updates service API and documentation
|
||||
|
||||
Release v1.5.2 (2016-11-03)
|
||||
===
|
||||
|
||||
Service Client Updates
|
||||
---
|
||||
`service/directconnect`: Updates service API and documentation
|
||||
|
||||
Release v1.5.1 (2016-11-02)
|
||||
===
|
||||
|
||||
Service Client Updates
|
||||
---
|
||||
`service/email`: Updates service API and documentation
|
||||
|
||||
Release v1.5.0 (2016-11-01)
|
||||
===
|
||||
|
||||
Service Client Updates
|
||||
---
|
||||
`service/cloudformation`: Updates service API and documentation
|
||||
`service/ecr`: Updates service paginators
|
||||
|
||||
SDK Feature Updates
|
||||
---
|
||||
* `private/model/api`: Add generated setters for API parameters (#918)
|
||||
* Adds setters to the SDK's API parameter types, and are a convenience method that reduce the need to use `aws.String` and like utility.
|
||||
|
||||
Release v1.4.22 (2016-10-25)
|
||||
===
|
||||
|
||||
Service Client Updates
|
||||
---
|
||||
* `service/elasticloadbalancingv2`: Updates service documentation.
|
||||
* `service/autoscaling`: Updates service documentation.
|
||||
|
||||
Release v1.4.21 (2016-10-24)
|
||||
===
|
||||
|
||||
Service Client Updates
|
||||
---
|
||||
* `service/sms`: AWS Server Migration Service (SMS) is an agentless service which makes it easier and faster for you to migrate thousands of on-premises workloads to AWS. AWS SMS allows you to automate, schedule, and track incremental replications of live server volumes, making it easier for you to coordinate large-scale server migrations.
|
||||
* `service/ecs`: Updates documentation.
|
||||
|
||||
SDK Feature Updates
|
||||
---
|
||||
* `private/models/api`: Improve code generation of documentation.
|
||||
|
||||
Release v1.4.20 (2016-10-20)
|
||||
===
|
||||
|
||||
Service Client Updates
|
||||
---
|
||||
* `service/budgets`: Adds new service, AWS Budgets.
|
||||
* `service/waf`: Updates service documentation.
|
||||
|
||||
Release v1.4.19 (2016-10-18)
|
||||
===
|
||||
|
||||
Service Client Updates
|
||||
---
|
||||
* `service/cloudfront`: Updates service API and documentation.
|
||||
* Ability to use Amazon CloudFront to deliver your content both via IPv6 and IPv4 using HTTP/HTTPS.
|
||||
* `service/configservice`: Update service API and documentation.
|
||||
* `service/iot`: Updates service API and documentation.
|
||||
* `service/kinesisanalytics`: Updates service API and documentation.
|
||||
* Whenever Amazon Kinesis Analytics is not able to detect schema for the given streaming source on DiscoverInputSchema API, we would return the raw records that was sampled to detect the schema.
|
||||
* `service/rds`: Updates service API and documentation.
|
||||
* Amazon Aurora integrates with other AWS services to allow you to extend your Aurora DB cluster to utilize other capabilities in the AWS cloud. Permission to access other AWS services is granted by creating an IAM role with the necessary permissions, and then associating the role with your DB cluster.
|
||||
|
||||
SDK Feature Updates
|
||||
---
|
||||
* `service/dynamodb/dynamodbattribute`: Add UnmarshalListOfMaps #897
|
||||
* Adds support for unmarshaling a list of maps. This is useful for unmarshaling the DynamoDB AttributeValue list of maps returned by APIs like Query and Scan.
|
||||
|
||||
Release v1.4.18 (2016-10-17)
|
||||
===
|
||||
|
||||
Service Model Updates
|
||||
---
|
||||
* `service/route53`: Updates service API and documentation.
|
||||
|
||||
Release v1.4.17
|
||||
===
|
||||
|
||||
Service Model Updates
|
||||
---
|
||||
* `service/acm`: Update service API, and documentation.
|
||||
* This change allows users to import third-party SSL/TLS certificates into ACM.
|
||||
* `service/elasticbeanstalk`: Update service API, documentation, and pagination.
|
||||
* Elastic Beanstalk DescribeApplicationVersions API is being updated to support pagination.
|
||||
* `service/gamelift`: Update service API, and documentation.
|
||||
* New APIs to protect game developer resource (builds, alias, fleets, instances, game sessions and player sessions) against abuse.
|
||||
|
||||
SDK Features
|
||||
---
|
||||
* `service/s3`: Add support for accelerate with dualstack [#887](https://github.com/aws/aws-sdk-go/issues/887)
|
||||
|
||||
Release v1.4.16 (2016-10-13)
|
||||
===
|
||||
|
||||
Service Model Updates
|
||||
---
|
||||
* `service/ecr`: Update Amazon EC2 Container Registry service model
|
||||
* DescribeImages is a new api used to expose image metadata which today includes image size and image creation timestamp.
|
||||
* `service/elasticache`: Update Amazon ElastiCache service model
|
||||
* Elasticache is launching a new major engine release of Redis, 3.2 (providing stability updates and new command sets over 2.8), as well as ElasticSupport for enabling Redis Cluster in 3.2, which provides support for multiple node groups to horizontally scale data, as well as superior engine failover capabilities
|
||||
|
||||
SDK Bug Fixes
|
||||
---
|
||||
* `aws/session`: Skip shared config on read errors [#883](https://github.com/aws/aws-sdk-go/issues/883)
|
||||
* `aws/signer/v4`: Add support for URL.EscapedPath to signer [#885](https://github.com/aws/aws-sdk-go/issues/885)
|
||||
|
||||
SDK Features
|
||||
---
|
||||
* `private/model/api`: Add docs for errors to API operations [#881](https://github.com/aws/aws-sdk-go/issues/881)
|
||||
* `private/model/api`: Improve field and waiter doc strings [#879](https://github.com/aws/aws-sdk-go/issues/879)
|
||||
* `service/dynamodb/dynamodbattribute`: Allow multiple struct tag elements [#886](https://github.com/aws/aws-sdk-go/issues/886)
|
||||
* Add build tags to internal SDK tools [#880](https://github.com/aws/aws-sdk-go/issues/880)
|
||||
|
||||
Release v1.4.15 (2016-10-06)
|
||||
===
|
||||
|
||||
Service Model Updates
|
||||
---
|
||||
* `service/cognitoidentityprovider`: Update Amazon Cognito Identity Provider service model
|
||||
* `service/devicefarm`: Update AWS Device Farm documentation
|
||||
* `service/opsworks`: Update AWS OpsWorks service model
|
||||
* `service/s3`: Update Amazon Simple Storage Service model
|
||||
* `service/waf`: Update AWS WAF service model
|
||||
|
||||
SDK Bug Fixes
|
||||
---
|
||||
* `aws/request`: Fix HTTP Request Body race condition [#874](https://github.com/aws/aws-sdk-go/issues/874)
|
||||
|
||||
SDK Feature Updates
|
||||
---
|
||||
* `aws/ec2metadata`: Add support for EC2 User Data [#872](https://github.com/aws/aws-sdk-go/issues/872)
|
||||
* `aws/signer/v4`: Remove logic determining if request needs to be resigned [#876](https://github.com/aws/aws-sdk-go/issues/876)
|
||||
|
||||
Release v1.4.14 (2016-09-29)
|
||||
===
|
||||
* `service/ec2`: api, documentation, and paginators updates.
|
||||
* `service/s3`: api and documentation updates.
|
||||
|
||||
Release v1.4.13 (2016-09-27)
|
||||
===
|
||||
* `service/codepipeline`: documentation updates.
|
||||
* `service/cloudformation`: api and documentation updates.
|
||||
* `service/kms`: documentation updates.
|
||||
* `service/elasticfilesystem`: documentation updates.
|
||||
* `service/snowball`: documentation updates.
|
29
vendor/github.com/aws/aws-sdk-go/Makefile
generated
vendored
29
vendor/github.com/aws/aws-sdk-go/Makefile
generated
vendored
@ -5,10 +5,13 @@ LINTIGNORESTUTTER='service/[^/]+/(api|service)\.go:.+(and that stutters)'
|
||||
LINTIGNOREINFLECT='service/[^/]+/(api|service)\.go:.+method .+ should be '
|
||||
LINTIGNOREINFLECTS3UPLOAD='service/s3/s3manager/upload\.go:.+struct field SSEKMSKeyId should be '
|
||||
LINTIGNOREDEPS='vendor/.+\.go'
|
||||
UNIT_TEST_TAGS="example codegen"
|
||||
|
||||
SDK_WITH_VENDOR_PKGS=$(shell go list ./... | grep -v "/vendor/src")
|
||||
SDK_WITH_VENDOR_PKGS=$(shell go list -tags ${UNIT_TEST_TAGS} ./... | grep -v "/vendor/src")
|
||||
SDK_ONLY_PKGS=$(shell go list ./... | grep -v "/vendor/")
|
||||
SDK_UNIT_TEST_ONLY_PKGS=$(shell go list -tags ${UNIT_TEST_TAGS} ./... | grep -v "/vendor/")
|
||||
SDK_GO_1_4=$(shell go version | grep "go1.4")
|
||||
SDK_GO_1_5=$(shell go version | grep "go1.5")
|
||||
SDK_GO_VERSION=$(shell go version | awk '''{print $$3}''' | tr -d '''\n''')
|
||||
|
||||
all: get-deps generate unit
|
||||
@ -50,11 +53,11 @@ build:
|
||||
|
||||
unit: get-deps-tests build verify
|
||||
@echo "go test SDK and vendor packages"
|
||||
@go test -tags $(SDK_ONLY_PKGS)
|
||||
@go test -tags ${UNIT_TEST_TAGS} $(SDK_UNIT_TEST_ONLY_PKGS)
|
||||
|
||||
unit-with-race-cover: get-deps-tests build verify
|
||||
@echo "go test SDK and vendor packages"
|
||||
@go test -tags -race -cpu=1,2,4 $(SDK_ONLY_PKGS)
|
||||
@go test -tags ${UNIT_TEST_TAGS} -race -cpu=1,2,4 $(SDK_UNIT_TEST_ONLY_PKGS)
|
||||
|
||||
integration: get-deps-tests integ-custom smoke-tests performance
|
||||
|
||||
@ -101,20 +104,18 @@ verify: get-deps-verify lint vet
|
||||
|
||||
lint:
|
||||
@echo "go lint SDK and vendor packages"
|
||||
@lint=`if [ -z "${SDK_GO_1_4}" ]; then golint ./...; else echo "skipping golint"; fi`; \
|
||||
@lint=`if [ \( -z "${SDK_GO_1_4}" \) -a \( -z "${SDK_GO_1_5}" \) ]; then golint ./...; else echo "skipping golint"; fi`; \
|
||||
lint=`echo "$$lint" | grep -E -v -e ${LINTIGNOREDOT} -e ${LINTIGNOREDOC} -e ${LINTIGNORECONST} -e ${LINTIGNORESTUTTER} -e ${LINTIGNOREINFLECT} -e ${LINTIGNOREDEPS} -e ${LINTIGNOREINFLECTS3UPLOAD}`; \
|
||||
echo "$$lint"; \
|
||||
if [ "$$lint" != "" ] && [ "$$lint" != "skipping golint" ]; then exit 1; fi
|
||||
|
||||
SDK_BASE_FOLDERS=$(shell ls -d */ | grep -v vendor | grep -v awsmigrate)
|
||||
ifneq (,$(findstring go1.5, ${SDK_GO_VERSION}))
|
||||
GO_VET_CMD=go tool vet --all -shadow
|
||||
ifneq (,$(findstring go1.4, ${SDK_GO_VERSION}))
|
||||
GO_VET_CMD=echo skipping go vet, ${SDK_GO_VERSION}
|
||||
else ifneq (,$(findstring go1.6, ${SDK_GO_VERSION}))
|
||||
GO_VET_CMD=go tool vet --all -shadow -example=false
|
||||
else ifneq (,$(findstring devel, ${SDK_GO_VERSION}))
|
||||
GO_VET_CMD=go tool vet --all -shadow -tests=false
|
||||
else
|
||||
GO_VET_CMD=echo skipping go vet, ${SDK_GO_VERSION}
|
||||
GO_VET_CMD=go tool vet --all -shadow
|
||||
endif
|
||||
|
||||
vet:
|
||||
@ -129,10 +130,11 @@ get-deps-tests:
|
||||
go get github.com/gucumber/gucumber/cmd/gucumber
|
||||
go get github.com/stretchr/testify
|
||||
go get github.com/smartystreets/goconvey
|
||||
go get golang.org/x/net/html
|
||||
|
||||
get-deps-verify:
|
||||
@echo "go get SDK verification utilities"
|
||||
@if [ -z "${SDK_GO_1_4}" ]; then go get github.com/golang/lint/golint; else echo "skipped getting golint"; fi
|
||||
@if [ \( -z "${SDK_GO_1_4}" \) -a \( -z "${SDK_GO_1_5}" \) ]; then go get github.com/golang/lint/golint; else echo "skipped getting golint"; fi
|
||||
|
||||
bench:
|
||||
@echo "go bench SDK packages"
|
||||
@ -144,9 +146,12 @@ bench-protocol:
|
||||
|
||||
docs:
|
||||
@echo "generate SDK docs"
|
||||
rm -rf doc && bundle install && bundle exec yard
|
||||
@# This env variable, DOCS, is for internal use
|
||||
@if [ -n "$(AWS_DOC_GEN_TOOL)" ]; then echo "For internal use. Subject to change."; $(AWS_DOC_GEN_TOOL) `pwd`; fi
|
||||
@if [ -z ${AWS_DOC_GEN_TOOL} ]; then\
|
||||
rm -rf doc && bundle install && bundle exec yard;\
|
||||
else\
|
||||
$(AWS_DOC_GEN_TOOL) `pwd`;\
|
||||
fi
|
||||
|
||||
api_info:
|
||||
@go run private/model/cli/api-info/api-info.go
|
||||
|
11
vendor/github.com/aws/aws-sdk-go/README.md
generated
vendored
11
vendor/github.com/aws/aws-sdk-go/README.md
generated
vendored
@ -17,7 +17,7 @@ If you are using Go 1.5 with the `GO15VENDOREXPERIMENT=1` vendoring flag, or 1.6
|
||||
|
||||
go get -u github.com/aws/aws-sdk-go
|
||||
|
||||
Otherwise if your Go environment does not have vendoring support enabled, or you do not want to include the vendored SDK's dependencies you can use the following command to retrieve the SDK and its non-testing dependencies using `go get`.
|
||||
Otherwise if your Go environment does not have vendoring support enabled, or you do not want to include the vendored SDK's dependencies you can use the following command to retrieve the SDK and its non-testing dependencies using `go get`.
|
||||
|
||||
go get -u github.com/aws/aws-sdk-go/aws/...
|
||||
go get -u github.com/aws/aws-sdk-go/service/...
|
||||
@ -25,7 +25,7 @@ Otherwise if your Go environment does not have vendoring support enabled, or you
|
||||
If you're looking to retrieve just the SDK without any dependencies use the following command.
|
||||
|
||||
go get -d github.com/aws/aws-sdk-go/
|
||||
|
||||
|
||||
These two processes will still include the `vendor` folder and it should be deleted if its not going to be used by your environment.
|
||||
|
||||
rm -rf $GOPATH/src/github.com/aws/aws-sdk-go/vendor
|
||||
@ -84,10 +84,15 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
sess, err := session.NewSession()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Create an EC2 service object in the "us-west-2" region
|
||||
// Note that you can also configure your region globally by
|
||||
// exporting the AWS_REGION environment variable
|
||||
svc := ec2.New(session.New(), &aws.Config{Region: aws.String("us-west-2")})
|
||||
svc := ec2.New(sess, &aws.Config{Region: aws.String("us-west-2")})
|
||||
|
||||
// Call the DescribeInstances Operation
|
||||
resp, err := svc.DescribeInstances(nil)
|
||||
|
10
vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go
generated
vendored
10
vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go
generated
vendored
@ -3,6 +3,7 @@ package awsutil
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Copy deeply copies a src structure to dst. Useful for copying request and
|
||||
@ -49,7 +50,14 @@ func rcopy(dst, src reflect.Value, root bool) {
|
||||
} else {
|
||||
e := src.Type().Elem()
|
||||
if dst.CanSet() && !src.IsNil() {
|
||||
dst.Set(reflect.New(e))
|
||||
if _, ok := src.Interface().(*time.Time); !ok {
|
||||
dst.Set(reflect.New(e))
|
||||
} else {
|
||||
tempValue := reflect.New(e)
|
||||
tempValue.Elem().Set(src.Elem())
|
||||
// Sets time.Time's unexported values
|
||||
dst.Set(tempValue)
|
||||
}
|
||||
}
|
||||
if src.Elem().IsValid() {
|
||||
// Keep the current root state since the depth hasn't changed
|
||||
|
233
vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go
generated
vendored
233
vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go
generated
vendored
@ -1,233 +0,0 @@
|
||||
package awsutil_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func ExampleCopy() {
|
||||
type Foo struct {
|
||||
A int
|
||||
B []*string
|
||||
}
|
||||
|
||||
// Create the initial value
|
||||
str1 := "hello"
|
||||
str2 := "bye bye"
|
||||
f1 := &Foo{A: 1, B: []*string{&str1, &str2}}
|
||||
|
||||
// Do the copy
|
||||
var f2 Foo
|
||||
awsutil.Copy(&f2, f1)
|
||||
|
||||
// Print the result
|
||||
fmt.Println(awsutil.Prettify(f2))
|
||||
|
||||
// Output:
|
||||
// {
|
||||
// A: 1,
|
||||
// B: ["hello","bye bye"]
|
||||
// }
|
||||
}
|
||||
|
||||
func TestCopy(t *testing.T) {
|
||||
type Foo struct {
|
||||
A int
|
||||
B []*string
|
||||
C map[string]*int
|
||||
}
|
||||
|
||||
// Create the initial value
|
||||
str1 := "hello"
|
||||
str2 := "bye bye"
|
||||
int1 := 1
|
||||
int2 := 2
|
||||
f1 := &Foo{
|
||||
A: 1,
|
||||
B: []*string{&str1, &str2},
|
||||
C: map[string]*int{
|
||||
"A": &int1,
|
||||
"B": &int2,
|
||||
},
|
||||
}
|
||||
|
||||
// Do the copy
|
||||
var f2 Foo
|
||||
awsutil.Copy(&f2, f1)
|
||||
|
||||
// Values are equal
|
||||
assert.Equal(t, f2.A, f1.A)
|
||||
assert.Equal(t, f2.B, f1.B)
|
||||
assert.Equal(t, f2.C, f1.C)
|
||||
|
||||
// But pointers are not!
|
||||
str3 := "nothello"
|
||||
int3 := 57
|
||||
f2.A = 100
|
||||
f2.B[0] = &str3
|
||||
f2.C["B"] = &int3
|
||||
assert.NotEqual(t, f2.A, f1.A)
|
||||
assert.NotEqual(t, f2.B, f1.B)
|
||||
assert.NotEqual(t, f2.C, f1.C)
|
||||
}
|
||||
|
||||
func TestCopyNestedWithUnexported(t *testing.T) {
|
||||
type Bar struct {
|
||||
a int
|
||||
B int
|
||||
}
|
||||
type Foo struct {
|
||||
A string
|
||||
B Bar
|
||||
}
|
||||
|
||||
f1 := &Foo{A: "string", B: Bar{a: 1, B: 2}}
|
||||
|
||||
var f2 Foo
|
||||
awsutil.Copy(&f2, f1)
|
||||
|
||||
// Values match
|
||||
assert.Equal(t, f2.A, f1.A)
|
||||
assert.NotEqual(t, f2.B, f1.B)
|
||||
assert.NotEqual(t, f2.B.a, f1.B.a)
|
||||
assert.Equal(t, f2.B.B, f2.B.B)
|
||||
}
|
||||
|
||||
func TestCopyIgnoreNilMembers(t *testing.T) {
|
||||
type Foo struct {
|
||||
A *string
|
||||
B []string
|
||||
C map[string]string
|
||||
}
|
||||
|
||||
f := &Foo{}
|
||||
assert.Nil(t, f.A)
|
||||
assert.Nil(t, f.B)
|
||||
assert.Nil(t, f.C)
|
||||
|
||||
var f2 Foo
|
||||
awsutil.Copy(&f2, f)
|
||||
assert.Nil(t, f2.A)
|
||||
assert.Nil(t, f2.B)
|
||||
assert.Nil(t, f2.C)
|
||||
|
||||
fcopy := awsutil.CopyOf(f)
|
||||
f3 := fcopy.(*Foo)
|
||||
assert.Nil(t, f3.A)
|
||||
assert.Nil(t, f3.B)
|
||||
assert.Nil(t, f3.C)
|
||||
}
|
||||
|
||||
func TestCopyPrimitive(t *testing.T) {
|
||||
str := "hello"
|
||||
var s string
|
||||
awsutil.Copy(&s, &str)
|
||||
assert.Equal(t, "hello", s)
|
||||
}
|
||||
|
||||
func TestCopyNil(t *testing.T) {
|
||||
var s string
|
||||
awsutil.Copy(&s, nil)
|
||||
assert.Equal(t, "", s)
|
||||
}
|
||||
|
||||
func TestCopyReader(t *testing.T) {
|
||||
var buf io.Reader = bytes.NewReader([]byte("hello world"))
|
||||
var r io.Reader
|
||||
awsutil.Copy(&r, buf)
|
||||
b, err := ioutil.ReadAll(r)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("hello world"), b)
|
||||
|
||||
// empty bytes because this is not a deep copy
|
||||
b, err = ioutil.ReadAll(buf)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte(""), b)
|
||||
}
|
||||
|
||||
func TestCopyDifferentStructs(t *testing.T) {
|
||||
type SrcFoo struct {
|
||||
A int
|
||||
B []*string
|
||||
C map[string]*int
|
||||
SrcUnique string
|
||||
SameNameDiffType int
|
||||
unexportedPtr *int
|
||||
ExportedPtr *int
|
||||
}
|
||||
type DstFoo struct {
|
||||
A int
|
||||
B []*string
|
||||
C map[string]*int
|
||||
DstUnique int
|
||||
SameNameDiffType string
|
||||
unexportedPtr *int
|
||||
ExportedPtr *int
|
||||
}
|
||||
|
||||
// Create the initial value
|
||||
str1 := "hello"
|
||||
str2 := "bye bye"
|
||||
int1 := 1
|
||||
int2 := 2
|
||||
f1 := &SrcFoo{
|
||||
A: 1,
|
||||
B: []*string{&str1, &str2},
|
||||
C: map[string]*int{
|
||||
"A": &int1,
|
||||
"B": &int2,
|
||||
},
|
||||
SrcUnique: "unique",
|
||||
SameNameDiffType: 1,
|
||||
unexportedPtr: &int1,
|
||||
ExportedPtr: &int2,
|
||||
}
|
||||
|
||||
// Do the copy
|
||||
var f2 DstFoo
|
||||
awsutil.Copy(&f2, f1)
|
||||
|
||||
// Values are equal
|
||||
assert.Equal(t, f2.A, f1.A)
|
||||
assert.Equal(t, f2.B, f1.B)
|
||||
assert.Equal(t, f2.C, f1.C)
|
||||
assert.Equal(t, "unique", f1.SrcUnique)
|
||||
assert.Equal(t, 1, f1.SameNameDiffType)
|
||||
assert.Equal(t, 0, f2.DstUnique)
|
||||
assert.Equal(t, "", f2.SameNameDiffType)
|
||||
assert.Equal(t, int1, *f1.unexportedPtr)
|
||||
assert.Nil(t, f2.unexportedPtr)
|
||||
assert.Equal(t, int2, *f1.ExportedPtr)
|
||||
assert.Equal(t, int2, *f2.ExportedPtr)
|
||||
}
|
||||
|
||||
func ExampleCopyOf() {
|
||||
type Foo struct {
|
||||
A int
|
||||
B []*string
|
||||
}
|
||||
|
||||
// Create the initial value
|
||||
str1 := "hello"
|
||||
str2 := "bye bye"
|
||||
f1 := &Foo{A: 1, B: []*string{&str1, &str2}}
|
||||
|
||||
// Do the copy
|
||||
v := awsutil.CopyOf(f1)
|
||||
var f2 *Foo = v.(*Foo)
|
||||
|
||||
// Print the result
|
||||
fmt.Println(awsutil.Prettify(f2))
|
||||
|
||||
// Output:
|
||||
// {
|
||||
// A: 1,
|
||||
// B: ["hello","bye bye"]
|
||||
// }
|
||||
}
|
29
vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal_test.go
generated
vendored
29
vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal_test.go
generated
vendored
@ -1,29 +0,0 @@
|
||||
package awsutil_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDeepEqual(t *testing.T) {
|
||||
cases := []struct {
|
||||
a, b interface{}
|
||||
equal bool
|
||||
}{
|
||||
{"a", "a", true},
|
||||
{"a", "b", false},
|
||||
{"a", aws.String(""), false},
|
||||
{"a", nil, false},
|
||||
{"a", aws.String("a"), true},
|
||||
{(*bool)(nil), (*bool)(nil), true},
|
||||
{(*bool)(nil), (*string)(nil), false},
|
||||
{nil, nil, true},
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
assert.Equal(t, c.equal, awsutil.DeepEqual(c.a, c.b), "%d, a:%v b:%v, %t", i, c.a, c.b, c.equal)
|
||||
}
|
||||
}
|
4
vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go
generated
vendored
4
vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go
generated
vendored
@ -106,8 +106,8 @@ func rValuesAtPath(v interface{}, path string, createPath, caseSensitive, nilTer
|
||||
|
||||
if indexStar || index != nil {
|
||||
nextvals = []reflect.Value{}
|
||||
for _, value := range values {
|
||||
value := reflect.Indirect(value)
|
||||
for _, valItem := range values {
|
||||
value := reflect.Indirect(valItem)
|
||||
if value.Kind() != reflect.Slice {
|
||||
continue
|
||||
}
|
||||
|
142
vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go
generated
vendored
142
vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go
generated
vendored
@ -1,142 +0,0 @@
|
||||
package awsutil_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type Struct struct {
|
||||
A []Struct
|
||||
z []Struct
|
||||
B *Struct
|
||||
D *Struct
|
||||
C string
|
||||
E map[string]string
|
||||
}
|
||||
|
||||
var data = Struct{
|
||||
A: []Struct{{C: "value1"}, {C: "value2"}, {C: "value3"}},
|
||||
z: []Struct{{C: "value1"}, {C: "value2"}, {C: "value3"}},
|
||||
B: &Struct{B: &Struct{C: "terminal"}, D: &Struct{C: "terminal2"}},
|
||||
C: "initial",
|
||||
}
|
||||
var data2 = Struct{A: []Struct{
|
||||
{A: []Struct{{C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}}},
|
||||
{A: []Struct{{C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}}},
|
||||
}}
|
||||
|
||||
func TestValueAtPathSuccess(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
expect []interface{}
|
||||
data interface{}
|
||||
path string
|
||||
}{
|
||||
{[]interface{}{"initial"}, data, "C"},
|
||||
{[]interface{}{"value1"}, data, "A[0].C"},
|
||||
{[]interface{}{"value2"}, data, "A[1].C"},
|
||||
{[]interface{}{"value3"}, data, "A[2].C"},
|
||||
{[]interface{}{"value3"}, data, "a[2].c"},
|
||||
{[]interface{}{"value3"}, data, "A[-1].C"},
|
||||
{[]interface{}{"value1", "value2", "value3"}, data, "A[].C"},
|
||||
{[]interface{}{"terminal"}, data, "B . B . C"},
|
||||
{[]interface{}{"initial"}, data, "A.D.X || C"},
|
||||
{[]interface{}{"initial"}, data, "A[0].B || C"},
|
||||
{[]interface{}{
|
||||
Struct{A: []Struct{{C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}}},
|
||||
Struct{A: []Struct{{C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}}},
|
||||
}, data2, "A"},
|
||||
}
|
||||
for i, c := range testCases {
|
||||
v, err := awsutil.ValuesAtPath(c.data, c.path)
|
||||
assert.NoError(t, err, "case %d, expected no error, %s", i, c.path)
|
||||
assert.Equal(t, c.expect, v, "case %d, %s", i, c.path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValueAtPathFailure(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
expect []interface{}
|
||||
errContains string
|
||||
data interface{}
|
||||
path string
|
||||
}{
|
||||
{nil, "", data, "C.x"},
|
||||
{nil, "SyntaxError: Invalid token: tDot", data, ".x"},
|
||||
{nil, "", data, "X.Y.Z"},
|
||||
{nil, "", data, "A[100].C"},
|
||||
{nil, "", data, "A[3].C"},
|
||||
{nil, "", data, "B.B.C.Z"},
|
||||
{nil, "", data, "z[-1].C"},
|
||||
{nil, "", nil, "A.B.C"},
|
||||
{[]interface{}{}, "", Struct{}, "A"},
|
||||
{nil, "", data, "A[0].B.C"},
|
||||
{nil, "", data, "D"},
|
||||
}
|
||||
|
||||
for i, c := range testCases {
|
||||
v, err := awsutil.ValuesAtPath(c.data, c.path)
|
||||
if c.errContains != "" {
|
||||
assert.Contains(t, err.Error(), c.errContains, "case %d, expected error, %s", i, c.path)
|
||||
continue
|
||||
} else {
|
||||
assert.NoError(t, err, "case %d, expected no error, %s", i, c.path)
|
||||
}
|
||||
assert.Equal(t, c.expect, v, "case %d, %s", i, c.path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetValueAtPathSuccess(t *testing.T) {
|
||||
var s Struct
|
||||
awsutil.SetValueAtPath(&s, "C", "test1")
|
||||
awsutil.SetValueAtPath(&s, "B.B.C", "test2")
|
||||
awsutil.SetValueAtPath(&s, "B.D.C", "test3")
|
||||
assert.Equal(t, "test1", s.C)
|
||||
assert.Equal(t, "test2", s.B.B.C)
|
||||
assert.Equal(t, "test3", s.B.D.C)
|
||||
|
||||
awsutil.SetValueAtPath(&s, "B.*.C", "test0")
|
||||
assert.Equal(t, "test0", s.B.B.C)
|
||||
assert.Equal(t, "test0", s.B.D.C)
|
||||
|
||||
var s2 Struct
|
||||
awsutil.SetValueAtPath(&s2, "b.b.c", "test0")
|
||||
assert.Equal(t, "test0", s2.B.B.C)
|
||||
awsutil.SetValueAtPath(&s2, "A", []Struct{{}})
|
||||
assert.Equal(t, []Struct{{}}, s2.A)
|
||||
|
||||
str := "foo"
|
||||
|
||||
s3 := Struct{}
|
||||
awsutil.SetValueAtPath(&s3, "b.b.c", str)
|
||||
assert.Equal(t, "foo", s3.B.B.C)
|
||||
|
||||
s3 = Struct{B: &Struct{B: &Struct{C: str}}}
|
||||
awsutil.SetValueAtPath(&s3, "b.b.c", nil)
|
||||
assert.Equal(t, "", s3.B.B.C)
|
||||
|
||||
s3 = Struct{}
|
||||
awsutil.SetValueAtPath(&s3, "b.b.c", nil)
|
||||
assert.Equal(t, "", s3.B.B.C)
|
||||
|
||||
s3 = Struct{}
|
||||
awsutil.SetValueAtPath(&s3, "b.b.c", &str)
|
||||
assert.Equal(t, "foo", s3.B.B.C)
|
||||
|
||||
var s4 struct{ Name *string }
|
||||
awsutil.SetValueAtPath(&s4, "Name", str)
|
||||
assert.Equal(t, str, *s4.Name)
|
||||
|
||||
s4 = struct{ Name *string }{}
|
||||
awsutil.SetValueAtPath(&s4, "Name", nil)
|
||||
assert.Equal(t, (*string)(nil), s4.Name)
|
||||
|
||||
s4 = struct{ Name *string }{Name: &str}
|
||||
awsutil.SetValueAtPath(&s4, "Name", nil)
|
||||
assert.Equal(t, (*string)(nil), s4.Name)
|
||||
|
||||
s4 = struct{ Name *string }{}
|
||||
awsutil.SetValueAtPath(&s4, "Name", &str)
|
||||
assert.Equal(t, str, *s4.Name)
|
||||
}
|
6
vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go
generated
vendored
6
vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go
generated
vendored
@ -61,6 +61,12 @@ func prettify(v reflect.Value, indent int, buf *bytes.Buffer) {
|
||||
|
||||
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
|
||||
case reflect.Slice:
|
||||
strtype := v.Type().String()
|
||||
if strtype == "[]uint8" {
|
||||
fmt.Fprintf(buf, "<binary> len %d", v.Len())
|
||||
break
|
||||
}
|
||||
|
||||
nl, id, id2 := "", "", ""
|
||||
if v.Len() > 3 {
|
||||
nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
|
||||
|
27
vendor/github.com/aws/aws-sdk-go/aws/client/client.go
generated
vendored
27
vendor/github.com/aws/aws-sdk-go/aws/client/client.go
generated
vendored
@ -2,7 +2,6 @@ package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http/httputil"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
@ -87,16 +86,24 @@ const logReqMsg = `DEBUG: Request %s/%s Details:
|
||||
%s
|
||||
-----------------------------------------------------`
|
||||
|
||||
const logReqErrMsg = `DEBUG ERROR: Request %s/%s:
|
||||
---[ REQUEST DUMP ERROR ]-----------------------------
|
||||
%s
|
||||
-----------------------------------------------------`
|
||||
|
||||
func logRequest(r *request.Request) {
|
||||
logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
|
||||
dumpedBody, _ := httputil.DumpRequestOut(r.HTTPRequest, logBody)
|
||||
dumpedBody, err := httputil.DumpRequestOut(r.HTTPRequest, logBody)
|
||||
if err != nil {
|
||||
r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg, r.ClientInfo.ServiceName, r.Operation.Name, err))
|
||||
return
|
||||
}
|
||||
|
||||
if logBody {
|
||||
// Reset the request body because dumpRequest will re-wrap the r.HTTPRequest's
|
||||
// Body as a NoOpCloser and will not be reset after read by the HTTP
|
||||
// client reader.
|
||||
r.Body.Seek(r.BodyStart, 0)
|
||||
r.HTTPRequest.Body = ioutil.NopCloser(r.Body)
|
||||
r.ResetBody()
|
||||
}
|
||||
|
||||
r.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.ClientInfo.ServiceName, r.Operation.Name, string(dumpedBody)))
|
||||
@ -107,11 +114,21 @@ const logRespMsg = `DEBUG: Response %s/%s Details:
|
||||
%s
|
||||
-----------------------------------------------------`
|
||||
|
||||
const logRespErrMsg = `DEBUG ERROR: Response %s/%s:
|
||||
---[ RESPONSE DUMP ERROR ]-----------------------------
|
||||
%s
|
||||
-----------------------------------------------------`
|
||||
|
||||
func logResponse(r *request.Request) {
|
||||
var msg = "no response data"
|
||||
if r.HTTPResponse != nil {
|
||||
logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
|
||||
dumpedBody, _ := httputil.DumpResponse(r.HTTPResponse, logBody)
|
||||
dumpedBody, err := httputil.DumpResponse(r.HTTPResponse, logBody)
|
||||
if err != nil {
|
||||
r.Config.Logger.Log(fmt.Sprintf(logRespErrMsg, r.ClientInfo.ServiceName, r.Operation.Name, err))
|
||||
return
|
||||
}
|
||||
|
||||
msg = string(dumpedBody)
|
||||
} else if r.Error != nil {
|
||||
msg = r.Error.Error()
|
||||
|
20
vendor/github.com/aws/aws-sdk-go/aws/config.go
generated
vendored
20
vendor/github.com/aws/aws-sdk-go/aws/config.go
generated
vendored
@ -137,9 +137,6 @@ type Config struct {
|
||||
// accelerate enabled. If the bucket is not enabled for accelerate an error
|
||||
// will be returned. The bucket name must be DNS compatible to also work
|
||||
// with accelerate.
|
||||
//
|
||||
// Not compatible with UseDualStack requests will fail if both flags are
|
||||
// specified.
|
||||
S3UseAccelerate *bool
|
||||
|
||||
// Set this to `true` to disable the EC2Metadata client from overriding the
|
||||
@ -185,6 +182,19 @@ type Config struct {
|
||||
// the delay of a request see the aws/client.DefaultRetryer and
|
||||
// aws/request.Retryer.
|
||||
SleepDelay func(time.Duration)
|
||||
|
||||
// DisableRestProtocolURICleaning will not clean the URL path when making rest protocol requests.
|
||||
// Will default to false. This would only be used for empty directory names in s3 requests.
|
||||
//
|
||||
// Example:
|
||||
// sess, err := session.NewSession(&aws.Config{DisableRestProtocolURICleaning: aws.Bool(true))
|
||||
//
|
||||
// svc := s3.New(sess)
|
||||
// out, err := svc.GetObject(&s3.GetObjectInput {
|
||||
// Bucket: aws.String("bucketname"),
|
||||
// Key: aws.String("//foo//bar//moo"),
|
||||
// })
|
||||
DisableRestProtocolURICleaning *bool
|
||||
}
|
||||
|
||||
// NewConfig returns a new Config pointer that can be chained with builder
|
||||
@ -406,6 +416,10 @@ func mergeInConfig(dst *Config, other *Config) {
|
||||
if other.SleepDelay != nil {
|
||||
dst.SleepDelay = other.SleepDelay
|
||||
}
|
||||
|
||||
if other.DisableRestProtocolURICleaning != nil {
|
||||
dst.DisableRestProtocolURICleaning = other.DisableRestProtocolURICleaning
|
||||
}
|
||||
}
|
||||
|
||||
// Copy will return a shallow copy of the Config object. If any additional
|
||||
|
86
vendor/github.com/aws/aws-sdk-go/aws/config_test.go
generated
vendored
86
vendor/github.com/aws/aws-sdk-go/aws/config_test.go
generated
vendored
@ -1,86 +0,0 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
)
|
||||
|
||||
var testCredentials = credentials.NewStaticCredentials("AKID", "SECRET", "SESSION")
|
||||
|
||||
var copyTestConfig = Config{
|
||||
Credentials: testCredentials,
|
||||
Endpoint: String("CopyTestEndpoint"),
|
||||
Region: String("COPY_TEST_AWS_REGION"),
|
||||
DisableSSL: Bool(true),
|
||||
HTTPClient: http.DefaultClient,
|
||||
LogLevel: LogLevel(LogDebug),
|
||||
Logger: NewDefaultLogger(),
|
||||
MaxRetries: Int(3),
|
||||
DisableParamValidation: Bool(true),
|
||||
DisableComputeChecksums: Bool(true),
|
||||
S3ForcePathStyle: Bool(true),
|
||||
}
|
||||
|
||||
func TestCopy(t *testing.T) {
|
||||
want := copyTestConfig
|
||||
got := copyTestConfig.Copy()
|
||||
if !reflect.DeepEqual(*got, want) {
|
||||
t.Errorf("Copy() = %+v", got)
|
||||
t.Errorf(" want %+v", want)
|
||||
}
|
||||
|
||||
got.Region = String("other")
|
||||
if got.Region == want.Region {
|
||||
t.Errorf("Expect setting copy values not not reflect in source")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopyReturnsNewInstance(t *testing.T) {
|
||||
want := copyTestConfig
|
||||
got := copyTestConfig.Copy()
|
||||
if got == &want {
|
||||
t.Errorf("Copy() = %p; want different instance as source %p", got, &want)
|
||||
}
|
||||
}
|
||||
|
||||
var mergeTestZeroValueConfig = Config{}
|
||||
|
||||
var mergeTestConfig = Config{
|
||||
Credentials: testCredentials,
|
||||
Endpoint: String("MergeTestEndpoint"),
|
||||
Region: String("MERGE_TEST_AWS_REGION"),
|
||||
DisableSSL: Bool(true),
|
||||
HTTPClient: http.DefaultClient,
|
||||
LogLevel: LogLevel(LogDebug),
|
||||
Logger: NewDefaultLogger(),
|
||||
MaxRetries: Int(10),
|
||||
DisableParamValidation: Bool(true),
|
||||
DisableComputeChecksums: Bool(true),
|
||||
S3ForcePathStyle: Bool(true),
|
||||
}
|
||||
|
||||
var mergeTests = []struct {
|
||||
cfg *Config
|
||||
in *Config
|
||||
want *Config
|
||||
}{
|
||||
{&Config{}, nil, &Config{}},
|
||||
{&Config{}, &mergeTestZeroValueConfig, &Config{}},
|
||||
{&Config{}, &mergeTestConfig, &mergeTestConfig},
|
||||
}
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
for i, tt := range mergeTests {
|
||||
got := tt.cfg.Copy()
|
||||
got.MergeIn(tt.in)
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Config %d %+v", i, tt.cfg)
|
||||
t.Errorf(" Merge(%+v)", tt.in)
|
||||
t.Errorf(" got %+v", got)
|
||||
t.Errorf(" want %+v", tt.want)
|
||||
}
|
||||
}
|
||||
}
|
437
vendor/github.com/aws/aws-sdk-go/aws/convert_types_test.go
generated
vendored
437
vendor/github.com/aws/aws-sdk-go/aws/convert_types_test.go
generated
vendored
@ -1,437 +0,0 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var testCasesStringSlice = [][]string{
|
||||
{"a", "b", "c", "d", "e"},
|
||||
{"a", "b", "", "", "e"},
|
||||
}
|
||||
|
||||
func TestStringSlice(t *testing.T) {
|
||||
for idx, in := range testCasesStringSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := StringSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := StringValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesStringValueSlice = [][]*string{
|
||||
{String("a"), String("b"), nil, String("c")},
|
||||
}
|
||||
|
||||
func TestStringValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesStringValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := StringValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := StringSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesStringMap = []map[string]string{
|
||||
{"a": "1", "b": "2", "c": "3"},
|
||||
}
|
||||
|
||||
func TestStringMap(t *testing.T) {
|
||||
for idx, in := range testCasesStringMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := StringMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := StringValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesBoolSlice = [][]bool{
|
||||
{true, true, false, false},
|
||||
}
|
||||
|
||||
func TestBoolSlice(t *testing.T) {
|
||||
for idx, in := range testCasesBoolSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := BoolSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := BoolValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesBoolValueSlice = [][]*bool{}
|
||||
|
||||
func TestBoolValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesBoolValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := BoolValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := BoolSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesBoolMap = []map[string]bool{
|
||||
{"a": true, "b": false, "c": true},
|
||||
}
|
||||
|
||||
func TestBoolMap(t *testing.T) {
|
||||
for idx, in := range testCasesBoolMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := BoolMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := BoolValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesIntSlice = [][]int{
|
||||
{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
func TestIntSlice(t *testing.T) {
|
||||
for idx, in := range testCasesIntSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := IntSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := IntValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesIntValueSlice = [][]*int{}
|
||||
|
||||
func TestIntValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesIntValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := IntValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := IntSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesIntMap = []map[string]int{
|
||||
{"a": 3, "b": 2, "c": 1},
|
||||
}
|
||||
|
||||
func TestIntMap(t *testing.T) {
|
||||
for idx, in := range testCasesIntMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := IntMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := IntValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesInt64Slice = [][]int64{
|
||||
{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
func TestInt64Slice(t *testing.T) {
|
||||
for idx, in := range testCasesInt64Slice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Int64Slice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Int64ValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesInt64ValueSlice = [][]*int64{}
|
||||
|
||||
func TestInt64ValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesInt64ValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Int64ValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := Int64Slice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesInt64Map = []map[string]int64{
|
||||
{"a": 3, "b": 2, "c": 1},
|
||||
}
|
||||
|
||||
func TestInt64Map(t *testing.T) {
|
||||
for idx, in := range testCasesInt64Map {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Int64Map(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Int64ValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesFloat64Slice = [][]float64{
|
||||
{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
func TestFloat64Slice(t *testing.T) {
|
||||
for idx, in := range testCasesFloat64Slice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Float64Slice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Float64ValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesFloat64ValueSlice = [][]*float64{}
|
||||
|
||||
func TestFloat64ValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesFloat64ValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Float64ValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := Float64Slice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesFloat64Map = []map[string]float64{
|
||||
{"a": 3, "b": 2, "c": 1},
|
||||
}
|
||||
|
||||
func TestFloat64Map(t *testing.T) {
|
||||
for idx, in := range testCasesFloat64Map {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Float64Map(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Float64ValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesTimeSlice = [][]time.Time{
|
||||
{time.Now(), time.Now().AddDate(100, 0, 0)},
|
||||
}
|
||||
|
||||
func TestTimeSlice(t *testing.T) {
|
||||
for idx, in := range testCasesTimeSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := TimeSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := TimeValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesTimeValueSlice = [][]*time.Time{}
|
||||
|
||||
func TestTimeValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesTimeValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := TimeValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := TimeSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesTimeMap = []map[string]time.Time{
|
||||
{"a": time.Now().AddDate(-100, 0, 0), "b": time.Now()},
|
||||
}
|
||||
|
||||
func TestTimeMap(t *testing.T) {
|
||||
for idx, in := range testCasesTimeMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := TimeMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := TimeValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
30
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go
generated
vendored
30
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go
generated
vendored
@ -10,9 +10,11 @@ import (
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
)
|
||||
|
||||
@ -67,6 +69,34 @@ var SDKVersionUserAgentHandler = request.NamedHandler{
|
||||
|
||||
var reStatusCode = regexp.MustCompile(`^(\d{3})`)
|
||||
|
||||
// ValidateReqSigHandler is a request handler to ensure that the request's
|
||||
// signature doesn't expire before it is sent. This can happen when a request
|
||||
// is built and signed signficantly before it is sent. Or signficant delays
|
||||
// occur whne retrying requests that would cause the signature to expire.
|
||||
var ValidateReqSigHandler = request.NamedHandler{
|
||||
Name: "core.ValidateReqSigHandler",
|
||||
Fn: func(r *request.Request) {
|
||||
// Unsigned requests are not signed
|
||||
if r.Config.Credentials == credentials.AnonymousCredentials {
|
||||
return
|
||||
}
|
||||
|
||||
signedTime := r.Time
|
||||
if !r.LastSignedAt.IsZero() {
|
||||
signedTime = r.LastSignedAt
|
||||
}
|
||||
|
||||
// 10 minutes to allow for some clock skew/delays in transmission.
|
||||
// Would be improved with aws/aws-sdk-go#423
|
||||
if signedTime.Add(10 * time.Minute).After(time.Now()) {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("request expired, resigning")
|
||||
r.Sign()
|
||||
},
|
||||
}
|
||||
|
||||
// SendHandler is a request handler to send service request using HTTP client.
|
||||
var SendHandler = request.NamedHandler{Name: "core.SendHandler", Fn: func(r *request.Request) {
|
||||
var err error
|
||||
|
192
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_test.go
generated
vendored
192
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_test.go
generated
vendored
@ -1,192 +0,0 @@
|
||||
package corehandlers_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/corehandlers"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/awstesting"
|
||||
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
)
|
||||
|
||||
func TestValidateEndpointHandler(t *testing.T) {
|
||||
os.Clearenv()
|
||||
|
||||
svc := awstesting.NewClient(aws.NewConfig().WithRegion("us-west-2"))
|
||||
svc.Handlers.Clear()
|
||||
svc.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
|
||||
|
||||
req := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil)
|
||||
err := req.Build()
|
||||
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestValidateEndpointHandlerErrorRegion(t *testing.T) {
|
||||
os.Clearenv()
|
||||
|
||||
svc := awstesting.NewClient()
|
||||
svc.Handlers.Clear()
|
||||
svc.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
|
||||
|
||||
req := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil)
|
||||
err := req.Build()
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, aws.ErrMissingRegion, err)
|
||||
}
|
||||
|
||||
type mockCredsProvider struct {
|
||||
expired bool
|
||||
retrieveCalled bool
|
||||
}
|
||||
|
||||
func (m *mockCredsProvider) Retrieve() (credentials.Value, error) {
|
||||
m.retrieveCalled = true
|
||||
return credentials.Value{ProviderName: "mockCredsProvider"}, nil
|
||||
}
|
||||
|
||||
func (m *mockCredsProvider) IsExpired() bool {
|
||||
return m.expired
|
||||
}
|
||||
|
||||
func TestAfterRetryRefreshCreds(t *testing.T) {
|
||||
os.Clearenv()
|
||||
credProvider := &mockCredsProvider{}
|
||||
|
||||
svc := awstesting.NewClient(&aws.Config{
|
||||
Credentials: credentials.NewCredentials(credProvider),
|
||||
MaxRetries: aws.Int(1),
|
||||
})
|
||||
|
||||
svc.Handlers.Clear()
|
||||
svc.Handlers.ValidateResponse.PushBack(func(r *request.Request) {
|
||||
r.Error = awserr.New("UnknownError", "", nil)
|
||||
r.HTTPResponse = &http.Response{StatusCode: 400, Body: ioutil.NopCloser(bytes.NewBuffer([]byte{}))}
|
||||
})
|
||||
svc.Handlers.UnmarshalError.PushBack(func(r *request.Request) {
|
||||
r.Error = awserr.New("ExpiredTokenException", "", nil)
|
||||
})
|
||||
svc.Handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler)
|
||||
|
||||
assert.True(t, svc.Config.Credentials.IsExpired(), "Expect to start out expired")
|
||||
assert.False(t, credProvider.retrieveCalled)
|
||||
|
||||
req := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil)
|
||||
req.Send()
|
||||
|
||||
assert.True(t, svc.Config.Credentials.IsExpired())
|
||||
assert.False(t, credProvider.retrieveCalled)
|
||||
|
||||
_, err := svc.Config.Credentials.Get()
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, credProvider.retrieveCalled)
|
||||
}
|
||||
|
||||
type testSendHandlerTransport struct{}
|
||||
|
||||
func (t *testSendHandlerTransport) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
return nil, fmt.Errorf("mock error")
|
||||
}
|
||||
|
||||
func TestSendHandlerError(t *testing.T) {
|
||||
svc := awstesting.NewClient(&aws.Config{
|
||||
HTTPClient: &http.Client{
|
||||
Transport: &testSendHandlerTransport{},
|
||||
},
|
||||
})
|
||||
svc.Handlers.Clear()
|
||||
svc.Handlers.Send.PushBackNamed(corehandlers.SendHandler)
|
||||
r := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil)
|
||||
|
||||
r.Send()
|
||||
|
||||
assert.Error(t, r.Error)
|
||||
assert.NotNil(t, r.HTTPResponse)
|
||||
}
|
||||
|
||||
func setupContentLengthTestServer(t *testing.T, hasContentLength bool, contentLength int64) *httptest.Server {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, ok := r.Header["Content-Length"]
|
||||
assert.Equal(t, hasContentLength, ok, "expect content length to be set, %t", hasContentLength)
|
||||
assert.Equal(t, contentLength, r.ContentLength)
|
||||
|
||||
b, err := ioutil.ReadAll(r.Body)
|
||||
assert.NoError(t, err)
|
||||
r.Body.Close()
|
||||
|
||||
authHeader := r.Header.Get("Authorization")
|
||||
if hasContentLength {
|
||||
assert.Contains(t, authHeader, "content-length")
|
||||
} else {
|
||||
assert.NotContains(t, authHeader, "content-length")
|
||||
}
|
||||
|
||||
assert.Equal(t, contentLength, int64(len(b)))
|
||||
}))
|
||||
|
||||
return server
|
||||
}
|
||||
|
||||
func TestBuildContentLength_ZeroBody(t *testing.T) {
|
||||
server := setupContentLengthTestServer(t, false, 0)
|
||||
|
||||
svc := s3.New(unit.Session, &aws.Config{
|
||||
Endpoint: aws.String(server.URL),
|
||||
S3ForcePathStyle: aws.Bool(true),
|
||||
DisableSSL: aws.Bool(true),
|
||||
})
|
||||
_, err := svc.GetObject(&s3.GetObjectInput{
|
||||
Bucket: aws.String("bucketname"),
|
||||
Key: aws.String("keyname"),
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestBuildContentLength_NegativeBody(t *testing.T) {
|
||||
server := setupContentLengthTestServer(t, false, 0)
|
||||
|
||||
svc := s3.New(unit.Session, &aws.Config{
|
||||
Endpoint: aws.String(server.URL),
|
||||
S3ForcePathStyle: aws.Bool(true),
|
||||
DisableSSL: aws.Bool(true),
|
||||
})
|
||||
req, _ := svc.GetObjectRequest(&s3.GetObjectInput{
|
||||
Bucket: aws.String("bucketname"),
|
||||
Key: aws.String("keyname"),
|
||||
})
|
||||
|
||||
req.HTTPRequest.Header.Set("Content-Length", "-1")
|
||||
|
||||
assert.NoError(t, req.Send())
|
||||
}
|
||||
|
||||
func TestBuildContentLength_WithBody(t *testing.T) {
|
||||
server := setupContentLengthTestServer(t, true, 1024)
|
||||
|
||||
svc := s3.New(unit.Session, &aws.Config{
|
||||
Endpoint: aws.String(server.URL),
|
||||
S3ForcePathStyle: aws.Bool(true),
|
||||
DisableSSL: aws.Bool(true),
|
||||
})
|
||||
_, err := svc.PutObject(&s3.PutObjectInput{
|
||||
Bucket: aws.String("bucketname"),
|
||||
Key: aws.String("keyname"),
|
||||
Body: bytes.NewReader(make([]byte, 1024)),
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
}
|
254
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator_test.go
generated
vendored
254
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator_test.go
generated
vendored
@ -1,254 +0,0 @@
|
||||
package corehandlers_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/client"
|
||||
"github.com/aws/aws-sdk-go/aws/client/metadata"
|
||||
"github.com/aws/aws-sdk-go/aws/corehandlers"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||
"github.com/aws/aws-sdk-go/service/kinesis"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var testSvc = func() *client.Client {
|
||||
s := &client.Client{
|
||||
Config: aws.Config{},
|
||||
ClientInfo: metadata.ClientInfo{
|
||||
ServiceName: "mock-service",
|
||||
APIVersion: "2015-01-01",
|
||||
},
|
||||
}
|
||||
return s
|
||||
}()
|
||||
|
||||
type StructShape struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
RequiredList []*ConditionalStructShape `required:"true"`
|
||||
RequiredMap map[string]*ConditionalStructShape `required:"true"`
|
||||
RequiredBool *bool `required:"true"`
|
||||
OptionalStruct *ConditionalStructShape
|
||||
|
||||
hiddenParameter *string
|
||||
}
|
||||
|
||||
func (s *StructShape) Validate() error {
|
||||
invalidParams := request.ErrInvalidParams{Context: "StructShape"}
|
||||
if s.RequiredList == nil {
|
||||
invalidParams.Add(request.NewErrParamRequired("RequiredList"))
|
||||
}
|
||||
if s.RequiredMap == nil {
|
||||
invalidParams.Add(request.NewErrParamRequired("RequiredMap"))
|
||||
}
|
||||
if s.RequiredBool == nil {
|
||||
invalidParams.Add(request.NewErrParamRequired("RequiredBool"))
|
||||
}
|
||||
if s.RequiredList != nil {
|
||||
for i, v := range s.RequiredList {
|
||||
if v == nil {
|
||||
continue
|
||||
}
|
||||
if err := v.Validate(); err != nil {
|
||||
invalidParams.AddNested(fmt.Sprintf("%s[%v]", "RequiredList", i), err.(request.ErrInvalidParams))
|
||||
}
|
||||
}
|
||||
}
|
||||
if s.RequiredMap != nil {
|
||||
for i, v := range s.RequiredMap {
|
||||
if v == nil {
|
||||
continue
|
||||
}
|
||||
if err := v.Validate(); err != nil {
|
||||
invalidParams.AddNested(fmt.Sprintf("%s[%v]", "RequiredMap", i), err.(request.ErrInvalidParams))
|
||||
}
|
||||
}
|
||||
}
|
||||
if s.OptionalStruct != nil {
|
||||
if err := s.OptionalStruct.Validate(); err != nil {
|
||||
invalidParams.AddNested("OptionalStruct", err.(request.ErrInvalidParams))
|
||||
}
|
||||
}
|
||||
|
||||
if invalidParams.Len() > 0 {
|
||||
return invalidParams
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ConditionalStructShape struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
Name *string `required:"true"`
|
||||
}
|
||||
|
||||
func (s *ConditionalStructShape) Validate() error {
|
||||
invalidParams := request.ErrInvalidParams{Context: "ConditionalStructShape"}
|
||||
if s.Name == nil {
|
||||
invalidParams.Add(request.NewErrParamRequired("Name"))
|
||||
}
|
||||
|
||||
if invalidParams.Len() > 0 {
|
||||
return invalidParams
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestNoErrors(t *testing.T) {
|
||||
input := &StructShape{
|
||||
RequiredList: []*ConditionalStructShape{},
|
||||
RequiredMap: map[string]*ConditionalStructShape{
|
||||
"key1": {Name: aws.String("Name")},
|
||||
"key2": {Name: aws.String("Name")},
|
||||
},
|
||||
RequiredBool: aws.Bool(true),
|
||||
OptionalStruct: &ConditionalStructShape{Name: aws.String("Name")},
|
||||
}
|
||||
|
||||
req := testSvc.NewRequest(&request.Operation{}, input, nil)
|
||||
corehandlers.ValidateParametersHandler.Fn(req)
|
||||
require.NoError(t, req.Error)
|
||||
}
|
||||
|
||||
func TestMissingRequiredParameters(t *testing.T) {
|
||||
input := &StructShape{}
|
||||
req := testSvc.NewRequest(&request.Operation{}, input, nil)
|
||||
corehandlers.ValidateParametersHandler.Fn(req)
|
||||
|
||||
require.Error(t, req.Error)
|
||||
assert.Equal(t, "InvalidParameter", req.Error.(awserr.Error).Code())
|
||||
assert.Equal(t, "3 validation error(s) found.", req.Error.(awserr.Error).Message())
|
||||
|
||||
errs := req.Error.(awserr.BatchedErrors).OrigErrs()
|
||||
assert.Len(t, errs, 3)
|
||||
assert.Equal(t, "ParamRequiredError: missing required field, StructShape.RequiredList.", errs[0].Error())
|
||||
assert.Equal(t, "ParamRequiredError: missing required field, StructShape.RequiredMap.", errs[1].Error())
|
||||
assert.Equal(t, "ParamRequiredError: missing required field, StructShape.RequiredBool.", errs[2].Error())
|
||||
|
||||
assert.Equal(t, "InvalidParameter: 3 validation error(s) found.\n- missing required field, StructShape.RequiredList.\n- missing required field, StructShape.RequiredMap.\n- missing required field, StructShape.RequiredBool.\n", req.Error.Error())
|
||||
}
|
||||
|
||||
func TestNestedMissingRequiredParameters(t *testing.T) {
|
||||
input := &StructShape{
|
||||
RequiredList: []*ConditionalStructShape{{}},
|
||||
RequiredMap: map[string]*ConditionalStructShape{
|
||||
"key1": {Name: aws.String("Name")},
|
||||
"key2": {},
|
||||
},
|
||||
RequiredBool: aws.Bool(true),
|
||||
OptionalStruct: &ConditionalStructShape{},
|
||||
}
|
||||
|
||||
req := testSvc.NewRequest(&request.Operation{}, input, nil)
|
||||
corehandlers.ValidateParametersHandler.Fn(req)
|
||||
|
||||
require.Error(t, req.Error)
|
||||
assert.Equal(t, "InvalidParameter", req.Error.(awserr.Error).Code())
|
||||
assert.Equal(t, "3 validation error(s) found.", req.Error.(awserr.Error).Message())
|
||||
|
||||
errs := req.Error.(awserr.BatchedErrors).OrigErrs()
|
||||
assert.Len(t, errs, 3)
|
||||
assert.Equal(t, "ParamRequiredError: missing required field, StructShape.RequiredList[0].Name.", errs[0].Error())
|
||||
assert.Equal(t, "ParamRequiredError: missing required field, StructShape.RequiredMap[key2].Name.", errs[1].Error())
|
||||
assert.Equal(t, "ParamRequiredError: missing required field, StructShape.OptionalStruct.Name.", errs[2].Error())
|
||||
}
|
||||
|
||||
type testInput struct {
|
||||
StringField *string `min:"5"`
|
||||
ListField []string `min:"3"`
|
||||
MapField map[string]string `min:"4"`
|
||||
}
|
||||
|
||||
func (s testInput) Validate() error {
|
||||
invalidParams := request.ErrInvalidParams{Context: "testInput"}
|
||||
if s.StringField != nil && len(*s.StringField) < 5 {
|
||||
invalidParams.Add(request.NewErrParamMinLen("StringField", 5))
|
||||
}
|
||||
if s.ListField != nil && len(s.ListField) < 3 {
|
||||
invalidParams.Add(request.NewErrParamMinLen("ListField", 3))
|
||||
}
|
||||
if s.MapField != nil && len(s.MapField) < 4 {
|
||||
invalidParams.Add(request.NewErrParamMinLen("MapField", 4))
|
||||
}
|
||||
|
||||
if invalidParams.Len() > 0 {
|
||||
return invalidParams
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var testsFieldMin = []struct {
|
||||
err awserr.Error
|
||||
in testInput
|
||||
}{
|
||||
{
|
||||
err: func() awserr.Error {
|
||||
invalidParams := request.ErrInvalidParams{Context: "testInput"}
|
||||
invalidParams.Add(request.NewErrParamMinLen("StringField", 5))
|
||||
return invalidParams
|
||||
}(),
|
||||
in: testInput{StringField: aws.String("abcd")},
|
||||
},
|
||||
{
|
||||
err: func() awserr.Error {
|
||||
invalidParams := request.ErrInvalidParams{Context: "testInput"}
|
||||
invalidParams.Add(request.NewErrParamMinLen("StringField", 5))
|
||||
invalidParams.Add(request.NewErrParamMinLen("ListField", 3))
|
||||
return invalidParams
|
||||
}(),
|
||||
in: testInput{StringField: aws.String("abcd"), ListField: []string{"a", "b"}},
|
||||
},
|
||||
{
|
||||
err: func() awserr.Error {
|
||||
invalidParams := request.ErrInvalidParams{Context: "testInput"}
|
||||
invalidParams.Add(request.NewErrParamMinLen("StringField", 5))
|
||||
invalidParams.Add(request.NewErrParamMinLen("ListField", 3))
|
||||
invalidParams.Add(request.NewErrParamMinLen("MapField", 4))
|
||||
return invalidParams
|
||||
}(),
|
||||
in: testInput{StringField: aws.String("abcd"), ListField: []string{"a", "b"}, MapField: map[string]string{"a": "a", "b": "b"}},
|
||||
},
|
||||
{
|
||||
err: nil,
|
||||
in: testInput{StringField: aws.String("abcde"),
|
||||
ListField: []string{"a", "b", "c"}, MapField: map[string]string{"a": "a", "b": "b", "c": "c", "d": "d"}},
|
||||
},
|
||||
}
|
||||
|
||||
func TestValidateFieldMinParameter(t *testing.T) {
|
||||
for i, c := range testsFieldMin {
|
||||
req := testSvc.NewRequest(&request.Operation{}, &c.in, nil)
|
||||
corehandlers.ValidateParametersHandler.Fn(req)
|
||||
|
||||
assert.Equal(t, c.err, req.Error, "%d case failed", i)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkValidateAny(b *testing.B) {
|
||||
input := &kinesis.PutRecordsInput{
|
||||
StreamName: aws.String("stream"),
|
||||
}
|
||||
for i := 0; i < 100; i++ {
|
||||
record := &kinesis.PutRecordsRequestEntry{
|
||||
Data: make([]byte, 10000),
|
||||
PartitionKey: aws.String("partition"),
|
||||
}
|
||||
input.Records = append(input.Records, record)
|
||||
}
|
||||
|
||||
req, _ := kinesis.New(unit.Session).PutRecordsRequest(input)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
corehandlers.ValidateParametersHandler.Fn(req)
|
||||
if err := req.Error; err != nil {
|
||||
b.Fatalf("validation failed: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
2
vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go
generated
vendored
@ -34,7 +34,7 @@ var (
|
||||
//
|
||||
// Example of ChainProvider to be used with an EnvProvider and EC2RoleProvider.
|
||||
// In this example EnvProvider will first check if any credentials are available
|
||||
// vai the environment variables. If there are none ChainProvider will check
|
||||
// via the environment variables. If there are none ChainProvider will check
|
||||
// the next Provider in the list, EC2RoleProvider in this case. If EC2RoleProvider
|
||||
// does not return any credentials ChainProvider will return the error
|
||||
// ErrNoValidProvidersFoundInChain
|
||||
|
154
vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider_test.go
generated
vendored
154
vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider_test.go
generated
vendored
@ -1,154 +0,0 @@
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type secondStubProvider struct {
|
||||
creds Value
|
||||
expired bool
|
||||
err error
|
||||
}
|
||||
|
||||
func (s *secondStubProvider) Retrieve() (Value, error) {
|
||||
s.expired = false
|
||||
s.creds.ProviderName = "secondStubProvider"
|
||||
return s.creds, s.err
|
||||
}
|
||||
func (s *secondStubProvider) IsExpired() bool {
|
||||
return s.expired
|
||||
}
|
||||
|
||||
func TestChainProviderWithNames(t *testing.T) {
|
||||
p := &ChainProvider{
|
||||
Providers: []Provider{
|
||||
&stubProvider{err: awserr.New("FirstError", "first provider error", nil)},
|
||||
&stubProvider{err: awserr.New("SecondError", "second provider error", nil)},
|
||||
&secondStubProvider{
|
||||
creds: Value{
|
||||
AccessKeyID: "AKIF",
|
||||
SecretAccessKey: "NOSECRET",
|
||||
SessionToken: "",
|
||||
},
|
||||
},
|
||||
&stubProvider{
|
||||
creds: Value{
|
||||
AccessKeyID: "AKID",
|
||||
SecretAccessKey: "SECRET",
|
||||
SessionToken: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
creds, err := p.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error")
|
||||
assert.Equal(t, "secondStubProvider", creds.ProviderName, "Expect provider name to match")
|
||||
|
||||
// Also check credentials
|
||||
assert.Equal(t, "AKIF", creds.AccessKeyID, "Expect access key ID to match")
|
||||
assert.Equal(t, "NOSECRET", creds.SecretAccessKey, "Expect secret access key to match")
|
||||
assert.Empty(t, creds.SessionToken, "Expect session token to be empty")
|
||||
|
||||
}
|
||||
|
||||
func TestChainProviderGet(t *testing.T) {
|
||||
p := &ChainProvider{
|
||||
Providers: []Provider{
|
||||
&stubProvider{err: awserr.New("FirstError", "first provider error", nil)},
|
||||
&stubProvider{err: awserr.New("SecondError", "second provider error", nil)},
|
||||
&stubProvider{
|
||||
creds: Value{
|
||||
AccessKeyID: "AKID",
|
||||
SecretAccessKey: "SECRET",
|
||||
SessionToken: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
creds, err := p.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error")
|
||||
assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match")
|
||||
assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match")
|
||||
assert.Empty(t, creds.SessionToken, "Expect session token to be empty")
|
||||
}
|
||||
|
||||
func TestChainProviderIsExpired(t *testing.T) {
|
||||
stubProvider := &stubProvider{expired: true}
|
||||
p := &ChainProvider{
|
||||
Providers: []Provider{
|
||||
stubProvider,
|
||||
},
|
||||
}
|
||||
|
||||
assert.True(t, p.IsExpired(), "Expect expired to be true before any Retrieve")
|
||||
_, err := p.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error")
|
||||
assert.False(t, p.IsExpired(), "Expect not expired after retrieve")
|
||||
|
||||
stubProvider.expired = true
|
||||
assert.True(t, p.IsExpired(), "Expect return of expired provider")
|
||||
|
||||
_, err = p.Retrieve()
|
||||
assert.False(t, p.IsExpired(), "Expect not expired after retrieve")
|
||||
}
|
||||
|
||||
func TestChainProviderWithNoProvider(t *testing.T) {
|
||||
p := &ChainProvider{
|
||||
Providers: []Provider{},
|
||||
}
|
||||
|
||||
assert.True(t, p.IsExpired(), "Expect expired with no providers")
|
||||
_, err := p.Retrieve()
|
||||
assert.Equal(t,
|
||||
ErrNoValidProvidersFoundInChain,
|
||||
err,
|
||||
"Expect no providers error returned")
|
||||
}
|
||||
|
||||
func TestChainProviderWithNoValidProvider(t *testing.T) {
|
||||
errs := []error{
|
||||
awserr.New("FirstError", "first provider error", nil),
|
||||
awserr.New("SecondError", "second provider error", nil),
|
||||
}
|
||||
p := &ChainProvider{
|
||||
Providers: []Provider{
|
||||
&stubProvider{err: errs[0]},
|
||||
&stubProvider{err: errs[1]},
|
||||
},
|
||||
}
|
||||
|
||||
assert.True(t, p.IsExpired(), "Expect expired with no providers")
|
||||
_, err := p.Retrieve()
|
||||
|
||||
assert.Equal(t,
|
||||
ErrNoValidProvidersFoundInChain,
|
||||
err,
|
||||
"Expect no providers error returned")
|
||||
}
|
||||
|
||||
func TestChainProviderWithNoValidProviderWithVerboseEnabled(t *testing.T) {
|
||||
errs := []error{
|
||||
awserr.New("FirstError", "first provider error", nil),
|
||||
awserr.New("SecondError", "second provider error", nil),
|
||||
}
|
||||
p := &ChainProvider{
|
||||
VerboseErrors: true,
|
||||
Providers: []Provider{
|
||||
&stubProvider{err: errs[0]},
|
||||
&stubProvider{err: errs[1]},
|
||||
},
|
||||
}
|
||||
|
||||
assert.True(t, p.IsExpired(), "Expect expired with no providers")
|
||||
_, err := p.Retrieve()
|
||||
|
||||
assert.Equal(t,
|
||||
awserr.NewBatchError("NoCredentialProviders", "no valid providers in chain", errs),
|
||||
err,
|
||||
"Expect no providers error returned")
|
||||
}
|
73
vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials_test.go
generated
vendored
73
vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials_test.go
generated
vendored
@ -1,73 +0,0 @@
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type stubProvider struct {
|
||||
creds Value
|
||||
expired bool
|
||||
err error
|
||||
}
|
||||
|
||||
func (s *stubProvider) Retrieve() (Value, error) {
|
||||
s.expired = false
|
||||
s.creds.ProviderName = "stubProvider"
|
||||
return s.creds, s.err
|
||||
}
|
||||
func (s *stubProvider) IsExpired() bool {
|
||||
return s.expired
|
||||
}
|
||||
|
||||
func TestCredentialsGet(t *testing.T) {
|
||||
c := NewCredentials(&stubProvider{
|
||||
creds: Value{
|
||||
AccessKeyID: "AKID",
|
||||
SecretAccessKey: "SECRET",
|
||||
SessionToken: "",
|
||||
},
|
||||
expired: true,
|
||||
})
|
||||
|
||||
creds, err := c.Get()
|
||||
assert.Nil(t, err, "Expected no error")
|
||||
assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match")
|
||||
assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match")
|
||||
assert.Empty(t, creds.SessionToken, "Expect session token to be empty")
|
||||
}
|
||||
|
||||
func TestCredentialsGetWithError(t *testing.T) {
|
||||
c := NewCredentials(&stubProvider{err: awserr.New("provider error", "", nil), expired: true})
|
||||
|
||||
_, err := c.Get()
|
||||
assert.Equal(t, "provider error", err.(awserr.Error).Code(), "Expected provider error")
|
||||
}
|
||||
|
||||
func TestCredentialsExpire(t *testing.T) {
|
||||
stub := &stubProvider{}
|
||||
c := NewCredentials(stub)
|
||||
|
||||
stub.expired = false
|
||||
assert.True(t, c.IsExpired(), "Expected to start out expired")
|
||||
c.Expire()
|
||||
assert.True(t, c.IsExpired(), "Expected to be expired")
|
||||
|
||||
c.forceRefresh = false
|
||||
assert.False(t, c.IsExpired(), "Expected not to be expired")
|
||||
|
||||
stub.expired = true
|
||||
assert.True(t, c.IsExpired(), "Expected to be expired")
|
||||
}
|
||||
|
||||
func TestCredentialsGetWithProviderName(t *testing.T) {
|
||||
stub := &stubProvider{}
|
||||
|
||||
c := NewCredentials(stub)
|
||||
|
||||
creds, err := c.Get()
|
||||
assert.Nil(t, err, "Expected no error")
|
||||
assert.Equal(t, creds.ProviderName, "stubProvider", "Expected provider name to match")
|
||||
}
|
2
vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go
generated
vendored
@ -111,7 +111,7 @@ func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// A ec2RoleCredRespBody provides the shape for unmarshalling credential
|
||||
// A ec2RoleCredRespBody provides the shape for unmarshaling credential
|
||||
// request responses.
|
||||
type ec2RoleCredRespBody struct {
|
||||
// Success State
|
||||
|
159
vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider_test.go
generated
vendored
159
vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider_test.go
generated
vendored
@ -1,159 +0,0 @@
|
||||
package ec2rolecreds_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
|
||||
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
||||
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||
)
|
||||
|
||||
const credsRespTmpl = `{
|
||||
"Code": "Success",
|
||||
"Type": "AWS-HMAC",
|
||||
"AccessKeyId" : "accessKey",
|
||||
"SecretAccessKey" : "secret",
|
||||
"Token" : "token",
|
||||
"Expiration" : "%s",
|
||||
"LastUpdated" : "2009-11-23T0:00:00Z"
|
||||
}`
|
||||
|
||||
const credsFailRespTmpl = `{
|
||||
"Code": "ErrorCode",
|
||||
"Message": "ErrorMsg",
|
||||
"LastUpdated": "2009-11-23T0:00:00Z"
|
||||
}`
|
||||
|
||||
func initTestServer(expireOn string, failAssume bool) *httptest.Server {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/latest/meta-data/iam/security-credentials" {
|
||||
fmt.Fprintln(w, "RoleName")
|
||||
} else if r.URL.Path == "/latest/meta-data/iam/security-credentials/RoleName" {
|
||||
if failAssume {
|
||||
fmt.Fprintf(w, credsFailRespTmpl)
|
||||
} else {
|
||||
fmt.Fprintf(w, credsRespTmpl, expireOn)
|
||||
}
|
||||
} else {
|
||||
http.Error(w, "bad request", http.StatusBadRequest)
|
||||
}
|
||||
}))
|
||||
|
||||
return server
|
||||
}
|
||||
|
||||
func TestEC2RoleProvider(t *testing.T) {
|
||||
server := initTestServer("2014-12-16T01:51:37Z", false)
|
||||
defer server.Close()
|
||||
|
||||
p := &ec2rolecreds.EC2RoleProvider{
|
||||
Client: ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")}),
|
||||
}
|
||||
|
||||
creds, err := p.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error, %v", err)
|
||||
|
||||
assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
|
||||
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||
assert.Equal(t, "token", creds.SessionToken, "Expect session token to match")
|
||||
}
|
||||
|
||||
func TestEC2RoleProviderFailAssume(t *testing.T) {
|
||||
server := initTestServer("2014-12-16T01:51:37Z", true)
|
||||
defer server.Close()
|
||||
|
||||
p := &ec2rolecreds.EC2RoleProvider{
|
||||
Client: ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")}),
|
||||
}
|
||||
|
||||
creds, err := p.Retrieve()
|
||||
assert.Error(t, err, "Expect error")
|
||||
|
||||
e := err.(awserr.Error)
|
||||
assert.Equal(t, "ErrorCode", e.Code())
|
||||
assert.Equal(t, "ErrorMsg", e.Message())
|
||||
assert.Nil(t, e.OrigErr())
|
||||
|
||||
assert.Equal(t, "", creds.AccessKeyID, "Expect access key ID to match")
|
||||
assert.Equal(t, "", creds.SecretAccessKey, "Expect secret access key to match")
|
||||
assert.Equal(t, "", creds.SessionToken, "Expect session token to match")
|
||||
}
|
||||
|
||||
func TestEC2RoleProviderIsExpired(t *testing.T) {
|
||||
server := initTestServer("2014-12-16T01:51:37Z", false)
|
||||
defer server.Close()
|
||||
|
||||
p := &ec2rolecreds.EC2RoleProvider{
|
||||
Client: ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")}),
|
||||
}
|
||||
p.CurrentTime = func() time.Time {
|
||||
return time.Date(2014, 12, 15, 21, 26, 0, 0, time.UTC)
|
||||
}
|
||||
|
||||
assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve.")
|
||||
|
||||
_, err := p.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error, %v", err)
|
||||
|
||||
assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve.")
|
||||
|
||||
p.CurrentTime = func() time.Time {
|
||||
return time.Date(3014, 12, 15, 21, 26, 0, 0, time.UTC)
|
||||
}
|
||||
|
||||
assert.True(t, p.IsExpired(), "Expect creds to be expired.")
|
||||
}
|
||||
|
||||
func TestEC2RoleProviderExpiryWindowIsExpired(t *testing.T) {
|
||||
server := initTestServer("2014-12-16T01:51:37Z", false)
|
||||
defer server.Close()
|
||||
|
||||
p := &ec2rolecreds.EC2RoleProvider{
|
||||
Client: ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")}),
|
||||
ExpiryWindow: time.Hour * 1,
|
||||
}
|
||||
p.CurrentTime = func() time.Time {
|
||||
return time.Date(2014, 12, 15, 0, 51, 37, 0, time.UTC)
|
||||
}
|
||||
|
||||
assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve.")
|
||||
|
||||
_, err := p.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error, %v", err)
|
||||
|
||||
assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve.")
|
||||
|
||||
p.CurrentTime = func() time.Time {
|
||||
return time.Date(2014, 12, 16, 0, 55, 37, 0, time.UTC)
|
||||
}
|
||||
|
||||
assert.True(t, p.IsExpired(), "Expect creds to be expired.")
|
||||
}
|
||||
|
||||
func BenchmarkEC3RoleProvider(b *testing.B) {
|
||||
server := initTestServer("2014-12-16T01:51:37Z", false)
|
||||
defer server.Close()
|
||||
|
||||
p := &ec2rolecreds.EC2RoleProvider{
|
||||
Client: ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")}),
|
||||
}
|
||||
_, err := p.Retrieve()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := p.Retrieve(); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
111
vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider_test.go
generated
vendored
111
vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider_test.go
generated
vendored
@ -1,111 +0,0 @@
|
||||
package endpointcreds_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials/endpointcreds"
|
||||
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRetrieveRefreshableCredentials(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
assert.Equal(t, "/path/to/endpoint", r.URL.Path)
|
||||
assert.Equal(t, "application/json", r.Header.Get("Accept"))
|
||||
assert.Equal(t, "else", r.URL.Query().Get("something"))
|
||||
|
||||
encoder := json.NewEncoder(w)
|
||||
err := encoder.Encode(map[string]interface{}{
|
||||
"AccessKeyID": "AKID",
|
||||
"SecretAccessKey": "SECRET",
|
||||
"Token": "TOKEN",
|
||||
"Expiration": time.Now().Add(1 * time.Hour),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("failed to write out creds", err)
|
||||
}
|
||||
}))
|
||||
|
||||
client := endpointcreds.NewProviderClient(*unit.Session.Config,
|
||||
unit.Session.Handlers,
|
||||
server.URL+"/path/to/endpoint?something=else",
|
||||
)
|
||||
creds, err := client.Retrieve()
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "AKID", creds.AccessKeyID)
|
||||
assert.Equal(t, "SECRET", creds.SecretAccessKey)
|
||||
assert.Equal(t, "TOKEN", creds.SessionToken)
|
||||
assert.False(t, client.IsExpired())
|
||||
|
||||
client.(*endpointcreds.Provider).CurrentTime = func() time.Time {
|
||||
return time.Now().Add(2 * time.Hour)
|
||||
}
|
||||
|
||||
assert.True(t, client.IsExpired())
|
||||
}
|
||||
|
||||
func TestRetrieveStaticCredentials(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
encoder := json.NewEncoder(w)
|
||||
err := encoder.Encode(map[string]interface{}{
|
||||
"AccessKeyID": "AKID",
|
||||
"SecretAccessKey": "SECRET",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("failed to write out creds", err)
|
||||
}
|
||||
}))
|
||||
|
||||
client := endpointcreds.NewProviderClient(*unit.Session.Config, unit.Session.Handlers, server.URL)
|
||||
creds, err := client.Retrieve()
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "AKID", creds.AccessKeyID)
|
||||
assert.Equal(t, "SECRET", creds.SecretAccessKey)
|
||||
assert.Empty(t, creds.SessionToken)
|
||||
assert.False(t, client.IsExpired())
|
||||
}
|
||||
|
||||
func TestFailedRetrieveCredentials(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(400)
|
||||
encoder := json.NewEncoder(w)
|
||||
err := encoder.Encode(map[string]interface{}{
|
||||
"Code": "Error",
|
||||
"Message": "Message",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("failed to write error", err)
|
||||
}
|
||||
}))
|
||||
|
||||
client := endpointcreds.NewProviderClient(*unit.Session.Config, unit.Session.Handlers, server.URL)
|
||||
creds, err := client.Retrieve()
|
||||
|
||||
assert.Error(t, err)
|
||||
aerr := err.(awserr.Error)
|
||||
|
||||
assert.Equal(t, "CredentialsEndpointError", aerr.Code())
|
||||
assert.Equal(t, "failed to load credentials", aerr.Message())
|
||||
|
||||
aerr = aerr.OrigErr().(awserr.Error)
|
||||
assert.Equal(t, "Error", aerr.Code())
|
||||
assert.Equal(t, "Message", aerr.Message())
|
||||
|
||||
assert.Empty(t, creds.AccessKeyID)
|
||||
assert.Empty(t, creds.SecretAccessKey)
|
||||
assert.Empty(t, creds.SessionToken)
|
||||
assert.True(t, client.IsExpired())
|
||||
}
|
70
vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider_test.go
generated
vendored
70
vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider_test.go
generated
vendored
@ -1,70 +0,0 @@
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEnvProviderRetrieve(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("AWS_ACCESS_KEY_ID", "access")
|
||||
os.Setenv("AWS_SECRET_ACCESS_KEY", "secret")
|
||||
os.Setenv("AWS_SESSION_TOKEN", "token")
|
||||
|
||||
e := EnvProvider{}
|
||||
creds, err := e.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error")
|
||||
|
||||
assert.Equal(t, "access", creds.AccessKeyID, "Expect access key ID to match")
|
||||
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||
assert.Equal(t, "token", creds.SessionToken, "Expect session token to match")
|
||||
}
|
||||
|
||||
func TestEnvProviderIsExpired(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("AWS_ACCESS_KEY_ID", "access")
|
||||
os.Setenv("AWS_SECRET_ACCESS_KEY", "secret")
|
||||
os.Setenv("AWS_SESSION_TOKEN", "token")
|
||||
|
||||
e := EnvProvider{}
|
||||
|
||||
assert.True(t, e.IsExpired(), "Expect creds to be expired before retrieve.")
|
||||
|
||||
_, err := e.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error")
|
||||
|
||||
assert.False(t, e.IsExpired(), "Expect creds to not be expired after retrieve.")
|
||||
}
|
||||
|
||||
func TestEnvProviderNoAccessKeyID(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("AWS_SECRET_ACCESS_KEY", "secret")
|
||||
|
||||
e := EnvProvider{}
|
||||
creds, err := e.Retrieve()
|
||||
assert.Equal(t, ErrAccessKeyIDNotFound, err, "ErrAccessKeyIDNotFound expected, but was %#v error: %#v", creds, err)
|
||||
}
|
||||
|
||||
func TestEnvProviderNoSecretAccessKey(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("AWS_ACCESS_KEY_ID", "access")
|
||||
|
||||
e := EnvProvider{}
|
||||
creds, err := e.Retrieve()
|
||||
assert.Equal(t, ErrSecretAccessKeyNotFound, err, "ErrSecretAccessKeyNotFound expected, but was %#v error: %#v", creds, err)
|
||||
}
|
||||
|
||||
func TestEnvProviderAlternateNames(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("AWS_ACCESS_KEY", "access")
|
||||
os.Setenv("AWS_SECRET_KEY", "secret")
|
||||
|
||||
e := EnvProvider{}
|
||||
creds, err := e.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error")
|
||||
|
||||
assert.Equal(t, "access", creds.AccessKeyID, "Expected access key ID")
|
||||
assert.Equal(t, "secret", creds.SecretAccessKey, "Expected secret access key")
|
||||
assert.Empty(t, creds.SessionToken, "Expected no token")
|
||||
}
|
116
vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider_test.go
generated
vendored
116
vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider_test.go
generated
vendored
@ -1,116 +0,0 @@
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSharedCredentialsProvider(t *testing.T) {
|
||||
os.Clearenv()
|
||||
|
||||
p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""}
|
||||
creds, err := p.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error")
|
||||
|
||||
assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
|
||||
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||
assert.Equal(t, "token", creds.SessionToken, "Expect session token to match")
|
||||
}
|
||||
|
||||
func TestSharedCredentialsProviderIsExpired(t *testing.T) {
|
||||
os.Clearenv()
|
||||
|
||||
p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""}
|
||||
|
||||
assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve")
|
||||
|
||||
_, err := p.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error")
|
||||
|
||||
assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve")
|
||||
}
|
||||
|
||||
func TestSharedCredentialsProviderWithAWS_SHARED_CREDENTIALS_FILE(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", "example.ini")
|
||||
p := SharedCredentialsProvider{}
|
||||
creds, err := p.Retrieve()
|
||||
|
||||
assert.Nil(t, err, "Expect no error")
|
||||
|
||||
assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
|
||||
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||
assert.Equal(t, "token", creds.SessionToken, "Expect session token to match")
|
||||
}
|
||||
|
||||
func TestSharedCredentialsProviderWithAWS_SHARED_CREDENTIALS_FILEAbsPath(t *testing.T) {
|
||||
os.Clearenv()
|
||||
wd, err := os.Getwd()
|
||||
assert.NoError(t, err)
|
||||
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", filepath.Join(wd, "example.ini"))
|
||||
p := SharedCredentialsProvider{}
|
||||
creds, err := p.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error")
|
||||
|
||||
assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
|
||||
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||
assert.Equal(t, "token", creds.SessionToken, "Expect session token to match")
|
||||
}
|
||||
|
||||
func TestSharedCredentialsProviderWithAWS_PROFILE(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("AWS_PROFILE", "no_token")
|
||||
|
||||
p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""}
|
||||
creds, err := p.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error")
|
||||
|
||||
assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
|
||||
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||
assert.Empty(t, creds.SessionToken, "Expect no token")
|
||||
}
|
||||
|
||||
func TestSharedCredentialsProviderWithoutTokenFromProfile(t *testing.T) {
|
||||
os.Clearenv()
|
||||
|
||||
p := SharedCredentialsProvider{Filename: "example.ini", Profile: "no_token"}
|
||||
creds, err := p.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error")
|
||||
|
||||
assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
|
||||
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||
assert.Empty(t, creds.SessionToken, "Expect no token")
|
||||
}
|
||||
|
||||
func TestSharedCredentialsProviderColonInCredFile(t *testing.T) {
|
||||
os.Clearenv()
|
||||
|
||||
p := SharedCredentialsProvider{Filename: "example.ini", Profile: "with_colon"}
|
||||
creds, err := p.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error")
|
||||
|
||||
assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
|
||||
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||
assert.Empty(t, creds.SessionToken, "Expect no token")
|
||||
}
|
||||
|
||||
func BenchmarkSharedCredentialsProvider(b *testing.B) {
|
||||
os.Clearenv()
|
||||
|
||||
p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""}
|
||||
_, err := p.Retrieve()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := p.Retrieve()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
34
vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider_test.go
generated
vendored
34
vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider_test.go
generated
vendored
@ -1,34 +0,0 @@
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStaticProviderGet(t *testing.T) {
|
||||
s := StaticProvider{
|
||||
Value: Value{
|
||||
AccessKeyID: "AKID",
|
||||
SecretAccessKey: "SECRET",
|
||||
SessionToken: "",
|
||||
},
|
||||
}
|
||||
|
||||
creds, err := s.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error")
|
||||
assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match")
|
||||
assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match")
|
||||
assert.Empty(t, creds.SessionToken, "Expect no session token")
|
||||
}
|
||||
|
||||
func TestStaticProviderIsExpired(t *testing.T) {
|
||||
s := StaticProvider{
|
||||
Value: Value{
|
||||
AccessKeyID: "AKID",
|
||||
SecretAccessKey: "SECRET",
|
||||
SessionToken: "",
|
||||
},
|
||||
}
|
||||
|
||||
assert.False(t, s.IsExpired(), "Expect static credentials to never expire")
|
||||
}
|
56
vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider_test.go
generated
vendored
56
vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider_test.go
generated
vendored
@ -1,56 +0,0 @@
|
||||
package stscreds
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/sts"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type stubSTS struct {
|
||||
}
|
||||
|
||||
func (s *stubSTS) AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) {
|
||||
expiry := time.Now().Add(60 * time.Minute)
|
||||
return &sts.AssumeRoleOutput{
|
||||
Credentials: &sts.Credentials{
|
||||
// Just reflect the role arn to the provider.
|
||||
AccessKeyId: input.RoleArn,
|
||||
SecretAccessKey: aws.String("assumedSecretAccessKey"),
|
||||
SessionToken: aws.String("assumedSessionToken"),
|
||||
Expiration: &expiry,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TestAssumeRoleProvider(t *testing.T) {
|
||||
stub := &stubSTS{}
|
||||
p := &AssumeRoleProvider{
|
||||
Client: stub,
|
||||
RoleARN: "roleARN",
|
||||
}
|
||||
|
||||
creds, err := p.Retrieve()
|
||||
assert.Nil(t, err, "Expect no error")
|
||||
|
||||
assert.Equal(t, "roleARN", creds.AccessKeyID, "Expect access key ID to be reflected role ARN")
|
||||
assert.Equal(t, "assumedSecretAccessKey", creds.SecretAccessKey, "Expect secret access key to match")
|
||||
assert.Equal(t, "assumedSessionToken", creds.SessionToken, "Expect session token to match")
|
||||
}
|
||||
|
||||
func BenchmarkAssumeRoleProvider(b *testing.B) {
|
||||
stub := &stubSTS{}
|
||||
p := &AssumeRoleProvider{
|
||||
Client: stub,
|
||||
RoleARN: "roleARN",
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := p.Retrieve(); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
1
vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go
generated
vendored
1
vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go
generated
vendored
@ -72,6 +72,7 @@ func Handlers() request.Handlers {
|
||||
handlers.Build.PushBackNamed(corehandlers.SDKVersionUserAgentHandler)
|
||||
handlers.Build.AfterEachFn = request.HandlerListStopOnError
|
||||
handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler)
|
||||
handlers.Send.PushBackNamed(corehandlers.ValidateReqSigHandler)
|
||||
handlers.Send.PushBackNamed(corehandlers.SendHandler)
|
||||
handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler)
|
||||
handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler)
|
||||
|
39
vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults_test.go
generated
vendored
39
vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults_test.go
generated
vendored
@ -1,39 +0,0 @@
|
||||
package defaults
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials/endpointcreds"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestECSCredProvider(t *testing.T) {
|
||||
defer os.Clearenv()
|
||||
os.Setenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI", "/abc/123")
|
||||
|
||||
provider := RemoteCredProvider(aws.Config{}, request.Handlers{})
|
||||
|
||||
assert.NotNil(t, provider)
|
||||
|
||||
ecsProvider, ok := provider.(*endpointcreds.Provider)
|
||||
assert.NotNil(t, ecsProvider)
|
||||
assert.True(t, ok)
|
||||
|
||||
assert.Equal(t, fmt.Sprintf("http://169.254.170.2/abc/123"),
|
||||
ecsProvider.Client.Endpoint)
|
||||
}
|
||||
|
||||
func TestDefaultEC2RoleProvider(t *testing.T) {
|
||||
provider := RemoteCredProvider(aws.Config{}, request.Handlers{})
|
||||
|
||||
assert.NotNil(t, provider)
|
||||
|
||||
ec2Provider, ok := provider.(*ec2rolecreds.EC2RoleProvider)
|
||||
assert.NotNil(t, ec2Provider)
|
||||
assert.True(t, ok)
|
||||
}
|
26
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go
generated
vendored
26
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go
generated
vendored
@ -3,6 +3,7 @@ package ec2metadata
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
@ -27,6 +28,27 @@ func (c *EC2Metadata) GetMetadata(p string) (string, error) {
|
||||
return output.Content, req.Send()
|
||||
}
|
||||
|
||||
// GetUserData returns the userdata that was configured for the service. If
|
||||
// there is no user-data setup for the EC2 instance a "NotFoundError" error
|
||||
// code will be returned.
|
||||
func (c *EC2Metadata) GetUserData() (string, error) {
|
||||
op := &request.Operation{
|
||||
Name: "GetUserData",
|
||||
HTTPMethod: "GET",
|
||||
HTTPPath: path.Join("/", "user-data"),
|
||||
}
|
||||
|
||||
output := &metadataOutput{}
|
||||
req := c.NewRequest(op, nil, output)
|
||||
req.Handlers.UnmarshalError.PushBack(func(r *request.Request) {
|
||||
if r.HTTPResponse.StatusCode == http.StatusNotFound {
|
||||
r.Error = awserr.New("NotFoundError", "user-data not found", r.Error)
|
||||
}
|
||||
})
|
||||
|
||||
return output.Content, req.Send()
|
||||
}
|
||||
|
||||
// GetDynamicData uses the path provided to request information from the EC2
|
||||
// instance metadata service for dynamic data. The content will be returned
|
||||
// as a string, or error if the request failed.
|
||||
@ -111,7 +133,7 @@ func (c *EC2Metadata) Available() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// An EC2IAMInfo provides the shape for unmarshalling
|
||||
// An EC2IAMInfo provides the shape for unmarshaling
|
||||
// an IAM info from the metadata API
|
||||
type EC2IAMInfo struct {
|
||||
Code string
|
||||
@ -120,7 +142,7 @@ type EC2IAMInfo struct {
|
||||
InstanceProfileID string
|
||||
}
|
||||
|
||||
// An EC2InstanceIdentityDocument provides the shape for unmarshalling
|
||||
// An EC2InstanceIdentityDocument provides the shape for unmarshaling
|
||||
// an instance identity document
|
||||
type EC2InstanceIdentityDocument struct {
|
||||
DevpayProductCodes []string `json:"devpayProductCodes"`
|
||||
|
195
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api_test.go
generated
vendored
195
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api_test.go
generated
vendored
@ -1,195 +0,0 @@
|
||||
package ec2metadata_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||
)
|
||||
|
||||
const instanceIdentityDocument = `{
|
||||
"devpayProductCodes" : null,
|
||||
"availabilityZone" : "us-east-1d",
|
||||
"privateIp" : "10.158.112.84",
|
||||
"version" : "2010-08-31",
|
||||
"region" : "us-east-1",
|
||||
"instanceId" : "i-1234567890abcdef0",
|
||||
"billingProducts" : null,
|
||||
"instanceType" : "t1.micro",
|
||||
"accountId" : "123456789012",
|
||||
"pendingTime" : "2015-11-19T16:32:11Z",
|
||||
"imageId" : "ami-5fb8c835",
|
||||
"kernelId" : "aki-919dcaf8",
|
||||
"ramdiskId" : null,
|
||||
"architecture" : "x86_64"
|
||||
}`
|
||||
|
||||
const validIamInfo = `{
|
||||
"Code" : "Success",
|
||||
"LastUpdated" : "2016-03-17T12:27:32Z",
|
||||
"InstanceProfileArn" : "arn:aws:iam::123456789012:instance-profile/my-instance-profile",
|
||||
"InstanceProfileId" : "AIPAABCDEFGHIJKLMN123"
|
||||
}`
|
||||
|
||||
const unsuccessfulIamInfo = `{
|
||||
"Code" : "Failed",
|
||||
"LastUpdated" : "2016-03-17T12:27:32Z",
|
||||
"InstanceProfileArn" : "arn:aws:iam::123456789012:instance-profile/my-instance-profile",
|
||||
"InstanceProfileId" : "AIPAABCDEFGHIJKLMN123"
|
||||
}`
|
||||
|
||||
func initTestServer(path string, resp string) *httptest.Server {
|
||||
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.RequestURI != path {
|
||||
http.Error(w, "not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write([]byte(resp))
|
||||
}))
|
||||
}
|
||||
|
||||
func TestEndpoint(t *testing.T) {
|
||||
c := ec2metadata.New(unit.Session)
|
||||
op := &request.Operation{
|
||||
Name: "GetMetadata",
|
||||
HTTPMethod: "GET",
|
||||
HTTPPath: path.Join("/", "meta-data", "testpath"),
|
||||
}
|
||||
|
||||
req := c.NewRequest(op, nil, nil)
|
||||
assert.Equal(t, "http://169.254.169.254/latest", req.ClientInfo.Endpoint)
|
||||
assert.Equal(t, "http://169.254.169.254/latest/meta-data/testpath", req.HTTPRequest.URL.String())
|
||||
}
|
||||
|
||||
func TestGetMetadata(t *testing.T) {
|
||||
server := initTestServer(
|
||||
"/latest/meta-data/some/path",
|
||||
"success", // real response includes suffix
|
||||
)
|
||||
defer server.Close()
|
||||
c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
|
||||
|
||||
resp, err := c.GetMetadata("some/path")
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "success", resp)
|
||||
}
|
||||
|
||||
func TestGetRegion(t *testing.T) {
|
||||
server := initTestServer(
|
||||
"/latest/meta-data/placement/availability-zone",
|
||||
"us-west-2a", // real response includes suffix
|
||||
)
|
||||
defer server.Close()
|
||||
c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
|
||||
|
||||
region, err := c.Region()
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "us-west-2", region)
|
||||
}
|
||||
|
||||
func TestMetadataAvailable(t *testing.T) {
|
||||
server := initTestServer(
|
||||
"/latest/meta-data/instance-id",
|
||||
"instance-id",
|
||||
)
|
||||
defer server.Close()
|
||||
c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
|
||||
|
||||
available := c.Available()
|
||||
|
||||
assert.True(t, available)
|
||||
}
|
||||
|
||||
func TestMetadataIAMInfo_success(t *testing.T) {
|
||||
server := initTestServer(
|
||||
"/latest/meta-data/iam/info",
|
||||
validIamInfo,
|
||||
)
|
||||
defer server.Close()
|
||||
c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
|
||||
|
||||
iamInfo, err := c.IAMInfo()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Success", iamInfo.Code)
|
||||
assert.Equal(t, "arn:aws:iam::123456789012:instance-profile/my-instance-profile", iamInfo.InstanceProfileArn)
|
||||
assert.Equal(t, "AIPAABCDEFGHIJKLMN123", iamInfo.InstanceProfileID)
|
||||
}
|
||||
|
||||
func TestMetadataIAMInfo_failure(t *testing.T) {
|
||||
server := initTestServer(
|
||||
"/latest/meta-data/iam/info",
|
||||
unsuccessfulIamInfo,
|
||||
)
|
||||
defer server.Close()
|
||||
c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
|
||||
|
||||
iamInfo, err := c.IAMInfo()
|
||||
assert.NotNil(t, err)
|
||||
assert.Equal(t, "", iamInfo.Code)
|
||||
assert.Equal(t, "", iamInfo.InstanceProfileArn)
|
||||
assert.Equal(t, "", iamInfo.InstanceProfileID)
|
||||
}
|
||||
|
||||
func TestMetadataNotAvailable(t *testing.T) {
|
||||
c := ec2metadata.New(unit.Session)
|
||||
c.Handlers.Send.Clear()
|
||||
c.Handlers.Send.PushBack(func(r *request.Request) {
|
||||
r.HTTPResponse = &http.Response{
|
||||
StatusCode: int(0),
|
||||
Status: http.StatusText(int(0)),
|
||||
Body: ioutil.NopCloser(bytes.NewReader([]byte{})),
|
||||
}
|
||||
r.Error = awserr.New("RequestError", "send request failed", nil)
|
||||
r.Retryable = aws.Bool(true) // network errors are retryable
|
||||
})
|
||||
|
||||
available := c.Available()
|
||||
|
||||
assert.False(t, available)
|
||||
}
|
||||
|
||||
func TestMetadataErrorResponse(t *testing.T) {
|
||||
c := ec2metadata.New(unit.Session)
|
||||
c.Handlers.Send.Clear()
|
||||
c.Handlers.Send.PushBack(func(r *request.Request) {
|
||||
r.HTTPResponse = &http.Response{
|
||||
StatusCode: http.StatusBadRequest,
|
||||
Status: http.StatusText(http.StatusBadRequest),
|
||||
Body: ioutil.NopCloser(strings.NewReader("error message text")),
|
||||
}
|
||||
r.Retryable = aws.Bool(false) // network errors are retryable
|
||||
})
|
||||
|
||||
data, err := c.GetMetadata("uri/path")
|
||||
assert.Empty(t, data)
|
||||
assert.Contains(t, err.Error(), "error message text")
|
||||
}
|
||||
|
||||
func TestEC2RoleProviderInstanceIdentity(t *testing.T) {
|
||||
server := initTestServer(
|
||||
"/latest/dynamic/instance-identity/document",
|
||||
instanceIdentityDocument,
|
||||
)
|
||||
defer server.Close()
|
||||
c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
|
||||
|
||||
doc, err := c.GetInstanceIdentityDocument()
|
||||
assert.Nil(t, err, "Expect no error, %v", err)
|
||||
assert.Equal(t, doc.AccountID, "123456789012")
|
||||
assert.Equal(t, doc.AvailabilityZone, "us-east-1d")
|
||||
assert.Equal(t, doc.Region, "us-east-1")
|
||||
}
|
78
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service_test.go
generated
vendored
78
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service_test.go
generated
vendored
@ -1,78 +0,0 @@
|
||||
package ec2metadata_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
||||
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestClientOverrideDefaultHTTPClientTimeout(t *testing.T) {
|
||||
svc := ec2metadata.New(unit.Session)
|
||||
|
||||
assert.NotEqual(t, http.DefaultClient, svc.Config.HTTPClient)
|
||||
assert.Equal(t, 5*time.Second, svc.Config.HTTPClient.Timeout)
|
||||
}
|
||||
|
||||
func TestClientNotOverrideDefaultHTTPClientTimeout(t *testing.T) {
|
||||
http.DefaultClient.Transport = &http.Transport{}
|
||||
defer func() {
|
||||
http.DefaultClient.Transport = nil
|
||||
}()
|
||||
|
||||
svc := ec2metadata.New(unit.Session)
|
||||
|
||||
assert.Equal(t, http.DefaultClient, svc.Config.HTTPClient)
|
||||
|
||||
tr, ok := svc.Config.HTTPClient.Transport.(*http.Transport)
|
||||
assert.True(t, ok)
|
||||
assert.NotNil(t, tr)
|
||||
assert.Nil(t, tr.Dial)
|
||||
}
|
||||
|
||||
func TestClientDisableOverrideDefaultHTTPClientTimeout(t *testing.T) {
|
||||
svc := ec2metadata.New(unit.Session, aws.NewConfig().WithEC2MetadataDisableTimeoutOverride(true))
|
||||
|
||||
assert.Equal(t, http.DefaultClient, svc.Config.HTTPClient)
|
||||
}
|
||||
|
||||
func TestClientOverrideDefaultHTTPClientTimeoutRace(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("us-east-1a"))
|
||||
}))
|
||||
|
||||
cfg := aws.NewConfig().WithEndpoint(server.URL)
|
||||
runEC2MetadataClients(t, cfg, 100)
|
||||
}
|
||||
|
||||
func TestClientOverrideDefaultHTTPClientTimeoutRaceWithTransport(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("us-east-1a"))
|
||||
}))
|
||||
|
||||
cfg := aws.NewConfig().WithEndpoint(server.URL).WithHTTPClient(&http.Client{
|
||||
Transport: http.DefaultTransport,
|
||||
})
|
||||
|
||||
runEC2MetadataClients(t, cfg, 100)
|
||||
}
|
||||
|
||||
func runEC2MetadataClients(t *testing.T, cfg *aws.Config, atOnce int) {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(atOnce)
|
||||
for i := 0; i < atOnce; i++ {
|
||||
go func() {
|
||||
svc := ec2metadata.New(unit.Session, cfg)
|
||||
_, err := svc.Region()
|
||||
assert.NoError(t, err)
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
87
vendor/github.com/aws/aws-sdk-go/aws/request/handlers_test.go
generated
vendored
87
vendor/github.com/aws/aws-sdk-go/aws/request/handlers_test.go
generated
vendored
@ -1,87 +0,0 @@
|
||||
package request_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
)
|
||||
|
||||
func TestHandlerList(t *testing.T) {
|
||||
s := ""
|
||||
r := &request.Request{}
|
||||
l := request.HandlerList{}
|
||||
l.PushBack(func(r *request.Request) {
|
||||
s += "a"
|
||||
r.Data = s
|
||||
})
|
||||
l.Run(r)
|
||||
assert.Equal(t, "a", s)
|
||||
assert.Equal(t, "a", r.Data)
|
||||
}
|
||||
|
||||
func TestMultipleHandlers(t *testing.T) {
|
||||
r := &request.Request{}
|
||||
l := request.HandlerList{}
|
||||
l.PushBack(func(r *request.Request) { r.Data = nil })
|
||||
l.PushFront(func(r *request.Request) { r.Data = aws.Bool(true) })
|
||||
l.Run(r)
|
||||
if r.Data != nil {
|
||||
t.Error("Expected handler to execute")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamedHandlers(t *testing.T) {
|
||||
l := request.HandlerList{}
|
||||
named := request.NamedHandler{Name: "Name", Fn: func(r *request.Request) {}}
|
||||
named2 := request.NamedHandler{Name: "NotName", Fn: func(r *request.Request) {}}
|
||||
l.PushBackNamed(named)
|
||||
l.PushBackNamed(named)
|
||||
l.PushBackNamed(named2)
|
||||
l.PushBack(func(r *request.Request) {})
|
||||
assert.Equal(t, 4, l.Len())
|
||||
l.Remove(named)
|
||||
assert.Equal(t, 2, l.Len())
|
||||
}
|
||||
|
||||
func TestLoggedHandlers(t *testing.T) {
|
||||
expectedHandlers := []string{"name1", "name2"}
|
||||
l := request.HandlerList{}
|
||||
loggedHandlers := []string{}
|
||||
l.AfterEachFn = request.HandlerListLogItem
|
||||
cfg := aws.Config{Logger: aws.LoggerFunc(func(args ...interface{}) {
|
||||
loggedHandlers = append(loggedHandlers, args[2].(string))
|
||||
})}
|
||||
|
||||
named1 := request.NamedHandler{Name: "name1", Fn: func(r *request.Request) {}}
|
||||
named2 := request.NamedHandler{Name: "name2", Fn: func(r *request.Request) {}}
|
||||
l.PushBackNamed(named1)
|
||||
l.PushBackNamed(named2)
|
||||
l.Run(&request.Request{Config: cfg})
|
||||
|
||||
assert.Equal(t, expectedHandlers, loggedHandlers)
|
||||
}
|
||||
|
||||
func TestStopHandlers(t *testing.T) {
|
||||
l := request.HandlerList{}
|
||||
stopAt := 1
|
||||
l.AfterEachFn = func(item request.HandlerListRunItem) bool {
|
||||
return item.Index != stopAt
|
||||
}
|
||||
|
||||
called := 0
|
||||
l.PushBackNamed(request.NamedHandler{Name: "name1", Fn: func(r *request.Request) {
|
||||
called++
|
||||
}})
|
||||
l.PushBackNamed(request.NamedHandler{Name: "name2", Fn: func(r *request.Request) {
|
||||
called++
|
||||
}})
|
||||
l.PushBackNamed(request.NamedHandler{Name: "name3", Fn: func(r *request.Request) {
|
||||
assert.Fail(t, "third handler should not be called")
|
||||
}})
|
||||
l.Run(&request.Request{})
|
||||
|
||||
assert.Equal(t, 2, called, "Expect only two handlers to be called")
|
||||
}
|
21
vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go
generated
vendored
21
vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go
generated
vendored
@ -1,5 +1,3 @@
|
||||
// +build go1.5
|
||||
|
||||
package request
|
||||
|
||||
import (
|
||||
@ -9,20 +7,13 @@ import (
|
||||
)
|
||||
|
||||
func copyHTTPRequest(r *http.Request, body io.ReadCloser) *http.Request {
|
||||
req := &http.Request{
|
||||
URL: &url.URL{},
|
||||
Header: http.Header{},
|
||||
Close: r.Close,
|
||||
Body: body,
|
||||
Host: r.Host,
|
||||
Method: r.Method,
|
||||
Proto: r.Proto,
|
||||
ContentLength: r.ContentLength,
|
||||
// Cancel will be deprecated in 1.7 and will be replaced with Context
|
||||
Cancel: r.Cancel,
|
||||
}
|
||||
|
||||
req := new(http.Request)
|
||||
*req = *r
|
||||
req.URL = &url.URL{}
|
||||
*req.URL = *r.URL
|
||||
req.Body = body
|
||||
|
||||
req.Header = http.Header{}
|
||||
for k, v := range r.Header {
|
||||
for _, vv := range v {
|
||||
req.Header.Add(k, vv)
|
||||
|
31
vendor/github.com/aws/aws-sdk-go/aws/request/http_request_1_4.go
generated
vendored
31
vendor/github.com/aws/aws-sdk-go/aws/request/http_request_1_4.go
generated
vendored
@ -1,31 +0,0 @@
|
||||
// +build !go1.5
|
||||
|
||||
package request
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func copyHTTPRequest(r *http.Request, body io.ReadCloser) *http.Request {
|
||||
req := &http.Request{
|
||||
URL: &url.URL{},
|
||||
Header: http.Header{},
|
||||
Close: r.Close,
|
||||
Body: body,
|
||||
Host: r.Host,
|
||||
Method: r.Method,
|
||||
Proto: r.Proto,
|
||||
ContentLength: r.ContentLength,
|
||||
}
|
||||
|
||||
*req.URL = *r.URL
|
||||
for k, v := range r.Header {
|
||||
for _, vv := range v {
|
||||
req.Header.Add(k, vv)
|
||||
}
|
||||
}
|
||||
|
||||
return req
|
||||
}
|
34
vendor/github.com/aws/aws-sdk-go/aws/request/http_request_copy_test.go
generated
vendored
34
vendor/github.com/aws/aws-sdk-go/aws/request/http_request_copy_test.go
generated
vendored
@ -1,34 +0,0 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRequestCopyRace(t *testing.T) {
|
||||
origReq := &http.Request{URL: &url.URL{}, Header: http.Header{}}
|
||||
origReq.Header.Set("Header", "OrigValue")
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 100; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
req := copyHTTPRequest(origReq, ioutil.NopCloser(&bytes.Buffer{}))
|
||||
req.Header.Set("Header", "Value")
|
||||
go func() {
|
||||
req2 := copyHTTPRequest(req, ioutil.NopCloser(&bytes.Buffer{}))
|
||||
req2.Header.Add("Header", "Value2")
|
||||
}()
|
||||
_ = req.Header.Get("Header")
|
||||
wg.Done()
|
||||
}()
|
||||
_ = origReq.Header.Get("Header")
|
||||
}
|
||||
origReq.Header.Get("Header")
|
||||
|
||||
wg.Wait()
|
||||
}
|
37
vendor/github.com/aws/aws-sdk-go/aws/request/http_request_retry_test.go
generated
vendored
37
vendor/github.com/aws/aws-sdk-go/aws/request/http_request_retry_test.go
generated
vendored
@ -1,37 +0,0 @@
|
||||
// +build go1.5
|
||||
|
||||
package request_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/awstesting/mock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRequestCancelRetry(t *testing.T) {
|
||||
c := make(chan struct{})
|
||||
|
||||
reqNum := 0
|
||||
s := mock.NewMockClient(aws.NewConfig().WithMaxRetries(10))
|
||||
s.Handlers.Validate.Clear()
|
||||
s.Handlers.Unmarshal.Clear()
|
||||
s.Handlers.UnmarshalMeta.Clear()
|
||||
s.Handlers.UnmarshalError.Clear()
|
||||
s.Handlers.Send.PushFront(func(r *request.Request) {
|
||||
reqNum++
|
||||
r.Error = errors.New("net/http: canceled")
|
||||
})
|
||||
out := &testData{}
|
||||
r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out)
|
||||
r.HTTPRequest.Cancel = c
|
||||
close(c)
|
||||
|
||||
err := r.Send()
|
||||
assert.True(t, strings.Contains(err.Error(), "canceled"))
|
||||
assert.Equal(t, 1, reqNum)
|
||||
}
|
19
vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go
generated
vendored
19
vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go
generated
vendored
@ -9,7 +9,7 @@ import (
|
||||
// with retrying requests
|
||||
type offsetReader struct {
|
||||
buf io.ReadSeeker
|
||||
lock sync.RWMutex
|
||||
lock sync.Mutex
|
||||
closed bool
|
||||
}
|
||||
|
||||
@ -21,7 +21,8 @@ func newOffsetReader(buf io.ReadSeeker, offset int64) *offsetReader {
|
||||
return reader
|
||||
}
|
||||
|
||||
// Close is a thread-safe close. Uses the write lock.
|
||||
// Close will close the instance of the offset reader's access to
|
||||
// the underlying io.ReadSeeker.
|
||||
func (o *offsetReader) Close() error {
|
||||
o.lock.Lock()
|
||||
defer o.lock.Unlock()
|
||||
@ -29,10 +30,10 @@ func (o *offsetReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read is a thread-safe read using a read lock.
|
||||
// Read is a thread-safe read of the underlying io.ReadSeeker
|
||||
func (o *offsetReader) Read(p []byte) (int, error) {
|
||||
o.lock.RLock()
|
||||
defer o.lock.RUnlock()
|
||||
o.lock.Lock()
|
||||
defer o.lock.Unlock()
|
||||
|
||||
if o.closed {
|
||||
return 0, io.EOF
|
||||
@ -41,6 +42,14 @@ func (o *offsetReader) Read(p []byte) (int, error) {
|
||||
return o.buf.Read(p)
|
||||
}
|
||||
|
||||
// Seek is a thread-safe seeking operation.
|
||||
func (o *offsetReader) Seek(offset int64, whence int) (int64, error) {
|
||||
o.lock.Lock()
|
||||
defer o.lock.Unlock()
|
||||
|
||||
return o.buf.Seek(offset, whence)
|
||||
}
|
||||
|
||||
// CloseAndCopy will return a new offsetReader with a copy of the old buffer
|
||||
// and close the old buffer.
|
||||
func (o *offsetReader) CloseAndCopy(offset int64) *offsetReader {
|
||||
|
122
vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader_test.go
generated
vendored
122
vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader_test.go
generated
vendored
@ -1,122 +0,0 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestOffsetReaderRead(t *testing.T) {
|
||||
buf := []byte("testData")
|
||||
reader := &offsetReader{buf: bytes.NewReader(buf)}
|
||||
|
||||
tempBuf := make([]byte, len(buf))
|
||||
|
||||
n, err := reader.Read(tempBuf)
|
||||
|
||||
assert.Equal(t, n, len(buf))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, buf, tempBuf)
|
||||
}
|
||||
|
||||
func TestOffsetReaderClose(t *testing.T) {
|
||||
buf := []byte("testData")
|
||||
reader := &offsetReader{buf: bytes.NewReader(buf)}
|
||||
|
||||
err := reader.Close()
|
||||
assert.Nil(t, err)
|
||||
|
||||
tempBuf := make([]byte, len(buf))
|
||||
n, err := reader.Read(tempBuf)
|
||||
assert.Equal(t, n, 0)
|
||||
assert.Equal(t, err, io.EOF)
|
||||
}
|
||||
|
||||
func TestOffsetReaderCloseAndCopy(t *testing.T) {
|
||||
buf := []byte("testData")
|
||||
tempBuf := make([]byte, len(buf))
|
||||
reader := &offsetReader{buf: bytes.NewReader(buf)}
|
||||
|
||||
newReader := reader.CloseAndCopy(0)
|
||||
|
||||
n, err := reader.Read(tempBuf)
|
||||
assert.Equal(t, n, 0)
|
||||
assert.Equal(t, err, io.EOF)
|
||||
|
||||
n, err = newReader.Read(tempBuf)
|
||||
assert.Equal(t, n, len(buf))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, buf, tempBuf)
|
||||
}
|
||||
|
||||
func TestOffsetReaderCloseAndCopyOffset(t *testing.T) {
|
||||
buf := []byte("testData")
|
||||
tempBuf := make([]byte, len(buf))
|
||||
reader := &offsetReader{buf: bytes.NewReader(buf)}
|
||||
|
||||
newReader := reader.CloseAndCopy(4)
|
||||
n, err := newReader.Read(tempBuf)
|
||||
assert.Equal(t, n, len(buf)-4)
|
||||
assert.Nil(t, err)
|
||||
|
||||
expected := []byte{'D', 'a', 't', 'a', 0, 0, 0, 0}
|
||||
assert.Equal(t, expected, tempBuf)
|
||||
}
|
||||
|
||||
func TestOffsetReaderRace(t *testing.T) {
|
||||
wg := sync.WaitGroup{}
|
||||
|
||||
f := func(reader *offsetReader) {
|
||||
defer wg.Done()
|
||||
var err error
|
||||
buf := make([]byte, 1)
|
||||
_, err = reader.Read(buf)
|
||||
for err != io.EOF {
|
||||
_, err = reader.Read(buf)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
closeFn := func(reader *offsetReader) {
|
||||
defer wg.Done()
|
||||
time.Sleep(time.Duration(rand.Intn(20)+1) * time.Millisecond)
|
||||
reader.Close()
|
||||
}
|
||||
for i := 0; i < 50; i++ {
|
||||
reader := &offsetReader{buf: bytes.NewReader(make([]byte, 1024*1024))}
|
||||
wg.Add(1)
|
||||
go f(reader)
|
||||
wg.Add(1)
|
||||
go closeFn(reader)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func BenchmarkOffsetReader(b *testing.B) {
|
||||
bufSize := 1024 * 1024 * 100
|
||||
buf := make([]byte, bufSize)
|
||||
reader := &offsetReader{buf: bytes.NewReader(buf)}
|
||||
|
||||
tempBuf := make([]byte, 1024)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
reader.Read(tempBuf)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkBytesReader(b *testing.B) {
|
||||
bufSize := 1024 * 1024 * 100
|
||||
buf := make([]byte, bufSize)
|
||||
reader := bytes.NewReader(buf)
|
||||
|
||||
tempBuf := make([]byte, 1024)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
reader.Read(tempBuf)
|
||||
}
|
||||
}
|
50
vendor/github.com/aws/aws-sdk-go/aws/request/request.go
generated
vendored
50
vendor/github.com/aws/aws-sdk-go/aws/request/request.go
generated
vendored
@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
@ -42,6 +41,12 @@ type Request struct {
|
||||
LastSignedAt time.Time
|
||||
|
||||
built bool
|
||||
|
||||
// Need to persist an intermideant body betweend the input Body and HTTP
|
||||
// request body because the HTTP Client's transport can maintain a reference
|
||||
// to the HTTP request's body after the client has returned. This value is
|
||||
// safe to use concurrently and rewraps the input Body for each HTTP request.
|
||||
safeBody *offsetReader
|
||||
}
|
||||
|
||||
// An Operation is the service API operation to be made.
|
||||
@ -135,8 +140,8 @@ func (r *Request) SetStringBody(s string) {
|
||||
|
||||
// SetReaderBody will set the request's body reader.
|
||||
func (r *Request) SetReaderBody(reader io.ReadSeeker) {
|
||||
r.HTTPRequest.Body = newOffsetReader(reader, 0)
|
||||
r.Body = reader
|
||||
r.ResetBody()
|
||||
}
|
||||
|
||||
// Presign returns the request's signed URL. Error will be returned
|
||||
@ -220,6 +225,24 @@ func (r *Request) Sign() error {
|
||||
return r.Error
|
||||
}
|
||||
|
||||
// ResetBody rewinds the request body backto its starting position, and
|
||||
// set's the HTTP Request body reference. When the body is read prior
|
||||
// to being sent in the HTTP request it will need to be rewound.
|
||||
func (r *Request) ResetBody() {
|
||||
if r.safeBody != nil {
|
||||
r.safeBody.Close()
|
||||
}
|
||||
|
||||
r.safeBody = newOffsetReader(r.Body, r.BodyStart)
|
||||
r.HTTPRequest.Body = r.safeBody
|
||||
}
|
||||
|
||||
// GetBody will return an io.ReadSeeker of the Request's underlying
|
||||
// input body with a concurrency safe wrapper.
|
||||
func (r *Request) GetBody() io.ReadSeeker {
|
||||
return r.safeBody
|
||||
}
|
||||
|
||||
// Send will send the request returning error if errors are encountered.
|
||||
//
|
||||
// Send will sign the request prior to sending. All Send Handlers will
|
||||
@ -231,6 +254,8 @@ func (r *Request) Sign() error {
|
||||
//
|
||||
// readLoop() and getConn(req *Request, cm connectMethod)
|
||||
// https://github.com/golang/go/blob/master/src/net/http/transport.go
|
||||
//
|
||||
// Send will not close the request.Request's body.
|
||||
func (r *Request) Send() error {
|
||||
for {
|
||||
if aws.BoolValue(r.Retryable) {
|
||||
@ -239,21 +264,15 @@ func (r *Request) Send() error {
|
||||
r.ClientInfo.ServiceName, r.Operation.Name, r.RetryCount))
|
||||
}
|
||||
|
||||
var body io.ReadCloser
|
||||
if reader, ok := r.HTTPRequest.Body.(*offsetReader); ok {
|
||||
body = reader.CloseAndCopy(r.BodyStart)
|
||||
} else {
|
||||
if r.Config.Logger != nil {
|
||||
r.Config.Logger.Log("Request body type has been overwritten. May cause race conditions")
|
||||
}
|
||||
r.Body.Seek(r.BodyStart, 0)
|
||||
body = ioutil.NopCloser(r.Body)
|
||||
}
|
||||
// The previous http.Request will have a reference to the r.Body
|
||||
// and the HTTP Client's Transport may still be reading from
|
||||
// the request's body even though the Client's Do returned.
|
||||
r.HTTPRequest = copyHTTPRequest(r.HTTPRequest, nil)
|
||||
r.ResetBody()
|
||||
|
||||
r.HTTPRequest = copyHTTPRequest(r.HTTPRequest, body)
|
||||
// Closing response body to ensure that no response body is leaked
|
||||
// between retry attempts.
|
||||
if r.HTTPResponse != nil && r.HTTPResponse.Body != nil {
|
||||
// Closing response body. Since we are setting a new request to send off, this
|
||||
// response will get squashed and leaked.
|
||||
r.HTTPResponse.Body.Close()
|
||||
}
|
||||
}
|
||||
@ -281,7 +300,6 @@ func (r *Request) Send() error {
|
||||
debugLogReqError(r, "Send Request", true, err)
|
||||
continue
|
||||
}
|
||||
|
||||
r.Handlers.UnmarshalMeta.Run(r)
|
||||
r.Handlers.ValidateResponse.Run(r)
|
||||
if r.Error != nil {
|
||||
|
33
vendor/github.com/aws/aws-sdk-go/aws/request/request_1_6_test.go
generated
vendored
33
vendor/github.com/aws/aws-sdk-go/aws/request/request_1_6_test.go
generated
vendored
@ -1,33 +0,0 @@
|
||||
// +build go1.6
|
||||
|
||||
package request_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"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/defaults"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/private/endpoints"
|
||||
)
|
||||
|
||||
// go version 1.4 and 1.5 do not return an error. Version 1.5 will url encode
|
||||
// the uri while 1.4 will not
|
||||
func TestRequestInvalidEndpoint(t *testing.T) {
|
||||
endpoint, _ := endpoints.NormalizeEndpoint("localhost:80 ", "test-service", "test-region", false, false)
|
||||
r := request.New(
|
||||
aws.Config{},
|
||||
metadata.ClientInfo{Endpoint: endpoint},
|
||||
defaults.Handlers(),
|
||||
client.DefaultRetryer{},
|
||||
&request.Operation{},
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
assert.Error(t, r.Error)
|
||||
}
|
455
vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination_test.go
generated
vendored
455
vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination_test.go
generated
vendored
@ -1,455 +0,0 @@
|
||||
package request_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||
"github.com/aws/aws-sdk-go/service/dynamodb"
|
||||
"github.com/aws/aws-sdk-go/service/route53"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
)
|
||||
|
||||
// Use DynamoDB methods for simplicity
|
||||
func TestPaginationQueryPage(t *testing.T) {
|
||||
db := dynamodb.New(unit.Session)
|
||||
tokens, pages, numPages, gotToEnd := []map[string]*dynamodb.AttributeValue{}, []map[string]*dynamodb.AttributeValue{}, 0, false
|
||||
|
||||
reqNum := 0
|
||||
resps := []*dynamodb.QueryOutput{
|
||||
{
|
||||
LastEvaluatedKey: map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key1")}},
|
||||
Count: aws.Int64(1),
|
||||
Items: []map[string]*dynamodb.AttributeValue{
|
||||
{
|
||||
"key": {S: aws.String("key1")},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
LastEvaluatedKey: map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key2")}},
|
||||
Count: aws.Int64(1),
|
||||
Items: []map[string]*dynamodb.AttributeValue{
|
||||
{
|
||||
"key": {S: aws.String("key2")},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
LastEvaluatedKey: map[string]*dynamodb.AttributeValue{},
|
||||
Count: aws.Int64(1),
|
||||
Items: []map[string]*dynamodb.AttributeValue{
|
||||
{
|
||||
"key": {S: aws.String("key3")},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
db.Handlers.Send.Clear() // mock sending
|
||||
db.Handlers.Unmarshal.Clear()
|
||||
db.Handlers.UnmarshalMeta.Clear()
|
||||
db.Handlers.ValidateResponse.Clear()
|
||||
db.Handlers.Build.PushBack(func(r *request.Request) {
|
||||
in := r.Params.(*dynamodb.QueryInput)
|
||||
if in == nil {
|
||||
tokens = append(tokens, nil)
|
||||
} else if len(in.ExclusiveStartKey) != 0 {
|
||||
tokens = append(tokens, in.ExclusiveStartKey)
|
||||
}
|
||||
})
|
||||
db.Handlers.Unmarshal.PushBack(func(r *request.Request) {
|
||||
r.Data = resps[reqNum]
|
||||
reqNum++
|
||||
})
|
||||
|
||||
params := &dynamodb.QueryInput{
|
||||
Limit: aws.Int64(2),
|
||||
TableName: aws.String("tablename"),
|
||||
}
|
||||
err := db.QueryPages(params, func(p *dynamodb.QueryOutput, last bool) bool {
|
||||
numPages++
|
||||
for _, item := range p.Items {
|
||||
pages = append(pages, item)
|
||||
}
|
||||
if last {
|
||||
if gotToEnd {
|
||||
assert.Fail(t, "last=true happened twice")
|
||||
}
|
||||
gotToEnd = true
|
||||
}
|
||||
return true
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t,
|
||||
[]map[string]*dynamodb.AttributeValue{
|
||||
{"key": {S: aws.String("key1")}},
|
||||
{"key": {S: aws.String("key2")}},
|
||||
}, tokens)
|
||||
assert.Equal(t,
|
||||
[]map[string]*dynamodb.AttributeValue{
|
||||
{"key": {S: aws.String("key1")}},
|
||||
{"key": {S: aws.String("key2")}},
|
||||
{"key": {S: aws.String("key3")}},
|
||||
}, pages)
|
||||
assert.Equal(t, 3, numPages)
|
||||
assert.True(t, gotToEnd)
|
||||
assert.Nil(t, params.ExclusiveStartKey)
|
||||
}
|
||||
|
||||
// Use DynamoDB methods for simplicity
|
||||
func TestPagination(t *testing.T) {
|
||||
db := dynamodb.New(unit.Session)
|
||||
tokens, pages, numPages, gotToEnd := []string{}, []string{}, 0, false
|
||||
|
||||
reqNum := 0
|
||||
resps := []*dynamodb.ListTablesOutput{
|
||||
{TableNames: []*string{aws.String("Table1"), aws.String("Table2")}, LastEvaluatedTableName: aws.String("Table2")},
|
||||
{TableNames: []*string{aws.String("Table3"), aws.String("Table4")}, LastEvaluatedTableName: aws.String("Table4")},
|
||||
{TableNames: []*string{aws.String("Table5")}},
|
||||
}
|
||||
|
||||
db.Handlers.Send.Clear() // mock sending
|
||||
db.Handlers.Unmarshal.Clear()
|
||||
db.Handlers.UnmarshalMeta.Clear()
|
||||
db.Handlers.ValidateResponse.Clear()
|
||||
db.Handlers.Build.PushBack(func(r *request.Request) {
|
||||
in := r.Params.(*dynamodb.ListTablesInput)
|
||||
if in == nil {
|
||||
tokens = append(tokens, "")
|
||||
} else if in.ExclusiveStartTableName != nil {
|
||||
tokens = append(tokens, *in.ExclusiveStartTableName)
|
||||
}
|
||||
})
|
||||
db.Handlers.Unmarshal.PushBack(func(r *request.Request) {
|
||||
r.Data = resps[reqNum]
|
||||
reqNum++
|
||||
})
|
||||
|
||||
params := &dynamodb.ListTablesInput{Limit: aws.Int64(2)}
|
||||
err := db.ListTablesPages(params, func(p *dynamodb.ListTablesOutput, last bool) bool {
|
||||
numPages++
|
||||
for _, t := range p.TableNames {
|
||||
pages = append(pages, *t)
|
||||
}
|
||||
if last {
|
||||
if gotToEnd {
|
||||
assert.Fail(t, "last=true happened twice")
|
||||
}
|
||||
gotToEnd = true
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
assert.Equal(t, []string{"Table2", "Table4"}, tokens)
|
||||
assert.Equal(t, []string{"Table1", "Table2", "Table3", "Table4", "Table5"}, pages)
|
||||
assert.Equal(t, 3, numPages)
|
||||
assert.True(t, gotToEnd)
|
||||
assert.Nil(t, err)
|
||||
assert.Nil(t, params.ExclusiveStartTableName)
|
||||
}
|
||||
|
||||
// Use DynamoDB methods for simplicity
|
||||
func TestPaginationEachPage(t *testing.T) {
|
||||
db := dynamodb.New(unit.Session)
|
||||
tokens, pages, numPages, gotToEnd := []string{}, []string{}, 0, false
|
||||
|
||||
reqNum := 0
|
||||
resps := []*dynamodb.ListTablesOutput{
|
||||
{TableNames: []*string{aws.String("Table1"), aws.String("Table2")}, LastEvaluatedTableName: aws.String("Table2")},
|
||||
{TableNames: []*string{aws.String("Table3"), aws.String("Table4")}, LastEvaluatedTableName: aws.String("Table4")},
|
||||
{TableNames: []*string{aws.String("Table5")}},
|
||||
}
|
||||
|
||||
db.Handlers.Send.Clear() // mock sending
|
||||
db.Handlers.Unmarshal.Clear()
|
||||
db.Handlers.UnmarshalMeta.Clear()
|
||||
db.Handlers.ValidateResponse.Clear()
|
||||
db.Handlers.Build.PushBack(func(r *request.Request) {
|
||||
in := r.Params.(*dynamodb.ListTablesInput)
|
||||
if in == nil {
|
||||
tokens = append(tokens, "")
|
||||
} else if in.ExclusiveStartTableName != nil {
|
||||
tokens = append(tokens, *in.ExclusiveStartTableName)
|
||||
}
|
||||
})
|
||||
db.Handlers.Unmarshal.PushBack(func(r *request.Request) {
|
||||
r.Data = resps[reqNum]
|
||||
reqNum++
|
||||
})
|
||||
|
||||
params := &dynamodb.ListTablesInput{Limit: aws.Int64(2)}
|
||||
req, _ := db.ListTablesRequest(params)
|
||||
err := req.EachPage(func(p interface{}, last bool) bool {
|
||||
numPages++
|
||||
for _, t := range p.(*dynamodb.ListTablesOutput).TableNames {
|
||||
pages = append(pages, *t)
|
||||
}
|
||||
if last {
|
||||
if gotToEnd {
|
||||
assert.Fail(t, "last=true happened twice")
|
||||
}
|
||||
gotToEnd = true
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
assert.Equal(t, []string{"Table2", "Table4"}, tokens)
|
||||
assert.Equal(t, []string{"Table1", "Table2", "Table3", "Table4", "Table5"}, pages)
|
||||
assert.Equal(t, 3, numPages)
|
||||
assert.True(t, gotToEnd)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
// Use DynamoDB methods for simplicity
|
||||
func TestPaginationEarlyExit(t *testing.T) {
|
||||
db := dynamodb.New(unit.Session)
|
||||
numPages, gotToEnd := 0, false
|
||||
|
||||
reqNum := 0
|
||||
resps := []*dynamodb.ListTablesOutput{
|
||||
{TableNames: []*string{aws.String("Table1"), aws.String("Table2")}, LastEvaluatedTableName: aws.String("Table2")},
|
||||
{TableNames: []*string{aws.String("Table3"), aws.String("Table4")}, LastEvaluatedTableName: aws.String("Table4")},
|
||||
{TableNames: []*string{aws.String("Table5")}},
|
||||
}
|
||||
|
||||
db.Handlers.Send.Clear() // mock sending
|
||||
db.Handlers.Unmarshal.Clear()
|
||||
db.Handlers.UnmarshalMeta.Clear()
|
||||
db.Handlers.ValidateResponse.Clear()
|
||||
db.Handlers.Unmarshal.PushBack(func(r *request.Request) {
|
||||
r.Data = resps[reqNum]
|
||||
reqNum++
|
||||
})
|
||||
|
||||
params := &dynamodb.ListTablesInput{Limit: aws.Int64(2)}
|
||||
err := db.ListTablesPages(params, func(p *dynamodb.ListTablesOutput, last bool) bool {
|
||||
numPages++
|
||||
if numPages == 2 {
|
||||
return false
|
||||
}
|
||||
if last {
|
||||
if gotToEnd {
|
||||
assert.Fail(t, "last=true happened twice")
|
||||
}
|
||||
gotToEnd = true
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
assert.Equal(t, 2, numPages)
|
||||
assert.False(t, gotToEnd)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestSkipPagination(t *testing.T) {
|
||||
client := s3.New(unit.Session)
|
||||
client.Handlers.Send.Clear() // mock sending
|
||||
client.Handlers.Unmarshal.Clear()
|
||||
client.Handlers.UnmarshalMeta.Clear()
|
||||
client.Handlers.ValidateResponse.Clear()
|
||||
client.Handlers.Unmarshal.PushBack(func(r *request.Request) {
|
||||
r.Data = &s3.HeadBucketOutput{}
|
||||
})
|
||||
|
||||
req, _ := client.HeadBucketRequest(&s3.HeadBucketInput{Bucket: aws.String("bucket")})
|
||||
|
||||
numPages, gotToEnd := 0, false
|
||||
req.EachPage(func(p interface{}, last bool) bool {
|
||||
numPages++
|
||||
if last {
|
||||
gotToEnd = true
|
||||
}
|
||||
return true
|
||||
})
|
||||
assert.Equal(t, 1, numPages)
|
||||
assert.True(t, gotToEnd)
|
||||
}
|
||||
|
||||
// Use S3 for simplicity
|
||||
func TestPaginationTruncation(t *testing.T) {
|
||||
client := s3.New(unit.Session)
|
||||
|
||||
reqNum := 0
|
||||
resps := []*s3.ListObjectsOutput{
|
||||
{IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key1")}}},
|
||||
{IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key2")}}},
|
||||
{IsTruncated: aws.Bool(false), Contents: []*s3.Object{{Key: aws.String("Key3")}}},
|
||||
{IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key4")}}},
|
||||
}
|
||||
|
||||
client.Handlers.Send.Clear() // mock sending
|
||||
client.Handlers.Unmarshal.Clear()
|
||||
client.Handlers.UnmarshalMeta.Clear()
|
||||
client.Handlers.ValidateResponse.Clear()
|
||||
client.Handlers.Unmarshal.PushBack(func(r *request.Request) {
|
||||
r.Data = resps[reqNum]
|
||||
reqNum++
|
||||
})
|
||||
|
||||
params := &s3.ListObjectsInput{Bucket: aws.String("bucket")}
|
||||
|
||||
results := []string{}
|
||||
err := client.ListObjectsPages(params, func(p *s3.ListObjectsOutput, last bool) bool {
|
||||
results = append(results, *p.Contents[0].Key)
|
||||
return true
|
||||
})
|
||||
|
||||
assert.Equal(t, []string{"Key1", "Key2", "Key3"}, results)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// Try again without truncation token at all
|
||||
reqNum = 0
|
||||
resps[1].IsTruncated = nil
|
||||
resps[2].IsTruncated = aws.Bool(true)
|
||||
results = []string{}
|
||||
err = client.ListObjectsPages(params, func(p *s3.ListObjectsOutput, last bool) bool {
|
||||
results = append(results, *p.Contents[0].Key)
|
||||
return true
|
||||
})
|
||||
|
||||
assert.Equal(t, []string{"Key1", "Key2"}, results)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestPaginationNilToken(t *testing.T) {
|
||||
client := route53.New(unit.Session)
|
||||
|
||||
reqNum := 0
|
||||
resps := []*route53.ListResourceRecordSetsOutput{
|
||||
{
|
||||
ResourceRecordSets: []*route53.ResourceRecordSet{
|
||||
{Name: aws.String("first.example.com.")},
|
||||
},
|
||||
IsTruncated: aws.Bool(true),
|
||||
NextRecordName: aws.String("second.example.com."),
|
||||
NextRecordType: aws.String("MX"),
|
||||
NextRecordIdentifier: aws.String("second"),
|
||||
MaxItems: aws.String("1"),
|
||||
},
|
||||
{
|
||||
ResourceRecordSets: []*route53.ResourceRecordSet{
|
||||
{Name: aws.String("second.example.com.")},
|
||||
},
|
||||
IsTruncated: aws.Bool(true),
|
||||
NextRecordName: aws.String("third.example.com."),
|
||||
NextRecordType: aws.String("MX"),
|
||||
MaxItems: aws.String("1"),
|
||||
},
|
||||
{
|
||||
ResourceRecordSets: []*route53.ResourceRecordSet{
|
||||
{Name: aws.String("third.example.com.")},
|
||||
},
|
||||
IsTruncated: aws.Bool(false),
|
||||
MaxItems: aws.String("1"),
|
||||
},
|
||||
}
|
||||
client.Handlers.Send.Clear() // mock sending
|
||||
client.Handlers.Unmarshal.Clear()
|
||||
client.Handlers.UnmarshalMeta.Clear()
|
||||
client.Handlers.ValidateResponse.Clear()
|
||||
|
||||
idents := []string{}
|
||||
client.Handlers.Build.PushBack(func(r *request.Request) {
|
||||
p := r.Params.(*route53.ListResourceRecordSetsInput)
|
||||
idents = append(idents, aws.StringValue(p.StartRecordIdentifier))
|
||||
|
||||
})
|
||||
client.Handlers.Unmarshal.PushBack(func(r *request.Request) {
|
||||
r.Data = resps[reqNum]
|
||||
reqNum++
|
||||
})
|
||||
|
||||
params := &route53.ListResourceRecordSetsInput{
|
||||
HostedZoneId: aws.String("id-zone"),
|
||||
}
|
||||
|
||||
results := []string{}
|
||||
err := client.ListResourceRecordSetsPages(params, func(p *route53.ListResourceRecordSetsOutput, last bool) bool {
|
||||
results = append(results, *p.ResourceRecordSets[0].Name)
|
||||
return true
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{"", "second", ""}, idents)
|
||||
assert.Equal(t, []string{"first.example.com.", "second.example.com.", "third.example.com."}, results)
|
||||
}
|
||||
|
||||
// Benchmarks
|
||||
var benchResps = []*dynamodb.ListTablesOutput{
|
||||
{TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")},
|
||||
{TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")},
|
||||
{TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")},
|
||||
{TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")},
|
||||
{TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")},
|
||||
{TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")},
|
||||
{TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")},
|
||||
{TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")},
|
||||
{TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")},
|
||||
{TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")},
|
||||
{TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")},
|
||||
{TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")},
|
||||
{TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")},
|
||||
{TableNames: []*string{aws.String("TABLE")}},
|
||||
}
|
||||
|
||||
var benchDb = func() *dynamodb.DynamoDB {
|
||||
db := dynamodb.New(unit.Session)
|
||||
db.Handlers.Send.Clear() // mock sending
|
||||
db.Handlers.Unmarshal.Clear()
|
||||
db.Handlers.UnmarshalMeta.Clear()
|
||||
db.Handlers.ValidateResponse.Clear()
|
||||
return db
|
||||
}
|
||||
|
||||
func BenchmarkCodegenIterator(b *testing.B) {
|
||||
reqNum := 0
|
||||
db := benchDb()
|
||||
db.Handlers.Unmarshal.PushBack(func(r *request.Request) {
|
||||
r.Data = benchResps[reqNum]
|
||||
reqNum++
|
||||
})
|
||||
|
||||
input := &dynamodb.ListTablesInput{Limit: aws.Int64(2)}
|
||||
iter := func(fn func(*dynamodb.ListTablesOutput, bool) bool) error {
|
||||
page, _ := db.ListTablesRequest(input)
|
||||
for ; page != nil; page = page.NextPage() {
|
||||
page.Send()
|
||||
out := page.Data.(*dynamodb.ListTablesOutput)
|
||||
if result := fn(out, !page.HasNextPage()); page.Error != nil || !result {
|
||||
return page.Error
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
reqNum = 0
|
||||
iter(func(p *dynamodb.ListTablesOutput, last bool) bool {
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEachPageIterator(b *testing.B) {
|
||||
reqNum := 0
|
||||
db := benchDb()
|
||||
db.Handlers.Unmarshal.PushBack(func(r *request.Request) {
|
||||
r.Data = benchResps[reqNum]
|
||||
reqNum++
|
||||
})
|
||||
|
||||
input := &dynamodb.ListTablesInput{Limit: aws.Int64(2)}
|
||||
for i := 0; i < b.N; i++ {
|
||||
reqNum = 0
|
||||
req, _ := db.ListTablesRequest(input)
|
||||
req.EachPage(func(p interface{}, last bool) bool {
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
380
vendor/github.com/aws/aws-sdk-go/aws/request/request_test.go
generated
vendored
380
vendor/github.com/aws/aws-sdk-go/aws/request/request_test.go
generated
vendored
@ -1,380 +0,0 @@
|
||||
package request_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/awstesting"
|
||||
)
|
||||
|
||||
type testData struct {
|
||||
Data string
|
||||
}
|
||||
|
||||
func body(str string) io.ReadCloser {
|
||||
return ioutil.NopCloser(bytes.NewReader([]byte(str)))
|
||||
}
|
||||
|
||||
func unmarshal(req *request.Request) {
|
||||
defer req.HTTPResponse.Body.Close()
|
||||
if req.Data != nil {
|
||||
json.NewDecoder(req.HTTPResponse.Body).Decode(req.Data)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func unmarshalError(req *request.Request) {
|
||||
bodyBytes, err := ioutil.ReadAll(req.HTTPResponse.Body)
|
||||
if err != nil {
|
||||
req.Error = awserr.New("UnmarshaleError", req.HTTPResponse.Status, err)
|
||||
return
|
||||
}
|
||||
if len(bodyBytes) == 0 {
|
||||
req.Error = awserr.NewRequestFailure(
|
||||
awserr.New("UnmarshaleError", req.HTTPResponse.Status, fmt.Errorf("empty body")),
|
||||
req.HTTPResponse.StatusCode,
|
||||
"",
|
||||
)
|
||||
return
|
||||
}
|
||||
var jsonErr jsonErrorResponse
|
||||
if err := json.Unmarshal(bodyBytes, &jsonErr); err != nil {
|
||||
req.Error = awserr.New("UnmarshaleError", "JSON unmarshal", err)
|
||||
return
|
||||
}
|
||||
req.Error = awserr.NewRequestFailure(
|
||||
awserr.New(jsonErr.Code, jsonErr.Message, nil),
|
||||
req.HTTPResponse.StatusCode,
|
||||
"",
|
||||
)
|
||||
}
|
||||
|
||||
type jsonErrorResponse struct {
|
||||
Code string `json:"__type"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// test that retries occur for 5xx status codes
|
||||
func TestRequestRecoverRetry5xx(t *testing.T) {
|
||||
reqNum := 0
|
||||
reqs := []http.Response{
|
||||
{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)},
|
||||
{StatusCode: 501, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)},
|
||||
{StatusCode: 200, Body: body(`{"data":"valid"}`)},
|
||||
}
|
||||
|
||||
s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10))
|
||||
s.Handlers.Validate.Clear()
|
||||
s.Handlers.Unmarshal.PushBack(unmarshal)
|
||||
s.Handlers.UnmarshalError.PushBack(unmarshalError)
|
||||
s.Handlers.Send.Clear() // mock sending
|
||||
s.Handlers.Send.PushBack(func(r *request.Request) {
|
||||
r.HTTPResponse = &reqs[reqNum]
|
||||
reqNum++
|
||||
})
|
||||
out := &testData{}
|
||||
r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out)
|
||||
err := r.Send()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 2, int(r.RetryCount))
|
||||
assert.Equal(t, "valid", out.Data)
|
||||
}
|
||||
|
||||
// test that retries occur for 4xx status codes with a response type that can be retried - see `shouldRetry`
|
||||
func TestRequestRecoverRetry4xxRetryable(t *testing.T) {
|
||||
reqNum := 0
|
||||
reqs := []http.Response{
|
||||
{StatusCode: 400, Body: body(`{"__type":"Throttling","message":"Rate exceeded."}`)},
|
||||
{StatusCode: 429, Body: body(`{"__type":"ProvisionedThroughputExceededException","message":"Rate exceeded."}`)},
|
||||
{StatusCode: 200, Body: body(`{"data":"valid"}`)},
|
||||
}
|
||||
|
||||
s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10))
|
||||
s.Handlers.Validate.Clear()
|
||||
s.Handlers.Unmarshal.PushBack(unmarshal)
|
||||
s.Handlers.UnmarshalError.PushBack(unmarshalError)
|
||||
s.Handlers.Send.Clear() // mock sending
|
||||
s.Handlers.Send.PushBack(func(r *request.Request) {
|
||||
r.HTTPResponse = &reqs[reqNum]
|
||||
reqNum++
|
||||
})
|
||||
out := &testData{}
|
||||
r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out)
|
||||
err := r.Send()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 2, int(r.RetryCount))
|
||||
assert.Equal(t, "valid", out.Data)
|
||||
}
|
||||
|
||||
// test that retries don't occur for 4xx status codes with a response type that can't be retried
|
||||
func TestRequest4xxUnretryable(t *testing.T) {
|
||||
s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10))
|
||||
s.Handlers.Validate.Clear()
|
||||
s.Handlers.Unmarshal.PushBack(unmarshal)
|
||||
s.Handlers.UnmarshalError.PushBack(unmarshalError)
|
||||
s.Handlers.Send.Clear() // mock sending
|
||||
s.Handlers.Send.PushBack(func(r *request.Request) {
|
||||
r.HTTPResponse = &http.Response{StatusCode: 401, Body: body(`{"__type":"SignatureDoesNotMatch","message":"Signature does not match."}`)}
|
||||
})
|
||||
out := &testData{}
|
||||
r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out)
|
||||
err := r.Send()
|
||||
assert.NotNil(t, err)
|
||||
if e, ok := err.(awserr.RequestFailure); ok {
|
||||
assert.Equal(t, 401, e.StatusCode())
|
||||
} else {
|
||||
assert.Fail(t, "Expected error to be a service failure")
|
||||
}
|
||||
assert.Equal(t, "SignatureDoesNotMatch", err.(awserr.Error).Code())
|
||||
assert.Equal(t, "Signature does not match.", err.(awserr.Error).Message())
|
||||
assert.Equal(t, 0, int(r.RetryCount))
|
||||
}
|
||||
|
||||
func TestRequestExhaustRetries(t *testing.T) {
|
||||
delays := []time.Duration{}
|
||||
sleepDelay := func(delay time.Duration) {
|
||||
delays = append(delays, delay)
|
||||
}
|
||||
|
||||
reqNum := 0
|
||||
reqs := []http.Response{
|
||||
{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)},
|
||||
{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)},
|
||||
{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)},
|
||||
{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)},
|
||||
}
|
||||
|
||||
s := awstesting.NewClient(aws.NewConfig().WithSleepDelay(sleepDelay))
|
||||
s.Handlers.Validate.Clear()
|
||||
s.Handlers.Unmarshal.PushBack(unmarshal)
|
||||
s.Handlers.UnmarshalError.PushBack(unmarshalError)
|
||||
s.Handlers.Send.Clear() // mock sending
|
||||
s.Handlers.Send.PushBack(func(r *request.Request) {
|
||||
r.HTTPResponse = &reqs[reqNum]
|
||||
reqNum++
|
||||
})
|
||||
r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, nil)
|
||||
err := r.Send()
|
||||
assert.NotNil(t, err)
|
||||
if e, ok := err.(awserr.RequestFailure); ok {
|
||||
assert.Equal(t, 500, e.StatusCode())
|
||||
} else {
|
||||
assert.Fail(t, "Expected error to be a service failure")
|
||||
}
|
||||
assert.Equal(t, "UnknownError", err.(awserr.Error).Code())
|
||||
assert.Equal(t, "An error occurred.", err.(awserr.Error).Message())
|
||||
assert.Equal(t, 3, int(r.RetryCount))
|
||||
|
||||
expectDelays := []struct{ min, max time.Duration }{{30, 59}, {60, 118}, {120, 236}}
|
||||
for i, v := range delays {
|
||||
min := expectDelays[i].min * time.Millisecond
|
||||
max := expectDelays[i].max * time.Millisecond
|
||||
assert.True(t, min <= v && v <= max,
|
||||
"Expect delay to be within range, i:%d, v:%s, min:%s, max:%s", i, v, min, max)
|
||||
}
|
||||
}
|
||||
|
||||
// test that the request is retried after the credentials are expired.
|
||||
func TestRequestRecoverExpiredCreds(t *testing.T) {
|
||||
reqNum := 0
|
||||
reqs := []http.Response{
|
||||
{StatusCode: 400, Body: body(`{"__type":"ExpiredTokenException","message":"expired token"}`)},
|
||||
{StatusCode: 200, Body: body(`{"data":"valid"}`)},
|
||||
}
|
||||
|
||||
s := awstesting.NewClient(&aws.Config{MaxRetries: aws.Int(10), Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "")})
|
||||
s.Handlers.Validate.Clear()
|
||||
s.Handlers.Unmarshal.PushBack(unmarshal)
|
||||
s.Handlers.UnmarshalError.PushBack(unmarshalError)
|
||||
|
||||
credExpiredBeforeRetry := false
|
||||
credExpiredAfterRetry := false
|
||||
|
||||
s.Handlers.AfterRetry.PushBack(func(r *request.Request) {
|
||||
credExpiredAfterRetry = r.Config.Credentials.IsExpired()
|
||||
})
|
||||
|
||||
s.Handlers.Sign.Clear()
|
||||
s.Handlers.Sign.PushBack(func(r *request.Request) {
|
||||
r.Config.Credentials.Get()
|
||||
})
|
||||
s.Handlers.Send.Clear() // mock sending
|
||||
s.Handlers.Send.PushBack(func(r *request.Request) {
|
||||
r.HTTPResponse = &reqs[reqNum]
|
||||
reqNum++
|
||||
})
|
||||
out := &testData{}
|
||||
r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out)
|
||||
err := r.Send()
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.False(t, credExpiredBeforeRetry, "Expect valid creds before retry check")
|
||||
assert.True(t, credExpiredAfterRetry, "Expect expired creds after retry check")
|
||||
assert.False(t, s.Config.Credentials.IsExpired(), "Expect valid creds after cred expired recovery")
|
||||
|
||||
assert.Equal(t, 1, int(r.RetryCount))
|
||||
assert.Equal(t, "valid", out.Data)
|
||||
}
|
||||
|
||||
func TestMakeAddtoUserAgentHandler(t *testing.T) {
|
||||
fn := request.MakeAddToUserAgentHandler("name", "version", "extra1", "extra2")
|
||||
r := &request.Request{HTTPRequest: &http.Request{Header: http.Header{}}}
|
||||
r.HTTPRequest.Header.Set("User-Agent", "foo/bar")
|
||||
fn(r)
|
||||
|
||||
assert.Equal(t, "foo/bar name/version (extra1; extra2)", r.HTTPRequest.Header.Get("User-Agent"))
|
||||
}
|
||||
|
||||
func TestMakeAddtoUserAgentFreeFormHandler(t *testing.T) {
|
||||
fn := request.MakeAddToUserAgentFreeFormHandler("name/version (extra1; extra2)")
|
||||
r := &request.Request{HTTPRequest: &http.Request{Header: http.Header{}}}
|
||||
r.HTTPRequest.Header.Set("User-Agent", "foo/bar")
|
||||
fn(r)
|
||||
|
||||
assert.Equal(t, "foo/bar name/version (extra1; extra2)", r.HTTPRequest.Header.Get("User-Agent"))
|
||||
}
|
||||
|
||||
func TestRequestUserAgent(t *testing.T) {
|
||||
s := awstesting.NewClient(&aws.Config{Region: aws.String("us-east-1")})
|
||||
// s.Handlers.Validate.Clear()
|
||||
|
||||
req := s.NewRequest(&request.Operation{Name: "Operation"}, nil, &testData{})
|
||||
req.HTTPRequest.Header.Set("User-Agent", "foo/bar")
|
||||
assert.NoError(t, req.Build())
|
||||
|
||||
expectUA := fmt.Sprintf("foo/bar %s/%s (%s; %s; %s)",
|
||||
aws.SDKName, aws.SDKVersion, runtime.Version(), runtime.GOOS, runtime.GOARCH)
|
||||
assert.Equal(t, expectUA, req.HTTPRequest.Header.Get("User-Agent"))
|
||||
}
|
||||
|
||||
func TestRequestThrottleRetries(t *testing.T) {
|
||||
delays := []time.Duration{}
|
||||
sleepDelay := func(delay time.Duration) {
|
||||
delays = append(delays, delay)
|
||||
}
|
||||
|
||||
reqNum := 0
|
||||
reqs := []http.Response{
|
||||
{StatusCode: 500, Body: body(`{"__type":"Throttling","message":"An error occurred."}`)},
|
||||
{StatusCode: 500, Body: body(`{"__type":"Throttling","message":"An error occurred."}`)},
|
||||
{StatusCode: 500, Body: body(`{"__type":"Throttling","message":"An error occurred."}`)},
|
||||
{StatusCode: 500, Body: body(`{"__type":"Throttling","message":"An error occurred."}`)},
|
||||
}
|
||||
|
||||
s := awstesting.NewClient(aws.NewConfig().WithSleepDelay(sleepDelay))
|
||||
s.Handlers.Validate.Clear()
|
||||
s.Handlers.Unmarshal.PushBack(unmarshal)
|
||||
s.Handlers.UnmarshalError.PushBack(unmarshalError)
|
||||
s.Handlers.Send.Clear() // mock sending
|
||||
s.Handlers.Send.PushBack(func(r *request.Request) {
|
||||
r.HTTPResponse = &reqs[reqNum]
|
||||
reqNum++
|
||||
})
|
||||
r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, nil)
|
||||
err := r.Send()
|
||||
assert.NotNil(t, err)
|
||||
if e, ok := err.(awserr.RequestFailure); ok {
|
||||
assert.Equal(t, 500, e.StatusCode())
|
||||
} else {
|
||||
assert.Fail(t, "Expected error to be a service failure")
|
||||
}
|
||||
assert.Equal(t, "Throttling", err.(awserr.Error).Code())
|
||||
assert.Equal(t, "An error occurred.", err.(awserr.Error).Message())
|
||||
assert.Equal(t, 3, int(r.RetryCount))
|
||||
|
||||
expectDelays := []struct{ min, max time.Duration }{{500, 999}, {1000, 1998}, {2000, 3996}}
|
||||
for i, v := range delays {
|
||||
min := expectDelays[i].min * time.Millisecond
|
||||
max := expectDelays[i].max * time.Millisecond
|
||||
assert.True(t, min <= v && v <= max,
|
||||
"Expect delay to be within range, i:%d, v:%s, min:%s, max:%s", i, v, min, max)
|
||||
}
|
||||
}
|
||||
|
||||
// test that retries occur for request timeouts when response.Body can be nil
|
||||
func TestRequestRecoverTimeoutWithNilBody(t *testing.T) {
|
||||
reqNum := 0
|
||||
reqs := []*http.Response{
|
||||
{StatusCode: 0, Body: nil}, // body can be nil when requests time out
|
||||
{StatusCode: 200, Body: body(`{"data":"valid"}`)},
|
||||
}
|
||||
errors := []error{
|
||||
errors.New("timeout"), nil,
|
||||
}
|
||||
|
||||
s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10))
|
||||
s.Handlers.Validate.Clear()
|
||||
s.Handlers.Unmarshal.PushBack(unmarshal)
|
||||
s.Handlers.UnmarshalError.PushBack(unmarshalError)
|
||||
s.Handlers.AfterRetry.Clear() // force retry on all errors
|
||||
s.Handlers.AfterRetry.PushBack(func(r *request.Request) {
|
||||
if r.Error != nil {
|
||||
r.Error = nil
|
||||
r.Retryable = aws.Bool(true)
|
||||
r.RetryCount++
|
||||
}
|
||||
})
|
||||
s.Handlers.Send.Clear() // mock sending
|
||||
s.Handlers.Send.PushBack(func(r *request.Request) {
|
||||
r.HTTPResponse = reqs[reqNum]
|
||||
r.Error = errors[reqNum]
|
||||
reqNum++
|
||||
})
|
||||
out := &testData{}
|
||||
r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out)
|
||||
err := r.Send()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 1, int(r.RetryCount))
|
||||
assert.Equal(t, "valid", out.Data)
|
||||
}
|
||||
|
||||
func TestRequestRecoverTimeoutWithNilResponse(t *testing.T) {
|
||||
reqNum := 0
|
||||
reqs := []*http.Response{
|
||||
nil,
|
||||
{StatusCode: 200, Body: body(`{"data":"valid"}`)},
|
||||
}
|
||||
errors := []error{
|
||||
errors.New("timeout"),
|
||||
nil,
|
||||
}
|
||||
|
||||
s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10))
|
||||
s.Handlers.Validate.Clear()
|
||||
s.Handlers.Unmarshal.PushBack(unmarshal)
|
||||
s.Handlers.UnmarshalError.PushBack(unmarshalError)
|
||||
s.Handlers.AfterRetry.Clear() // force retry on all errors
|
||||
s.Handlers.AfterRetry.PushBack(func(r *request.Request) {
|
||||
if r.Error != nil {
|
||||
r.Error = nil
|
||||
r.Retryable = aws.Bool(true)
|
||||
r.RetryCount++
|
||||
}
|
||||
})
|
||||
s.Handlers.Send.Clear() // mock sending
|
||||
s.Handlers.Send.PushBack(func(r *request.Request) {
|
||||
r.HTTPResponse = reqs[reqNum]
|
||||
r.Error = errors[reqNum]
|
||||
reqNum++
|
||||
})
|
||||
out := &testData{}
|
||||
r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out)
|
||||
err := r.Send()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 1, int(r.RetryCount))
|
||||
assert.Equal(t, "valid", out.Data)
|
||||
}
|
16
vendor/github.com/aws/aws-sdk-go/aws/request/retryer_test.go
generated
vendored
16
vendor/github.com/aws/aws-sdk-go/aws/request/retryer_test.go
generated
vendored
@ -1,16 +0,0 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
)
|
||||
|
||||
func TestRequestThrottling(t *testing.T) {
|
||||
req := Request{}
|
||||
|
||||
req.Error = awserr.New("Throttling", "", nil)
|
||||
assert.True(t, req.IsErrorThrottle())
|
||||
}
|
8
vendor/github.com/aws/aws-sdk-go/aws/session/doc.go
generated
vendored
8
vendor/github.com/aws/aws-sdk-go/aws/session/doc.go
generated
vendored
@ -66,7 +66,7 @@ through code instead of being driven by environment variables only.
|
||||
Use NewSessionWithOptions when you want to provide the config profile, or
|
||||
override the shared config state (AWS_SDK_LOAD_CONFIG).
|
||||
|
||||
// Equivalent to session.New
|
||||
// Equivalent to session.NewSession()
|
||||
sess, err := session.NewSessionWithOptions(session.Options{})
|
||||
|
||||
// Specify profile to load for the session's config
|
||||
@ -85,12 +85,6 @@ override the shared config state (AWS_SDK_LOAD_CONFIG).
|
||||
SharedConfigState: SharedConfigEnable,
|
||||
})
|
||||
|
||||
Deprecated "New" function
|
||||
|
||||
The New session function has been deprecated because it does not provide good
|
||||
way to return errors that occur when loading the configuration files and values.
|
||||
Because of this, the NewWithError
|
||||
|
||||
Adding Handlers
|
||||
|
||||
You can add handlers to a session for processing HTTP requests. All service
|
||||
|
276
vendor/github.com/aws/aws-sdk-go/aws/session/env_config_test.go
generated
vendored
276
vendor/github.com/aws/aws-sdk-go/aws/session/env_config_test.go
generated
vendored
@ -1,276 +0,0 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLoadEnvConfig_Creds(t *testing.T) {
|
||||
env := stashEnv()
|
||||
defer popEnv(env)
|
||||
|
||||
cases := []struct {
|
||||
Env map[string]string
|
||||
Val credentials.Value
|
||||
}{
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_ACCESS_KEY": "AKID",
|
||||
},
|
||||
Val: credentials.Value{},
|
||||
},
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_ACCESS_KEY_ID": "AKID",
|
||||
},
|
||||
Val: credentials.Value{},
|
||||
},
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_SECRET_KEY": "SECRET",
|
||||
},
|
||||
Val: credentials.Value{},
|
||||
},
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_SECRET_ACCESS_KEY": "SECRET",
|
||||
},
|
||||
Val: credentials.Value{},
|
||||
},
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_ACCESS_KEY_ID": "AKID",
|
||||
"AWS_SECRET_ACCESS_KEY": "SECRET",
|
||||
},
|
||||
Val: credentials.Value{
|
||||
AccessKeyID: "AKID", SecretAccessKey: "SECRET",
|
||||
ProviderName: "EnvConfigCredentials",
|
||||
},
|
||||
},
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_ACCESS_KEY": "AKID",
|
||||
"AWS_SECRET_KEY": "SECRET",
|
||||
},
|
||||
Val: credentials.Value{
|
||||
AccessKeyID: "AKID", SecretAccessKey: "SECRET",
|
||||
ProviderName: "EnvConfigCredentials",
|
||||
},
|
||||
},
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_ACCESS_KEY": "AKID",
|
||||
"AWS_SECRET_KEY": "SECRET",
|
||||
"AWS_SESSION_TOKEN": "TOKEN",
|
||||
},
|
||||
Val: credentials.Value{
|
||||
AccessKeyID: "AKID", SecretAccessKey: "SECRET", SessionToken: "TOKEN",
|
||||
ProviderName: "EnvConfigCredentials",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
os.Clearenv()
|
||||
|
||||
for k, v := range c.Env {
|
||||
os.Setenv(k, v)
|
||||
}
|
||||
|
||||
cfg := loadEnvConfig()
|
||||
assert.Equal(t, c.Val, cfg.Creds)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadEnvConfig(t *testing.T) {
|
||||
env := stashEnv()
|
||||
defer popEnv(env)
|
||||
|
||||
cases := []struct {
|
||||
Env map[string]string
|
||||
Region, Profile string
|
||||
UseSharedConfigCall bool
|
||||
}{
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_REGION": "region",
|
||||
"AWS_PROFILE": "profile",
|
||||
},
|
||||
Region: "region", Profile: "profile",
|
||||
},
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_REGION": "region",
|
||||
"AWS_DEFAULT_REGION": "default_region",
|
||||
"AWS_PROFILE": "profile",
|
||||
"AWS_DEFAULT_PROFILE": "default_profile",
|
||||
},
|
||||
Region: "region", Profile: "profile",
|
||||
},
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_REGION": "region",
|
||||
"AWS_DEFAULT_REGION": "default_region",
|
||||
"AWS_PROFILE": "profile",
|
||||
"AWS_DEFAULT_PROFILE": "default_profile",
|
||||
"AWS_SDK_LOAD_CONFIG": "1",
|
||||
},
|
||||
Region: "region", Profile: "profile",
|
||||
},
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_DEFAULT_REGION": "default_region",
|
||||
"AWS_DEFAULT_PROFILE": "default_profile",
|
||||
},
|
||||
},
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_DEFAULT_REGION": "default_region",
|
||||
"AWS_DEFAULT_PROFILE": "default_profile",
|
||||
"AWS_SDK_LOAD_CONFIG": "1",
|
||||
},
|
||||
Region: "default_region", Profile: "default_profile",
|
||||
},
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_REGION": "region",
|
||||
"AWS_PROFILE": "profile",
|
||||
},
|
||||
Region: "region", Profile: "profile",
|
||||
UseSharedConfigCall: true,
|
||||
},
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_REGION": "region",
|
||||
"AWS_DEFAULT_REGION": "default_region",
|
||||
"AWS_PROFILE": "profile",
|
||||
"AWS_DEFAULT_PROFILE": "default_profile",
|
||||
},
|
||||
Region: "region", Profile: "profile",
|
||||
UseSharedConfigCall: true,
|
||||
},
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_REGION": "region",
|
||||
"AWS_DEFAULT_REGION": "default_region",
|
||||
"AWS_PROFILE": "profile",
|
||||
"AWS_DEFAULT_PROFILE": "default_profile",
|
||||
"AWS_SDK_LOAD_CONFIG": "1",
|
||||
},
|
||||
Region: "region", Profile: "profile",
|
||||
UseSharedConfigCall: true,
|
||||
},
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_DEFAULT_REGION": "default_region",
|
||||
"AWS_DEFAULT_PROFILE": "default_profile",
|
||||
},
|
||||
Region: "default_region", Profile: "default_profile",
|
||||
UseSharedConfigCall: true,
|
||||
},
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_DEFAULT_REGION": "default_region",
|
||||
"AWS_DEFAULT_PROFILE": "default_profile",
|
||||
"AWS_SDK_LOAD_CONFIG": "1",
|
||||
},
|
||||
Region: "default_region", Profile: "default_profile",
|
||||
UseSharedConfigCall: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
os.Clearenv()
|
||||
|
||||
for k, v := range c.Env {
|
||||
os.Setenv(k, v)
|
||||
}
|
||||
|
||||
var cfg envConfig
|
||||
if c.UseSharedConfigCall {
|
||||
cfg = loadSharedEnvConfig()
|
||||
} else {
|
||||
cfg = loadEnvConfig()
|
||||
}
|
||||
|
||||
assert.Equal(t, c.Region, cfg.Region)
|
||||
assert.Equal(t, c.Profile, cfg.Profile)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSharedCredsFilename(t *testing.T) {
|
||||
env := stashEnv()
|
||||
defer popEnv(env)
|
||||
|
||||
os.Setenv("USERPROFILE", "profile_dir")
|
||||
expect := filepath.Join("profile_dir", ".aws", "credentials")
|
||||
name := sharedCredentialsFilename()
|
||||
assert.Equal(t, expect, name)
|
||||
|
||||
os.Setenv("HOME", "home_dir")
|
||||
expect = filepath.Join("home_dir", ".aws", "credentials")
|
||||
name = sharedCredentialsFilename()
|
||||
assert.Equal(t, expect, name)
|
||||
|
||||
expect = filepath.Join("path/to/credentials/file")
|
||||
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", expect)
|
||||
name = sharedCredentialsFilename()
|
||||
assert.Equal(t, expect, name)
|
||||
}
|
||||
|
||||
func TestSharedConfigFilename(t *testing.T) {
|
||||
env := stashEnv()
|
||||
defer popEnv(env)
|
||||
|
||||
os.Setenv("USERPROFILE", "profile_dir")
|
||||
expect := filepath.Join("profile_dir", ".aws", "config")
|
||||
name := sharedConfigFilename()
|
||||
assert.Equal(t, expect, name)
|
||||
|
||||
os.Setenv("HOME", "home_dir")
|
||||
expect = filepath.Join("home_dir", ".aws", "config")
|
||||
name = sharedConfigFilename()
|
||||
assert.Equal(t, expect, name)
|
||||
|
||||
expect = filepath.Join("path/to/config/file")
|
||||
os.Setenv("AWS_CONFIG_FILE", expect)
|
||||
name = sharedConfigFilename()
|
||||
assert.Equal(t, expect, name)
|
||||
}
|
||||
|
||||
func TestSetEnvValue(t *testing.T) {
|
||||
env := stashEnv()
|
||||
defer popEnv(env)
|
||||
|
||||
os.Setenv("empty_key", "")
|
||||
os.Setenv("second_key", "2")
|
||||
os.Setenv("third_key", "3")
|
||||
|
||||
var dst string
|
||||
setFromEnvVal(&dst, []string{
|
||||
"empty_key", "first_key", "second_key", "third_key",
|
||||
})
|
||||
|
||||
assert.Equal(t, "2", dst)
|
||||
}
|
||||
|
||||
func stashEnv() []string {
|
||||
env := os.Environ()
|
||||
os.Clearenv()
|
||||
|
||||
return env
|
||||
}
|
||||
|
||||
func popEnv(env []string) {
|
||||
os.Clearenv()
|
||||
|
||||
for _, e := range env {
|
||||
p := strings.SplitN(e, "=", 2)
|
||||
os.Setenv(p[0], p[1])
|
||||
}
|
||||
}
|
7
vendor/github.com/aws/aws-sdk-go/aws/session/session.go
generated
vendored
7
vendor/github.com/aws/aws-sdk-go/aws/session/session.go
generated
vendored
@ -179,7 +179,12 @@ type Options struct {
|
||||
// SharedConfigState: SharedConfigEnable,
|
||||
// })
|
||||
func NewSessionWithOptions(opts Options) (*Session, error) {
|
||||
envCfg := loadEnvConfig()
|
||||
var envCfg envConfig
|
||||
if opts.SharedConfigState == SharedConfigEnable {
|
||||
envCfg = loadSharedEnvConfig()
|
||||
} else {
|
||||
envCfg = loadEnvConfig()
|
||||
}
|
||||
|
||||
if len(opts.Profile) > 0 {
|
||||
envCfg.Profile = opts.Profile
|
||||
|
344
vendor/github.com/aws/aws-sdk-go/aws/session/session_test.go
generated
vendored
344
vendor/github.com/aws/aws-sdk-go/aws/session/session_test.go
generated
vendored
@ -1,344 +0,0 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/defaults"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
)
|
||||
|
||||
func TestNewDefaultSession(t *testing.T) {
|
||||
oldEnv := initSessionTestEnv()
|
||||
defer popEnv(oldEnv)
|
||||
|
||||
s := New(&aws.Config{Region: aws.String("region")})
|
||||
|
||||
assert.Equal(t, "region", *s.Config.Region)
|
||||
assert.Equal(t, http.DefaultClient, s.Config.HTTPClient)
|
||||
assert.NotNil(t, s.Config.Logger)
|
||||
assert.Equal(t, aws.LogOff, *s.Config.LogLevel)
|
||||
}
|
||||
|
||||
func TestNew_WithCustomCreds(t *testing.T) {
|
||||
oldEnv := initSessionTestEnv()
|
||||
defer popEnv(oldEnv)
|
||||
|
||||
customCreds := credentials.NewStaticCredentials("AKID", "SECRET", "TOKEN")
|
||||
s := New(&aws.Config{Credentials: customCreds})
|
||||
|
||||
assert.Equal(t, customCreds, s.Config.Credentials)
|
||||
}
|
||||
|
||||
type mockLogger struct {
|
||||
*bytes.Buffer
|
||||
}
|
||||
|
||||
func (w mockLogger) Log(args ...interface{}) {
|
||||
fmt.Fprintln(w, args...)
|
||||
}
|
||||
|
||||
func TestNew_WithSessionLoadError(t *testing.T) {
|
||||
oldEnv := initSessionTestEnv()
|
||||
defer popEnv(oldEnv)
|
||||
|
||||
os.Setenv("AWS_SDK_LOAD_CONFIG", "1")
|
||||
os.Setenv("AWS_CONFIG_FILE", testConfigFilename)
|
||||
os.Setenv("AWS_PROFILE", "assume_role_invalid_source_profile")
|
||||
|
||||
logger := bytes.Buffer{}
|
||||
s := New(&aws.Config{Logger: &mockLogger{&logger}})
|
||||
|
||||
assert.NotNil(t, s)
|
||||
|
||||
svc := s3.New(s)
|
||||
_, err := svc.ListBuckets(&s3.ListBucketsInput{})
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, logger.String(), "ERROR: failed to create session with AWS_SDK_LOAD_CONFIG enabled")
|
||||
assert.Contains(t, err.Error(), SharedConfigAssumeRoleError{
|
||||
RoleARN: "assume_role_invalid_source_profile_role_arn",
|
||||
}.Error())
|
||||
}
|
||||
|
||||
func TestSessionCopy(t *testing.T) {
|
||||
oldEnv := initSessionTestEnv()
|
||||
defer popEnv(oldEnv)
|
||||
|
||||
os.Setenv("AWS_REGION", "orig_region")
|
||||
|
||||
s := Session{
|
||||
Config: defaults.Config(),
|
||||
Handlers: defaults.Handlers(),
|
||||
}
|
||||
|
||||
newSess := s.Copy(&aws.Config{Region: aws.String("new_region")})
|
||||
|
||||
assert.Equal(t, "orig_region", *s.Config.Region)
|
||||
assert.Equal(t, "new_region", *newSess.Config.Region)
|
||||
}
|
||||
|
||||
func TestSessionClientConfig(t *testing.T) {
|
||||
s, err := NewSession(&aws.Config{Region: aws.String("orig_region")})
|
||||
assert.NoError(t, err)
|
||||
|
||||
cfg := s.ClientConfig("s3", &aws.Config{Region: aws.String("us-west-2")})
|
||||
|
||||
assert.Equal(t, "https://s3-us-west-2.amazonaws.com", cfg.Endpoint)
|
||||
assert.Empty(t, cfg.SigningRegion)
|
||||
assert.Equal(t, "us-west-2", *cfg.Config.Region)
|
||||
}
|
||||
|
||||
func TestNewSession_NoCredentials(t *testing.T) {
|
||||
oldEnv := initSessionTestEnv()
|
||||
defer popEnv(oldEnv)
|
||||
|
||||
s, err := NewSession()
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NotNil(t, s.Config.Credentials)
|
||||
assert.NotEqual(t, credentials.AnonymousCredentials, s.Config.Credentials)
|
||||
}
|
||||
|
||||
func TestNewSessionWithOptions_OverrideProfile(t *testing.T) {
|
||||
oldEnv := initSessionTestEnv()
|
||||
defer popEnv(oldEnv)
|
||||
|
||||
os.Setenv("AWS_SDK_LOAD_CONFIG", "1")
|
||||
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename)
|
||||
os.Setenv("AWS_PROFILE", "other_profile")
|
||||
|
||||
s, err := NewSessionWithOptions(Options{
|
||||
Profile: "full_profile",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "full_profile_region", *s.Config.Region)
|
||||
|
||||
creds, err := s.Config.Credentials.Get()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "full_profile_akid", creds.AccessKeyID)
|
||||
assert.Equal(t, "full_profile_secret", creds.SecretAccessKey)
|
||||
assert.Empty(t, creds.SessionToken)
|
||||
assert.Contains(t, creds.ProviderName, "SharedConfigCredentials")
|
||||
}
|
||||
|
||||
func TestNewSessionWithOptions_OverrideSharedConfigEnable(t *testing.T) {
|
||||
oldEnv := initSessionTestEnv()
|
||||
defer popEnv(oldEnv)
|
||||
|
||||
os.Setenv("AWS_SDK_LOAD_CONFIG", "0")
|
||||
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename)
|
||||
os.Setenv("AWS_PROFILE", "full_profile")
|
||||
|
||||
s, err := NewSessionWithOptions(Options{
|
||||
SharedConfigState: SharedConfigEnable,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "full_profile_region", *s.Config.Region)
|
||||
|
||||
creds, err := s.Config.Credentials.Get()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "full_profile_akid", creds.AccessKeyID)
|
||||
assert.Equal(t, "full_profile_secret", creds.SecretAccessKey)
|
||||
assert.Empty(t, creds.SessionToken)
|
||||
assert.Contains(t, creds.ProviderName, "SharedConfigCredentials")
|
||||
}
|
||||
|
||||
func TestNewSessionWithOptions_OverrideSharedConfigDisable(t *testing.T) {
|
||||
oldEnv := initSessionTestEnv()
|
||||
defer popEnv(oldEnv)
|
||||
|
||||
os.Setenv("AWS_SDK_LOAD_CONFIG", "1")
|
||||
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename)
|
||||
os.Setenv("AWS_PROFILE", "full_profile")
|
||||
|
||||
s, err := NewSessionWithOptions(Options{
|
||||
SharedConfigState: SharedConfigDisable,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Empty(t, *s.Config.Region)
|
||||
|
||||
creds, err := s.Config.Credentials.Get()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "full_profile_akid", creds.AccessKeyID)
|
||||
assert.Equal(t, "full_profile_secret", creds.SecretAccessKey)
|
||||
assert.Empty(t, creds.SessionToken)
|
||||
assert.Contains(t, creds.ProviderName, "SharedConfigCredentials")
|
||||
}
|
||||
|
||||
func TestNewSessionWithOptions_Overrides(t *testing.T) {
|
||||
cases := []struct {
|
||||
InEnvs map[string]string
|
||||
InProfile string
|
||||
OutRegion string
|
||||
OutCreds credentials.Value
|
||||
}{
|
||||
{
|
||||
InEnvs: map[string]string{
|
||||
"AWS_SDK_LOAD_CONFIG": "0",
|
||||
"AWS_SHARED_CREDENTIALS_FILE": testConfigFilename,
|
||||
"AWS_PROFILE": "other_profile",
|
||||
},
|
||||
InProfile: "full_profile",
|
||||
OutRegion: "full_profile_region",
|
||||
OutCreds: credentials.Value{
|
||||
AccessKeyID: "full_profile_akid",
|
||||
SecretAccessKey: "full_profile_secret",
|
||||
ProviderName: "SharedConfigCredentials",
|
||||
},
|
||||
},
|
||||
{
|
||||
InEnvs: map[string]string{
|
||||
"AWS_SDK_LOAD_CONFIG": "0",
|
||||
"AWS_SHARED_CREDENTIALS_FILE": testConfigFilename,
|
||||
"AWS_REGION": "env_region",
|
||||
"AWS_ACCESS_KEY": "env_akid",
|
||||
"AWS_SECRET_ACCESS_KEY": "env_secret",
|
||||
"AWS_PROFILE": "other_profile",
|
||||
},
|
||||
InProfile: "full_profile",
|
||||
OutRegion: "env_region",
|
||||
OutCreds: credentials.Value{
|
||||
AccessKeyID: "env_akid",
|
||||
SecretAccessKey: "env_secret",
|
||||
ProviderName: "EnvConfigCredentials",
|
||||
},
|
||||
},
|
||||
{
|
||||
InEnvs: map[string]string{
|
||||
"AWS_SDK_LOAD_CONFIG": "0",
|
||||
"AWS_SHARED_CREDENTIALS_FILE": testConfigFilename,
|
||||
"AWS_CONFIG_FILE": testConfigOtherFilename,
|
||||
"AWS_PROFILE": "shared_profile",
|
||||
},
|
||||
InProfile: "config_file_load_order",
|
||||
OutRegion: "shared_config_region",
|
||||
OutCreds: credentials.Value{
|
||||
AccessKeyID: "shared_config_akid",
|
||||
SecretAccessKey: "shared_config_secret",
|
||||
ProviderName: "SharedConfigCredentials",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
oldEnv := initSessionTestEnv()
|
||||
defer popEnv(oldEnv)
|
||||
|
||||
for k, v := range c.InEnvs {
|
||||
os.Setenv(k, v)
|
||||
}
|
||||
|
||||
s, err := NewSessionWithOptions(Options{
|
||||
Profile: c.InProfile,
|
||||
SharedConfigState: SharedConfigEnable,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
creds, err := s.Config.Credentials.Get()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, c.OutRegion, *s.Config.Region)
|
||||
assert.Equal(t, c.OutCreds.AccessKeyID, creds.AccessKeyID)
|
||||
assert.Equal(t, c.OutCreds.SecretAccessKey, creds.SecretAccessKey)
|
||||
assert.Equal(t, c.OutCreds.SessionToken, creds.SessionToken)
|
||||
assert.Contains(t, creds.ProviderName, c.OutCreds.ProviderName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSesisonAssumeRole(t *testing.T) {
|
||||
oldEnv := initSessionTestEnv()
|
||||
defer popEnv(oldEnv)
|
||||
|
||||
os.Setenv("AWS_REGION", "us-east-1")
|
||||
os.Setenv("AWS_SDK_LOAD_CONFIG", "1")
|
||||
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename)
|
||||
os.Setenv("AWS_PROFILE", "assume_role_w_creds")
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
const respMsg = `
|
||||
<AssumeRoleResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
|
||||
<AssumeRoleResult>
|
||||
<AssumedRoleUser>
|
||||
<Arn>arn:aws:sts::account_id:assumed-role/role/session_name</Arn>
|
||||
<AssumedRoleId>AKID:session_name</AssumedRoleId>
|
||||
</AssumedRoleUser>
|
||||
<Credentials>
|
||||
<AccessKeyId>AKID</AccessKeyId>
|
||||
<SecretAccessKey>SECRET</SecretAccessKey>
|
||||
<SessionToken>SESSION_TOKEN</SessionToken>
|
||||
<Expiration>%s</Expiration>
|
||||
</Credentials>
|
||||
</AssumeRoleResult>
|
||||
<ResponseMetadata>
|
||||
<RequestId>request-id</RequestId>
|
||||
</ResponseMetadata>
|
||||
</AssumeRoleResponse>
|
||||
`
|
||||
w.Write([]byte(fmt.Sprintf(respMsg, time.Now().Add(15*time.Minute).Format("2006-01-02T15:04:05Z"))))
|
||||
}))
|
||||
|
||||
s, err := NewSession(&aws.Config{Endpoint: aws.String(server.URL), DisableSSL: aws.Bool(true)})
|
||||
|
||||
creds, err := s.Config.Credentials.Get()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "AKID", creds.AccessKeyID)
|
||||
assert.Equal(t, "SECRET", creds.SecretAccessKey)
|
||||
assert.Equal(t, "SESSION_TOKEN", creds.SessionToken)
|
||||
assert.Contains(t, creds.ProviderName, "AssumeRoleProvider")
|
||||
}
|
||||
|
||||
func TestSessionAssumeRole_DisableSharedConfig(t *testing.T) {
|
||||
// Backwards compatibility with Shared config disabled
|
||||
// assume role should not be built into the config.
|
||||
oldEnv := initSessionTestEnv()
|
||||
defer popEnv(oldEnv)
|
||||
|
||||
os.Setenv("AWS_SDK_LOAD_CONFIG", "0")
|
||||
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename)
|
||||
os.Setenv("AWS_PROFILE", "assume_role_w_creds")
|
||||
|
||||
s, err := NewSession()
|
||||
assert.NoError(t, err)
|
||||
|
||||
creds, err := s.Config.Credentials.Get()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "assume_role_w_creds_akid", creds.AccessKeyID)
|
||||
assert.Equal(t, "assume_role_w_creds_secret", creds.SecretAccessKey)
|
||||
assert.Contains(t, creds.ProviderName, "SharedConfigCredentials")
|
||||
}
|
||||
|
||||
func TestSessionAssumeRole_InvalidSourceProfile(t *testing.T) {
|
||||
// Backwards compatibility with Shared config disabled
|
||||
// assume role should not be built into the config.
|
||||
oldEnv := initSessionTestEnv()
|
||||
defer popEnv(oldEnv)
|
||||
|
||||
os.Setenv("AWS_SDK_LOAD_CONFIG", "1")
|
||||
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename)
|
||||
os.Setenv("AWS_PROFILE", "assume_role_invalid_source_profile")
|
||||
|
||||
s, err := NewSession()
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "SharedConfigAssumeRoleError: failed to load assume role")
|
||||
assert.Nil(t, s)
|
||||
}
|
||||
|
||||
func initSessionTestEnv() (oldEnv []string) {
|
||||
oldEnv = stashEnv()
|
||||
os.Setenv("AWS_CONFIG_FILE", "file_not_exists")
|
||||
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", "file_not_exists")
|
||||
|
||||
return oldEnv
|
||||
}
|
9
vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go
generated
vendored
9
vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go
generated
vendored
@ -2,7 +2,7 @@ package session
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
@ -105,12 +105,13 @@ func loadSharedConfigIniFiles(filenames []string) ([]sharedConfigFile, error) {
|
||||
files := make([]sharedConfigFile, 0, len(filenames))
|
||||
|
||||
for _, filename := range filenames {
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
// Trim files from the list that don't exist.
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
// Skip files which can't be opened and read for whatever reason
|
||||
continue
|
||||
}
|
||||
|
||||
f, err := ini.Load(filename)
|
||||
f, err := ini.Load(b)
|
||||
if err != nil {
|
||||
return nil, SharedConfigLoadError{Filename: filename}
|
||||
}
|
||||
|
264
vendor/github.com/aws/aws-sdk-go/aws/session/shared_config_test.go
generated
vendored
264
vendor/github.com/aws/aws-sdk-go/aws/session/shared_config_test.go
generated
vendored
@ -1,264 +0,0 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/go-ini/ini"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var (
|
||||
testConfigFilename = filepath.Join("testdata", "shared_config")
|
||||
testConfigOtherFilename = filepath.Join("testdata", "shared_config_other")
|
||||
)
|
||||
|
||||
func TestLoadSharedConfig(t *testing.T) {
|
||||
cases := []struct {
|
||||
Filenames []string
|
||||
Profile string
|
||||
Expected sharedConfig
|
||||
Err error
|
||||
}{
|
||||
{
|
||||
Filenames: []string{"file_not_exists"},
|
||||
Profile: "default",
|
||||
},
|
||||
{
|
||||
Filenames: []string{testConfigFilename},
|
||||
Expected: sharedConfig{
|
||||
Region: "default_region",
|
||||
},
|
||||
},
|
||||
{
|
||||
Filenames: []string{testConfigOtherFilename, testConfigFilename},
|
||||
Profile: "config_file_load_order",
|
||||
Expected: sharedConfig{
|
||||
Region: "shared_config_region",
|
||||
Creds: credentials.Value{
|
||||
AccessKeyID: "shared_config_akid",
|
||||
SecretAccessKey: "shared_config_secret",
|
||||
ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Filenames: []string{testConfigFilename, testConfigOtherFilename},
|
||||
Profile: "config_file_load_order",
|
||||
Expected: sharedConfig{
|
||||
Region: "shared_config_other_region",
|
||||
Creds: credentials.Value{
|
||||
AccessKeyID: "shared_config_other_akid",
|
||||
SecretAccessKey: "shared_config_other_secret",
|
||||
ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigOtherFilename),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Filenames: []string{testConfigOtherFilename, testConfigFilename},
|
||||
Profile: "assume_role",
|
||||
Expected: sharedConfig{
|
||||
AssumeRole: assumeRoleConfig{
|
||||
RoleARN: "assume_role_role_arn",
|
||||
SourceProfile: "complete_creds",
|
||||
},
|
||||
AssumeRoleSource: &sharedConfig{
|
||||
Creds: credentials.Value{
|
||||
AccessKeyID: "complete_creds_akid",
|
||||
SecretAccessKey: "complete_creds_secret",
|
||||
ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Filenames: []string{testConfigOtherFilename, testConfigFilename},
|
||||
Profile: "assume_role_invalid_source_profile",
|
||||
Expected: sharedConfig{
|
||||
AssumeRole: assumeRoleConfig{
|
||||
RoleARN: "assume_role_invalid_source_profile_role_arn",
|
||||
SourceProfile: "profile_not_exists",
|
||||
},
|
||||
},
|
||||
Err: SharedConfigAssumeRoleError{RoleARN: "assume_role_invalid_source_profile_role_arn"},
|
||||
},
|
||||
{
|
||||
Filenames: []string{testConfigOtherFilename, testConfigFilename},
|
||||
Profile: "assume_role_w_creds",
|
||||
Expected: sharedConfig{
|
||||
Creds: credentials.Value{
|
||||
AccessKeyID: "assume_role_w_creds_akid",
|
||||
SecretAccessKey: "assume_role_w_creds_secret",
|
||||
ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename),
|
||||
},
|
||||
AssumeRole: assumeRoleConfig{
|
||||
RoleARN: "assume_role_w_creds_role_arn",
|
||||
SourceProfile: "assume_role_w_creds",
|
||||
ExternalID: "1234",
|
||||
RoleSessionName: "assume_role_w_creds_session_name",
|
||||
},
|
||||
AssumeRoleSource: &sharedConfig{
|
||||
Creds: credentials.Value{
|
||||
AccessKeyID: "assume_role_w_creds_akid",
|
||||
SecretAccessKey: "assume_role_w_creds_secret",
|
||||
ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Filenames: []string{testConfigOtherFilename, testConfigFilename},
|
||||
Profile: "assume_role_wo_creds",
|
||||
Expected: sharedConfig{
|
||||
AssumeRole: assumeRoleConfig{
|
||||
RoleARN: "assume_role_wo_creds_role_arn",
|
||||
SourceProfile: "assume_role_wo_creds",
|
||||
},
|
||||
},
|
||||
Err: SharedConfigAssumeRoleError{RoleARN: "assume_role_wo_creds_role_arn"},
|
||||
},
|
||||
{
|
||||
Filenames: []string{filepath.Join("testdata", "shared_config_invalid_ini")},
|
||||
Profile: "profile_name",
|
||||
Err: SharedConfigLoadError{Filename: filepath.Join("testdata", "shared_config_invalid_ini")},
|
||||
},
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
cfg, err := loadSharedConfig(c.Profile, c.Filenames)
|
||||
if c.Err != nil {
|
||||
assert.Contains(t, err.Error(), c.Err.Error(), "expected error, %d", i)
|
||||
continue
|
||||
}
|
||||
|
||||
assert.NoError(t, err, "unexpected error, %d", i)
|
||||
assert.Equal(t, c.Expected, cfg, "not equal, %d", i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadSharedConfigFromFile(t *testing.T) {
|
||||
filename := testConfigFilename
|
||||
f, err := ini.Load(filename)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load test config file, %s, %v", filename, err)
|
||||
}
|
||||
iniFile := sharedConfigFile{IniData: f, Filename: filename}
|
||||
|
||||
cases := []struct {
|
||||
Profile string
|
||||
Expected sharedConfig
|
||||
Err error
|
||||
}{
|
||||
{
|
||||
Profile: "default",
|
||||
Expected: sharedConfig{Region: "default_region"},
|
||||
},
|
||||
{
|
||||
Profile: "alt_profile_name",
|
||||
Expected: sharedConfig{Region: "alt_profile_name_region"},
|
||||
},
|
||||
{
|
||||
Profile: "short_profile_name_first",
|
||||
Expected: sharedConfig{Region: "short_profile_name_first_short"},
|
||||
},
|
||||
{
|
||||
Profile: "partial_creds",
|
||||
Expected: sharedConfig{},
|
||||
},
|
||||
{
|
||||
Profile: "complete_creds",
|
||||
Expected: sharedConfig{
|
||||
Creds: credentials.Value{
|
||||
AccessKeyID: "complete_creds_akid",
|
||||
SecretAccessKey: "complete_creds_secret",
|
||||
ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Profile: "complete_creds_with_token",
|
||||
Expected: sharedConfig{
|
||||
Creds: credentials.Value{
|
||||
AccessKeyID: "complete_creds_with_token_akid",
|
||||
SecretAccessKey: "complete_creds_with_token_secret",
|
||||
SessionToken: "complete_creds_with_token_token",
|
||||
ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Profile: "full_profile",
|
||||
Expected: sharedConfig{
|
||||
Creds: credentials.Value{
|
||||
AccessKeyID: "full_profile_akid",
|
||||
SecretAccessKey: "full_profile_secret",
|
||||
ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename),
|
||||
},
|
||||
Region: "full_profile_region",
|
||||
},
|
||||
},
|
||||
{
|
||||
Profile: "partial_assume_role",
|
||||
Expected: sharedConfig{},
|
||||
},
|
||||
{
|
||||
Profile: "assume_role",
|
||||
Expected: sharedConfig{
|
||||
AssumeRole: assumeRoleConfig{
|
||||
RoleARN: "assume_role_role_arn",
|
||||
SourceProfile: "complete_creds",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Profile: "does_not_exists",
|
||||
Err: SharedConfigProfileNotExistsError{Profile: "does_not_exists"},
|
||||
},
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
cfg := sharedConfig{}
|
||||
|
||||
err := cfg.setFromIniFile(c.Profile, iniFile)
|
||||
if c.Err != nil {
|
||||
assert.Contains(t, err.Error(), c.Err.Error(), "expected error, %d", i)
|
||||
continue
|
||||
}
|
||||
|
||||
assert.NoError(t, err, "unexpected error, %d", i)
|
||||
assert.Equal(t, c.Expected, cfg, "not equal, %d", i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadSharedConfigIniFiles(t *testing.T) {
|
||||
cases := []struct {
|
||||
Filenames []string
|
||||
Expected []sharedConfigFile
|
||||
}{
|
||||
{
|
||||
Filenames: []string{"not_exists", testConfigFilename},
|
||||
Expected: []sharedConfigFile{
|
||||
{Filename: testConfigFilename},
|
||||
},
|
||||
},
|
||||
{
|
||||
Filenames: []string{testConfigFilename, testConfigOtherFilename},
|
||||
Expected: []sharedConfigFile{
|
||||
{Filename: testConfigFilename},
|
||||
{Filename: testConfigOtherFilename},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
files, err := loadSharedConfigIniFiles(c.Filenames)
|
||||
assert.NoError(t, err, "unexpected error, %d", i)
|
||||
assert.Equal(t, len(c.Expected), len(files), "expected num files, %d", i)
|
||||
|
||||
for i, expectedFile := range c.Expected {
|
||||
assert.Equal(t, expectedFile.Filename, files[i].Filename)
|
||||
}
|
||||
}
|
||||
}
|
77
vendor/github.com/aws/aws-sdk-go/aws/signer/v4/functional_test.go
generated
vendored
77
vendor/github.com/aws/aws-sdk-go/aws/signer/v4/functional_test.go
generated
vendored
@ -1,77 +0,0 @@
|
||||
package v4_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPresignHandler(t *testing.T) {
|
||||
svc := s3.New(unit.Session)
|
||||
req, _ := svc.PutObjectRequest(&s3.PutObjectInput{
|
||||
Bucket: aws.String("bucket"),
|
||||
Key: aws.String("key"),
|
||||
ContentDisposition: aws.String("a+b c$d"),
|
||||
ACL: aws.String("public-read"),
|
||||
})
|
||||
req.Time = time.Unix(0, 0)
|
||||
urlstr, err := req.Presign(5 * time.Minute)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
expectedDate := "19700101T000000Z"
|
||||
expectedHeaders := "content-disposition;host;x-amz-acl"
|
||||
expectedSig := "b2754ba8ffeb74a40b94767017e24c4672107d6d5a894648d5d332ca61f5ffe4"
|
||||
expectedCred := "AKID/19700101/mock-region/s3/aws4_request"
|
||||
|
||||
u, _ := url.Parse(urlstr)
|
||||
urlQ := u.Query()
|
||||
assert.Equal(t, expectedSig, urlQ.Get("X-Amz-Signature"))
|
||||
assert.Equal(t, expectedCred, urlQ.Get("X-Amz-Credential"))
|
||||
assert.Equal(t, expectedHeaders, urlQ.Get("X-Amz-SignedHeaders"))
|
||||
assert.Equal(t, expectedDate, urlQ.Get("X-Amz-Date"))
|
||||
assert.Equal(t, "300", urlQ.Get("X-Amz-Expires"))
|
||||
|
||||
assert.NotContains(t, urlstr, "+") // + encoded as %20
|
||||
}
|
||||
|
||||
func TestPresignRequest(t *testing.T) {
|
||||
svc := s3.New(unit.Session)
|
||||
req, _ := svc.PutObjectRequest(&s3.PutObjectInput{
|
||||
Bucket: aws.String("bucket"),
|
||||
Key: aws.String("key"),
|
||||
ContentDisposition: aws.String("a+b c$d"),
|
||||
ACL: aws.String("public-read"),
|
||||
})
|
||||
req.Time = time.Unix(0, 0)
|
||||
urlstr, headers, err := req.PresignRequest(5 * time.Minute)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
expectedDate := "19700101T000000Z"
|
||||
expectedHeaders := "content-disposition;host;x-amz-acl;x-amz-content-sha256"
|
||||
expectedSig := "0d200ba61501d752acd06f39ef4dbe7d83ffd5ea15978dc3476dfc00b8eb574e"
|
||||
expectedCred := "AKID/19700101/mock-region/s3/aws4_request"
|
||||
expectedHeaderMap := http.Header{
|
||||
"x-amz-acl": []string{"public-read"},
|
||||
"content-disposition": []string{"a+b c$d"},
|
||||
"x-amz-content-sha256": []string{"UNSIGNED-PAYLOAD"},
|
||||
}
|
||||
|
||||
u, _ := url.Parse(urlstr)
|
||||
urlQ := u.Query()
|
||||
assert.Equal(t, expectedSig, urlQ.Get("X-Amz-Signature"))
|
||||
assert.Equal(t, expectedCred, urlQ.Get("X-Amz-Credential"))
|
||||
assert.Equal(t, expectedHeaders, urlQ.Get("X-Amz-SignedHeaders"))
|
||||
assert.Equal(t, expectedDate, urlQ.Get("X-Amz-Date"))
|
||||
assert.Equal(t, expectedHeaderMap, headers)
|
||||
assert.Equal(t, "300", urlQ.Get("X-Amz-Expires"))
|
||||
|
||||
assert.NotContains(t, urlstr, "+") // + encoded as %20
|
||||
}
|
57
vendor/github.com/aws/aws-sdk-go/aws/signer/v4/header_rules_test.go
generated
vendored
57
vendor/github.com/aws/aws-sdk-go/aws/signer/v4/header_rules_test.go
generated
vendored
@ -1,57 +0,0 @@
|
||||
package v4
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRuleCheckWhitelist(t *testing.T) {
|
||||
w := whitelist{
|
||||
mapRule{
|
||||
"Cache-Control": struct{}{},
|
||||
},
|
||||
}
|
||||
|
||||
assert.True(t, w.IsValid("Cache-Control"))
|
||||
assert.False(t, w.IsValid("Cache-"))
|
||||
}
|
||||
|
||||
func TestRuleCheckBlacklist(t *testing.T) {
|
||||
b := blacklist{
|
||||
mapRule{
|
||||
"Cache-Control": struct{}{},
|
||||
},
|
||||
}
|
||||
|
||||
assert.False(t, b.IsValid("Cache-Control"))
|
||||
assert.True(t, b.IsValid("Cache-"))
|
||||
}
|
||||
|
||||
func TestRuleCheckPattern(t *testing.T) {
|
||||
p := patterns{"X-Amz-Meta-"}
|
||||
|
||||
assert.True(t, p.IsValid("X-Amz-Meta-"))
|
||||
assert.True(t, p.IsValid("X-Amz-Meta-Star"))
|
||||
assert.False(t, p.IsValid("Cache-"))
|
||||
}
|
||||
|
||||
func TestRuleComplexWhitelist(t *testing.T) {
|
||||
w := rules{
|
||||
whitelist{
|
||||
mapRule{
|
||||
"Cache-Control": struct{}{},
|
||||
},
|
||||
},
|
||||
patterns{"X-Amz-Meta-"},
|
||||
}
|
||||
|
||||
r := rules{
|
||||
inclusiveRules{patterns{"X-Amz-"}, blacklist{w}},
|
||||
}
|
||||
|
||||
assert.True(t, r.IsValid("X-Amz-Blah"))
|
||||
assert.False(t, r.IsValid("X-Amz-Meta-"))
|
||||
assert.False(t, r.IsValid("X-Amz-Meta-Star"))
|
||||
assert.False(t, r.IsValid("Cache-Control"))
|
||||
}
|
24
vendor/github.com/aws/aws-sdk-go/aws/signer/v4/uri_path.go
generated
vendored
Normal file
24
vendor/github.com/aws/aws-sdk-go/aws/signer/v4/uri_path.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
// +build go1.5
|
||||
|
||||
package v4
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func getURIPath(u *url.URL) string {
|
||||
var uri string
|
||||
|
||||
if len(u.Opaque) > 0 {
|
||||
uri = "/" + strings.Join(strings.Split(u.Opaque, "/")[3:], "/")
|
||||
} else {
|
||||
uri = u.EscapedPath()
|
||||
}
|
||||
|
||||
if len(uri) == 0 {
|
||||
uri = "/"
|
||||
}
|
||||
|
||||
return uri
|
||||
}
|
24
vendor/github.com/aws/aws-sdk-go/aws/signer/v4/uri_path_1_4.go
generated
vendored
Normal file
24
vendor/github.com/aws/aws-sdk-go/aws/signer/v4/uri_path_1_4.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
// +build !go1.5
|
||||
|
||||
package v4
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func getURIPath(u *url.URL) string {
|
||||
var uri string
|
||||
|
||||
if len(u.Opaque) > 0 {
|
||||
uri = "/" + strings.Join(strings.Split(u.Opaque, "/")[3:], "/")
|
||||
} else {
|
||||
uri = u.Path
|
||||
}
|
||||
|
||||
if len(uri) == 0 {
|
||||
uri = "/"
|
||||
}
|
||||
|
||||
return uri
|
||||
}
|
123
vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go
generated
vendored
123
vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go
generated
vendored
@ -2,6 +2,48 @@
|
||||
//
|
||||
// Provides request signing for request that need to be signed with
|
||||
// AWS V4 Signatures.
|
||||
//
|
||||
// Standalone Signer
|
||||
//
|
||||
// Generally using the signer outside of the SDK should not require any additional
|
||||
// logic when using Go v1.5 or higher. The signer does this by taking advantage
|
||||
// of the URL.EscapedPath method. If your request URI requires additional escaping
|
||||
// you many need to use the URL.Opaque to define what the raw URI should be sent
|
||||
// to the service as.
|
||||
//
|
||||
// The signer will first check the URL.Opaque field, and use its value if set.
|
||||
// The signer does require the URL.Opaque field to be set in the form of:
|
||||
//
|
||||
// "//<hostname>/<path>"
|
||||
//
|
||||
// // e.g.
|
||||
// "//example.com/some/path"
|
||||
//
|
||||
// The leading "//" and hostname are required or the URL.Opaque escaping will
|
||||
// not work correctly.
|
||||
//
|
||||
// If URL.Opaque is not set the signer will fallback to the URL.EscapedPath()
|
||||
// method and using the returned value. If you're using Go v1.4 you must set
|
||||
// URL.Opaque if the URI path needs escaping. If URL.Opaque is not set with
|
||||
// Go v1.5 the signer will fallback to URL.Path.
|
||||
//
|
||||
// AWS v4 signature validation requires that the canonical string's URI path
|
||||
// element must be the URI escaped form of the HTTP request's path.
|
||||
// http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
|
||||
//
|
||||
// The Go HTTP client will perform escaping automatically on the request. Some
|
||||
// of these escaping may cause signature validation errors because the HTTP
|
||||
// request differs from the URI path or query that the signature was generated.
|
||||
// https://golang.org/pkg/net/url/#URL.EscapedPath
|
||||
//
|
||||
// Because of this, it is recommended that when using the signer outside of the
|
||||
// SDK that explicitly escaping the request prior to being signed is preferable,
|
||||
// and will help prevent signature validation errors. This can be done by setting
|
||||
// the URL.Opaque or URL.RawPath. The SDK will use URL.Opaque first and then
|
||||
// call URL.EscapedPath() if Opaque is not set.
|
||||
//
|
||||
// Test `TestStandaloneSign` provides a complete example of using the signer
|
||||
// outside of the SDK and pre-escaping the URI path.
|
||||
package v4
|
||||
|
||||
import (
|
||||
@ -11,6 +53,7 @@ import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
@ -119,6 +162,15 @@ type Signer struct {
|
||||
// request's query string.
|
||||
DisableHeaderHoisting bool
|
||||
|
||||
// Disables the automatic escaping of the URI path of the request for the
|
||||
// siganture's canonical string's path. For services that do not need additional
|
||||
// escaping then use this to disable the signer escaping the path.
|
||||
//
|
||||
// S3 is an example of a service that does not need additional escaping.
|
||||
//
|
||||
// http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
|
||||
DisableURIPathEscaping bool
|
||||
|
||||
// currentTimeFn returns the time value which represents the current time.
|
||||
// This value should only be used for testing. If it is nil the default
|
||||
// time.Now will be used.
|
||||
@ -150,6 +202,8 @@ type signingCtx struct {
|
||||
ExpireTime time.Duration
|
||||
SignedHeaderVals http.Header
|
||||
|
||||
DisableURIPathEscaping bool
|
||||
|
||||
credValues credentials.Value
|
||||
isPresign bool
|
||||
formattedTime string
|
||||
@ -175,6 +229,12 @@ type signingCtx struct {
|
||||
// is not needed as the full request context will be captured by the http.Request
|
||||
// value. It is included for reference though.
|
||||
//
|
||||
// Sign will set the request's Body to be the `body` parameter passed in. If
|
||||
// the body is not already an io.ReadCloser, it will be wrapped within one. If
|
||||
// a `nil` body parameter passed to Sign, the request's Body field will be
|
||||
// also set to nil. Its important to note that this functionality will not
|
||||
// change the request's ContentLength of the request.
|
||||
//
|
||||
// Sign differs from Presign in that it will sign the request using HTTP
|
||||
// header values. This type of signing is intended for http.Request values that
|
||||
// will not be shared, or are shared in a way the header values on the request
|
||||
@ -229,22 +289,22 @@ func (v4 Signer) signWithBody(r *http.Request, body io.ReadSeeker, service, regi
|
||||
}
|
||||
|
||||
ctx := &signingCtx{
|
||||
Request: r,
|
||||
Body: body,
|
||||
Query: r.URL.Query(),
|
||||
Time: signTime,
|
||||
ExpireTime: exp,
|
||||
isPresign: exp != 0,
|
||||
ServiceName: service,
|
||||
Region: region,
|
||||
Request: r,
|
||||
Body: body,
|
||||
Query: r.URL.Query(),
|
||||
Time: signTime,
|
||||
ExpireTime: exp,
|
||||
isPresign: exp != 0,
|
||||
ServiceName: service,
|
||||
Region: region,
|
||||
DisableURIPathEscaping: v4.DisableURIPathEscaping,
|
||||
}
|
||||
|
||||
for key := range ctx.Query {
|
||||
sort.Strings(ctx.Query[key])
|
||||
}
|
||||
|
||||
if ctx.isRequestSigned() {
|
||||
if !v4.Credentials.IsExpired() && currentTimeFn().Before(ctx.Time.Add(10*time.Minute)) {
|
||||
// If the request is already signed, and the credentials have not
|
||||
// expired, and the request is not too old ignore the signing request.
|
||||
return ctx.SignedHeaderVals, nil
|
||||
}
|
||||
ctx.Time = currentTimeFn()
|
||||
ctx.handlePresignRemoval()
|
||||
}
|
||||
@ -258,6 +318,20 @@ func (v4 Signer) signWithBody(r *http.Request, body io.ReadSeeker, service, regi
|
||||
ctx.assignAmzQueryValues()
|
||||
ctx.build(v4.DisableHeaderHoisting)
|
||||
|
||||
// If the request is not presigned the body should be attached to it. This
|
||||
// prevents the confusion of wanting to send a signed request without
|
||||
// the body the request was signed for attached.
|
||||
if !ctx.isPresign {
|
||||
var reader io.ReadCloser
|
||||
if body != nil {
|
||||
var ok bool
|
||||
if reader, ok = body.(io.ReadCloser); !ok {
|
||||
reader = ioutil.NopCloser(body)
|
||||
}
|
||||
}
|
||||
r.Body = reader
|
||||
}
|
||||
|
||||
if v4.Debug.Matches(aws.LogDebugWithSigning) {
|
||||
v4.logSigningInfo(ctx)
|
||||
}
|
||||
@ -338,6 +412,10 @@ func signSDKRequestWithCurrTime(req *request.Request, curTimeFn func() time.Time
|
||||
v4.Logger = req.Config.Logger
|
||||
v4.DisableHeaderHoisting = req.NotHoist
|
||||
v4.currentTimeFn = curTimeFn
|
||||
if name == "s3" {
|
||||
// S3 service should not have any escaping applied
|
||||
v4.DisableURIPathEscaping = true
|
||||
}
|
||||
})
|
||||
|
||||
signingTime := req.Time
|
||||
@ -345,7 +423,9 @@ func signSDKRequestWithCurrTime(req *request.Request, curTimeFn func() time.Time
|
||||
signingTime = req.LastSignedAt
|
||||
}
|
||||
|
||||
signedHeaders, err := v4.signWithBody(req.HTTPRequest, req.Body, name, region, req.ExpireTime, signingTime)
|
||||
signedHeaders, err := v4.signWithBody(req.HTTPRequest, req.GetBody(),
|
||||
name, region, req.ExpireTime, signingTime,
|
||||
)
|
||||
if err != nil {
|
||||
req.Error = err
|
||||
req.SignedHeaderVals = nil
|
||||
@ -356,7 +436,7 @@ func signSDKRequestWithCurrTime(req *request.Request, curTimeFn func() time.Time
|
||||
req.LastSignedAt = curTimeFn()
|
||||
}
|
||||
|
||||
const logSignInfoMsg = `DEBUG: Request Signiture:
|
||||
const logSignInfoMsg = `DEBUG: Request Signature:
|
||||
---[ CANONICAL STRING ]-----------------------------
|
||||
%s
|
||||
---[ STRING TO SIGN ]--------------------------------
|
||||
@ -492,17 +572,10 @@ func (ctx *signingCtx) buildCanonicalHeaders(r rule, header http.Header) {
|
||||
|
||||
func (ctx *signingCtx) buildCanonicalString() {
|
||||
ctx.Request.URL.RawQuery = strings.Replace(ctx.Query.Encode(), "+", "%20", -1)
|
||||
uri := ctx.Request.URL.Opaque
|
||||
if uri != "" {
|
||||
uri = "/" + strings.Join(strings.Split(uri, "/")[3:], "/")
|
||||
} else {
|
||||
uri = ctx.Request.URL.Path
|
||||
}
|
||||
if uri == "" {
|
||||
uri = "/"
|
||||
}
|
||||
|
||||
if ctx.ServiceName != "s3" {
|
||||
uri := getURIPath(ctx.Request.URL)
|
||||
|
||||
if !ctx.DisableURIPathEscaping {
|
||||
uri = rest.EscapePath(uri, false)
|
||||
}
|
||||
|
||||
|
353
vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4_test.go
generated
vendored
353
vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4_test.go
generated
vendored
@ -1,353 +0,0 @@
|
||||
package v4
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/awstesting"
|
||||
)
|
||||
|
||||
func TestStripExcessHeaders(t *testing.T) {
|
||||
vals := []string{
|
||||
"123",
|
||||
"1 2 3",
|
||||
" 1 2 3",
|
||||
"1 2 3",
|
||||
"1 23",
|
||||
"1 2 3",
|
||||
"1 2 ",
|
||||
" 1 2 ",
|
||||
}
|
||||
|
||||
expected := []string{
|
||||
"123",
|
||||
"1 2 3",
|
||||
"1 2 3",
|
||||
"1 2 3",
|
||||
"1 23",
|
||||
"1 2 3",
|
||||
"1 2",
|
||||
"1 2",
|
||||
}
|
||||
|
||||
newVals := stripExcessSpaces(vals)
|
||||
for i := 0; i < len(newVals); i++ {
|
||||
assert.Equal(t, expected[i], newVals[i], "test: %d", i)
|
||||
}
|
||||
}
|
||||
|
||||
func buildRequest(serviceName, region, body string) (*http.Request, io.ReadSeeker) {
|
||||
endpoint := "https://" + serviceName + "." + region + ".amazonaws.com"
|
||||
reader := strings.NewReader(body)
|
||||
req, _ := http.NewRequest("POST", endpoint, reader)
|
||||
req.URL.Opaque = "//example.org/bucket/key-._~,!@#$%^&*()"
|
||||
req.Header.Add("X-Amz-Target", "prefix.Operation")
|
||||
req.Header.Add("Content-Type", "application/x-amz-json-1.0")
|
||||
req.Header.Add("Content-Length", string(len(body)))
|
||||
req.Header.Add("X-Amz-Meta-Other-Header", "some-value=!@#$%^&* (+)")
|
||||
req.Header.Add("X-Amz-Meta-Other-Header_With_Underscore", "some-value=!@#$%^&* (+)")
|
||||
req.Header.Add("X-amz-Meta-Other-Header_With_Underscore", "some-value=!@#$%^&* (+)")
|
||||
return req, reader
|
||||
}
|
||||
|
||||
func buildSigner() Signer {
|
||||
return Signer{
|
||||
Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"),
|
||||
}
|
||||
}
|
||||
|
||||
func removeWS(text string) string {
|
||||
text = strings.Replace(text, " ", "", -1)
|
||||
text = strings.Replace(text, "\n", "", -1)
|
||||
text = strings.Replace(text, "\t", "", -1)
|
||||
return text
|
||||
}
|
||||
|
||||
func assertEqual(t *testing.T, expected, given string) {
|
||||
if removeWS(expected) != removeWS(given) {
|
||||
t.Errorf("\nExpected: %s\nGiven: %s", expected, given)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPresignRequest(t *testing.T) {
|
||||
req, body := buildRequest("dynamodb", "us-east-1", "{}")
|
||||
|
||||
signer := buildSigner()
|
||||
signer.Presign(req, body, "dynamodb", "us-east-1", 300*time.Second, time.Unix(0, 0))
|
||||
|
||||
expectedDate := "19700101T000000Z"
|
||||
expectedHeaders := "content-length;content-type;host;x-amz-meta-other-header;x-amz-meta-other-header_with_underscore"
|
||||
expectedSig := "ea7856749041f727690c580569738282e99c79355fe0d8f125d3b5535d2ece83"
|
||||
expectedCred := "AKID/19700101/us-east-1/dynamodb/aws4_request"
|
||||
expectedTarget := "prefix.Operation"
|
||||
|
||||
q := req.URL.Query()
|
||||
assert.Equal(t, expectedSig, q.Get("X-Amz-Signature"))
|
||||
assert.Equal(t, expectedCred, q.Get("X-Amz-Credential"))
|
||||
assert.Equal(t, expectedHeaders, q.Get("X-Amz-SignedHeaders"))
|
||||
assert.Equal(t, expectedDate, q.Get("X-Amz-Date"))
|
||||
assert.Empty(t, q.Get("X-Amz-Meta-Other-Header"))
|
||||
assert.Equal(t, expectedTarget, q.Get("X-Amz-Target"))
|
||||
}
|
||||
|
||||
func TestSignRequest(t *testing.T) {
|
||||
req, body := buildRequest("dynamodb", "us-east-1", "{}")
|
||||
signer := buildSigner()
|
||||
signer.Sign(req, body, "dynamodb", "us-east-1", time.Unix(0, 0))
|
||||
|
||||
expectedDate := "19700101T000000Z"
|
||||
expectedSig := "AWS4-HMAC-SHA256 Credential=AKID/19700101/us-east-1/dynamodb/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date;x-amz-meta-other-header;x-amz-meta-other-header_with_underscore;x-amz-security-token;x-amz-target, Signature=ea766cabd2ec977d955a3c2bae1ae54f4515d70752f2207618396f20aa85bd21"
|
||||
|
||||
q := req.Header
|
||||
assert.Equal(t, expectedSig, q.Get("Authorization"))
|
||||
assert.Equal(t, expectedDate, q.Get("X-Amz-Date"))
|
||||
}
|
||||
|
||||
func TestSignBodyS3(t *testing.T) {
|
||||
req, body := buildRequest("s3", "us-east-1", "hello")
|
||||
signer := buildSigner()
|
||||
signer.Sign(req, body, "s3", "us-east-1", time.Now())
|
||||
hash := req.Header.Get("X-Amz-Content-Sha256")
|
||||
assert.Equal(t, "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824", hash)
|
||||
}
|
||||
|
||||
func TestSignBodyGlacier(t *testing.T) {
|
||||
req, body := buildRequest("glacier", "us-east-1", "hello")
|
||||
signer := buildSigner()
|
||||
signer.Sign(req, body, "glacier", "us-east-1", time.Now())
|
||||
hash := req.Header.Get("X-Amz-Content-Sha256")
|
||||
assert.Equal(t, "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824", hash)
|
||||
}
|
||||
|
||||
func TestPresignEmptyBodyS3(t *testing.T) {
|
||||
req, body := buildRequest("s3", "us-east-1", "hello")
|
||||
signer := buildSigner()
|
||||
signer.Presign(req, body, "s3", "us-east-1", 5*time.Minute, time.Now())
|
||||
hash := req.Header.Get("X-Amz-Content-Sha256")
|
||||
assert.Equal(t, "UNSIGNED-PAYLOAD", hash)
|
||||
}
|
||||
|
||||
func TestSignPrecomputedBodyChecksum(t *testing.T) {
|
||||
req, body := buildRequest("dynamodb", "us-east-1", "hello")
|
||||
req.Header.Set("X-Amz-Content-Sha256", "PRECOMPUTED")
|
||||
signer := buildSigner()
|
||||
signer.Sign(req, body, "dynamodb", "us-east-1", time.Now())
|
||||
hash := req.Header.Get("X-Amz-Content-Sha256")
|
||||
assert.Equal(t, "PRECOMPUTED", hash)
|
||||
}
|
||||
|
||||
func TestAnonymousCredentials(t *testing.T) {
|
||||
svc := awstesting.NewClient(&aws.Config{Credentials: credentials.AnonymousCredentials})
|
||||
r := svc.NewRequest(
|
||||
&request.Operation{
|
||||
Name: "BatchGetItem",
|
||||
HTTPMethod: "POST",
|
||||
HTTPPath: "/",
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
SignSDKRequest(r)
|
||||
|
||||
urlQ := r.HTTPRequest.URL.Query()
|
||||
assert.Empty(t, urlQ.Get("X-Amz-Signature"))
|
||||
assert.Empty(t, urlQ.Get("X-Amz-Credential"))
|
||||
assert.Empty(t, urlQ.Get("X-Amz-SignedHeaders"))
|
||||
assert.Empty(t, urlQ.Get("X-Amz-Date"))
|
||||
|
||||
hQ := r.HTTPRequest.Header
|
||||
assert.Empty(t, hQ.Get("Authorization"))
|
||||
assert.Empty(t, hQ.Get("X-Amz-Date"))
|
||||
}
|
||||
|
||||
func TestIgnoreResignRequestWithValidCreds(t *testing.T) {
|
||||
svc := awstesting.NewClient(&aws.Config{
|
||||
Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"),
|
||||
Region: aws.String("us-west-2"),
|
||||
})
|
||||
r := svc.NewRequest(
|
||||
&request.Operation{
|
||||
Name: "BatchGetItem",
|
||||
HTTPMethod: "POST",
|
||||
HTTPPath: "/",
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
SignSDKRequest(r)
|
||||
sig := r.HTTPRequest.Header.Get("Authorization")
|
||||
|
||||
SignSDKRequest(r)
|
||||
assert.Equal(t, sig, r.HTTPRequest.Header.Get("Authorization"))
|
||||
}
|
||||
|
||||
func TestIgnorePreResignRequestWithValidCreds(t *testing.T) {
|
||||
svc := awstesting.NewClient(&aws.Config{
|
||||
Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"),
|
||||
Region: aws.String("us-west-2"),
|
||||
})
|
||||
r := svc.NewRequest(
|
||||
&request.Operation{
|
||||
Name: "BatchGetItem",
|
||||
HTTPMethod: "POST",
|
||||
HTTPPath: "/",
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
r.ExpireTime = time.Minute * 10
|
||||
|
||||
SignSDKRequest(r)
|
||||
sig := r.HTTPRequest.Header.Get("X-Amz-Signature")
|
||||
|
||||
SignSDKRequest(r)
|
||||
assert.Equal(t, sig, r.HTTPRequest.Header.Get("X-Amz-Signature"))
|
||||
}
|
||||
|
||||
func TestResignRequestExpiredCreds(t *testing.T) {
|
||||
creds := credentials.NewStaticCredentials("AKID", "SECRET", "SESSION")
|
||||
svc := awstesting.NewClient(&aws.Config{Credentials: creds})
|
||||
r := svc.NewRequest(
|
||||
&request.Operation{
|
||||
Name: "BatchGetItem",
|
||||
HTTPMethod: "POST",
|
||||
HTTPPath: "/",
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
SignSDKRequest(r)
|
||||
querySig := r.HTTPRequest.Header.Get("Authorization")
|
||||
var origSignedHeaders string
|
||||
for _, p := range strings.Split(querySig, ", ") {
|
||||
if strings.HasPrefix(p, "SignedHeaders=") {
|
||||
origSignedHeaders = p[len("SignedHeaders="):]
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.NotEmpty(t, origSignedHeaders)
|
||||
assert.NotContains(t, origSignedHeaders, "authorization")
|
||||
origSignedAt := r.LastSignedAt
|
||||
|
||||
creds.Expire()
|
||||
|
||||
signSDKRequestWithCurrTime(r, func() time.Time {
|
||||
// Simulate one second has passed so that signature's date changes
|
||||
// when it is resigned.
|
||||
return time.Now().Add(1 * time.Second)
|
||||
})
|
||||
updatedQuerySig := r.HTTPRequest.Header.Get("Authorization")
|
||||
assert.NotEqual(t, querySig, updatedQuerySig)
|
||||
|
||||
var updatedSignedHeaders string
|
||||
for _, p := range strings.Split(updatedQuerySig, ", ") {
|
||||
if strings.HasPrefix(p, "SignedHeaders=") {
|
||||
updatedSignedHeaders = p[len("SignedHeaders="):]
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.NotEmpty(t, updatedSignedHeaders)
|
||||
assert.NotContains(t, updatedQuerySig, "authorization")
|
||||
assert.NotEqual(t, origSignedAt, r.LastSignedAt)
|
||||
}
|
||||
|
||||
func TestPreResignRequestExpiredCreds(t *testing.T) {
|
||||
provider := &credentials.StaticProvider{Value: credentials.Value{
|
||||
AccessKeyID: "AKID",
|
||||
SecretAccessKey: "SECRET",
|
||||
SessionToken: "SESSION",
|
||||
}}
|
||||
creds := credentials.NewCredentials(provider)
|
||||
svc := awstesting.NewClient(&aws.Config{Credentials: creds})
|
||||
r := svc.NewRequest(
|
||||
&request.Operation{
|
||||
Name: "BatchGetItem",
|
||||
HTTPMethod: "POST",
|
||||
HTTPPath: "/",
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
r.ExpireTime = time.Minute * 10
|
||||
|
||||
SignSDKRequest(r)
|
||||
querySig := r.HTTPRequest.URL.Query().Get("X-Amz-Signature")
|
||||
signedHeaders := r.HTTPRequest.URL.Query().Get("X-Amz-SignedHeaders")
|
||||
assert.NotEmpty(t, signedHeaders)
|
||||
origSignedAt := r.LastSignedAt
|
||||
|
||||
creds.Expire()
|
||||
|
||||
signSDKRequestWithCurrTime(r, func() time.Time {
|
||||
// Simulate the request occurred 15 minutes in the past
|
||||
return time.Now().Add(-48 * time.Hour)
|
||||
})
|
||||
assert.NotEqual(t, querySig, r.HTTPRequest.URL.Query().Get("X-Amz-Signature"))
|
||||
resignedHeaders := r.HTTPRequest.URL.Query().Get("X-Amz-SignedHeaders")
|
||||
assert.Equal(t, signedHeaders, resignedHeaders)
|
||||
assert.NotContains(t, signedHeaders, "x-amz-signedHeaders")
|
||||
assert.NotEqual(t, origSignedAt, r.LastSignedAt)
|
||||
}
|
||||
|
||||
func TestResignRequestExpiredRequest(t *testing.T) {
|
||||
creds := credentials.NewStaticCredentials("AKID", "SECRET", "SESSION")
|
||||
svc := awstesting.NewClient(&aws.Config{Credentials: creds})
|
||||
r := svc.NewRequest(
|
||||
&request.Operation{
|
||||
Name: "BatchGetItem",
|
||||
HTTPMethod: "POST",
|
||||
HTTPPath: "/",
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
SignSDKRequest(r)
|
||||
querySig := r.HTTPRequest.Header.Get("Authorization")
|
||||
origSignedAt := r.LastSignedAt
|
||||
|
||||
signSDKRequestWithCurrTime(r, func() time.Time {
|
||||
// Simulate the request occurred 15 minutes in the past
|
||||
return time.Now().Add(15 * time.Minute)
|
||||
})
|
||||
assert.NotEqual(t, querySig, r.HTTPRequest.Header.Get("Authorization"))
|
||||
assert.NotEqual(t, origSignedAt, r.LastSignedAt)
|
||||
}
|
||||
|
||||
func BenchmarkPresignRequest(b *testing.B) {
|
||||
signer := buildSigner()
|
||||
req, body := buildRequest("dynamodb", "us-east-1", "{}")
|
||||
for i := 0; i < b.N; i++ {
|
||||
signer.Presign(req, body, "dynamodb", "us-east-1", 300*time.Second, time.Now())
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSignRequest(b *testing.B) {
|
||||
signer := buildSigner()
|
||||
req, body := buildRequest("dynamodb", "us-east-1", "{}")
|
||||
for i := 0; i < b.N; i++ {
|
||||
signer.Sign(req, body, "dynamodb", "us-east-1", time.Now())
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkStripExcessSpaces(b *testing.B) {
|
||||
vals := []string{
|
||||
`AWS4-HMAC-SHA256 Credential=AKIDFAKEIDFAKEID/20160628/us-west-2/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature=1234567890abcdef1234567890abcdef1234567890abcdef`,
|
||||
`123 321 123 321`,
|
||||
` 123 321 123 321 `,
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
stripExcessSpaces(vals)
|
||||
}
|
||||
}
|
75
vendor/github.com/aws/aws-sdk-go/aws/types_test.go
generated
vendored
75
vendor/github.com/aws/aws-sdk-go/aws/types_test.go
generated
vendored
@ -1,75 +0,0 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestWriteAtBuffer(t *testing.T) {
|
||||
b := &WriteAtBuffer{}
|
||||
|
||||
n, err := b.WriteAt([]byte{1}, 0)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, n)
|
||||
|
||||
n, err = b.WriteAt([]byte{1, 1, 1}, 5)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 3, n)
|
||||
|
||||
n, err = b.WriteAt([]byte{2}, 1)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, n)
|
||||
|
||||
n, err = b.WriteAt([]byte{3}, 2)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, n)
|
||||
|
||||
assert.Equal(t, []byte{1, 2, 3, 0, 0, 1, 1, 1}, b.Bytes())
|
||||
}
|
||||
|
||||
func BenchmarkWriteAtBuffer(b *testing.B) {
|
||||
buf := &WriteAtBuffer{}
|
||||
r := rand.New(rand.NewSource(1))
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
to := r.Intn(10) * 4096
|
||||
bs := make([]byte, to)
|
||||
buf.WriteAt(bs, r.Int63n(10)*4096)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkWriteAtBufferOrderedWrites(b *testing.B) {
|
||||
// test the performance of a WriteAtBuffer when written in an
|
||||
// ordered fashion. This is similar to the behavior of the
|
||||
// s3.Downloader, since downloads the first chunk of the file, then
|
||||
// the second, and so on.
|
||||
//
|
||||
// This test simulates a 150MB file being written in 30 ordered 5MB chunks.
|
||||
chunk := int64(5e6)
|
||||
max := chunk * 30
|
||||
// we'll write the same 5MB chunk every time
|
||||
tmp := make([]byte, chunk)
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf := &WriteAtBuffer{}
|
||||
for i := int64(0); i < max; i += chunk {
|
||||
buf.WriteAt(tmp, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkWriteAtBufferParallel(b *testing.B) {
|
||||
buf := &WriteAtBuffer{}
|
||||
r := rand.New(rand.NewSource(1))
|
||||
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
to := r.Intn(10) * 4096
|
||||
bs := make([]byte, to)
|
||||
buf.WriteAt(bs, r.Int63n(10)*4096)
|
||||
}
|
||||
})
|
||||
}
|
2
vendor/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
@ -5,4 +5,4 @@ package aws
|
||||
const SDKName = "aws-sdk-go"
|
||||
|
||||
// SDKVersion is the version of this SDK
|
||||
const SDKVersion = "1.4.1"
|
||||
const SDKVersion = "1.5.8"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user