update AWS SDK to 1.13.12, remove unused Azure package
Signed-off-by: Steve Kriss <steve@heptio.com>pull/341/head
parent
a05ae1a7cf
commit
0dddfc3e0f
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
54
vendor/github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions/client.go
generated
vendored
54
vendor/github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions/client.go
generated
vendored
|
@ -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,
|
|
||||||
}
|
|
||||||
}
|
|
132
vendor/github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions/models.go
generated
vendored
132
vendor/github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions/models.go
generated
vendored
|
@ -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)))
|
|
||||||
}
|
|
252
vendor/github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions/subscriptionsgroup.go
generated
vendored
252
vendor/github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions/subscriptionsgroup.go
generated
vendored
|
@ -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
|
|
||||||
}
|
|
124
vendor/github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions/tenants.go
generated
vendored
124
vendor/github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions/tenants.go
generated
vendored
|
@ -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
|
|
||||||
}
|
|
28
vendor/github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions/version.go
generated
vendored
28
vendor/github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions/version.go
generated
vendored
|
@ -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
|
@ -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.
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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"
|
|
@ -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" .
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
},
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
|
@ -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
|
||||||
|
)
|
29
vendor/github.com/aws/aws-sdk-go/internal/sdkrand/locked_source.go
generated
vendored
Normal file
29
vendor/github.com/aws/aws-sdk-go/internal/sdkrand/locked_source.go
generated
vendored
Normal 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())})
|
|
@ -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()))
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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()))
|
||||||
|
|
|
@ -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 == "" {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
//
|
//
|
||||||
|
|
|
@ -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
|
@ -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()
|
||||||
|
}
|
|
@ -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))
|
|
||||||
}
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
//
|
//
|
||||||
|
|
|
@ -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)
|
||||||
//
|
//
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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"`
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
//
|
//
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue