update AWS SDK to 1.13.12, remove unused Azure package

Signed-off-by: Steve Kriss <steve@heptio.com>
pull/341/head
Steve Kriss 2018-03-13 11:06:15 -07:00
parent a05ae1a7cf
commit 0dddfc3e0f
63 changed files with 16511 additions and 3243 deletions

13
Gopkg.lock generated
View File

@ -9,7 +9,7 @@
[[projects]] [[projects]]
name = "github.com/Azure/azure-sdk-for-go" name = "github.com/Azure/azure-sdk-for-go"
packages = ["arm/disk","arm/examples/helpers","arm/resources/subscriptions","storage"] packages = ["arm/disk","arm/examples/helpers","storage"]
revision = "2d49bb8f2cee530cc16f1f1a9f0aae763dee257d" revision = "2d49bb8f2cee530cc16f1f1a9f0aae763dee257d"
version = "v10.2.1-beta" version = "v10.2.1-beta"
@ -33,9 +33,9 @@
[[projects]] [[projects]]
name = "github.com/aws/aws-sdk-go" name = "github.com/aws/aws-sdk-go"
packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/corehandlers","aws/credentials","aws/credentials/ec2rolecreds","aws/credentials/endpointcreds","aws/credentials/stscreds","aws/defaults","aws/ec2metadata","aws/endpoints","aws/request","aws/session","aws/signer/v4","internal/shareddefaults","private/protocol","private/protocol/ec2query","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/restxml","private/protocol/xml/xmlutil","service/ec2","service/s3","service/s3/s3iface","service/s3/s3manager","service/sts"] packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/corehandlers","aws/credentials","aws/credentials/ec2rolecreds","aws/credentials/endpointcreds","aws/credentials/stscreds","aws/defaults","aws/ec2metadata","aws/endpoints","aws/request","aws/session","aws/signer/v4","internal/sdkio","internal/sdkrand","internal/shareddefaults","private/protocol","private/protocol/ec2query","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/restxml","private/protocol/xml/xmlutil","service/ec2","service/s3","service/s3/s3iface","service/s3/s3manager","service/sts"]
revision = "1850f427c33c2558a2118dc55c1cf95a633d7432" revision = "1f8fb9d0919e5a58992207db9512a03f76ab0274"
version = "v1.10.27" version = "v1.13.12"
[[projects]] [[projects]]
name = "github.com/cpuguy83/go-md2man" name = "github.com/cpuguy83/go-md2man"
@ -196,8 +196,7 @@
[[projects]] [[projects]]
name = "github.com/jmespath/go-jmespath" name = "github.com/jmespath/go-jmespath"
packages = ["."] packages = ["."]
revision = "3433f3ea46d9f8019119e7dd41274e112a2359a9" revision = "0b12d6b5"
version = "0.2.2"
[[projects]] [[projects]]
name = "github.com/json-iterator/go" name = "github.com/json-iterator/go"
@ -421,6 +420,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "dfaf28e8f08499e84a51042b2d93178446e7cea44835bf34ce9a56b3f236a30f" inputs-digest = "33e72fc9ce7ad76cee7ef7a8da5e39f620206c4f024fa1f514e9281f193e2e6d"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View File

@ -45,7 +45,7 @@ required = [
[[constraint]] [[constraint]]
name = "github.com/aws/aws-sdk-go" name = "github.com/aws/aws-sdk-go"
version = "1.10.26" version = "1.13.12"
[[constraint]] [[constraint]]
branch = "master" branch = "master"

View File

@ -1,54 +0,0 @@
// Package subscriptions implements the Azure ARM Subscriptions service API
// version 2016-06-01.
//
// All resource groups and resources exist within subscriptions. These
// operation enable you get information about your subscriptions and tenants. A
// tenant is a dedicated instance of Azure Active Directory (Azure AD) for your
// organization.
package subscriptions
// Copyright (c) Microsoft and contributors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Code generated by Microsoft (R) AutoRest Code Generator 1.0.1.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
import (
"github.com/Azure/go-autorest/autorest"
)
const (
// DefaultBaseURI is the default URI used for the service Subscriptions
DefaultBaseURI = "https://management.azure.com"
)
// ManagementClient is the base client for Subscriptions.
type ManagementClient struct {
autorest.Client
BaseURI string
}
// New creates an instance of the ManagementClient client.
func New() ManagementClient {
return NewWithBaseURI(DefaultBaseURI)
}
// NewWithBaseURI creates an instance of the ManagementClient client.
func NewWithBaseURI(baseURI string) ManagementClient {
return ManagementClient{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: baseURI,
}
}

View File

@ -1,132 +0,0 @@
package subscriptions
// Copyright (c) Microsoft and contributors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Code generated by Microsoft (R) AutoRest Code Generator 1.0.1.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/to"
"net/http"
)
// SpendingLimit enumerates the values for spending limit.
type SpendingLimit string
const (
// CurrentPeriodOff specifies the current period off state for spending
// limit.
CurrentPeriodOff SpendingLimit = "CurrentPeriodOff"
// Off specifies the off state for spending limit.
Off SpendingLimit = "Off"
// On specifies the on state for spending limit.
On SpendingLimit = "On"
)
// State enumerates the values for state.
type State string
const (
// Deleted specifies the deleted state for state.
Deleted State = "Deleted"
// Disabled specifies the disabled state for state.
Disabled State = "Disabled"
// Enabled specifies the enabled state for state.
Enabled State = "Enabled"
// PastDue specifies the past due state for state.
PastDue State = "PastDue"
// Warned specifies the warned state for state.
Warned State = "Warned"
)
// ListResult is subscription list operation response.
type ListResult struct {
autorest.Response `json:"-"`
Value *[]Subscription `json:"value,omitempty"`
NextLink *string `json:"nextLink,omitempty"`
}
// ListResultPreparer prepares a request to retrieve the next set of results. It returns
// nil if no more results exist.
func (client ListResult) ListResultPreparer() (*http.Request, error) {
if client.NextLink == nil || len(to.String(client.NextLink)) <= 0 {
return nil, nil
}
return autorest.Prepare(&http.Request{},
autorest.AsJSON(),
autorest.AsGet(),
autorest.WithBaseURL(to.String(client.NextLink)))
}
// Location is location information.
type Location struct {
ID *string `json:"id,omitempty"`
SubscriptionID *string `json:"subscriptionId,omitempty"`
Name *string `json:"name,omitempty"`
DisplayName *string `json:"displayName,omitempty"`
Latitude *string `json:"latitude,omitempty"`
Longitude *string `json:"longitude,omitempty"`
}
// LocationListResult is location list operation response.
type LocationListResult struct {
autorest.Response `json:"-"`
Value *[]Location `json:"value,omitempty"`
}
// Policies is subscription policies.
type Policies struct {
LocationPlacementID *string `json:"locationPlacementId,omitempty"`
QuotaID *string `json:"quotaId,omitempty"`
SpendingLimit SpendingLimit `json:"spendingLimit,omitempty"`
}
// Subscription is subscription information.
type Subscription struct {
autorest.Response `json:"-"`
ID *string `json:"id,omitempty"`
SubscriptionID *string `json:"subscriptionId,omitempty"`
DisplayName *string `json:"displayName,omitempty"`
State State `json:"state,omitempty"`
SubscriptionPolicies *Policies `json:"subscriptionPolicies,omitempty"`
AuthorizationSource *string `json:"authorizationSource,omitempty"`
}
// TenantIDDescription is tenant Id information.
type TenantIDDescription struct {
ID *string `json:"id,omitempty"`
TenantID *string `json:"tenantId,omitempty"`
}
// TenantListResult is tenant Ids information.
type TenantListResult struct {
autorest.Response `json:"-"`
Value *[]TenantIDDescription `json:"value,omitempty"`
NextLink *string `json:"nextLink,omitempty"`
}
// TenantListResultPreparer prepares a request to retrieve the next set of results. It returns
// nil if no more results exist.
func (client TenantListResult) TenantListResultPreparer() (*http.Request, error) {
if client.NextLink == nil || len(to.String(client.NextLink)) <= 0 {
return nil, nil
}
return autorest.Prepare(&http.Request{},
autorest.AsJSON(),
autorest.AsGet(),
autorest.WithBaseURL(to.String(client.NextLink)))
}

View File

@ -1,252 +0,0 @@
package subscriptions
// Copyright (c) Microsoft and contributors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Code generated by Microsoft (R) AutoRest Code Generator 1.0.1.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"net/http"
)
// GroupClient is the all resource groups and resources exist within
// subscriptions. These operation enable you get information about your
// subscriptions and tenants. A tenant is a dedicated instance of Azure Active
// Directory (Azure AD) for your organization.
type GroupClient struct {
ManagementClient
}
// NewGroupClient creates an instance of the GroupClient client.
func NewGroupClient() GroupClient {
return NewGroupClientWithBaseURI(DefaultBaseURI)
}
// NewGroupClientWithBaseURI creates an instance of the GroupClient client.
func NewGroupClientWithBaseURI(baseURI string) GroupClient {
return GroupClient{NewWithBaseURI(baseURI)}
}
// Get gets details about a specified subscription.
//
// subscriptionID is the ID of the target subscription.
func (client GroupClient) Get(subscriptionID string) (result Subscription, err error) {
req, err := client.GetPreparer(subscriptionID)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "Get", resp, "Failure responding to request")
}
return
}
// GetPreparer prepares the Get request.
func (client GroupClient) GetPreparer(subscriptionID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"subscriptionId": autorest.Encode("path", subscriptionID),
}
const APIVersion = "2016-06-01"
queryParameters := map[string]interface{}{
"api-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(client.BaseURI),
autorest.WithPathParameters("/subscriptions/{subscriptionId}", pathParameters),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare(&http.Request{})
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client GroupClient) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req)
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client GroupClient) GetResponder(resp *http.Response) (result Subscription, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
// List gets all subscriptions for a tenant.
func (client GroupClient) List() (result ListResult, err error) {
req, err := client.ListPreparer()
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "List", nil, "Failure preparing request")
return
}
resp, err := client.ListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "List", resp, "Failure sending request")
return
}
result, err = client.ListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "List", resp, "Failure responding to request")
}
return
}
// ListPreparer prepares the List request.
func (client GroupClient) ListPreparer() (*http.Request, error) {
const APIVersion = "2016-06-01"
queryParameters := map[string]interface{}{
"api-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(client.BaseURI),
autorest.WithPath("/subscriptions"),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare(&http.Request{})
}
// ListSender sends the List request. The method will close the
// http.Response Body if it receives an error.
func (client GroupClient) ListSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req)
}
// ListResponder handles the response to the List request. The method always
// closes the http.Response Body.
func (client GroupClient) ListResponder(resp *http.Response) (result ListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
// ListNextResults retrieves the next set of results, if any.
func (client GroupClient) ListNextResults(lastResults ListResult) (result ListResult, err error) {
req, err := lastResults.ListResultPreparer()
if err != nil {
return result, autorest.NewErrorWithError(err, "subscriptions.GroupClient", "List", nil, "Failure preparing next results request")
}
if req == nil {
return
}
resp, err := client.ListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
return result, autorest.NewErrorWithError(err, "subscriptions.GroupClient", "List", resp, "Failure sending next results request")
}
result, err = client.ListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "List", resp, "Failure responding to next results request")
}
return
}
// ListLocations this operation provides all the locations that are available
// for resource providers; however, each resource provider may support a subset
// of this list.
//
// subscriptionID is the ID of the target subscription.
func (client GroupClient) ListLocations(subscriptionID string) (result LocationListResult, err error) {
req, err := client.ListLocationsPreparer(subscriptionID)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "ListLocations", nil, "Failure preparing request")
return
}
resp, err := client.ListLocationsSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "ListLocations", resp, "Failure sending request")
return
}
result, err = client.ListLocationsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "ListLocations", resp, "Failure responding to request")
}
return
}
// ListLocationsPreparer prepares the ListLocations request.
func (client GroupClient) ListLocationsPreparer(subscriptionID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"subscriptionId": autorest.Encode("path", subscriptionID),
}
const APIVersion = "2016-06-01"
queryParameters := map[string]interface{}{
"api-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(client.BaseURI),
autorest.WithPathParameters("/subscriptions/{subscriptionId}/locations", pathParameters),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare(&http.Request{})
}
// ListLocationsSender sends the ListLocations request. The method will close the
// http.Response Body if it receives an error.
func (client GroupClient) ListLocationsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req)
}
// ListLocationsResponder handles the response to the ListLocations request. The method always
// closes the http.Response Body.
func (client GroupClient) ListLocationsResponder(resp *http.Response) (result LocationListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}

View File

@ -1,124 +0,0 @@
package subscriptions
// Copyright (c) Microsoft and contributors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Code generated by Microsoft (R) AutoRest Code Generator 1.0.1.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"net/http"
)
// TenantsClient is the all resource groups and resources exist within
// subscriptions. These operation enable you get information about your
// subscriptions and tenants. A tenant is a dedicated instance of Azure Active
// Directory (Azure AD) for your organization.
type TenantsClient struct {
ManagementClient
}
// NewTenantsClient creates an instance of the TenantsClient client.
func NewTenantsClient() TenantsClient {
return NewTenantsClientWithBaseURI(DefaultBaseURI)
}
// NewTenantsClientWithBaseURI creates an instance of the TenantsClient client.
func NewTenantsClientWithBaseURI(baseURI string) TenantsClient {
return TenantsClient{NewWithBaseURI(baseURI)}
}
// List gets the tenants for your account.
func (client TenantsClient) List() (result TenantListResult, err error) {
req, err := client.ListPreparer()
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "List", nil, "Failure preparing request")
return
}
resp, err := client.ListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "List", resp, "Failure sending request")
return
}
result, err = client.ListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "List", resp, "Failure responding to request")
}
return
}
// ListPreparer prepares the List request.
func (client TenantsClient) ListPreparer() (*http.Request, error) {
const APIVersion = "2016-06-01"
queryParameters := map[string]interface{}{
"api-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(client.BaseURI),
autorest.WithPath("/tenants"),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare(&http.Request{})
}
// ListSender sends the List request. The method will close the
// http.Response Body if it receives an error.
func (client TenantsClient) ListSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req)
}
// ListResponder handles the response to the List request. The method always
// closes the http.Response Body.
func (client TenantsClient) ListResponder(resp *http.Response) (result TenantListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
// ListNextResults retrieves the next set of results, if any.
func (client TenantsClient) ListNextResults(lastResults TenantListResult) (result TenantListResult, err error) {
req, err := lastResults.TenantListResultPreparer()
if err != nil {
return result, autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "List", nil, "Failure preparing next results request")
}
if req == nil {
return
}
resp, err := client.ListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
return result, autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "List", resp, "Failure sending next results request")
}
result, err = client.ListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "List", resp, "Failure responding to next results request")
}
return
}

View File

@ -1,28 +0,0 @@
package subscriptions
// Copyright (c) Microsoft and contributors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Code generated by Microsoft (R) AutoRest Code Generator 1.1.0.0
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
// UserAgent returns the UserAgent string to use when sending http.Requests.
func UserAgent() string {
return "Azure-SDK-For-Go/v10.2.0-beta arm-subscriptions/2016-06-01"
}
// Version returns the semantic version (see http://semver.org) of the client.
func Version() string {
return "v10.2.0-beta"
}

File diff suppressed because it is too large Load Diff

4
vendor/github.com/aws/aws-sdk-go/CODE_OF_CONDUCT.md generated vendored Normal file
View File

@ -0,0 +1,4 @@
## Code of Conduct
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
opensource-codeofconduct@amazon.com with any additional questions or comments.

View File

@ -67,7 +67,7 @@ Please be aware of the following notes prior to opening a pull request:
5. The JSON files under the SDK's `models` folder are sourced from outside the SDK. 5. The JSON files under the SDK's `models` folder are sourced from outside the SDK.
Such as `models/apis/ec2/2016-11-15/api.json`. We will not accept pull requests Such as `models/apis/ec2/2016-11-15/api.json`. We will not accept pull requests
directly on these models. If you discover an issue with the models please directly on these models. If you discover an issue with the models please
create a Github [issue](issues) describing the issue. create a [GitHub issue][issues] describing the issue.
### Testing ### Testing

20
vendor/github.com/aws/aws-sdk-go/Gopkg.lock generated vendored Normal file
View File

@ -0,0 +1,20 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
name = "github.com/go-ini/ini"
packages = ["."]
revision = "300e940a926eb277d3901b20bdfcc54928ad3642"
version = "v1.25.4"
[[projects]]
name = "github.com/jmespath/go-jmespath"
packages = ["."]
revision = "0b12d6b5"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "51a86a867df617990082dec6b868e4efe2fdb2ed0e02a3daa93cd30f962b5085"
solver-name = "gps-cdcl"
solver-version = 1

48
vendor/github.com/aws/aws-sdk-go/Gopkg.toml generated vendored Normal file
View File

@ -0,0 +1,48 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
ignored = [
# Testing/Example/Codegen dependencies
"github.com/stretchr/testify",
"github.com/stretchr/testify/assert",
"github.com/stretchr/testify/require",
"github.com/go-sql-driver/mysql",
"github.com/gucumber/gucumber",
"github.com/pkg/errors",
"golang.org/x/net",
"golang.org/x/net/html",
"golang.org/x/net/http2",
"golang.org/x/text",
"golang.org/x/text/html",
"golang.org/x/tools",
"golang.org/x/tools/go/loader",
]
[[constraint]]
name = "github.com/go-ini/ini"
version = "1.25.4"
[[constraint]]
name = "github.com/jmespath/go-jmespath"
revision = "0b12d6b5"
#version = "0.2.2"

View File

@ -74,7 +74,7 @@ smoke-tests: get-deps-tests
performance: get-deps-tests performance: get-deps-tests
AWS_TESTING_LOG_RESULTS=${log-detailed} AWS_TESTING_REGION=$(region) AWS_TESTING_DB_TABLE=$(table) gucumber -go-tags "integration" ./awstesting/performance AWS_TESTING_LOG_RESULTS=${log-detailed} AWS_TESTING_REGION=$(region) AWS_TESTING_DB_TABLE=$(table) gucumber -go-tags "integration" ./awstesting/performance
sandbox-tests: sandbox-test-go15 sandbox-test-go15-novendorexp sandbox-test-go16 sandbox-test-go17 sandbox-test-go18 sandbox-test-gotip sandbox-tests: sandbox-test-go15 sandbox-test-go15-novendorexp sandbox-test-go16 sandbox-test-go17 sandbox-test-go18 sandbox-test-go19 sandbox-test-gotip
sandbox-build-go15: sandbox-build-go15:
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.5 -t "aws-sdk-go-1.5" . docker build -f ./awstesting/sandbox/Dockerfile.test.go1.5 -t "aws-sdk-go-1.5" .
@ -111,6 +111,13 @@ sandbox-go18: sandbox-build-go18
sandbox-test-go18: sandbox-build-go18 sandbox-test-go18: sandbox-build-go18
docker run -t aws-sdk-go-1.8 docker run -t aws-sdk-go-1.8
sandbox-build-go19:
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.8 -t "aws-sdk-go-1.9" .
sandbox-go19: sandbox-build-go19
docker run -i -t aws-sdk-go-1.9 bash
sandbox-test-go19: sandbox-build-go19
docker run -t aws-sdk-go-1.9
sandbox-build-gotip: sandbox-build-gotip:
@echo "Run make update-aws-golang-tip, if this test fails because missing aws-golang:tip container" @echo "Run make update-aws-golang-tip, if this test fails because missing aws-golang:tip container"
docker build -f ./awstesting/sandbox/Dockerfile.test.gotip -t "aws-sdk-go-tip" . docker build -f ./awstesting/sandbox/Dockerfile.test.gotip -t "aws-sdk-go-tip" .

View File

@ -6,6 +6,8 @@ aws-sdk-go is the official AWS SDK for the Go programming language.
Checkout our [release notes](https://github.com/aws/aws-sdk-go/releases) for information about the latest bug fixes, updates, and features added to the SDK. Checkout our [release notes](https://github.com/aws/aws-sdk-go/releases) for information about the latest bug fixes, updates, and features added to the SDK.
We [announced](https://aws.amazon.com/blogs/developer/aws-sdk-for-go-2-0-developer-preview/) the Developer Preview for the [v2 AWS SDK for Go](). The v2 SDK is available at https://github.com/aws/aws-sdk-go-v2, and `go get github.com/aws/aws-sdk-go-v2` via `go get`. Check out the v2 SDK's [changes and updates](https://github.com/aws/aws-sdk-go-v2/blob/master/CHANGELOG.md), and let us know what you think. We want your feedback.
## Installing ## Installing
If you are using Go 1.5 with the `GO15VENDOREXPERIMENT=1` vendoring flag, or 1.6 and higher you can use the following command to retrieve the SDK. The SDK's non-testing dependencies will be included and are vendored in the `vendor` folder. If you are using Go 1.5 with the `GO15VENDOREXPERIMENT=1` vendoring flag, or 1.6 and higher you can use the following command to retrieve the SDK. The SDK's non-testing dependencies will be included and are vendored in the `vendor` folder.
@ -185,7 +187,7 @@ Option's SharedConfigState parameter.
})) }))
``` ```
[credentials_pkg]: ttps://docs.aws.amazon.com/sdk-for-go/api/aws/credentials [credentials_pkg]: https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials
### Configuring AWS Region ### Configuring AWS Region
@ -305,7 +307,7 @@ documentation for the errors that could be returned.
// will leak connections. // will leak connections.
defer result.Body.Close() defer result.Body.Close()
fmt.Println("Object Size:", aws.StringValue(result.ContentLength)) fmt.Println("Object Size:", aws.Int64Value(result.ContentLength))
``` ```
### API Request Pagination and Resource Waiters ### API Request Pagination and Resource Waiters

View File

@ -1,11 +1,11 @@
package client package client
import ( import (
"math/rand" "strconv"
"sync"
"time" "time"
"github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/internal/sdkrand"
) )
// DefaultRetryer implements basic retry logic using exponential backoff for // DefaultRetryer implements basic retry logic using exponential backoff for
@ -30,25 +30,27 @@ func (d DefaultRetryer) MaxRetries() int {
return d.NumMaxRetries return d.NumMaxRetries
} }
var seededRand = rand.New(&lockedSource{src: rand.NewSource(time.Now().UnixNano())})
// RetryRules returns the delay duration before retrying this request again // RetryRules returns the delay duration before retrying this request again
func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration { func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration {
// Set the upper limit of delay in retrying at ~five minutes // Set the upper limit of delay in retrying at ~five minutes
minTime := 30 minTime := 30
throttle := d.shouldThrottle(r) throttle := d.shouldThrottle(r)
if throttle { if throttle {
if delay, ok := getRetryDelay(r); ok {
return delay
}
minTime = 500 minTime = 500
} }
retryCount := r.RetryCount retryCount := r.RetryCount
if retryCount > 13 { if throttle && retryCount > 8 {
retryCount = 13
} else if throttle && retryCount > 8 {
retryCount = 8 retryCount = 8
} else if retryCount > 13 {
retryCount = 13
} }
delay := (1 << uint(retryCount)) * (seededRand.Intn(minTime) + minTime) delay := (1 << uint(retryCount)) * (sdkrand.SeededRand.Intn(minTime) + minTime)
return time.Duration(delay) * time.Millisecond return time.Duration(delay) * time.Millisecond
} }
@ -60,7 +62,7 @@ func (d DefaultRetryer) ShouldRetry(r *request.Request) bool {
return *r.Retryable return *r.Retryable
} }
if r.HTTPResponse.StatusCode >= 500 { if r.HTTPResponse.StatusCode >= 500 && r.HTTPResponse.StatusCode != 501 {
return true return true
} }
return r.IsErrorRetryable() || d.shouldThrottle(r) return r.IsErrorRetryable() || d.shouldThrottle(r)
@ -68,29 +70,47 @@ func (d DefaultRetryer) ShouldRetry(r *request.Request) bool {
// ShouldThrottle returns true if the request should be throttled. // ShouldThrottle returns true if the request should be throttled.
func (d DefaultRetryer) shouldThrottle(r *request.Request) bool { func (d DefaultRetryer) shouldThrottle(r *request.Request) bool {
if r.HTTPResponse.StatusCode == 502 || switch r.HTTPResponse.StatusCode {
r.HTTPResponse.StatusCode == 503 || case 429:
r.HTTPResponse.StatusCode == 504 { case 502:
return true case 503:
case 504:
default:
return r.IsErrorThrottle()
} }
return r.IsErrorThrottle()
return true
} }
// lockedSource is a thread-safe implementation of rand.Source // This will look in the Retry-After header, RFC 7231, for how long
type lockedSource struct { // it will wait before attempting another request
lk sync.Mutex func getRetryDelay(r *request.Request) (time.Duration, bool) {
src rand.Source if !canUseRetryAfterHeader(r) {
return 0, false
}
delayStr := r.HTTPResponse.Header.Get("Retry-After")
if len(delayStr) == 0 {
return 0, false
}
delay, err := strconv.Atoi(delayStr)
if err != nil {
return 0, false
}
return time.Duration(delay) * time.Second, true
} }
func (r *lockedSource) Int63() (n int64) { // Will look at the status code to see if the retry header pertains to
r.lk.Lock() // the status code.
n = r.src.Int63() func canUseRetryAfterHeader(r *request.Request) bool {
r.lk.Unlock() switch r.HTTPResponse.StatusCode {
return case 429:
} case 503:
default:
return false
}
func (r *lockedSource) Seed(seed int64) { return true
r.lk.Lock()
r.src.Seed(seed)
r.lk.Unlock()
} }

View File

@ -46,6 +46,7 @@ func (reader *teeReaderCloser) Close() error {
func logRequest(r *request.Request) { func logRequest(r *request.Request) {
logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody) logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
bodySeekable := aws.IsReaderSeekable(r.Body)
dumpedBody, err := httputil.DumpRequestOut(r.HTTPRequest, logBody) dumpedBody, err := httputil.DumpRequestOut(r.HTTPRequest, logBody)
if err != nil { if err != nil {
r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg, r.ClientInfo.ServiceName, r.Operation.Name, err)) r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg, r.ClientInfo.ServiceName, r.Operation.Name, err))
@ -53,6 +54,9 @@ func logRequest(r *request.Request) {
} }
if logBody { if logBody {
if !bodySeekable {
r.SetReaderBody(aws.ReadSeekCloser(r.HTTPRequest.Body))
}
// Reset the request body because dumpRequest will re-wrap the r.HTTPRequest's // 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 // Body as a NoOpCloser and will not be reset after read by the HTTP
// client reader. // client reader.

View File

@ -151,6 +151,12 @@ type Config struct {
// with accelerate. // with accelerate.
S3UseAccelerate *bool S3UseAccelerate *bool
// Set this to `true` to disable the S3 service client from automatically
// adding the ContentMD5 to S3 Object Put and Upload API calls. This option
// will also disable the SDK from performing object ContentMD5 validation
// on GetObject API calls.
S3DisableContentMD5Validation *bool
// Set this to `true` to disable the EC2Metadata client from overriding the // Set this to `true` to disable the EC2Metadata client from overriding the
// default http.Client's Timeout. This is helpful if you do not want the // default http.Client's Timeout. This is helpful if you do not want the
// EC2Metadata client to create a new http.Client. This options is only // EC2Metadata client to create a new http.Client. This options is only
@ -168,7 +174,7 @@ type Config struct {
// //
EC2MetadataDisableTimeoutOverride *bool EC2MetadataDisableTimeoutOverride *bool
// Instructs the endpiont to be generated for a service client to // Instructs the endpoint to be generated for a service client to
// be the dual stack endpoint. The dual stack endpoint will support // be the dual stack endpoint. The dual stack endpoint will support
// both IPv4 and IPv6 addressing. // both IPv4 and IPv6 addressing.
// //
@ -336,6 +342,15 @@ func (c *Config) WithS3Disable100Continue(disable bool) *Config {
func (c *Config) WithS3UseAccelerate(enable bool) *Config { func (c *Config) WithS3UseAccelerate(enable bool) *Config {
c.S3UseAccelerate = &enable c.S3UseAccelerate = &enable
return c return c
}
// WithS3DisableContentMD5Validation sets a config
// S3DisableContentMD5Validation value returning a Config pointer for chaining.
func (c *Config) WithS3DisableContentMD5Validation(enable bool) *Config {
c.S3DisableContentMD5Validation = &enable
return c
} }
// WithUseDualStack sets a config UseDualStack value returning a Config // WithUseDualStack sets a config UseDualStack value returning a Config
@ -435,6 +450,10 @@ func mergeInConfig(dst *Config, other *Config) {
dst.S3UseAccelerate = other.S3UseAccelerate dst.S3UseAccelerate = other.S3UseAccelerate
} }
if other.S3DisableContentMD5Validation != nil {
dst.S3DisableContentMD5Validation = other.S3DisableContentMD5Validation
}
if other.UseDualStack != nil { if other.UseDualStack != nil {
dst.UseDualStack = other.UseDualStack dst.UseDualStack = other.UseDualStack
} }

View File

@ -3,12 +3,10 @@ package corehandlers
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"regexp" "regexp"
"runtime"
"strconv" "strconv"
"time" "time"
@ -36,18 +34,13 @@ var BuildContentLengthHandler = request.NamedHandler{Name: "core.BuildContentLen
if slength := r.HTTPRequest.Header.Get("Content-Length"); slength != "" { if slength := r.HTTPRequest.Header.Get("Content-Length"); slength != "" {
length, _ = strconv.ParseInt(slength, 10, 64) length, _ = strconv.ParseInt(slength, 10, 64)
} else { } else {
switch body := r.Body.(type) { if r.Body != nil {
case nil: var err error
length = 0 length, err = aws.SeekerLen(r.Body)
case lener: if err != nil {
length = int64(body.Len()) r.Error = awserr.New(request.ErrCodeSerialization, "failed to get request body's length", err)
case io.Seeker: return
r.BodyStart, _ = body.Seek(0, 1) }
end, _ := body.Seek(0, 2)
body.Seek(r.BodyStart, 0) // make sure to seek back to original location
length = end - r.BodyStart
default:
panic("Cannot get length of body, must provide `ContentLength`")
} }
} }
@ -60,13 +53,6 @@ var BuildContentLengthHandler = request.NamedHandler{Name: "core.BuildContentLen
} }
}} }}
// SDKVersionUserAgentHandler is a request handler for adding the SDK Version to the user agent.
var SDKVersionUserAgentHandler = request.NamedHandler{
Name: "core.SDKVersionUserAgentHandler",
Fn: request.MakeAddToUserAgentHandler(aws.SDKName, aws.SDKVersion,
runtime.Version(), runtime.GOOS, runtime.GOARCH),
}
var reStatusCode = regexp.MustCompile(`^(\d{3})`) var reStatusCode = regexp.MustCompile(`^(\d{3})`)
// ValidateReqSigHandler is a request handler to ensure that the request's // ValidateReqSigHandler is a request handler to ensure that the request's

View File

@ -0,0 +1,37 @@
package corehandlers
import (
"os"
"runtime"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
)
// SDKVersionUserAgentHandler is a request handler for adding the SDK Version
// to the user agent.
var SDKVersionUserAgentHandler = request.NamedHandler{
Name: "core.SDKVersionUserAgentHandler",
Fn: request.MakeAddToUserAgentHandler(aws.SDKName, aws.SDKVersion,
runtime.Version(), runtime.GOOS, runtime.GOARCH),
}
const execEnvVar = `AWS_EXECUTION_ENV`
const execEnvUAKey = `exec_env`
// AddHostExecEnvUserAgentHander is a request handler appending the SDK's
// execution environment to the user agent.
//
// If the environment variable AWS_EXECUTION_ENV is set, its value will be
// appended to the user agent string.
var AddHostExecEnvUserAgentHander = request.NamedHandler{
Name: "core.AddHostExecEnvUserAgentHander",
Fn: func(r *request.Request) {
v := os.Getenv(execEnvVar)
if len(v) == 0 {
return
}
request.AddToUserAgent(r, execEnvUAKey+"/"+v)
},
}

View File

@ -9,6 +9,7 @@ package defaults
import ( import (
"fmt" "fmt"
"net"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
@ -72,6 +73,7 @@ func Handlers() request.Handlers {
handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler) handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
handlers.Validate.AfterEachFn = request.HandlerListStopOnError handlers.Validate.AfterEachFn = request.HandlerListStopOnError
handlers.Build.PushBackNamed(corehandlers.SDKVersionUserAgentHandler) handlers.Build.PushBackNamed(corehandlers.SDKVersionUserAgentHandler)
handlers.Build.PushBackNamed(corehandlers.AddHostExecEnvUserAgentHander)
handlers.Build.AfterEachFn = request.HandlerListStopOnError handlers.Build.AfterEachFn = request.HandlerListStopOnError
handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler) handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler)
handlers.Send.PushBackNamed(corehandlers.ValidateReqSigHandler) handlers.Send.PushBackNamed(corehandlers.ValidateReqSigHandler)
@ -118,14 +120,43 @@ func RemoteCredProvider(cfg aws.Config, handlers request.Handlers) credentials.P
return ec2RoleProvider(cfg, handlers) return ec2RoleProvider(cfg, handlers)
} }
var lookupHostFn = net.LookupHost
func isLoopbackHost(host string) (bool, error) {
ip := net.ParseIP(host)
if ip != nil {
return ip.IsLoopback(), nil
}
// Host is not an ip, perform lookup
addrs, err := lookupHostFn(host)
if err != nil {
return false, err
}
for _, addr := range addrs {
if !net.ParseIP(addr).IsLoopback() {
return false, nil
}
}
return true, nil
}
func localHTTPCredProvider(cfg aws.Config, handlers request.Handlers, u string) credentials.Provider { func localHTTPCredProvider(cfg aws.Config, handlers request.Handlers, u string) credentials.Provider {
var errMsg string var errMsg string
parsed, err := url.Parse(u) parsed, err := url.Parse(u)
if err != nil { if err != nil {
errMsg = fmt.Sprintf("invalid URL, %v", err) errMsg = fmt.Sprintf("invalid URL, %v", err)
} else if host := aws.URLHostname(parsed); !(host == "localhost" || host == "127.0.0.1") { } else {
errMsg = fmt.Sprintf("invalid host address, %q, only localhost and 127.0.0.1 are valid.", host) host := aws.URLHostname(parsed)
if len(host) == 0 {
errMsg = "unable to parse host from local HTTP cred provider URL"
} else if isLoopback, loopbackErr := isLoopbackHost(host); loopbackErr != nil {
errMsg = fmt.Sprintf("failed to resolve host %q, %v", host, loopbackErr)
} else if !isLoopback {
errMsg = fmt.Sprintf("invalid endpoint host, %q, only loopback hosts are allowed.", host)
}
} }
if len(errMsg) > 0 { if len(errMsg) > 0 {

View File

@ -1,5 +1,10 @@
// Package ec2metadata provides the client for making API calls to the // Package ec2metadata provides the client for making API calls to the
// EC2 Metadata service. // EC2 Metadata service.
//
// This package's client can be disabled completely by setting the environment
// variable "AWS_EC2_METADATA_DISABLED=true". This environment variable set to
// true instructs the SDK to disable the EC2 Metadata client. The client cannot
// be used while the environemnt variable is set to true, (case insensitive).
package ec2metadata package ec2metadata
import ( import (
@ -7,17 +12,21 @@ import (
"errors" "errors"
"io" "io"
"net/http" "net/http"
"os"
"strings"
"time" "time"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client" "github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/client/metadata" "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/aws/request"
) )
// ServiceName is the name of the service. // ServiceName is the name of the service.
const ServiceName = "ec2metadata" const ServiceName = "ec2metadata"
const disableServiceEnvVar = "AWS_EC2_METADATA_DISABLED"
// A EC2Metadata is an EC2 Metadata service Client. // A EC2Metadata is an EC2 Metadata service Client.
type EC2Metadata struct { type EC2Metadata struct {
@ -75,6 +84,21 @@ func NewClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegio
svc.Handlers.Validate.Clear() svc.Handlers.Validate.Clear()
svc.Handlers.Validate.PushBack(validateEndpointHandler) svc.Handlers.Validate.PushBack(validateEndpointHandler)
// Disable the EC2 Metadata service if the environment variable is set.
// This shortcirctes the service's functionality to always fail to send
// requests.
if strings.ToLower(os.Getenv(disableServiceEnvVar)) == "true" {
svc.Handlers.Send.SwapNamed(request.NamedHandler{
Name: corehandlers.SendHandler.Name,
Fn: func(r *request.Request) {
r.Error = awserr.New(
request.CanceledErrorCode,
"EC2 IMDS access disabled via "+disableServiceEnvVar+" env var",
nil)
},
})
}
// Add additional options to the service config // Add additional options to the service config
for _, option := range opts { for _, option := range opts {
option(svc.Client) option(svc.Client)

View File

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"os"
"github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/awserr"
) )
@ -84,11 +85,34 @@ func decodeV3Endpoints(modelDef modelDefinition, opts DecodeModelOptions) (Resol
custAddEC2Metadata(p) custAddEC2Metadata(p)
custAddS3DualStack(p) custAddS3DualStack(p)
custRmIotDataService(p) custRmIotDataService(p)
custFixCloudHSMv2SigningName(p)
} }
return ps, nil return ps, nil
} }
func custFixCloudHSMv2SigningName(p *partition) {
// Workaround for aws/aws-sdk-go#1745 until the endpoint model can be
// fixed upstream. TODO remove this once the endpoints model is updated.
s, ok := p.Services["cloudhsmv2"]
if !ok {
return
}
if len(s.Defaults.CredentialScope.Service) != 0 {
fmt.Fprintf(os.Stderr, "cloudhsmv2 signing name already set, ignoring override.\n")
// If the value is already set don't override
return
}
s.Defaults.CredentialScope.Service = "cloudhsm"
fmt.Fprintf(os.Stderr, "cloudhsmv2 signing name not set, overriding.\n")
p.Services["cloudhsmv2"] = s
}
func custAddS3DualStack(p *partition) { func custAddS3DualStack(p *partition) {
if p.ID != "aws" { if p.ID != "aws" {
return return

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,8 @@ package request
import ( import (
"io" "io"
"sync" "sync"
"github.com/aws/aws-sdk-go/internal/sdkio"
) )
// offsetReader is a thread-safe io.ReadCloser to prevent racing // offsetReader is a thread-safe io.ReadCloser to prevent racing
@ -15,7 +17,7 @@ type offsetReader struct {
func newOffsetReader(buf io.ReadSeeker, offset int64) *offsetReader { func newOffsetReader(buf io.ReadSeeker, offset int64) *offsetReader {
reader := &offsetReader{} reader := &offsetReader{}
buf.Seek(offset, 0) buf.Seek(offset, sdkio.SeekStart)
reader.buf = buf reader.buf = buf
return reader return reader

View File

@ -14,6 +14,7 @@ import (
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client/metadata" "github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/internal/sdkio"
) )
const ( const (
@ -28,6 +29,10 @@ const (
// during body reads. // during body reads.
ErrCodeResponseTimeout = "ResponseTimeout" ErrCodeResponseTimeout = "ResponseTimeout"
// ErrCodeInvalidPresignExpire is returned when the expire time provided to
// presign is invalid
ErrCodeInvalidPresignExpire = "InvalidPresignExpireError"
// CanceledErrorCode is the error code that will be returned by an // CanceledErrorCode is the error code that will be returned by an
// API request that was canceled. Requests given a aws.Context may // API request that was canceled. Requests given a aws.Context may
// return this error when canceled. // return this error when canceled.
@ -42,7 +47,6 @@ type Request struct {
Retryer Retryer
Time time.Time Time time.Time
ExpireTime time.Duration
Operation *Operation Operation *Operation
HTTPRequest *http.Request HTTPRequest *http.Request
HTTPResponse *http.Response HTTPResponse *http.Response
@ -60,6 +64,11 @@ type Request struct {
LastSignedAt time.Time LastSignedAt time.Time
DisableFollowRedirects bool DisableFollowRedirects bool
// A value greater than 0 instructs the request to be signed as Presigned URL
// You should not set this field directly. Instead use Request's
// Presign or PresignRequest methods.
ExpireTime time.Duration
context aws.Context context aws.Context
built bool built bool
@ -104,6 +113,8 @@ func New(cfg aws.Config, clientInfo metadata.ClientInfo, handlers Handlers,
err = awserr.New("InvalidEndpointURL", "invalid endpoint uri", err) err = awserr.New("InvalidEndpointURL", "invalid endpoint uri", err)
} }
SanitizeHostForHeader(httpReq)
r := &Request{ r := &Request{
Config: cfg, Config: cfg,
ClientInfo: clientInfo, ClientInfo: clientInfo,
@ -214,6 +225,9 @@ func (r *Request) SetContext(ctx aws.Context) {
// WillRetry returns if the request's can be retried. // WillRetry returns if the request's can be retried.
func (r *Request) WillRetry() bool { func (r *Request) WillRetry() bool {
if !aws.IsReaderSeekable(r.Body) && r.HTTPRequest.Body != NoBody {
return false
}
return r.Error != nil && aws.BoolValue(r.Retryable) && r.RetryCount < r.MaxRetries() return r.Error != nil && aws.BoolValue(r.Retryable) && r.RetryCount < r.MaxRetries()
} }
@ -245,45 +259,70 @@ func (r *Request) SetStringBody(s string) {
// SetReaderBody will set the request's body reader. // SetReaderBody will set the request's body reader.
func (r *Request) SetReaderBody(reader io.ReadSeeker) { func (r *Request) SetReaderBody(reader io.ReadSeeker) {
r.Body = reader r.Body = reader
r.BodyStart, _ = reader.Seek(0, sdkio.SeekCurrent) // Get the Bodies current offset.
r.ResetBody() r.ResetBody()
} }
// Presign returns the request's signed URL. Error will be returned // Presign returns the request's signed URL. Error will be returned
// if the signing fails. // if the signing fails.
func (r *Request) Presign(expireTime time.Duration) (string, error) { //
r.ExpireTime = expireTime // It is invalid to create a presigned URL with a expire duration 0 or less. An
// error is returned if expire duration is 0 or less.
func (r *Request) Presign(expire time.Duration) (string, error) {
r = r.copy()
// Presign requires all headers be hoisted. There is no way to retrieve
// the signed headers not hoisted without this. Making the presigned URL
// useless.
r.NotHoist = false r.NotHoist = false
if r.Operation.BeforePresignFn != nil { u, _, err := getPresignedURL(r, expire)
r = r.copy() return u, err
err := r.Operation.BeforePresignFn(r)
if err != nil {
return "", err
}
}
r.Sign()
if r.Error != nil {
return "", r.Error
}
return r.HTTPRequest.URL.String(), nil
} }
// PresignRequest behaves just like presign, with the addition of returning a // PresignRequest behaves just like presign, with the addition of returning a
// set of headers that were signed. // set of headers that were signed.
// //
// It is invalid to create a presigned URL with a expire duration 0 or less. An
// error is returned if expire duration is 0 or less.
//
// Returns the URL string for the API operation with signature in the query string, // Returns the URL string for the API operation with signature in the query string,
// and the HTTP headers that were included in the signature. These headers must // and the HTTP headers that were included in the signature. These headers must
// be included in any HTTP request made with the presigned URL. // be included in any HTTP request made with the presigned URL.
// //
// To prevent hoisting any headers to the query string set NotHoist to true on // To prevent hoisting any headers to the query string set NotHoist to true on
// this Request value prior to calling PresignRequest. // this Request value prior to calling PresignRequest.
func (r *Request) PresignRequest(expireTime time.Duration) (string, http.Header, error) { func (r *Request) PresignRequest(expire time.Duration) (string, http.Header, error) {
r.ExpireTime = expireTime r = r.copy()
r.Sign() return getPresignedURL(r, expire)
if r.Error != nil { }
return "", nil, r.Error
// IsPresigned returns true if the request represents a presigned API url.
func (r *Request) IsPresigned() bool {
return r.ExpireTime != 0
}
func getPresignedURL(r *Request, expire time.Duration) (string, http.Header, error) {
if expire <= 0 {
return "", nil, awserr.New(
ErrCodeInvalidPresignExpire,
"presigned URL requires an expire duration greater than 0",
nil,
)
} }
r.ExpireTime = expire
if r.Operation.BeforePresignFn != nil {
if err := r.Operation.BeforePresignFn(r); err != nil {
return "", nil, err
}
}
if err := r.Sign(); err != nil {
return "", nil, err
}
return r.HTTPRequest.URL.String(), r.SignedHeaderVals, nil return r.HTTPRequest.URL.String(), r.SignedHeaderVals, nil
} }
@ -364,7 +403,7 @@ func (r *Request) getNextRequestBody() (io.ReadCloser, error) {
// of the SDK if they used that field. // of the SDK if they used that field.
// //
// Related golang/go#18257 // Related golang/go#18257
l, err := computeBodyLength(r.Body) l, err := aws.SeekerLen(r.Body)
if err != nil { if err != nil {
return nil, awserr.New(ErrCodeSerialization, "failed to compute request body size", err) return nil, awserr.New(ErrCodeSerialization, "failed to compute request body size", err)
} }
@ -382,7 +421,8 @@ func (r *Request) getNextRequestBody() (io.ReadCloser, error) {
// Transfer-Encoding: chunked bodies for these methods. // Transfer-Encoding: chunked bodies for these methods.
// //
// This would only happen if a aws.ReaderSeekerCloser was used with // This would only happen if a aws.ReaderSeekerCloser was used with
// a io.Reader that was not also an io.Seeker. // a io.Reader that was not also an io.Seeker, or did not implement
// Len() method.
switch r.Operation.HTTPMethod { switch r.Operation.HTTPMethod {
case "GET", "HEAD", "DELETE": case "GET", "HEAD", "DELETE":
body = NoBody body = NoBody
@ -394,42 +434,6 @@ func (r *Request) getNextRequestBody() (io.ReadCloser, error) {
return body, nil return body, nil
} }
// Attempts to compute the length of the body of the reader using the
// io.Seeker interface. If the value is not seekable because of being
// a ReaderSeekerCloser without an unerlying Seeker -1 will be returned.
// If no error occurs the length of the body will be returned.
func computeBodyLength(r io.ReadSeeker) (int64, error) {
seekable := true
// Determine if the seeker is actually seekable. ReaderSeekerCloser
// hides the fact that a io.Readers might not actually be seekable.
switch v := r.(type) {
case aws.ReaderSeekerCloser:
seekable = v.IsSeeker()
case *aws.ReaderSeekerCloser:
seekable = v.IsSeeker()
}
if !seekable {
return -1, nil
}
curOffset, err := r.Seek(0, 1)
if err != nil {
return 0, err
}
endOffset, err := r.Seek(0, 2)
if err != nil {
return 0, err
}
_, err = r.Seek(curOffset, 0)
if err != nil {
return 0, err
}
return endOffset - curOffset, nil
}
// GetBody will return an io.ReadSeeker of the Request's underlying // GetBody will return an io.ReadSeeker of the Request's underlying
// input body with a concurrency safe wrapper. // input body with a concurrency safe wrapper.
func (r *Request) GetBody() io.ReadSeeker { func (r *Request) GetBody() io.ReadSeeker {
@ -579,3 +583,72 @@ func shouldRetryCancel(r *Request) bool {
errStr != "net/http: request canceled while waiting for connection") errStr != "net/http: request canceled while waiting for connection")
} }
// SanitizeHostForHeader removes default port from host and updates request.Host
func SanitizeHostForHeader(r *http.Request) {
host := getHost(r)
port := portOnly(host)
if port != "" && isDefaultPort(r.URL.Scheme, port) {
r.Host = stripPort(host)
}
}
// Returns host from request
func getHost(r *http.Request) string {
if r.Host != "" {
return r.Host
}
return r.URL.Host
}
// Hostname returns u.Host, without any port number.
//
// If Host is an IPv6 literal with a port number, Hostname returns the
// IPv6 literal without the square brackets. IPv6 literals may include
// a zone identifier.
//
// Copied from the Go 1.8 standard library (net/url)
func stripPort(hostport string) string {
colon := strings.IndexByte(hostport, ':')
if colon == -1 {
return hostport
}
if i := strings.IndexByte(hostport, ']'); i != -1 {
return strings.TrimPrefix(hostport[:i], "[")
}
return hostport[:colon]
}
// Port returns the port part of u.Host, without the leading colon.
// If u.Host doesn't contain a port, Port returns an empty string.
//
// Copied from the Go 1.8 standard library (net/url)
func portOnly(hostport string) string {
colon := strings.IndexByte(hostport, ':')
if colon == -1 {
return ""
}
if i := strings.Index(hostport, "]:"); i != -1 {
return hostport[i+len("]:"):]
}
if strings.Contains(hostport, "]") {
return ""
}
return hostport[colon+len(":"):]
}
// Returns true if the specified URI is using the standard port
// (i.e. port 80 for HTTP URIs or 443 for HTTPS URIs)
func isDefaultPort(scheme, port string) bool {
if port == "" {
return true
}
lowerCaseScheme := strings.ToLower(scheme)
if (lowerCaseScheme == "http" && port == "80") || (lowerCaseScheme == "https" && port == "443") {
return true
}
return false
}

View File

@ -142,13 +142,28 @@ func (r *Request) nextPageTokens() []interface{} {
tokens := []interface{}{} tokens := []interface{}{}
tokenAdded := false tokenAdded := false
for _, outToken := range r.Operation.OutputTokens { for _, outToken := range r.Operation.OutputTokens {
v, _ := awsutil.ValuesAtPath(r.Data, outToken) vs, _ := awsutil.ValuesAtPath(r.Data, outToken)
if len(v) > 0 { if len(vs) == 0 {
tokens = append(tokens, v[0])
tokenAdded = true
} else {
tokens = append(tokens, nil) tokens = append(tokens, nil)
continue
} }
v := vs[0]
switch tv := v.(type) {
case *string:
if len(aws.StringValue(tv)) == 0 {
tokens = append(tokens, nil)
continue
}
case string:
if len(tv) == 0 {
tokens = append(tokens, nil)
continue
}
}
tokenAdded = true
tokens = append(tokens, v)
} }
if !tokenAdded { if !tokenAdded {
return nil return nil

View File

@ -5,8 +5,12 @@ import (
"strconv" "strconv"
"github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/defaults"
) )
// EnvProviderName provides a name of the provider when config is loaded from environment.
const EnvProviderName = "EnvConfigCredentials"
// envConfig is a collection of environment values the SDK will read // envConfig is a collection of environment values the SDK will read
// setup config from. All environment values are optional. But some values // setup config from. All environment values are optional. But some values
// such as credentials require multiple values to be complete or the values // such as credentials require multiple values to be complete or the values
@ -157,7 +161,7 @@ func envConfigLoad(enableSharedConfig bool) envConfig {
if len(cfg.Creds.AccessKeyID) == 0 || len(cfg.Creds.SecretAccessKey) == 0 { if len(cfg.Creds.AccessKeyID) == 0 || len(cfg.Creds.SecretAccessKey) == 0 {
cfg.Creds = credentials.Value{} cfg.Creds = credentials.Value{}
} else { } else {
cfg.Creds.ProviderName = "EnvConfigCredentials" cfg.Creds.ProviderName = EnvProviderName
} }
regionKeys := regionEnvKeys regionKeys := regionEnvKeys
@ -173,6 +177,13 @@ func envConfigLoad(enableSharedConfig bool) envConfig {
setFromEnvVal(&cfg.SharedCredentialsFile, sharedCredsFileEnvKey) setFromEnvVal(&cfg.SharedCredentialsFile, sharedCredsFileEnvKey)
setFromEnvVal(&cfg.SharedConfigFile, sharedConfigFileEnvKey) setFromEnvVal(&cfg.SharedConfigFile, sharedConfigFileEnvKey)
if len(cfg.SharedCredentialsFile) == 0 {
cfg.SharedCredentialsFile = defaults.SharedCredentialsFilename()
}
if len(cfg.SharedConfigFile) == 0 {
cfg.SharedConfigFile = defaults.SharedConfigFilename()
}
cfg.CustomCABundle = os.Getenv("AWS_CA_BUNDLE") cfg.CustomCABundle = os.Getenv("AWS_CA_BUNDLE")
return cfg return cfg

View File

@ -26,7 +26,7 @@ import (
// Sessions are safe to create service clients concurrently, but it is not safe // Sessions are safe to create service clients concurrently, but it is not safe
// to mutate the Session concurrently. // to mutate the Session concurrently.
// //
// The Session satisfies the service client's client.ClientConfigProvider. // The Session satisfies the service client's client.ConfigProvider.
type Session struct { type Session struct {
Config *aws.Config Config *aws.Config
Handlers request.Handlers Handlers request.Handlers
@ -58,7 +58,12 @@ func New(cfgs ...*aws.Config) *Session {
envCfg := loadEnvConfig() envCfg := loadEnvConfig()
if envCfg.EnableSharedConfig { if envCfg.EnableSharedConfig {
s, err := newSession(Options{}, envCfg, cfgs...) var cfg aws.Config
cfg.MergeIn(cfgs...)
s, err := NewSessionWithOptions(Options{
Config: cfg,
SharedConfigState: SharedConfigEnable,
})
if err != nil { if err != nil {
// Old session.New expected all errors to be discovered when // Old session.New expected all errors to be discovered when
// a request is made, and would report the errors then. This // a request is made, and would report the errors then. This
@ -243,13 +248,6 @@ func NewSessionWithOptions(opts Options) (*Session, error) {
envCfg.EnableSharedConfig = true envCfg.EnableSharedConfig = true
} }
if len(envCfg.SharedCredentialsFile) == 0 {
envCfg.SharedCredentialsFile = defaults.SharedCredentialsFilename()
}
if len(envCfg.SharedConfigFile) == 0 {
envCfg.SharedConfigFile = defaults.SharedConfigFilename()
}
// Only use AWS_CA_BUNDLE if session option is not provided. // Only use AWS_CA_BUNDLE if session option is not provided.
if len(envCfg.CustomCABundle) != 0 && opts.CustomCABundle == nil { if len(envCfg.CustomCABundle) != 0 && opts.CustomCABundle == nil {
f, err := os.Open(envCfg.CustomCABundle) f, err := os.Open(envCfg.CustomCABundle)

View File

@ -71,6 +71,7 @@ import (
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/internal/sdkio"
"github.com/aws/aws-sdk-go/private/protocol/rest" "github.com/aws/aws-sdk-go/private/protocol/rest"
) )
@ -268,7 +269,7 @@ type signingCtx struct {
// "X-Amz-Content-Sha256" header with a precomputed value. The signer will // "X-Amz-Content-Sha256" header with a precomputed value. The signer will
// only compute the hash if the request header value is empty. // only compute the hash if the request header value is empty.
func (v4 Signer) Sign(r *http.Request, body io.ReadSeeker, service, region string, signTime time.Time) (http.Header, error) { func (v4 Signer) Sign(r *http.Request, body io.ReadSeeker, service, region string, signTime time.Time) (http.Header, error) {
return v4.signWithBody(r, body, service, region, 0, signTime) return v4.signWithBody(r, body, service, region, 0, false, signTime)
} }
// Presign signs AWS v4 requests with the provided body, service name, region // Presign signs AWS v4 requests with the provided body, service name, region
@ -302,10 +303,10 @@ func (v4 Signer) Sign(r *http.Request, body io.ReadSeeker, service, region strin
// presigned request's signature you can set the "X-Amz-Content-Sha256" // presigned request's signature you can set the "X-Amz-Content-Sha256"
// HTTP header and that will be included in the request's signature. // HTTP header and that will be included in the request's signature.
func (v4 Signer) Presign(r *http.Request, body io.ReadSeeker, service, region string, exp time.Duration, signTime time.Time) (http.Header, error) { func (v4 Signer) Presign(r *http.Request, body io.ReadSeeker, service, region string, exp time.Duration, signTime time.Time) (http.Header, error) {
return v4.signWithBody(r, body, service, region, exp, signTime) return v4.signWithBody(r, body, service, region, exp, true, signTime)
} }
func (v4 Signer) signWithBody(r *http.Request, body io.ReadSeeker, service, region string, exp time.Duration, signTime time.Time) (http.Header, error) { func (v4 Signer) signWithBody(r *http.Request, body io.ReadSeeker, service, region string, exp time.Duration, isPresign bool, signTime time.Time) (http.Header, error) {
currentTimeFn := v4.currentTimeFn currentTimeFn := v4.currentTimeFn
if currentTimeFn == nil { if currentTimeFn == nil {
currentTimeFn = time.Now currentTimeFn = time.Now
@ -317,7 +318,7 @@ func (v4 Signer) signWithBody(r *http.Request, body io.ReadSeeker, service, regi
Query: r.URL.Query(), Query: r.URL.Query(),
Time: signTime, Time: signTime,
ExpireTime: exp, ExpireTime: exp,
isPresign: exp != 0, isPresign: isPresign,
ServiceName: service, ServiceName: service,
Region: region, Region: region,
DisableURIPathEscaping: v4.DisableURIPathEscaping, DisableURIPathEscaping: v4.DisableURIPathEscaping,
@ -339,8 +340,11 @@ func (v4 Signer) signWithBody(r *http.Request, body io.ReadSeeker, service, regi
return http.Header{}, err return http.Header{}, err
} }
ctx.sanitizeHostForHeader()
ctx.assignAmzQueryValues() ctx.assignAmzQueryValues()
ctx.build(v4.DisableHeaderHoisting) if err := ctx.build(v4.DisableHeaderHoisting); err != nil {
return nil, err
}
// If the request is not presigned the body should be attached to it. This // 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 // prevents the confusion of wanting to send a signed request without
@ -363,6 +367,10 @@ func (v4 Signer) signWithBody(r *http.Request, body io.ReadSeeker, service, regi
return ctx.SignedHeaderVals, nil return ctx.SignedHeaderVals, nil
} }
func (ctx *signingCtx) sanitizeHostForHeader() {
request.SanitizeHostForHeader(ctx.Request)
}
func (ctx *signingCtx) handlePresignRemoval() { func (ctx *signingCtx) handlePresignRemoval() {
if !ctx.isPresign { if !ctx.isPresign {
return return
@ -467,7 +475,7 @@ func signSDKRequestWithCurrTime(req *request.Request, curTimeFn func() time.Time
} }
signedHeaders, err := v4.signWithBody(req.HTTPRequest, req.GetBody(), signedHeaders, err := v4.signWithBody(req.HTTPRequest, req.GetBody(),
name, region, req.ExpireTime, signingTime, name, region, req.ExpireTime, req.ExpireTime > 0, signingTime,
) )
if err != nil { if err != nil {
req.Error = err req.Error = err
@ -498,11 +506,13 @@ func (v4 *Signer) logSigningInfo(ctx *signingCtx) {
v4.Logger.Log(msg) v4.Logger.Log(msg)
} }
func (ctx *signingCtx) build(disableHeaderHoisting bool) { func (ctx *signingCtx) build(disableHeaderHoisting bool) error {
ctx.buildTime() // no depends ctx.buildTime() // no depends
ctx.buildCredentialString() // no depends ctx.buildCredentialString() // no depends
ctx.buildBodyDigest() if err := ctx.buildBodyDigest(); err != nil {
return err
}
unsignedHeaders := ctx.Request.Header unsignedHeaders := ctx.Request.Header
if ctx.isPresign { if ctx.isPresign {
@ -530,6 +540,8 @@ func (ctx *signingCtx) build(disableHeaderHoisting bool) {
} }
ctx.Request.Header.Set("Authorization", strings.Join(parts, ", ")) ctx.Request.Header.Set("Authorization", strings.Join(parts, ", "))
} }
return nil
} }
func (ctx *signingCtx) buildTime() { func (ctx *signingCtx) buildTime() {
@ -656,7 +668,7 @@ func (ctx *signingCtx) buildSignature() {
ctx.signature = hex.EncodeToString(signature) ctx.signature = hex.EncodeToString(signature)
} }
func (ctx *signingCtx) buildBodyDigest() { func (ctx *signingCtx) buildBodyDigest() error {
hash := ctx.Request.Header.Get("X-Amz-Content-Sha256") hash := ctx.Request.Header.Get("X-Amz-Content-Sha256")
if hash == "" { if hash == "" {
if ctx.unsignedPayload || (ctx.isPresign && ctx.ServiceName == "s3") { if ctx.unsignedPayload || (ctx.isPresign && ctx.ServiceName == "s3") {
@ -664,6 +676,9 @@ func (ctx *signingCtx) buildBodyDigest() {
} else if ctx.Body == nil { } else if ctx.Body == nil {
hash = emptyStringSHA256 hash = emptyStringSHA256
} else { } else {
if !aws.IsReaderSeekable(ctx.Body) {
return fmt.Errorf("cannot use unseekable request body %T, for signed request with body", ctx.Body)
}
hash = hex.EncodeToString(makeSha256Reader(ctx.Body)) hash = hex.EncodeToString(makeSha256Reader(ctx.Body))
} }
if ctx.unsignedPayload || ctx.ServiceName == "s3" || ctx.ServiceName == "glacier" { if ctx.unsignedPayload || ctx.ServiceName == "s3" || ctx.ServiceName == "glacier" {
@ -671,6 +686,8 @@ func (ctx *signingCtx) buildBodyDigest() {
} }
} }
ctx.bodyDigest = hash ctx.bodyDigest = hash
return nil
} }
// isRequestSigned returns if the request is currently signed or presigned // isRequestSigned returns if the request is currently signed or presigned
@ -710,8 +727,8 @@ func makeSha256(data []byte) []byte {
func makeSha256Reader(reader io.ReadSeeker) []byte { func makeSha256Reader(reader io.ReadSeeker) []byte {
hash := sha256.New() hash := sha256.New()
start, _ := reader.Seek(0, 1) start, _ := reader.Seek(0, sdkio.SeekCurrent)
defer reader.Seek(start, 0) defer reader.Seek(start, sdkio.SeekStart)
io.Copy(hash, reader) io.Copy(hash, reader)
return hash.Sum(nil) return hash.Sum(nil)

View File

@ -3,6 +3,8 @@ package aws
import ( import (
"io" "io"
"sync" "sync"
"github.com/aws/aws-sdk-go/internal/sdkio"
) )
// ReadSeekCloser wraps a io.Reader returning a ReaderSeekerCloser. Should // ReadSeekCloser wraps a io.Reader returning a ReaderSeekerCloser. Should
@ -22,6 +24,22 @@ type ReaderSeekerCloser struct {
r io.Reader r io.Reader
} }
// IsReaderSeekable returns if the underlying reader type can be seeked. A
// io.Reader might not actually be seekable if it is the ReaderSeekerCloser
// type.
func IsReaderSeekable(r io.Reader) bool {
switch v := r.(type) {
case ReaderSeekerCloser:
return v.IsSeeker()
case *ReaderSeekerCloser:
return v.IsSeeker()
case io.ReadSeeker:
return true
default:
return false
}
}
// Read reads from the reader up to size of p. The number of bytes read, and // Read reads from the reader up to size of p. The number of bytes read, and
// error if it occurred will be returned. // error if it occurred will be returned.
// //
@ -56,6 +74,71 @@ func (r ReaderSeekerCloser) IsSeeker() bool {
return ok return ok
} }
// HasLen returns the length of the underlying reader if the value implements
// the Len() int method.
func (r ReaderSeekerCloser) HasLen() (int, bool) {
type lenner interface {
Len() int
}
if lr, ok := r.r.(lenner); ok {
return lr.Len(), true
}
return 0, false
}
// GetLen returns the length of the bytes remaining in the underlying reader.
// Checks first for Len(), then io.Seeker to determine the size of the
// underlying reader.
//
// Will return -1 if the length cannot be determined.
func (r ReaderSeekerCloser) GetLen() (int64, error) {
if l, ok := r.HasLen(); ok {
return int64(l), nil
}
if s, ok := r.r.(io.Seeker); ok {
return seekerLen(s)
}
return -1, nil
}
// SeekerLen attempts to get the number of bytes remaining at the seeker's
// current position. Returns the number of bytes remaining or error.
func SeekerLen(s io.Seeker) (int64, error) {
// Determine if the seeker is actually seekable. ReaderSeekerCloser
// hides the fact that a io.Readers might not actually be seekable.
switch v := s.(type) {
case ReaderSeekerCloser:
return v.GetLen()
case *ReaderSeekerCloser:
return v.GetLen()
}
return seekerLen(s)
}
func seekerLen(s io.Seeker) (int64, error) {
curOffset, err := s.Seek(0, sdkio.SeekCurrent)
if err != nil {
return 0, err
}
endOffset, err := s.Seek(0, sdkio.SeekEnd)
if err != nil {
return 0, err
}
_, err = s.Seek(curOffset, sdkio.SeekStart)
if err != nil {
return 0, err
}
return endOffset - curOffset, nil
}
// Close closes the ReaderSeekerCloser. // Close closes the ReaderSeekerCloser.
// //
// If the ReaderSeekerCloser is not an io.Closer nothing will be done. // If the ReaderSeekerCloser is not an io.Closer nothing will be done.

View File

@ -5,4 +5,4 @@ package aws
const SDKName = "aws-sdk-go" const SDKName = "aws-sdk-go"
// SDKVersion is the version of this SDK // SDKVersion is the version of this SDK
const SDKVersion = "1.10.27" const SDKVersion = "1.13.12"

21
vendor/github.com/aws/aws-sdk-go/buildspec.yml generated vendored Normal file
View File

@ -0,0 +1,21 @@
version: 0.2
phases:
build:
commands:
- echo Build started on `date`
- export GOPATH=/go
- export SDK_CB_ROOT=`pwd`
- export SDK_GO_ROOT=/go/src/github.com/aws/aws-sdk-go
- mkdir -p /go/src/github.com/aws
- ln -s $SDK_CB_ROOT $SDK_GO_ROOT
- cd $SDK_GO_ROOT
- make unit
- cd $SDK_CB_ROOT
- #echo Compiling the Go code...
post_build:
commands:
- echo Build completed on `date`
#artifacts:
# files:
# - hello

View File

@ -197,7 +197,7 @@
// regions different from the Session's region. // regions different from the Session's region.
// //
// svc := s3.New(sess, &aws.Config{ // svc := s3.New(sess, &aws.Config{
// Region: aws.String(ednpoints.UsWest2RegionID), // Region: aws.String(endpoints.UsWest2RegionID),
// }) // })
// //
// See the Config type in the aws package for more information and additional // See the Config type in the aws package for more information and additional

View File

@ -0,0 +1,10 @@
// +build !go1.7
package sdkio
// Copy of Go 1.7 io package's Seeker constants.
const (
SeekStart = 0 // seek relative to the origin of the file
SeekCurrent = 1 // seek relative to the current offset
SeekEnd = 2 // seek relative to the end
)

View File

@ -0,0 +1,12 @@
// +build go1.7
package sdkio
import "io"
// Alias for Go 1.7 io package Seeker constants
const (
SeekStart = io.SeekStart // seek relative to the origin of the file
SeekCurrent = io.SeekCurrent // seek relative to the current offset
SeekEnd = io.SeekEnd // seek relative to the end
)

View File

@ -0,0 +1,29 @@
package sdkrand
import (
"math/rand"
"sync"
"time"
)
// lockedSource is a thread-safe implementation of rand.Source
type lockedSource struct {
lk sync.Mutex
src rand.Source
}
func (r *lockedSource) Int63() (n int64) {
r.lk.Lock()
n = r.src.Int63()
r.lk.Unlock()
return
}
func (r *lockedSource) Seed(seed int64) {
r.lk.Lock()
r.src.Seed(seed)
r.lk.Unlock()
}
// SeededRand is a new RNG using a thread safe implementation of rand.Source
var SeededRand = rand.New(&lockedSource{src: rand.NewSource(time.Now().UnixNano())})

View File

@ -24,7 +24,7 @@ func Build(r *request.Request) {
r.Error = awserr.New("SerializationError", "failed encoding EC2 Query request", err) r.Error = awserr.New("SerializationError", "failed encoding EC2 Query request", err)
} }
if r.ExpireTime == 0 { if !r.IsPresigned() {
r.HTTPRequest.Method = "POST" r.HTTPRequest.Method = "POST"
r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8") r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
r.SetBufferBody([]byte(body.Encode())) r.SetBufferBody([]byte(body.Encode()))

View File

@ -0,0 +1,76 @@
package protocol
import (
"encoding/base64"
"encoding/json"
"fmt"
"strconv"
"github.com/aws/aws-sdk-go/aws"
)
// EscapeMode is the mode that should be use for escaping a value
type EscapeMode uint
// The modes for escaping a value before it is marshaled, and unmarshaled.
const (
NoEscape EscapeMode = iota
Base64Escape
QuotedEscape
)
// EncodeJSONValue marshals the value into a JSON string, and optionally base64
// encodes the string before returning it.
//
// Will panic if the escape mode is unknown.
func EncodeJSONValue(v aws.JSONValue, escape EscapeMode) (string, error) {
b, err := json.Marshal(v)
if err != nil {
return "", err
}
switch escape {
case NoEscape:
return string(b), nil
case Base64Escape:
return base64.StdEncoding.EncodeToString(b), nil
case QuotedEscape:
return strconv.Quote(string(b)), nil
}
panic(fmt.Sprintf("EncodeJSONValue called with unknown EscapeMode, %v", escape))
}
// DecodeJSONValue will attempt to decode the string input as a JSONValue.
// Optionally decoding base64 the value first before JSON unmarshaling.
//
// Will panic if the escape mode is unknown.
func DecodeJSONValue(v string, escape EscapeMode) (aws.JSONValue, error) {
var b []byte
var err error
switch escape {
case NoEscape:
b = []byte(v)
case Base64Escape:
b, err = base64.StdEncoding.DecodeString(v)
case QuotedEscape:
var u string
u, err = strconv.Unquote(v)
b = []byte(u)
default:
panic(fmt.Sprintf("DecodeJSONValue called with unknown EscapeMode, %v", escape))
}
if err != nil {
return nil, err
}
m := aws.JSONValue{}
err = json.Unmarshal(b, &m)
if err != nil {
return nil, err
}
return m, nil
}

View File

@ -25,7 +25,7 @@ func Build(r *request.Request) {
return return
} }
if r.ExpireTime == 0 { if !r.IsPresigned() {
r.HTTPRequest.Method = "POST" r.HTTPRequest.Method = "POST"
r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8") r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
r.SetBufferBody([]byte(body.Encode())) r.SetBufferBody([]byte(body.Encode()))

View File

@ -121,6 +121,10 @@ func (q *queryParser) parseList(v url.Values, value reflect.Value, prefix string
return nil return nil
} }
if _, ok := value.Interface().([]byte); ok {
return q.parseScalar(v, value, prefix, tag)
}
// check for unflattened list member // check for unflattened list member
if !q.isEC2 && tag.Get("flattened") == "" { if !q.isEC2 && tag.Get("flattened") == "" {
if listName := tag.Get("locationNameList"); listName == "" { if listName := tag.Get("locationNameList"); listName == "" {

View File

@ -4,7 +4,6 @@ package rest
import ( import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"encoding/json"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -18,6 +17,7 @@ import (
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/private/protocol"
) )
// RFC822 returns an RFC822 formatted timestamp for AWS protocols // RFC822 returns an RFC822 formatted timestamp for AWS protocols
@ -252,13 +252,12 @@ func EscapePath(path string, encodeSep bool) string {
return buf.String() return buf.String()
} }
func convertType(v reflect.Value, tag reflect.StructTag) (string, error) { func convertType(v reflect.Value, tag reflect.StructTag) (str string, err error) {
v = reflect.Indirect(v) v = reflect.Indirect(v)
if !v.IsValid() { if !v.IsValid() {
return "", errValueNotSet return "", errValueNotSet
} }
var str string
switch value := v.Interface().(type) { switch value := v.Interface().(type) {
case string: case string:
str = value str = value
@ -273,17 +272,19 @@ func convertType(v reflect.Value, tag reflect.StructTag) (string, error) {
case time.Time: case time.Time:
str = value.UTC().Format(RFC822) str = value.UTC().Format(RFC822)
case aws.JSONValue: case aws.JSONValue:
b, err := json.Marshal(value) if len(value) == 0 {
if err != nil { return "", errValueNotSet
return "", err
} }
escaping := protocol.NoEscape
if tag.Get("location") == "header" { if tag.Get("location") == "header" {
str = base64.StdEncoding.EncodeToString(b) escaping = protocol.Base64Escape
} else { }
str = string(b) str, err = protocol.EncodeJSONValue(value, escaping)
if err != nil {
return "", fmt.Errorf("unable to encode JSONValue, %v", err)
} }
default: default:
err := fmt.Errorf("Unsupported value for param %v (%s)", v.Interface(), v.Type()) err := fmt.Errorf("unsupported value for param %v (%s)", v.Interface(), v.Type())
return "", err return "", err
} }
return str, nil return str, nil

View File

@ -3,7 +3,6 @@ package rest
import ( import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"encoding/json"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -16,6 +15,7 @@ import (
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/private/protocol"
) )
// UnmarshalHandler is a named request handler for unmarshaling rest protocol requests // UnmarshalHandler is a named request handler for unmarshaling rest protocol requests
@ -204,17 +204,11 @@ func unmarshalHeader(v reflect.Value, header string, tag reflect.StructTag) erro
} }
v.Set(reflect.ValueOf(&t)) v.Set(reflect.ValueOf(&t))
case aws.JSONValue: case aws.JSONValue:
b := []byte(header) escaping := protocol.NoEscape
var err error
if tag.Get("location") == "header" { if tag.Get("location") == "header" {
b, err = base64.StdEncoding.DecodeString(header) escaping = protocol.Base64Escape
if err != nil {
return err
}
} }
m, err := protocol.DecodeJSONValue(header, escaping)
m := aws.JSONValue{}
err = json.Unmarshal(b, &m)
if err != nil { if err != nil {
return err return err
} }

File diff suppressed because it is too large Load Diff

View File

@ -5,11 +5,64 @@ import (
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awsutil" "github.com/aws/aws-sdk-go/aws/awsutil"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/endpoints" "github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/internal/sdkrand"
) )
type retryer struct {
client.DefaultRetryer
}
func (d retryer) RetryRules(r *request.Request) time.Duration {
switch r.Operation.Name {
case opModifyNetworkInterfaceAttribute:
fallthrough
case opAssignPrivateIpAddresses:
return customRetryRule(r)
default:
return d.DefaultRetryer.RetryRules(r)
}
}
func customRetryRule(r *request.Request) time.Duration {
retryTimes := []time.Duration{
time.Second,
3 * time.Second,
5 * time.Second,
}
count := r.RetryCount
if count >= len(retryTimes) {
count = len(retryTimes) - 1
}
minTime := int(retryTimes[count])
return time.Duration(sdkrand.SeededRand.Intn(minTime) + minTime)
}
func setCustomRetryer(c *client.Client) {
maxRetries := aws.IntValue(c.Config.MaxRetries)
if c.Config.MaxRetries == nil || maxRetries == aws.UseServiceDefaultRetries {
maxRetries = 3
}
c.Retryer = retryer{
DefaultRetryer: client.DefaultRetryer{
NumMaxRetries: maxRetries,
},
}
}
func init() { func init() {
initClient = func(c *client.Client) {
if c.Config.Retryer == nil {
// Only override the retryer with a custom one if the config
// does not already contain a retryer
setCustomRetryer(c)
}
}
initRequest = func(r *request.Request) { initRequest = func(r *request.Request) {
if r.Operation.Name == opCopySnapshot { // fill the PresignedURL parameter if r.Operation.Name == opCopySnapshot { // fill the PresignedURL parameter
r.Handlers.Build.PushFront(fillPresignedURL) r.Handlers.Build.PushFront(fillPresignedURL)

View File

@ -4,9 +4,8 @@
// requests to Amazon Elastic Compute Cloud. // requests to Amazon Elastic Compute Cloud.
// //
// Amazon Elastic Compute Cloud (Amazon EC2) provides resizable computing capacity // Amazon Elastic Compute Cloud (Amazon EC2) provides resizable computing capacity
// in the Amazon Web Services (AWS) cloud. Using Amazon EC2 eliminates your // in the AWS Cloud. Using Amazon EC2 eliminates the need to invest in hardware
// need to invest in hardware up front, so you can develop and deploy applications // up front, so you can develop and deploy applications faster.
// faster.
// //
// See https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15 for more information on this service. // See https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15 for more information on this service.
// //
@ -15,7 +14,7 @@
// //
// Using the Client // Using the Client
// //
// To Amazon Elastic Compute Cloud with the SDK use the New function to create // To contact Amazon Elastic Compute Cloud with the SDK use the New function to create
// a new service client. With that client you can make API requests to the service. // a new service client. With that client you can make API requests to the service.
// These clients are safe to use concurrently. // These clients are safe to use concurrently.
// //

View File

@ -1025,6 +1025,11 @@ func (c *EC2) WaitUntilSpotInstanceRequestFulfilledWithContext(ctx aws.Context,
Matcher: request.PathAllWaiterMatch, Argument: "SpotInstanceRequests[].Status.Code", Matcher: request.PathAllWaiterMatch, Argument: "SpotInstanceRequests[].Status.Code",
Expected: "fulfilled", Expected: "fulfilled",
}, },
{
State: request.SuccessWaiterState,
Matcher: request.PathAllWaiterMatch, Argument: "SpotInstanceRequests[].Status.Code",
Expected: "request-canceled-and-instance-running",
},
{ {
State: request.FailureWaiterState, State: request.FailureWaiterState,
Matcher: request.PathAnyWaiterMatch, Argument: "SpotInstanceRequests[].Status.Code", Matcher: request.PathAnyWaiterMatch, Argument: "SpotInstanceRequests[].Status.Code",

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,249 @@
package s3
import (
"bytes"
"crypto/md5"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"fmt"
"hash"
"io"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/internal/sdkio"
)
const (
contentMD5Header = "Content-Md5"
contentSha256Header = "X-Amz-Content-Sha256"
amzTeHeader = "X-Amz-Te"
amzTxEncodingHeader = "X-Amz-Transfer-Encoding"
appendMD5TxEncoding = "append-md5"
)
// contentMD5 computes and sets the HTTP Content-MD5 header for requests that
// require it.
func contentMD5(r *request.Request) {
h := md5.New()
if !aws.IsReaderSeekable(r.Body) {
if r.Config.Logger != nil {
r.Config.Logger.Log(fmt.Sprintf(
"Unable to compute Content-MD5 for unseekable body, S3.%s",
r.Operation.Name))
}
return
}
if _, err := copySeekableBody(h, r.Body); err != nil {
r.Error = awserr.New("ContentMD5", "failed to compute body MD5", err)
return
}
// encode the md5 checksum in base64 and set the request header.
v := base64.StdEncoding.EncodeToString(h.Sum(nil))
r.HTTPRequest.Header.Set(contentMD5Header, v)
}
// computeBodyHashes will add Content MD5 and Content Sha256 hashes to the
// request. If the body is not seekable or S3DisableContentMD5Validation set
// this handler will be ignored.
func computeBodyHashes(r *request.Request) {
if aws.BoolValue(r.Config.S3DisableContentMD5Validation) {
return
}
if r.IsPresigned() {
return
}
if r.Error != nil || !aws.IsReaderSeekable(r.Body) {
return
}
var md5Hash, sha256Hash hash.Hash
hashers := make([]io.Writer, 0, 2)
// Determine upfront which hashes can be set without overriding user
// provide header data.
if v := r.HTTPRequest.Header.Get(contentMD5Header); len(v) == 0 {
md5Hash = md5.New()
hashers = append(hashers, md5Hash)
}
if v := r.HTTPRequest.Header.Get(contentSha256Header); len(v) == 0 {
sha256Hash = sha256.New()
hashers = append(hashers, sha256Hash)
}
// Create the destination writer based on the hashes that are not already
// provided by the user.
var dst io.Writer
switch len(hashers) {
case 0:
return
case 1:
dst = hashers[0]
default:
dst = io.MultiWriter(hashers...)
}
if _, err := copySeekableBody(dst, r.Body); err != nil {
r.Error = awserr.New("BodyHashError", "failed to compute body hashes", err)
return
}
// For the hashes created, set the associated headers that the user did not
// already provide.
if md5Hash != nil {
sum := make([]byte, md5.Size)
encoded := make([]byte, md5Base64EncLen)
base64.StdEncoding.Encode(encoded, md5Hash.Sum(sum[0:0]))
r.HTTPRequest.Header[contentMD5Header] = []string{string(encoded)}
}
if sha256Hash != nil {
encoded := make([]byte, sha256HexEncLen)
sum := make([]byte, sha256.Size)
hex.Encode(encoded, sha256Hash.Sum(sum[0:0]))
r.HTTPRequest.Header[contentSha256Header] = []string{string(encoded)}
}
}
const (
md5Base64EncLen = (md5.Size + 2) / 3 * 4 // base64.StdEncoding.EncodedLen
sha256HexEncLen = sha256.Size * 2 // hex.EncodedLen
)
func copySeekableBody(dst io.Writer, src io.ReadSeeker) (int64, error) {
curPos, err := src.Seek(0, sdkio.SeekCurrent)
if err != nil {
return 0, err
}
// hash the body. seek back to the first position after reading to reset
// the body for transmission. copy errors may be assumed to be from the
// body.
n, err := io.Copy(dst, src)
if err != nil {
return n, err
}
_, err = src.Seek(curPos, sdkio.SeekStart)
if err != nil {
return n, err
}
return n, nil
}
// Adds the x-amz-te: append_md5 header to the request. This requests the service
// responds with a trailing MD5 checksum.
//
// Will not ask for append MD5 if disabled, the request is presigned or,
// or the API operation does not support content MD5 validation.
func askForTxEncodingAppendMD5(r *request.Request) {
if aws.BoolValue(r.Config.S3DisableContentMD5Validation) {
return
}
if r.IsPresigned() {
return
}
r.HTTPRequest.Header.Set(amzTeHeader, appendMD5TxEncoding)
}
func useMD5ValidationReader(r *request.Request) {
if r.Error != nil {
return
}
if v := r.HTTPResponse.Header.Get(amzTxEncodingHeader); v != appendMD5TxEncoding {
return
}
var bodyReader *io.ReadCloser
var contentLen int64
switch tv := r.Data.(type) {
case *GetObjectOutput:
bodyReader = &tv.Body
contentLen = aws.Int64Value(tv.ContentLength)
// Update ContentLength hiden the trailing MD5 checksum.
tv.ContentLength = aws.Int64(contentLen - md5.Size)
tv.ContentRange = aws.String(r.HTTPResponse.Header.Get("X-Amz-Content-Range"))
default:
r.Error = awserr.New("ChecksumValidationError",
fmt.Sprintf("%s: %s header received on unsupported API, %s",
amzTxEncodingHeader, appendMD5TxEncoding, r.Operation.Name,
), nil)
return
}
if contentLen < md5.Size {
r.Error = awserr.New("ChecksumValidationError",
fmt.Sprintf("invalid Content-Length %d for %s %s",
contentLen, appendMD5TxEncoding, amzTxEncodingHeader,
), nil)
return
}
// Wrap and swap the response body reader with the validation reader.
*bodyReader = newMD5ValidationReader(*bodyReader, contentLen-md5.Size)
}
type md5ValidationReader struct {
rawReader io.ReadCloser
payload io.Reader
hash hash.Hash
payloadLen int64
read int64
}
func newMD5ValidationReader(reader io.ReadCloser, payloadLen int64) *md5ValidationReader {
h := md5.New()
return &md5ValidationReader{
rawReader: reader,
payload: io.TeeReader(&io.LimitedReader{R: reader, N: payloadLen}, h),
hash: h,
payloadLen: payloadLen,
}
}
func (v *md5ValidationReader) Read(p []byte) (n int, err error) {
n, err = v.payload.Read(p)
if err != nil && err != io.EOF {
return n, err
}
v.read += int64(n)
if err == io.EOF {
if v.read != v.payloadLen {
return n, io.ErrUnexpectedEOF
}
expectSum := make([]byte, md5.Size)
actualSum := make([]byte, md5.Size)
if _, sumReadErr := io.ReadFull(v.rawReader, expectSum); sumReadErr != nil {
return n, sumReadErr
}
actualSum = v.hash.Sum(actualSum[0:0])
if !bytes.Equal(expectSum, actualSum) {
return n, awserr.New("InvalidChecksum",
fmt.Sprintf("expected MD5 checksum %s, got %s",
hex.EncodeToString(expectSum),
hex.EncodeToString(actualSum),
),
nil)
}
}
return n, err
}
func (v *md5ValidationReader) Close() error {
return v.rawReader.Close()
}

View File

@ -1,36 +0,0 @@
package s3
import (
"crypto/md5"
"encoding/base64"
"io"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
)
// contentMD5 computes and sets the HTTP Content-MD5 header for requests that
// require it.
func contentMD5(r *request.Request) {
h := md5.New()
// hash the body. seek back to the first position after reading to reset
// the body for transmission. copy errors may be assumed to be from the
// body.
_, err := io.Copy(h, r.Body)
if err != nil {
r.Error = awserr.New("ContentMD5", "failed to read body", err)
return
}
_, err = r.Body.Seek(0, 0)
if err != nil {
r.Error = awserr.New("ContentMD5", "failed to seek body", err)
return
}
// encode the md5 checksum in base64 and set the request header.
sum := h.Sum(nil)
sum64 := make([]byte, base64.StdEncoding.EncodedLen(len(sum)))
base64.StdEncoding.Encode(sum64, sum)
r.HTTPRequest.Header.Set("Content-MD5", string(sum64))
}

View File

@ -42,6 +42,11 @@ func defaultInitRequestFn(r *request.Request) {
r.Handlers.Validate.PushFront(populateLocationConstraint) r.Handlers.Validate.PushFront(populateLocationConstraint)
case opCopyObject, opUploadPartCopy, opCompleteMultipartUpload: case opCopyObject, opUploadPartCopy, opCompleteMultipartUpload:
r.Handlers.Unmarshal.PushFront(copyMultipartStatusOKUnmarhsalError) r.Handlers.Unmarshal.PushFront(copyMultipartStatusOKUnmarhsalError)
case opPutObject, opUploadPart:
r.Handlers.Build.PushBack(computeBodyHashes)
case opGetObject:
r.Handlers.Build.PushBack(askForTxEncodingAppendMD5)
r.Handlers.Unmarshal.PushBack(useMD5ValidationReader)
} }
} }

View File

@ -10,7 +10,7 @@
// //
// Using the Client // Using the Client
// //
// To Amazon Simple Storage Service with the SDK use the New function to create // To contact Amazon Simple Storage Service with the SDK use the New function to create
// a new service client. With that client you can make API requests to the service. // a new service client. With that client you can make API requests to the service.
// These clients are safe to use concurrently. // These clients are safe to use concurrently.
// //

View File

@ -35,7 +35,7 @@
// //
// The s3manager package's Downloader provides concurrently downloading of Objects // The s3manager package's Downloader provides concurrently downloading of Objects
// from S3. The Downloader will write S3 Object content with an io.WriterAt. // from S3. The Downloader will write S3 Object content with an io.WriterAt.
// Once the Downloader instance is created you can call Upload concurrently from // Once the Downloader instance is created you can call Download concurrently from
// multiple goroutines safely. // multiple goroutines safely.
// //
// // The session the S3 Downloader will use // // The session the S3 Downloader will use
@ -56,7 +56,7 @@
// Key: aws.String(myString), // Key: aws.String(myString),
// }) // })
// if err != nil { // if err != nil {
// return fmt.Errorf("failed to upload file, %v", err) // return fmt.Errorf("failed to download file, %v", err)
// } // }
// fmt.Printf("file downloaded, %d bytes\n", n) // fmt.Printf("file downloaded, %d bytes\n", n)
// //

View File

@ -92,6 +92,10 @@ type S3API interface {
DeleteBucketCorsWithContext(aws.Context, *s3.DeleteBucketCorsInput, ...request.Option) (*s3.DeleteBucketCorsOutput, error) DeleteBucketCorsWithContext(aws.Context, *s3.DeleteBucketCorsInput, ...request.Option) (*s3.DeleteBucketCorsOutput, error)
DeleteBucketCorsRequest(*s3.DeleteBucketCorsInput) (*request.Request, *s3.DeleteBucketCorsOutput) DeleteBucketCorsRequest(*s3.DeleteBucketCorsInput) (*request.Request, *s3.DeleteBucketCorsOutput)
DeleteBucketEncryption(*s3.DeleteBucketEncryptionInput) (*s3.DeleteBucketEncryptionOutput, error)
DeleteBucketEncryptionWithContext(aws.Context, *s3.DeleteBucketEncryptionInput, ...request.Option) (*s3.DeleteBucketEncryptionOutput, error)
DeleteBucketEncryptionRequest(*s3.DeleteBucketEncryptionInput) (*request.Request, *s3.DeleteBucketEncryptionOutput)
DeleteBucketInventoryConfiguration(*s3.DeleteBucketInventoryConfigurationInput) (*s3.DeleteBucketInventoryConfigurationOutput, error) DeleteBucketInventoryConfiguration(*s3.DeleteBucketInventoryConfigurationInput) (*s3.DeleteBucketInventoryConfigurationOutput, error)
DeleteBucketInventoryConfigurationWithContext(aws.Context, *s3.DeleteBucketInventoryConfigurationInput, ...request.Option) (*s3.DeleteBucketInventoryConfigurationOutput, error) DeleteBucketInventoryConfigurationWithContext(aws.Context, *s3.DeleteBucketInventoryConfigurationInput, ...request.Option) (*s3.DeleteBucketInventoryConfigurationOutput, error)
DeleteBucketInventoryConfigurationRequest(*s3.DeleteBucketInventoryConfigurationInput) (*request.Request, *s3.DeleteBucketInventoryConfigurationOutput) DeleteBucketInventoryConfigurationRequest(*s3.DeleteBucketInventoryConfigurationInput) (*request.Request, *s3.DeleteBucketInventoryConfigurationOutput)
@ -148,6 +152,10 @@ type S3API interface {
GetBucketCorsWithContext(aws.Context, *s3.GetBucketCorsInput, ...request.Option) (*s3.GetBucketCorsOutput, error) GetBucketCorsWithContext(aws.Context, *s3.GetBucketCorsInput, ...request.Option) (*s3.GetBucketCorsOutput, error)
GetBucketCorsRequest(*s3.GetBucketCorsInput) (*request.Request, *s3.GetBucketCorsOutput) GetBucketCorsRequest(*s3.GetBucketCorsInput) (*request.Request, *s3.GetBucketCorsOutput)
GetBucketEncryption(*s3.GetBucketEncryptionInput) (*s3.GetBucketEncryptionOutput, error)
GetBucketEncryptionWithContext(aws.Context, *s3.GetBucketEncryptionInput, ...request.Option) (*s3.GetBucketEncryptionOutput, error)
GetBucketEncryptionRequest(*s3.GetBucketEncryptionInput) (*request.Request, *s3.GetBucketEncryptionOutput)
GetBucketInventoryConfiguration(*s3.GetBucketInventoryConfigurationInput) (*s3.GetBucketInventoryConfigurationOutput, error) GetBucketInventoryConfiguration(*s3.GetBucketInventoryConfigurationInput) (*s3.GetBucketInventoryConfigurationOutput, error)
GetBucketInventoryConfigurationWithContext(aws.Context, *s3.GetBucketInventoryConfigurationInput, ...request.Option) (*s3.GetBucketInventoryConfigurationOutput, error) GetBucketInventoryConfigurationWithContext(aws.Context, *s3.GetBucketInventoryConfigurationInput, ...request.Option) (*s3.GetBucketInventoryConfigurationOutput, error)
GetBucketInventoryConfigurationRequest(*s3.GetBucketInventoryConfigurationInput) (*request.Request, *s3.GetBucketInventoryConfigurationOutput) GetBucketInventoryConfigurationRequest(*s3.GetBucketInventoryConfigurationInput) (*request.Request, *s3.GetBucketInventoryConfigurationOutput)
@ -295,6 +303,10 @@ type S3API interface {
PutBucketCorsWithContext(aws.Context, *s3.PutBucketCorsInput, ...request.Option) (*s3.PutBucketCorsOutput, error) PutBucketCorsWithContext(aws.Context, *s3.PutBucketCorsInput, ...request.Option) (*s3.PutBucketCorsOutput, error)
PutBucketCorsRequest(*s3.PutBucketCorsInput) (*request.Request, *s3.PutBucketCorsOutput) PutBucketCorsRequest(*s3.PutBucketCorsInput) (*request.Request, *s3.PutBucketCorsOutput)
PutBucketEncryption(*s3.PutBucketEncryptionInput) (*s3.PutBucketEncryptionOutput, error)
PutBucketEncryptionWithContext(aws.Context, *s3.PutBucketEncryptionInput, ...request.Option) (*s3.PutBucketEncryptionOutput, error)
PutBucketEncryptionRequest(*s3.PutBucketEncryptionInput) (*request.Request, *s3.PutBucketEncryptionOutput)
PutBucketInventoryConfiguration(*s3.PutBucketInventoryConfigurationInput) (*s3.PutBucketInventoryConfigurationOutput, error) PutBucketInventoryConfiguration(*s3.PutBucketInventoryConfigurationInput) (*s3.PutBucketInventoryConfigurationOutput, error)
PutBucketInventoryConfigurationWithContext(aws.Context, *s3.PutBucketInventoryConfigurationInput, ...request.Option) (*s3.PutBucketInventoryConfigurationOutput, error) PutBucketInventoryConfigurationWithContext(aws.Context, *s3.PutBucketInventoryConfigurationInput, ...request.Option) (*s3.PutBucketInventoryConfigurationOutput, error)
PutBucketInventoryConfigurationRequest(*s3.PutBucketInventoryConfigurationInput) (*request.Request, *s3.PutBucketInventoryConfigurationOutput) PutBucketInventoryConfigurationRequest(*s3.PutBucketInventoryConfigurationInput) (*request.Request, *s3.PutBucketInventoryConfigurationOutput)

View File

@ -60,7 +60,15 @@ func newError(err error, bucket, key *string) Error {
} }
func (err *Error) Error() string { func (err *Error) Error() string {
return fmt.Sprintf("failed to upload %q to %q:\n%s", err.Key, err.Bucket, err.OrigErr.Error()) origErr := ""
if err.OrigErr != nil {
origErr = ":\n" + err.OrigErr.Error()
}
return fmt.Sprintf("failed to upload %q to %q%s",
aws.StringValue(err.Key),
aws.StringValue(err.Bucket),
origErr,
)
} }
// NewBatchError will return a BatchError that satisfies the awserr.Error interface. // NewBatchError will return a BatchError that satisfies the awserr.Error interface.
@ -206,7 +214,7 @@ type BatchDelete struct {
// }, // },
// } // }
// //
// if err := batcher.Delete(&s3manager.DeleteObjectsIterator{ // if err := batcher.Delete(aws.BackgroundContext(), &s3manager.DeleteObjectsIterator{
// Objects: objects, // Objects: objects,
// }); err != nil { // }); err != nil {
// return err // return err
@ -239,7 +247,7 @@ func NewBatchDeleteWithClient(client s3iface.S3API, options ...func(*BatchDelete
// }, // },
// } // }
// //
// if err := batcher.Delete(&s3manager.DeleteObjectsIterator{ // if err := batcher.Delete(aws.BackgroundContext(), &s3manager.DeleteObjectsIterator{
// Objects: objects, // Objects: objects,
// }); err != nil { // }); err != nil {
// return err // return err
@ -312,7 +320,7 @@ func (d *BatchDelete) Delete(ctx aws.Context, iter BatchDeleteIterator) error {
} }
if len(input.Delete.Objects) == d.BatchSize || !parity { if len(input.Delete.Objects) == d.BatchSize || !parity {
if err := deleteBatch(d, input, objects); err != nil { if err := deleteBatch(ctx, d, input, objects); err != nil {
errs = append(errs, err...) errs = append(errs, err...)
} }
@ -331,7 +339,7 @@ func (d *BatchDelete) Delete(ctx aws.Context, iter BatchDeleteIterator) error {
} }
if input != nil && len(input.Delete.Objects) > 0 { if input != nil && len(input.Delete.Objects) > 0 {
if err := deleteBatch(d, input, objects); err != nil { if err := deleteBatch(ctx, d, input, objects); err != nil {
errs = append(errs, err...) errs = append(errs, err...)
} }
} }
@ -352,10 +360,10 @@ func initDeleteObjectsInput(o *s3.DeleteObjectInput) *s3.DeleteObjectsInput {
} }
// deleteBatch will delete a batch of items in the objects parameters. // deleteBatch will delete a batch of items in the objects parameters.
func deleteBatch(d *BatchDelete, input *s3.DeleteObjectsInput, objects []BatchDeleteObject) []Error { func deleteBatch(ctx aws.Context, d *BatchDelete, input *s3.DeleteObjectsInput, objects []BatchDeleteObject) []Error {
errs := []Error{} errs := []Error{}
if result, err := d.Client.DeleteObjects(input); err != nil { if result, err := d.Client.DeleteObjectsWithContext(ctx, input); err != nil {
for i := 0; i < len(input.Delete.Objects); i++ { for i := 0; i < len(input.Delete.Objects); i++ {
errs = append(errs, newError(err, input.Bucket, input.Delete.Objects[i].Key)) errs = append(errs, newError(err, input.Bucket, input.Delete.Objects[i].Key))
} }

View File

@ -14,8 +14,11 @@ import (
// //
// The request will not be signed, and will not use your AWS credentials. // The request will not be signed, and will not use your AWS credentials.
// //
// A "NotFound" error code will be returned if the bucket does not exist in // A "NotFound" error code will be returned if the bucket does not exist in the
// the AWS partition the regionHint belongs to. // AWS partition the regionHint belongs to. If the regionHint parameter is an
// empty string GetBucketRegion will fallback to the ConfigProvider's region
// config. If the regionHint is empty, and the ConfigProvider does not have a
// region value, an error will be returned..
// //
// For example to get the region of a bucket which exists in "eu-central-1" // For example to get the region of a bucket which exists in "eu-central-1"
// you could provide a region hint of "us-west-2". // you could provide a region hint of "us-west-2".
@ -33,9 +36,11 @@ import (
// fmt.Printf("Bucket %s is in %s region\n", bucket, region) // fmt.Printf("Bucket %s is in %s region\n", bucket, region)
// //
func GetBucketRegion(ctx aws.Context, c client.ConfigProvider, bucket, regionHint string, opts ...request.Option) (string, error) { func GetBucketRegion(ctx aws.Context, c client.ConfigProvider, bucket, regionHint string, opts ...request.Option) (string, error) {
svc := s3.New(c, &aws.Config{ var cfg aws.Config
Region: aws.String(regionHint), if len(regionHint) != 0 {
}) cfg.Region = aws.String(regionHint)
}
svc := s3.New(c, &cfg)
return GetBucketRegionWithClient(ctx, svc, bucket, opts...) return GetBucketRegionWithClient(ctx, svc, bucket, opts...)
} }

View File

@ -117,6 +117,9 @@ type UploadInput struct {
// The language the content is in. // The language the content is in.
ContentLanguage *string `location:"header" locationName:"Content-Language" type:"string"` ContentLanguage *string `location:"header" locationName:"Content-Language" type:"string"`
// The base64-encoded 128-bit MD5 digest of the part data.
ContentMD5 *string `location:"header" locationName:"Content-MD5" type:"string"`
// A standard MIME type describing the format of the object data. // A standard MIME type describing the format of the object data.
ContentType *string `location:"header" locationName:"Content-Type" type:"string"` ContentType *string `location:"header" locationName:"Content-Type" type:"string"`
@ -218,8 +221,11 @@ type Uploader struct {
// if this value is set to zero, the DefaultUploadPartSize value will be used. // if this value is set to zero, the DefaultUploadPartSize value will be used.
PartSize int64 PartSize int64
// The number of goroutines to spin up in parallel when sending parts. // The number of goroutines to spin up in parallel per call to Upload when
// If this is set to zero, the DefaultUploadConcurrency value will be used. // sending parts. If this is set to zero, the DefaultUploadConcurrency value
// will be used.
//
// The concurrency pool is not shared between calls to Upload.
Concurrency int Concurrency int
// Setting this value to true will cause the SDK to avoid calling // Setting this value to true will cause the SDK to avoid calling
@ -437,6 +443,8 @@ type uploader struct {
readerPos int64 // current reader position readerPos int64 // current reader position
totalSize int64 // set to -1 if the size is not known totalSize int64 // set to -1 if the size is not known
bufferPool sync.Pool
} }
// internal logic for deciding whether to upload a single part or use a // internal logic for deciding whether to upload a single part or use a
@ -450,7 +458,7 @@ func (u *uploader) upload() (*UploadOutput, error) {
} }
// Do one read to determine if we have more than one part // Do one read to determine if we have more than one part
reader, _, err := u.nextReader() reader, _, part, err := u.nextReader()
if err == io.EOF { // single part if err == io.EOF { // single part
return u.singlePart(reader) return u.singlePart(reader)
} else if err != nil { } else if err != nil {
@ -458,7 +466,7 @@ func (u *uploader) upload() (*UploadOutput, error) {
} }
mu := multiuploader{uploader: u} mu := multiuploader{uploader: u}
return mu.upload(reader) return mu.upload(reader, part)
} }
// init will initialize all default options. // init will initialize all default options.
@ -470,6 +478,10 @@ func (u *uploader) init() {
u.cfg.PartSize = DefaultUploadPartSize u.cfg.PartSize = DefaultUploadPartSize
} }
u.bufferPool = sync.Pool{
New: func() interface{} { return make([]byte, u.cfg.PartSize) },
}
// Try to get the total size for some optimizations // Try to get the total size for some optimizations
u.initSize() u.initSize()
} }
@ -481,10 +493,7 @@ func (u *uploader) initSize() {
switch r := u.in.Body.(type) { switch r := u.in.Body.(type) {
case io.Seeker: case io.Seeker:
pos, _ := r.Seek(0, 1) n, err := aws.SeekerLen(r)
defer r.Seek(pos, 0)
n, err := r.Seek(0, 2)
if err != nil { if err != nil {
return return
} }
@ -504,7 +513,7 @@ func (u *uploader) initSize() {
// This operation increases the shared u.readerPos counter, but note that it // This operation increases the shared u.readerPos counter, but note that it
// does not need to be wrapped in a mutex because nextReader is only called // does not need to be wrapped in a mutex because nextReader is only called
// from the main thread. // from the main thread.
func (u *uploader) nextReader() (io.ReadSeeker, int, error) { func (u *uploader) nextReader() (io.ReadSeeker, int, []byte, error) {
type readerAtSeeker interface { type readerAtSeeker interface {
io.ReaderAt io.ReaderAt
io.ReadSeeker io.ReadSeeker
@ -526,14 +535,14 @@ func (u *uploader) nextReader() (io.ReadSeeker, int, error) {
reader := io.NewSectionReader(r, u.readerPos, n) reader := io.NewSectionReader(r, u.readerPos, n)
u.readerPos += n u.readerPos += n
return reader, int(n), err return reader, int(n), nil, err
default: default:
part := make([]byte, u.cfg.PartSize) part := u.bufferPool.Get().([]byte)
n, err := readFillBuf(r, part) n, err := readFillBuf(r, part)
u.readerPos += int64(n) u.readerPos += int64(n)
return bytes.NewReader(part[0:n]), n, err return bytes.NewReader(part[0:n]), n, part, err
} }
} }
@ -583,8 +592,9 @@ type multiuploader struct {
// keeps track of a single chunk of data being sent to S3. // keeps track of a single chunk of data being sent to S3.
type chunk struct { type chunk struct {
buf io.ReadSeeker buf io.ReadSeeker
num int64 part []byte
num int64
} }
// completedParts is a wrapper to make parts sortable by their part number, // completedParts is a wrapper to make parts sortable by their part number,
@ -597,7 +607,7 @@ func (a completedParts) Less(i, j int) bool { return *a[i].PartNumber < *a[j].Pa
// upload will perform a multipart upload using the firstBuf buffer containing // upload will perform a multipart upload using the firstBuf buffer containing
// the first chunk of data. // the first chunk of data.
func (u *multiuploader) upload(firstBuf io.ReadSeeker) (*UploadOutput, error) { func (u *multiuploader) upload(firstBuf io.ReadSeeker, firstPart []byte) (*UploadOutput, error) {
params := &s3.CreateMultipartUploadInput{} params := &s3.CreateMultipartUploadInput{}
awsutil.Copy(params, u.in) awsutil.Copy(params, u.in)
@ -617,7 +627,7 @@ func (u *multiuploader) upload(firstBuf io.ReadSeeker) (*UploadOutput, error) {
// Send part 1 to the workers // Send part 1 to the workers
var num int64 = 1 var num int64 = 1
ch <- chunk{buf: firstBuf, num: num} ch <- chunk{buf: firstBuf, part: firstPart, num: num}
// Read and queue the rest of the parts // Read and queue the rest of the parts
for u.geterr() == nil && err == nil { for u.geterr() == nil && err == nil {
@ -638,7 +648,8 @@ func (u *multiuploader) upload(firstBuf io.ReadSeeker) (*UploadOutput, error) {
var reader io.ReadSeeker var reader io.ReadSeeker
var nextChunkLen int var nextChunkLen int
reader, nextChunkLen, err = u.nextReader() var part []byte
reader, nextChunkLen, part, err = u.nextReader()
if err != nil && err != io.EOF { if err != nil && err != io.EOF {
u.seterr(awserr.New( u.seterr(awserr.New(
@ -655,7 +666,7 @@ func (u *multiuploader) upload(firstBuf io.ReadSeeker) (*UploadOutput, error) {
break break
} }
ch <- chunk{buf: reader, num: num} ch <- chunk{buf: reader, part: part, num: num}
} }
// Close the channel, wait for workers, and complete upload // Close the channel, wait for workers, and complete upload
@ -711,6 +722,8 @@ func (u *multiuploader) send(c chunk) error {
PartNumber: &c.num, PartNumber: &c.num,
} }
resp, err := u.cfg.S3.UploadPartWithContext(u.ctx, params, u.cfg.RequestOptions...) resp, err := u.cfg.S3.UploadPartWithContext(u.ctx, params, u.cfg.RequestOptions...)
// put the byte array back into the pool to conserve memory
u.bufferPool.Put(c.part)
if err != nil { if err != nil {
return err return err
} }

View File

@ -7,6 +7,7 @@ import (
"github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/internal/sdkio"
) )
func copyMultipartStatusOKUnmarhsalError(r *request.Request) { func copyMultipartStatusOKUnmarhsalError(r *request.Request) {
@ -17,7 +18,7 @@ func copyMultipartStatusOKUnmarhsalError(r *request.Request) {
} }
body := bytes.NewReader(b) body := bytes.NewReader(b)
r.HTTPResponse.Body = ioutil.NopCloser(body) r.HTTPResponse.Body = ioutil.NopCloser(body)
defer body.Seek(0, 0) defer body.Seek(0, sdkio.SeekStart)
if body.Len() == 0 { if body.Len() == 0 {
// If there is no body don't attempt to parse the body. // If there is no body don't attempt to parse the body.

View File

@ -35,7 +35,7 @@ const opAssumeRole = "AssumeRole"
// fmt.Println(resp) // fmt.Println(resp)
// } // }
// //
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRole // See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRole
func (c *STS) AssumeRoleRequest(input *AssumeRoleInput) (req *request.Request, output *AssumeRoleOutput) { func (c *STS) AssumeRoleRequest(input *AssumeRoleInput) (req *request.Request, output *AssumeRoleOutput) {
op := &request.Operation{ op := &request.Operation{
Name: opAssumeRole, Name: opAssumeRole,
@ -121,7 +121,12 @@ func (c *STS) AssumeRoleRequest(input *AssumeRoleInput) (req *request.Request, o
// the user to call AssumeRole on the ARN of the role in the other account. // the user to call AssumeRole on the ARN of the role in the other account.
// If the user is in the same account as the role, then you can either attach // If the user is in the same account as the role, then you can either attach
// a policy to the user (identical to the previous different account user), // a policy to the user (identical to the previous different account user),
// or you can add the user as a principal directly in the role's trust policy // or you can add the user as a principal directly in the role's trust policy.
// In this case, the trust policy acts as the only resource-based policy in
// IAM, and users in the same account as the role do not need explicit permission
// to assume the role. For more information about trust policies and resource-based
// policies, see IAM Policies (http://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html)
// in the IAM User Guide.
// //
// Using MFA with AssumeRole // Using MFA with AssumeRole
// //
@ -168,7 +173,7 @@ func (c *STS) AssumeRoleRequest(input *AssumeRoleInput) (req *request.Request, o
// and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) // and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
// in the IAM User Guide. // in the IAM User Guide.
// //
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRole // See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRole
func (c *STS) AssumeRole(input *AssumeRoleInput) (*AssumeRoleOutput, error) { func (c *STS) AssumeRole(input *AssumeRoleInput) (*AssumeRoleOutput, error) {
req, out := c.AssumeRoleRequest(input) req, out := c.AssumeRoleRequest(input)
return out, req.Send() return out, req.Send()
@ -215,7 +220,7 @@ const opAssumeRoleWithSAML = "AssumeRoleWithSAML"
// fmt.Println(resp) // fmt.Println(resp)
// } // }
// //
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithSAML // See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithSAML
func (c *STS) AssumeRoleWithSAMLRequest(input *AssumeRoleWithSAMLInput) (req *request.Request, output *AssumeRoleWithSAMLOutput) { func (c *STS) AssumeRoleWithSAMLRequest(input *AssumeRoleWithSAMLInput) (req *request.Request, output *AssumeRoleWithSAMLOutput) {
op := &request.Operation{ op := &request.Operation{
Name: opAssumeRoleWithSAML, Name: opAssumeRoleWithSAML,
@ -341,7 +346,7 @@ func (c *STS) AssumeRoleWithSAMLRequest(input *AssumeRoleWithSAMLInput) (req *re
// and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) // and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
// in the IAM User Guide. // in the IAM User Guide.
// //
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithSAML // See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithSAML
func (c *STS) AssumeRoleWithSAML(input *AssumeRoleWithSAMLInput) (*AssumeRoleWithSAMLOutput, error) { func (c *STS) AssumeRoleWithSAML(input *AssumeRoleWithSAMLInput) (*AssumeRoleWithSAMLOutput, error) {
req, out := c.AssumeRoleWithSAMLRequest(input) req, out := c.AssumeRoleWithSAMLRequest(input)
return out, req.Send() return out, req.Send()
@ -388,7 +393,7 @@ const opAssumeRoleWithWebIdentity = "AssumeRoleWithWebIdentity"
// fmt.Println(resp) // fmt.Println(resp)
// } // }
// //
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithWebIdentity // See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithWebIdentity
func (c *STS) AssumeRoleWithWebIdentityRequest(input *AssumeRoleWithWebIdentityInput) (req *request.Request, output *AssumeRoleWithWebIdentityOutput) { func (c *STS) AssumeRoleWithWebIdentityRequest(input *AssumeRoleWithWebIdentityInput) (req *request.Request, output *AssumeRoleWithWebIdentityOutput) {
op := &request.Operation{ op := &request.Operation{
Name: opAssumeRoleWithWebIdentity, Name: opAssumeRoleWithWebIdentity,
@ -492,7 +497,7 @@ func (c *STS) AssumeRoleWithWebIdentityRequest(input *AssumeRoleWithWebIdentityI
// the information from these providers to get and use temporary security // the information from these providers to get and use temporary security
// credentials. // credentials.
// //
// * Web Identity Federation with Mobile Applications (http://aws.amazon.com/articles/4617974389850313). // * Web Identity Federation with Mobile Applications (http://aws.amazon.com/articles/web-identity-federation-with-mobile-applications).
// This article discusses web identity federation and shows an example of // This article discusses web identity federation and shows an example of
// how to use web identity federation to get access to content in Amazon // how to use web identity federation to get access to content in Amazon
// S3. // S3.
@ -543,7 +548,7 @@ func (c *STS) AssumeRoleWithWebIdentityRequest(input *AssumeRoleWithWebIdentityI
// and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) // and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
// in the IAM User Guide. // in the IAM User Guide.
// //
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithWebIdentity // See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithWebIdentity
func (c *STS) AssumeRoleWithWebIdentity(input *AssumeRoleWithWebIdentityInput) (*AssumeRoleWithWebIdentityOutput, error) { func (c *STS) AssumeRoleWithWebIdentity(input *AssumeRoleWithWebIdentityInput) (*AssumeRoleWithWebIdentityOutput, error) {
req, out := c.AssumeRoleWithWebIdentityRequest(input) req, out := c.AssumeRoleWithWebIdentityRequest(input)
return out, req.Send() return out, req.Send()
@ -590,7 +595,7 @@ const opDecodeAuthorizationMessage = "DecodeAuthorizationMessage"
// fmt.Println(resp) // fmt.Println(resp)
// } // }
// //
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/DecodeAuthorizationMessage // See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/DecodeAuthorizationMessage
func (c *STS) DecodeAuthorizationMessageRequest(input *DecodeAuthorizationMessageInput) (req *request.Request, output *DecodeAuthorizationMessageOutput) { func (c *STS) DecodeAuthorizationMessageRequest(input *DecodeAuthorizationMessageInput) (req *request.Request, output *DecodeAuthorizationMessageOutput) {
op := &request.Operation{ op := &request.Operation{
Name: opDecodeAuthorizationMessage, Name: opDecodeAuthorizationMessage,
@ -655,7 +660,7 @@ func (c *STS) DecodeAuthorizationMessageRequest(input *DecodeAuthorizationMessag
// invalid. This can happen if the token contains invalid characters, such as // invalid. This can happen if the token contains invalid characters, such as
// linebreaks. // linebreaks.
// //
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/DecodeAuthorizationMessage // See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/DecodeAuthorizationMessage
func (c *STS) DecodeAuthorizationMessage(input *DecodeAuthorizationMessageInput) (*DecodeAuthorizationMessageOutput, error) { func (c *STS) DecodeAuthorizationMessage(input *DecodeAuthorizationMessageInput) (*DecodeAuthorizationMessageOutput, error) {
req, out := c.DecodeAuthorizationMessageRequest(input) req, out := c.DecodeAuthorizationMessageRequest(input)
return out, req.Send() return out, req.Send()
@ -702,7 +707,7 @@ const opGetCallerIdentity = "GetCallerIdentity"
// fmt.Println(resp) // fmt.Println(resp)
// } // }
// //
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetCallerIdentity // See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetCallerIdentity
func (c *STS) GetCallerIdentityRequest(input *GetCallerIdentityInput) (req *request.Request, output *GetCallerIdentityOutput) { func (c *STS) GetCallerIdentityRequest(input *GetCallerIdentityInput) (req *request.Request, output *GetCallerIdentityOutput) {
op := &request.Operation{ op := &request.Operation{
Name: opGetCallerIdentity, Name: opGetCallerIdentity,
@ -730,7 +735,7 @@ func (c *STS) GetCallerIdentityRequest(input *GetCallerIdentityInput) (req *requ
// //
// See the AWS API reference guide for AWS Security Token Service's // See the AWS API reference guide for AWS Security Token Service's
// API operation GetCallerIdentity for usage and error information. // API operation GetCallerIdentity for usage and error information.
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetCallerIdentity // See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetCallerIdentity
func (c *STS) GetCallerIdentity(input *GetCallerIdentityInput) (*GetCallerIdentityOutput, error) { func (c *STS) GetCallerIdentity(input *GetCallerIdentityInput) (*GetCallerIdentityOutput, error) {
req, out := c.GetCallerIdentityRequest(input) req, out := c.GetCallerIdentityRequest(input)
return out, req.Send() return out, req.Send()
@ -777,7 +782,7 @@ const opGetFederationToken = "GetFederationToken"
// fmt.Println(resp) // fmt.Println(resp)
// } // }
// //
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetFederationToken // See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetFederationToken
func (c *STS) GetFederationTokenRequest(input *GetFederationTokenInput) (req *request.Request, output *GetFederationTokenOutput) { func (c *STS) GetFederationTokenRequest(input *GetFederationTokenInput) (req *request.Request, output *GetFederationTokenOutput) {
op := &request.Operation{ op := &request.Operation{
Name: opGetFederationToken, Name: opGetFederationToken,
@ -899,7 +904,7 @@ func (c *STS) GetFederationTokenRequest(input *GetFederationTokenInput) (req *re
// and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) // and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
// in the IAM User Guide. // in the IAM User Guide.
// //
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetFederationToken // See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetFederationToken
func (c *STS) GetFederationToken(input *GetFederationTokenInput) (*GetFederationTokenOutput, error) { func (c *STS) GetFederationToken(input *GetFederationTokenInput) (*GetFederationTokenOutput, error) {
req, out := c.GetFederationTokenRequest(input) req, out := c.GetFederationTokenRequest(input)
return out, req.Send() return out, req.Send()
@ -946,7 +951,7 @@ const opGetSessionToken = "GetSessionToken"
// fmt.Println(resp) // fmt.Println(resp)
// } // }
// //
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetSessionToken // See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetSessionToken
func (c *STS) GetSessionTokenRequest(input *GetSessionTokenInput) (req *request.Request, output *GetSessionTokenOutput) { func (c *STS) GetSessionTokenRequest(input *GetSessionTokenInput) (req *request.Request, output *GetSessionTokenOutput) {
op := &request.Operation{ op := &request.Operation{
Name: opGetSessionToken, Name: opGetSessionToken,
@ -1027,7 +1032,7 @@ func (c *STS) GetSessionTokenRequest(input *GetSessionTokenInput) (req *request.
// and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) // and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
// in the IAM User Guide. // in the IAM User Guide.
// //
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetSessionToken // See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetSessionToken
func (c *STS) GetSessionToken(input *GetSessionTokenInput) (*GetSessionTokenOutput, error) { func (c *STS) GetSessionToken(input *GetSessionTokenInput) (*GetSessionTokenOutput, error) {
req, out := c.GetSessionTokenRequest(input) req, out := c.GetSessionTokenRequest(input)
return out, req.Send() return out, req.Send()
@ -1049,7 +1054,6 @@ func (c *STS) GetSessionTokenWithContext(ctx aws.Context, input *GetSessionToken
return out, req.Send() return out, req.Send()
} }
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleRequest
type AssumeRoleInput struct { type AssumeRoleInput struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
@ -1241,7 +1245,6 @@ func (s *AssumeRoleInput) SetTokenCode(v string) *AssumeRoleInput {
// Contains the response to a successful AssumeRole request, including temporary // Contains the response to a successful AssumeRole request, including temporary
// AWS credentials that can be used to make AWS requests. // AWS credentials that can be used to make AWS requests.
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleResponse
type AssumeRoleOutput struct { type AssumeRoleOutput struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
@ -1295,7 +1298,6 @@ func (s *AssumeRoleOutput) SetPackedPolicySize(v int64) *AssumeRoleOutput {
return s return s
} }
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithSAMLRequest
type AssumeRoleWithSAMLInput struct { type AssumeRoleWithSAMLInput struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
@ -1436,7 +1438,6 @@ func (s *AssumeRoleWithSAMLInput) SetSAMLAssertion(v string) *AssumeRoleWithSAML
// Contains the response to a successful AssumeRoleWithSAML request, including // Contains the response to a successful AssumeRoleWithSAML request, including
// temporary AWS credentials that can be used to make AWS requests. // temporary AWS credentials that can be used to make AWS requests.
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithSAMLResponse
type AssumeRoleWithSAMLOutput struct { type AssumeRoleWithSAMLOutput struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
@ -1548,7 +1549,6 @@ func (s *AssumeRoleWithSAMLOutput) SetSubjectType(v string) *AssumeRoleWithSAMLO
return s return s
} }
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithWebIdentityRequest
type AssumeRoleWithWebIdentityInput struct { type AssumeRoleWithWebIdentityInput struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
@ -1711,7 +1711,6 @@ func (s *AssumeRoleWithWebIdentityInput) SetWebIdentityToken(v string) *AssumeRo
// Contains the response to a successful AssumeRoleWithWebIdentity request, // Contains the response to a successful AssumeRoleWithWebIdentity request,
// including temporary AWS credentials that can be used to make AWS requests. // including temporary AWS credentials that can be used to make AWS requests.
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithWebIdentityResponse
type AssumeRoleWithWebIdentityOutput struct { type AssumeRoleWithWebIdentityOutput struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
@ -1804,7 +1803,6 @@ func (s *AssumeRoleWithWebIdentityOutput) SetSubjectFromWebIdentityToken(v strin
// The identifiers for the temporary security credentials that the operation // The identifiers for the temporary security credentials that the operation
// returns. // returns.
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumedRoleUser
type AssumedRoleUser struct { type AssumedRoleUser struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
@ -1847,7 +1845,6 @@ func (s *AssumedRoleUser) SetAssumedRoleId(v string) *AssumedRoleUser {
} }
// AWS credentials for API authentication. // AWS credentials for API authentication.
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/Credentials
type Credentials struct { type Credentials struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
@ -1906,7 +1903,6 @@ func (s *Credentials) SetSessionToken(v string) *Credentials {
return s return s
} }
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/DecodeAuthorizationMessageRequest
type DecodeAuthorizationMessageInput struct { type DecodeAuthorizationMessageInput struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
@ -1951,7 +1947,6 @@ func (s *DecodeAuthorizationMessageInput) SetEncodedMessage(v string) *DecodeAut
// A document that contains additional information about the authorization status // A document that contains additional information about the authorization status
// of a request from an encoded message that is returned in response to an AWS // of a request from an encoded message that is returned in response to an AWS
// request. // request.
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/DecodeAuthorizationMessageResponse
type DecodeAuthorizationMessageOutput struct { type DecodeAuthorizationMessageOutput struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
@ -1976,7 +1971,6 @@ func (s *DecodeAuthorizationMessageOutput) SetDecodedMessage(v string) *DecodeAu
} }
// Identifiers for the federated user that is associated with the credentials. // Identifiers for the federated user that is associated with the credentials.
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/FederatedUser
type FederatedUser struct { type FederatedUser struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
@ -2017,7 +2011,6 @@ func (s *FederatedUser) SetFederatedUserId(v string) *FederatedUser {
return s return s
} }
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetCallerIdentityRequest
type GetCallerIdentityInput struct { type GetCallerIdentityInput struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
} }
@ -2034,7 +2027,6 @@ func (s GetCallerIdentityInput) GoString() string {
// Contains the response to a successful GetCallerIdentity request, including // Contains the response to a successful GetCallerIdentity request, including
// information about the entity making the request. // information about the entity making the request.
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetCallerIdentityResponse
type GetCallerIdentityOutput struct { type GetCallerIdentityOutput struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
@ -2080,7 +2072,6 @@ func (s *GetCallerIdentityOutput) SetUserId(v string) *GetCallerIdentityOutput {
return s return s
} }
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetFederationTokenRequest
type GetFederationTokenInput struct { type GetFederationTokenInput struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
@ -2189,7 +2180,6 @@ func (s *GetFederationTokenInput) SetPolicy(v string) *GetFederationTokenInput {
// Contains the response to a successful GetFederationToken request, including // Contains the response to a successful GetFederationToken request, including
// temporary AWS credentials that can be used to make AWS requests. // temporary AWS credentials that can be used to make AWS requests.
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetFederationTokenResponse
type GetFederationTokenOutput struct { type GetFederationTokenOutput struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
@ -2242,7 +2232,6 @@ func (s *GetFederationTokenOutput) SetPackedPolicySize(v int64) *GetFederationTo
return s return s
} }
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetSessionTokenRequest
type GetSessionTokenInput struct { type GetSessionTokenInput struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
@ -2327,7 +2316,6 @@ func (s *GetSessionTokenInput) SetTokenCode(v string) *GetSessionTokenInput {
// Contains the response to a successful GetSessionToken request, including // Contains the response to a successful GetSessionToken request, including
// temporary AWS credentials that can be used to make AWS requests. // temporary AWS credentials that can be used to make AWS requests.
// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetSessionTokenResponse
type GetSessionTokenOutput struct { type GetSessionTokenOutput struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`

View File

@ -56,7 +56,7 @@
// //
// Using the Client // Using the Client
// //
// To AWS Security Token Service with the SDK use the New function to create // To contact AWS Security Token Service with the SDK use the New function to create
// a new service client. With that client you can make API requests to the service. // a new service client. With that client you can make API requests to the service.
// These clients are safe to use concurrently. // These clients are safe to use concurrently.
// //

View File

@ -35,7 +35,7 @@ buildfuzz:
go-fuzz-build github.com/jmespath/go-jmespath/fuzz go-fuzz-build github.com/jmespath/go-jmespath/fuzz
fuzz: buildfuzz fuzz: buildfuzz
go-fuzz -bin=./jmespath-fuzz.zip -workdir=fuzz/corpus go-fuzz -bin=./jmespath-fuzz.zip -workdir=fuzz/testdata
bench: bench:
go test -bench . -cpuprofile cpu.out go test -bench . -cpuprofile cpu.out

View File

@ -1,5 +1,42 @@
package jmespath package jmespath
import "strconv"
// JmesPath is the epresentation of a compiled JMES path query. A JmesPath is
// safe for concurrent use by multiple goroutines.
type JMESPath struct {
ast ASTNode
intr *treeInterpreter
}
// Compile parses a JMESPath expression and returns, if successful, a JMESPath
// object that can be used to match against data.
func Compile(expression string) (*JMESPath, error) {
parser := NewParser()
ast, err := parser.Parse(expression)
if err != nil {
return nil, err
}
jmespath := &JMESPath{ast: ast, intr: newInterpreter()}
return jmespath, nil
}
// MustCompile is like Compile but panics if the expression cannot be parsed.
// It simplifies safe initialization of global variables holding compiled
// JMESPaths.
func MustCompile(expression string) *JMESPath {
jmespath, err := Compile(expression)
if err != nil {
panic(`jmespath: Compile(` + strconv.Quote(expression) + `): ` + err.Error())
}
return jmespath
}
// Search evaluates a JMESPath expression against input data and returns the result.
func (jp *JMESPath) Search(data interface{}) (interface{}, error) {
return jp.intr.Execute(jp.ast, data)
}
// Search evaluates a JMESPath expression against input data and returns the result. // Search evaluates a JMESPath expression against input data and returns the result.
func Search(expression string, data interface{}) (interface{}, error) { func Search(expression string, data interface{}) (interface{}, error) {
intr := newInterpreter() intr := newInterpreter()

View File

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"math" "math"
"reflect"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
@ -124,197 +125,197 @@ type functionCaller struct {
func newFunctionCaller() *functionCaller { func newFunctionCaller() *functionCaller {
caller := &functionCaller{} caller := &functionCaller{}
caller.functionTable = map[string]functionEntry{ caller.functionTable = map[string]functionEntry{
"length": functionEntry{ "length": {
name: "length", name: "length",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpString, jpArray, jpObject}}, {types: []jpType{jpString, jpArray, jpObject}},
}, },
handler: jpfLength, handler: jpfLength,
}, },
"starts_with": functionEntry{ "starts_with": {
name: "starts_with", name: "starts_with",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpString}}, {types: []jpType{jpString}},
argSpec{types: []jpType{jpString}}, {types: []jpType{jpString}},
}, },
handler: jpfStartsWith, handler: jpfStartsWith,
}, },
"abs": functionEntry{ "abs": {
name: "abs", name: "abs",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpNumber}}, {types: []jpType{jpNumber}},
}, },
handler: jpfAbs, handler: jpfAbs,
}, },
"avg": functionEntry{ "avg": {
name: "avg", name: "avg",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpArrayNumber}}, {types: []jpType{jpArrayNumber}},
}, },
handler: jpfAvg, handler: jpfAvg,
}, },
"ceil": functionEntry{ "ceil": {
name: "ceil", name: "ceil",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpNumber}}, {types: []jpType{jpNumber}},
}, },
handler: jpfCeil, handler: jpfCeil,
}, },
"contains": functionEntry{ "contains": {
name: "contains", name: "contains",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpArray, jpString}}, {types: []jpType{jpArray, jpString}},
argSpec{types: []jpType{jpAny}}, {types: []jpType{jpAny}},
}, },
handler: jpfContains, handler: jpfContains,
}, },
"ends_with": functionEntry{ "ends_with": {
name: "ends_with", name: "ends_with",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpString}}, {types: []jpType{jpString}},
argSpec{types: []jpType{jpString}}, {types: []jpType{jpString}},
}, },
handler: jpfEndsWith, handler: jpfEndsWith,
}, },
"floor": functionEntry{ "floor": {
name: "floor", name: "floor",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpNumber}}, {types: []jpType{jpNumber}},
}, },
handler: jpfFloor, handler: jpfFloor,
}, },
"map": functionEntry{ "map": {
name: "amp", name: "amp",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpExpref}}, {types: []jpType{jpExpref}},
argSpec{types: []jpType{jpArray}}, {types: []jpType{jpArray}},
}, },
handler: jpfMap, handler: jpfMap,
hasExpRef: true, hasExpRef: true,
}, },
"max": functionEntry{ "max": {
name: "max", name: "max",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpArrayNumber, jpArrayString}}, {types: []jpType{jpArrayNumber, jpArrayString}},
}, },
handler: jpfMax, handler: jpfMax,
}, },
"merge": functionEntry{ "merge": {
name: "merge", name: "merge",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpObject}, variadic: true}, {types: []jpType{jpObject}, variadic: true},
}, },
handler: jpfMerge, handler: jpfMerge,
}, },
"max_by": functionEntry{ "max_by": {
name: "max_by", name: "max_by",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpArray}}, {types: []jpType{jpArray}},
argSpec{types: []jpType{jpExpref}}, {types: []jpType{jpExpref}},
}, },
handler: jpfMaxBy, handler: jpfMaxBy,
hasExpRef: true, hasExpRef: true,
}, },
"sum": functionEntry{ "sum": {
name: "sum", name: "sum",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpArrayNumber}}, {types: []jpType{jpArrayNumber}},
}, },
handler: jpfSum, handler: jpfSum,
}, },
"min": functionEntry{ "min": {
name: "min", name: "min",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpArrayNumber, jpArrayString}}, {types: []jpType{jpArrayNumber, jpArrayString}},
}, },
handler: jpfMin, handler: jpfMin,
}, },
"min_by": functionEntry{ "min_by": {
name: "min_by", name: "min_by",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpArray}}, {types: []jpType{jpArray}},
argSpec{types: []jpType{jpExpref}}, {types: []jpType{jpExpref}},
}, },
handler: jpfMinBy, handler: jpfMinBy,
hasExpRef: true, hasExpRef: true,
}, },
"type": functionEntry{ "type": {
name: "type", name: "type",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpAny}}, {types: []jpType{jpAny}},
}, },
handler: jpfType, handler: jpfType,
}, },
"keys": functionEntry{ "keys": {
name: "keys", name: "keys",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpObject}}, {types: []jpType{jpObject}},
}, },
handler: jpfKeys, handler: jpfKeys,
}, },
"values": functionEntry{ "values": {
name: "values", name: "values",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpObject}}, {types: []jpType{jpObject}},
}, },
handler: jpfValues, handler: jpfValues,
}, },
"sort": functionEntry{ "sort": {
name: "sort", name: "sort",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpArrayString, jpArrayNumber}}, {types: []jpType{jpArrayString, jpArrayNumber}},
}, },
handler: jpfSort, handler: jpfSort,
}, },
"sort_by": functionEntry{ "sort_by": {
name: "sort_by", name: "sort_by",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpArray}}, {types: []jpType{jpArray}},
argSpec{types: []jpType{jpExpref}}, {types: []jpType{jpExpref}},
}, },
handler: jpfSortBy, handler: jpfSortBy,
hasExpRef: true, hasExpRef: true,
}, },
"join": functionEntry{ "join": {
name: "join", name: "join",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpString}}, {types: []jpType{jpString}},
argSpec{types: []jpType{jpArrayString}}, {types: []jpType{jpArrayString}},
}, },
handler: jpfJoin, handler: jpfJoin,
}, },
"reverse": functionEntry{ "reverse": {
name: "reverse", name: "reverse",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpArray, jpString}}, {types: []jpType{jpArray, jpString}},
}, },
handler: jpfReverse, handler: jpfReverse,
}, },
"to_array": functionEntry{ "to_array": {
name: "to_array", name: "to_array",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpAny}}, {types: []jpType{jpAny}},
}, },
handler: jpfToArray, handler: jpfToArray,
}, },
"to_string": functionEntry{ "to_string": {
name: "to_string", name: "to_string",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpAny}}, {types: []jpType{jpAny}},
}, },
handler: jpfToString, handler: jpfToString,
}, },
"to_number": functionEntry{ "to_number": {
name: "to_number", name: "to_number",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpAny}}, {types: []jpType{jpAny}},
}, },
handler: jpfToNumber, handler: jpfToNumber,
}, },
"not_null": functionEntry{ "not_null": {
name: "not_null", name: "not_null",
arguments: []argSpec{ arguments: []argSpec{
argSpec{types: []jpType{jpAny}, variadic: true}, {types: []jpType{jpAny}, variadic: true},
}, },
handler: jpfNotNull, handler: jpfNotNull,
}, },
@ -357,7 +358,7 @@ func (a *argSpec) typeCheck(arg interface{}) error {
return nil return nil
} }
case jpArray: case jpArray:
if _, ok := arg.([]interface{}); ok { if isSliceType(arg) {
return nil return nil
} }
case jpObject: case jpObject:
@ -409,8 +410,9 @@ func jpfLength(arguments []interface{}) (interface{}, error) {
arg := arguments[0] arg := arguments[0]
if c, ok := arg.(string); ok { if c, ok := arg.(string); ok {
return float64(utf8.RuneCountInString(c)), nil return float64(utf8.RuneCountInString(c)), nil
} else if c, ok := arg.([]interface{}); ok { } else if isSliceType(arg) {
return float64(len(c)), nil v := reflect.ValueOf(arg)
return float64(v.Len()), nil
} else if c, ok := arg.(map[string]interface{}); ok { } else if c, ok := arg.(map[string]interface{}); ok {
return float64(len(c)), nil return float64(len(c)), nil
} }

View File

@ -353,7 +353,7 @@ func (p *Parser) nud(token token) (ASTNode, error) {
case tFlatten: case tFlatten:
left := ASTNode{ left := ASTNode{
nodeType: ASTFlatten, nodeType: ASTFlatten,
children: []ASTNode{ASTNode{nodeType: ASTIdentity}}, children: []ASTNode{{nodeType: ASTIdentity}},
} }
right, err := p.parseProjectionRHS(bindingPowers[tFlatten]) right, err := p.parseProjectionRHS(bindingPowers[tFlatten])
if err != nil { if err != nil {
@ -378,7 +378,7 @@ func (p *Parser) nud(token token) (ASTNode, error) {
} }
return ASTNode{ return ASTNode{
nodeType: ASTProjection, nodeType: ASTProjection,
children: []ASTNode{ASTNode{nodeType: ASTIdentity}, right}, children: []ASTNode{{nodeType: ASTIdentity}, right},
}, nil }, nil
} else { } else {
return p.parseMultiSelectList() return p.parseMultiSelectList()