diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 5041d0473..7f0c41785 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -15,58 +15,58 @@ }, { "ImportPath": "github.com/aws/aws-sdk-go/aws", - "Comment": "v0.9.15", - "Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d" + "Comment": "v0.9.16-1-g66c840e", + "Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781" }, { "ImportPath": "github.com/aws/aws-sdk-go/internal/endpoints", - "Comment": "v0.9.15", - "Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d" + "Comment": "v0.9.16-1-g66c840e", + "Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781" }, { "ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/ec2query", - "Comment": "v0.9.15", - "Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d" + "Comment": "v0.9.16-1-g66c840e", + "Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781" }, { "ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/query", - "Comment": "v0.9.15", - "Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d" + "Comment": "v0.9.16-1-g66c840e", + "Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781" }, { "ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/rest", - "Comment": "v0.9.15", - "Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d" + "Comment": "v0.9.16-1-g66c840e", + "Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781" }, { "ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/restxml", - "Comment": "v0.9.15", - "Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d" + "Comment": "v0.9.16-1-g66c840e", + "Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781" }, { "ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil", - "Comment": "v0.9.15", - "Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d" + "Comment": "v0.9.16-1-g66c840e", + "Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781" }, { "ImportPath": "github.com/aws/aws-sdk-go/internal/signer/v4", - "Comment": "v0.9.15", - "Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d" + "Comment": "v0.9.16-1-g66c840e", + "Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781" }, { "ImportPath": "github.com/aws/aws-sdk-go/service/ec2", - "Comment": "v0.9.15", - "Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d" + "Comment": "v0.9.16-1-g66c840e", + "Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781" }, { "ImportPath": "github.com/aws/aws-sdk-go/service/iam", - "Comment": "v0.9.15", - "Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d" + "Comment": "v0.9.16-1-g66c840e", + "Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781" }, { "ImportPath": "github.com/aws/aws-sdk-go/service/s3", - "Comment": "v0.9.15", - "Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d" + "Comment": "v0.9.16-1-g66c840e", + "Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781" }, { "ImportPath": "github.com/coreos/go-etcd/etcd", @@ -93,8 +93,8 @@ }, { "ImportPath": "github.com/gocql/gocql", - "Comment": "1st_gen_framing-282-g6e86253", - "Rev": "6e86253e1c7c91bcdcfe3afd6417d3ddfbe5771c" + "Comment": "1st_gen_framing-323-g8041a37", + "Rev": "8041a37b40f2ca115d6c2902b279250eb627d7af" }, { "ImportPath": "github.com/golang/snappy", @@ -102,7 +102,7 @@ }, { "ImportPath": "github.com/google/go-github/github", - "Rev": "9420d0f48acb838ccf8a7f8dde9eaee19af71132" + "Rev": "84fc80440d3bb3a82d297b827308ce11dcf047eb" }, { "ImportPath": "github.com/google/go-querystring/query", @@ -110,13 +110,17 @@ }, { "ImportPath": "github.com/hashicorp/consul/api", - "Comment": "v0.5.2-334-gd6af59c", - "Rev": "d6af59cdedcc01e71bccf90061decbb724425fe5" + "Comment": "v0.5.2-469-g6a350d5", + "Rev": "6a350d5d19a41f94e0c99a933410e8545c4e7a51" }, { "ImportPath": "github.com/hashicorp/errwrap", "Rev": "7554cd9344cec97297fa6649b055a8c98c2a1e55" }, + { + "ImportPath": "github.com/hashicorp/go-cleanhttp", + "Rev": "5df5ddc69534f1a4697289f1dca2193fbb40213f" + }, { "ImportPath": "github.com/hashicorp/go-multierror", "Rev": "d30f09973e19c1dfcd120b2d9c4f168e68d6b5d5" @@ -147,8 +151,8 @@ }, { "ImportPath": "github.com/lib/pq", - "Comment": "go1.0-cutoff-60-gffe986a", - "Rev": "ffe986aba3e6cfcded8b06615965941408891ef0" + "Comment": "go1.0-cutoff-61-g83c4f41", + "Rev": "83c4f410d0aed80a0f44bac6a576a7f2435791f3" }, { "ImportPath": "github.com/mitchellh/cli", @@ -213,11 +217,11 @@ }, { "ImportPath": "golang.org/x/net/context", - "Rev": "21c3935a8fc0f954d03e6b8a560c9600ffee38d2" + "Rev": "2cba614e8ff920c60240d2677bc019af32ee04e5" }, { "ImportPath": "golang.org/x/oauth2", - "Rev": "ef4eca6b097fad7cec79afcc278d213a6de1c960" + "Rev": "038cb4adce85ed41e285c2e7cc6221a92bfa44aa" }, { "ImportPath": "gopkg.in/asn1-ber.v1", diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config.go index a72f70222..cd2aade28 100644 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config.go +++ b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config.go @@ -7,8 +7,8 @@ import ( "github.com/aws/aws-sdk-go/aws/credentials" ) -// The default number of retries for a service. The value of -1 indicates that -// the service specific retry default will be used. +// DefaultRetries is the default number of retries for a service. The value of +// -1 indicates that the service specific retry default will be used. const DefaultRetries = -1 // A Config provides service configuration for service clients. By default, diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go index 2fcb391a2..597feb4fa 100644 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go +++ b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go @@ -20,7 +20,7 @@ type lener interface { Len() int } -// BuildContentLength builds the content length of a request based on the body, +// BuildContentLengthHandler builds the content length of a request based on the body, // or will use the HTTPRequest.Header's "Content-Length" if defined. If unable // to determine request body length and no "Content-Length" was specified it will panic. var BuildContentLengthHandler = request.NamedHandler{"core.BuildContentLengthHandler", func(r *request.Request) { diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go index a22197734..c70d422df 100644 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go +++ b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go @@ -10,7 +10,7 @@ import ( "github.com/aws/aws-sdk-go/aws/request" ) -// ValidateParameters is a request handler to validate the input parameters. +// ValidateParametersHandler is a request handler to validate the input parameters. // Validating parameters only has meaning if done prior to the request being sent. var ValidateParametersHandler = request.NamedHandler{"core.ValidateParametersHandler", func(r *request.Request) { if r.ParamsFilled() { diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/credentials.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/credentials.go index 2834a088a..5dd71f02e 100644 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/credentials.go +++ b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/credentials.go @@ -53,8 +53,8 @@ import ( "time" ) -// Create an empty Credential object that can be used as dummy placeholder -// credentials for requests that do not need signed. +// AnonymousCredentials is an empty Credential object that can be used as +// dummy placeholder credentials for requests that do not need signed. // // This Credentials can be used to configure a service to not sign requests // when making service API calls. For example, when accessing public diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/version.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/version.go index a1247d110..b7de9e351 100644 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/version.go +++ b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/version.go @@ -5,4 +5,4 @@ package aws const SDKName = "aws-sdk-go" // SDKVersion is the version of this SDK -const SDKVersion = "0.9.15" +const SDKVersion = "0.9.16" diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/iam/api.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/iam/api.go index f46bfb4cd..354aecdc3 100644 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/iam/api.go +++ b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/iam/api.go @@ -3572,23 +3572,23 @@ func (c *IAM) SimulateCustomPolicyRequest(input *SimulateCustomPolicyInput) (req return } -// Simulate a set of IAM policies against a list of API actions and AWS resources -// to determine the policies' effective permissions. The policies are provided -// as a list of strings. +// Simulate how a set of IAM policies and optionally a resource-based policy +// works with a list of API actions and AWS resources to determine the policies' +// effective permissions. The policies are provided as strings. // -// The simulation does not perform the API actions, it only checks the authorization +// The simulation does not perform the API actions; it only checks the authorization // to determine if the simulated policies allow or deny the actions. // // If you want to simulate existing policies attached to an IAM user, group, // or role, use SimulatePrincipalPolicy instead. // // Context keys are variables maintained by AWS and its services that provide -// details about the context of an API query request, and can be evaluated by -// using the Condition element of an IAM policy. To get the list of context -// keys required by the policies to simulate them correctly, use GetContextKeysForCustomPolicy. +// details about the context of an API query request. You can use the Condition +// element of an IAM policy to evaluate context keys. To get the list of context +// keys that the policies require for correct simulation, use GetContextKeysForCustomPolicy. // -// If the output is long, you can paginate the results using the MaxItems and -// Marker parameters. +// If the output is long, you can use MaxItems and Marker parameters to paginate +// the results. func (c *IAM) SimulateCustomPolicy(input *SimulateCustomPolicyInput) (*SimulatePolicyResponse, error) { req, out := c.SimulateCustomPolicyRequest(input) err := req.Send() @@ -3615,16 +3615,19 @@ func (c *IAM) SimulatePrincipalPolicyRequest(input *SimulatePrincipalPolicyInput return } -// Simulate the set of IAM policies attached to an IAM entity against a list -// of API actions and AWS resources to determine the policies' effective permissions. -// The entity can be an IAM user, group, or role. If you specify a user, then -// the simulation also includes all of the policies attached to groups that -// the user is a member of. +// Simulate how a set of IAM policies attached to an IAM entity works with a +// list of API actions and AWS resources to determine the policies' effective +// permissions. The entity can be an IAM user, group, or role. If you specify +// a user, then the simulation also includes all of the policies that are attached +// to groups that the user belongs to . // // You can optionally include a list of one or more additional policies specified // as strings to include in the simulation. If you want to simulate only policies // specified as strings, use SimulateCustomPolicy instead. // +// You can also optionally include one resource-based policy to be evaluated +// with each of the resources included in the simulation. +// // The simulation does not perform the API actions, it only checks the authorization // to determine if the simulated policies allow or deny the actions. // @@ -3633,12 +3636,12 @@ func (c *IAM) SimulatePrincipalPolicyRequest(input *SimulatePrincipalPolicyInput // allowing them to use SimulateCustomPolicy instead. // // Context keys are variables maintained by AWS and its services that provide -// details about the context of an API query request, and can be evaluated by -// using the Condition element of an IAM policy. To get the list of context -// keys required by the policies to simulate them correctly, use GetContextKeysForPrincipalPolicy. +// details about the context of an API query request. You can use the Condition +// element of an IAM policy to evaluate context keys. To get the list of context +// keys that the policies require for correct simulation, use GetContextKeysForPrincipalPolicy. // -// If the output is long, you can paginate the results using the MaxItems and -// Marker parameters. +// If the output is long, you can use the MaxItems and Marker parameters to +// paginate the results. func (c *IAM) SimulatePrincipalPolicy(input *SimulatePrincipalPolicyInput) (*SimulatePolicyResponse, error) { req, out := c.SimulatePrincipalPolicyRequest(input) err := req.Send() @@ -6335,6 +6338,14 @@ type EvaluationResult struct { // The result of the simulation. EvalDecision *string `type:"string" required:"true" enum:"PolicyEvaluationDecisionType"` + // Additional details about the results of the evaluation decision. When there + // are both IAM policies and resource policies, this parameter explains how + // each set of policies contributes to the final evaluation decision. When simulating + // cross-account access to a resource, both the resource-based policy and the + // caller's IAM policy must grant access. See How IAM Roles Differ from Resource-based + // Policies + EvalDecisionDetails map[string]*string `type:"map"` + // The ARN of the resource that the indicated API action was tested on. EvalResourceName *string `min:"1" type:"string" required:"true"` @@ -6471,19 +6482,19 @@ type GetAccountAuthorizationDetailsInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` metadataGetAccountAuthorizationDetailsInput `json:"-" xml:"-"` @@ -6901,19 +6912,19 @@ type GetGroupInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` metadataGetGroupInput `json:"-" xml:"-"` @@ -7757,19 +7768,19 @@ func (s InstanceProfile) GoString() string { type ListAccessKeysInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The name of the user. @@ -7829,19 +7840,19 @@ func (s ListAccessKeysOutput) GoString() string { type ListAccountAliasesInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` metadataListAccountAliasesInput `json:"-" xml:"-"` @@ -7902,19 +7913,19 @@ type ListAttachedGroupPoliciesInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The path prefix for filtering the results. This parameter is optional. If @@ -7975,19 +7986,19 @@ func (s ListAttachedGroupPoliciesOutput) GoString() string { type ListAttachedRolePoliciesInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The path prefix for filtering the results. This parameter is optional. If @@ -8051,19 +8062,19 @@ func (s ListAttachedRolePoliciesOutput) GoString() string { type ListAttachedUserPoliciesInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The path prefix for filtering the results. This parameter is optional. If @@ -8134,19 +8145,19 @@ type ListEntitiesForPolicyInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The path prefix for filtering the results. This parameter is optional. If @@ -8223,19 +8234,19 @@ type ListGroupPoliciesInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` metadataListGroupPoliciesInput `json:"-" xml:"-"` @@ -8292,19 +8303,19 @@ func (s ListGroupPoliciesOutput) GoString() string { type ListGroupsForUserInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The name of the user to list groups for. @@ -8364,19 +8375,19 @@ func (s ListGroupsForUserOutput) GoString() string { type ListGroupsInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The path prefix for filtering the results. For example, the prefix /division_abc/subdivision_xyz/ @@ -8440,19 +8451,19 @@ func (s ListGroupsOutput) GoString() string { type ListInstanceProfilesForRoleInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The name of the role to list instance profiles for. @@ -8512,19 +8523,19 @@ func (s ListInstanceProfilesForRoleOutput) GoString() string { type ListInstanceProfilesInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The path prefix for filtering the results. For example, the prefix /application_abc/component_xyz/ @@ -8588,19 +8599,19 @@ func (s ListInstanceProfilesOutput) GoString() string { type ListMFADevicesInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The name of the user whose MFA devices you want to list. @@ -8700,19 +8711,19 @@ func (s ListOpenIDConnectProvidersOutput) GoString() string { type ListPoliciesInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // A flag to filter the results to only the attached policies. @@ -8789,19 +8800,19 @@ func (s ListPoliciesOutput) GoString() string { type ListPolicyVersionsInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The Amazon Resource Name (ARN). ARNs are unique identifiers for AWS resources. @@ -8869,19 +8880,19 @@ func (s ListPolicyVersionsOutput) GoString() string { type ListRolePoliciesInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The name of the role to list policies for. @@ -8941,19 +8952,19 @@ func (s ListRolePoliciesOutput) GoString() string { type ListRolesInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The path prefix for filtering the results. For example, the prefix /application_abc/component_xyz/ @@ -9057,19 +9068,19 @@ func (s ListSAMLProvidersOutput) GoString() string { type ListSSHPublicKeysInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The name of the IAM user to list SSH public keys for. If none is specified, @@ -9131,19 +9142,19 @@ func (s ListSSHPublicKeysOutput) GoString() string { type ListServerCertificatesInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The path prefix for filtering the results. For example: /company/servercerts @@ -9207,19 +9218,19 @@ func (s ListServerCertificatesOutput) GoString() string { type ListSigningCertificatesInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The name of the user. @@ -9279,19 +9290,19 @@ func (s ListSigningCertificatesOutput) GoString() string { type ListUserPoliciesInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The name of the user to list policies for. @@ -9351,19 +9362,19 @@ func (s ListUserPoliciesOutput) GoString() string { type ListUsersInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // The path prefix for filtering the results. For example: /division_abc/subdivision_xyz/, @@ -9432,19 +9443,19 @@ type ListVirtualMFADevicesInput struct { // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` metadataListVirtualMFADevicesInput `json:"-" xml:"-"` @@ -10693,35 +10704,48 @@ func (s SigningCertificate) GoString() string { type SimulateCustomPolicyInput struct { // A list of names of API actions to evaluate in the simulation. Each action - // is evaluated for each resource. Each action must include the service identifier, - // such as iam:CreateUser. + // is evaluated against each resource. Each action must include the service + // identifier, such as iam:CreateUser. ActionNames []*string `type:"list" required:"true"` - // A list of context keys and corresponding values that are used by the simulation. + // The ARN of the user that you want to use as the simulated caller of the APIs. + // CallerArn is required if you include a ResourcePolicy so that the policy's + // Principal element has a value to use in evaluating the policy. + // + // You can specify only the ARN of an IAM user. You cannot specify the ARN + // of an assumed role, federated user, or a service principal. + CallerArn *string `min:"1" type:"string"` + + // A list of context keys and corresponding values for the simulation to use. // Whenever a context key is evaluated by a Condition element in one of the // simulated IAM permission policies, the corresponding value is supplied. ContextEntries []*ContextEntry `type:"list"` // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // A list of policy documents to include in the simulation. Each document is // specified as a string containing the complete, valid JSON text of an IAM - // policy. + // policy. Do not include any resource-based policies in this parameter. Any + // resource-based policy must be submitted with the ResourcePolicy parameter. + // The policies cannot be "scope-down" policies, such as you could include in + // a call to GetFederationToken (http://docs.aws.amazon.com/IAM/latest/APIReference/API_GetFederationToken.html) + // or one of the AssumeRole (http://docs.aws.amazon.com/IAM/latest/APIReference/API_AssumeRole.html) + // APIs to restrict what a user can do while using the temporary credentials. PolicyInputList []*string `type:"list" required:"true"` // A list of ARNs of AWS resources to include in the simulation. If this parameter @@ -10729,8 +10753,31 @@ type SimulateCustomPolicyInput struct { // the ActionNames parameter is evaluated for each resource in this list. The // simulation determines the access result (allowed or denied) of each combination // and reports it in the response. + // + // The simulation does not automatically retrieve policies for the specified + // resources. If you want to include a resource policy in the simulation, then + // you must include the policy as a string in the ResourcePolicy parameter. + // + // If you include a ResourcePolicy, then it must be applicable to all of the + // resources included in the simulation or you receive an invalid input error. ResourceArns []*string `type:"list"` + // An AWS account ID that specifies the owner of any simulated resource that + // does not identify its owner in the resource ARN, such as an S3 bucket or + // object. If ResourceOwner is specified, it is also used as the account owner + // of any ResourcePolicy included in the simulation. If the ResourceOwner parameter + // is not specified, then the owner of the resources and the resource policy + // defaults to the account of the identity provided in CallerArn. This parameter + // is required only if you specify a resource-based policy and account that + // owns the resource is different from the account that owns the simulated calling + // user CallerArn. + ResourceOwner *string `min:"1" type:"string"` + + // A resource-based policy to include in the simulation provided as a string. + // Each resource in the simulation is treated as if it had this policy attached. + // You can include only one resource-based policy in a simulation. + ResourcePolicy *string `min:"1" type:"string"` + metadataSimulateCustomPolicyInput `json:"-" xml:"-"` } @@ -10789,26 +10836,41 @@ type SimulatePrincipalPolicyInput struct { // such as iam:CreateUser. ActionNames []*string `type:"list" required:"true"` - // A list of context keys and corresponding values that are used by the simulation. + // The ARN of the user that you want to specify as the simulated caller of the + // APIs. If you do not specify a CallerArn, it defaults to the ARN of the user + // that you specify in PolicySourceArn, if you specified a user. If you include + // both a PolicySourceArn (for example, arn:aws:iam::123456789012:user/David) + // and a CallerArn (for example, arn:aws:iam::123456789012:user/Bob), the result + // is that you simulate calling the APIs as Bob, as if Bob had David's policies. + // + // You can specify only the ARN of an IAM user. You cannot specify the ARN + // of an assumed role, federated user, or a service principal. + // + // CallerArn is required if you include a ResourcePolicy and the PolicySourceArn + // is not the ARN for an IAM user. This is required so that the resource-based + // policy's Principal element has a value to use in evaluating the policy. + CallerArn *string `min:"1" type:"string"` + + // A list of context keys and corresponding values for the simulation to use. // Whenever a context key is evaluated by a Condition element in one of the - // simulated IAM permission policies, the corresponding value is supplied. + // simulated policies, the corresponding value is supplied. ContextEntries []*ContextEntry `type:"list"` // Use this parameter only when paginating results and only after you receive // a response indicating that the results are truncated. Set it to the value - // of the Marker element in the response you received to inform the next call - // about where to start. + // of the Marker element in the response that you received to indicate where + // the next call should start. Marker *string `min:"1" type:"string"` // Use this only when paginating results to indicate the maximum number of items - // you want in the response. If there are additional items beyond the maximum - // you specify, the IsTruncated response element is true. + // you want in the response. If additional items exist beyond the maximum you + // specify, the IsTruncated response element is true. // // This parameter is optional. If you do not include it, it defaults to 100. // Note that IAM might return fewer results, even when there are more results - // available. If this is the case, the IsTruncated response element returns - // true and Marker contains a value to include in the subsequent call that tells - // the service where to continue from. + // available. In that case, the IsTruncated response element returns true and + // Marker contains a value to include in the subsequent call that tells the + // service where to continue from. MaxItems *int64 `min:"1" type:"integer"` // An optional list of additional policy documents to include in the simulation. @@ -10818,9 +10880,9 @@ type SimulatePrincipalPolicyInput struct { // The Amazon Resource Name (ARN) of a user, group, or role whose policies you // want to include in the simulation. If you specify a user, group, or role, - // the simulation includes all policies associated with that entity. If you - // specify a user, the simulation also includes all policies attached to any - // groups the user is a member of. + // the simulation includes all policies that are associated with that entity. + // If you specify a user, the simulation also includes all policies that are + // attached to any groups the user belongs to. PolicySourceArn *string `min:"20" type:"string" required:"true"` // A list of ARNs of AWS resources to include in the simulation. If this parameter @@ -10828,8 +10890,28 @@ type SimulatePrincipalPolicyInput struct { // the ActionNames parameter is evaluated for each resource in this list. The // simulation determines the access result (allowed or denied) of each combination // and reports it in the response. + // + // The simulation does not automatically retrieve policies for the specified + // resources. If you want to include a resource policy in the simulation, then + // you must include the policy as a string in the ResourcePolicy parameter. ResourceArns []*string `type:"list"` + // An AWS account ID that specifies the owner of any simulated resource that + // does not identify its owner in the resource ARN, such as an S3 bucket or + // object. If ResourceOwner is specified, it is also used as the account owner + // of any ResourcePolicy included in the simulation. If the ResourceOwner parameter + // is not specified, then the owner of the resources and the resource policy + // defaults to the account of the identity provided in CallerArn. This parameter + // is required only if you specify a resource-based policy and account that + // owns the resource is different from the account that owns the simulated calling + // user CallerArn. + ResourceOwner *string `min:"1" type:"string"` + + // A resource-based policy to include in the simulation provided as a string. + // Each resource in the simulation is treated as if it had this policy attached. + // You can include only one resource-based policy in a simulation. + ResourcePolicy *string `min:"1" type:"string"` + metadataSimulatePrincipalPolicyInput `json:"-" xml:"-"` } @@ -11831,6 +11913,8 @@ const ( // @enum PolicySourceType PolicySourceTypeUserManaged = "user-managed" // @enum PolicySourceType + PolicySourceTypeResource = "resource" + // @enum PolicySourceType PolicySourceTypeNone = "none" ) diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/s3/s3manager/download.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/s3/s3manager/download.go index 39825cfe6..e98b00d47 100644 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/s3/s3manager/download.go +++ b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/s3/s3manager/download.go @@ -13,13 +13,16 @@ import ( "github.com/aws/aws-sdk-go/service/s3/s3iface" ) -// The default range of bytes to get at a time when using Download(). +// DefaultDownloadPartSize is the default range of bytes to get at a time when +// using Download(). var DefaultDownloadPartSize int64 = 1024 * 1024 * 5 -// The default number of goroutines to spin up when using Download(). +// DefaultDownloadConcurrency is the default number of goroutines to spin up +// when using Download(). var DefaultDownloadConcurrency = 5 -// The default set of options used when opts is nil in Download(). +// DefaultDownloadOptions is the default set of options used when opts is nil +// in Download(). var DefaultDownloadOptions = &DownloadOptions{ PartSize: DefaultDownloadPartSize, Concurrency: DefaultDownloadConcurrency, diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/s3/s3manager/upload.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/s3/s3manager/upload.go index 95691acfb..3f2158c95 100644 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/s3/s3manager/upload.go +++ b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/s3/s3manager/upload.go @@ -14,19 +14,24 @@ import ( "github.com/aws/aws-sdk-go/service/s3/s3iface" ) -// The maximum allowed number of parts in a multi-part upload on Amazon S3. +// MaxUploadParts is the maximum allowed number of parts in a multi-part upload +// on Amazon S3. var MaxUploadParts = 10000 -// The minimum allowed part size when uploading a part to Amazon S3. +// MinUploadPartSize is the minimum allowed part size when uploading a part to +// Amazon S3. var MinUploadPartSize int64 = 1024 * 1024 * 5 -// The default part size to buffer chunks of a payload into. +// DefaultUploadPartSize is the default part size to buffer chunks of a +// payload into. var DefaultUploadPartSize = MinUploadPartSize -// The default number of goroutines to spin up when using Upload(). +// DefaultUploadConcurrency is the default number of goroutines to spin up when +// using Upload(). var DefaultUploadConcurrency = 5 -// The default set of options used when opts is nil in Upload(). +// DefaultUploadOptions is the default set of options used when opts is nil in +// Upload(). var DefaultUploadOptions = &UploadOptions{ PartSize: DefaultUploadPartSize, Concurrency: DefaultUploadConcurrency, diff --git a/Godeps/_workspace/src/github.com/gocql/gocql/.travis.yml b/Godeps/_workspace/src/github.com/gocql/gocql/.travis.yml index c59308a77..fe9a024e6 100644 --- a/Godeps/_workspace/src/github.com/gocql/gocql/.travis.yml +++ b/Godeps/_workspace/src/github.com/gocql/gocql/.travis.yml @@ -13,10 +13,14 @@ env: global: - GOMAXPROCS=2 matrix: - - CASS=2.0.17 AUTH=false - - CASS=2.1.9 AUTH=false - - CASS=2.1.9 AUTH=true - - CASS=2.2.1 AUTH=false + - CASS=2.0.17 + AUTH=false + - CASS=2.1.11 + AUTH=false + - CASS=2.1.11 + AUTH=true + - CASS=2.2.3 + AUTH=false go: - 1.4 @@ -35,7 +39,7 @@ install: script: - set -e - go test -v -tags unit - - PATH=$PATH:$HOME/.local/bin bash -x integration.sh $CASS $AUTH + - PATH=$PATH:$HOME/.local/bin bash integration.sh $CASS $AUTH - go vet . notifications: diff --git a/Godeps/_workspace/src/github.com/gocql/gocql/AUTHORS b/Godeps/_workspace/src/github.com/gocql/gocql/AUTHORS index 88b57e605..03dc16564 100644 --- a/Godeps/_workspace/src/github.com/gocql/gocql/AUTHORS +++ b/Godeps/_workspace/src/github.com/gocql/gocql/AUTHORS @@ -55,3 +55,4 @@ Adrian Casajus John Weldon Adrien Bustany Andrey Smirnov +Adam Weiner diff --git a/Godeps/_workspace/src/github.com/gocql/gocql/cluster.go b/Godeps/_workspace/src/github.com/gocql/gocql/cluster.go index 817cbeb41..d838ef40f 100644 --- a/Godeps/_workspace/src/github.com/gocql/gocql/cluster.go +++ b/Godeps/_workspace/src/github.com/gocql/gocql/cluster.go @@ -50,6 +50,33 @@ type DiscoveryConfig struct { Sleep time.Duration } +// PoolConfig configures the connection pool used by the driver, it defaults to +// using a round robbin host selection policy and a round robbin connection selection +// policy for each host. +type PoolConfig struct { + // HostSelectionPolicy sets the policy for selecting which host to use for a + // given query (default: RoundRobinHostPolicy()) + HostSelectionPolicy HostSelectionPolicy + + // ConnSelectionPolicy sets the policy factory for selecting a connection to use for + // each host for a query (default: RoundRobinConnPolicy()) + ConnSelectionPolicy func() ConnSelectionPolicy +} + +func (p PoolConfig) buildPool(cfg *ClusterConfig) (*policyConnPool, error) { + hostSelection := p.HostSelectionPolicy + if hostSelection == nil { + hostSelection = RoundRobinHostPolicy() + } + + connSelection := p.ConnSelectionPolicy + if connSelection == nil { + connSelection = RoundRobinConnPolicy() + } + + return newPolicyConnPool(cfg, hostSelection, connSelection) +} + // ClusterConfig is a struct to configure the default cluster implementation // of gocoql. It has a varity of attributes that can be used to modify the // behavior to fit the most common use cases. Applications that requre a @@ -68,7 +95,6 @@ type ClusterConfig struct { Authenticator Authenticator // authenticator (default: nil) RetryPolicy RetryPolicy // Default retry policy to use for queries (default: 0) SocketKeepalive time.Duration // The keepalive period to use, enabled if > 0 (default: 0) - ConnPoolType NewPoolFunc // The function used to create the connection pool for the session (default: NewSimplePool) DiscoverHosts bool // If set, gocql will attempt to automatically discover other members of the Cassandra cluster (default: false) MaxPreparedStmts int // Sets the maximum cache size for prepared statements globally for gocql (default: 1000) MaxRoutingKeyInfo int // Sets the maximum cache size for query info about statements for each session (default: 1000) @@ -77,6 +103,12 @@ type ClusterConfig struct { Discovery DiscoveryConfig SslOpts *SslOptions DefaultTimestamp bool // Sends a client side timestamp for all requests which overrides the timestamp at which it arrives at the server. (default: true, only enabled for protocol 3 and above) + // PoolConfig configures the underlying connection pool, allowing the + // configuration of host selection and connection selection policies. + PoolConfig PoolConfig + + // internal config for testing + disableControlConn bool } // NewCluster generates a new config for the default cluster implementation. @@ -89,7 +121,6 @@ func NewCluster(hosts ...string) *ClusterConfig { Port: 9042, NumConns: 2, Consistency: Quorum, - ConnPoolType: NewSimplePool, DiscoverHosts: false, MaxPreparedStmts: defaultMaxPreparedStmts, MaxRoutingKeyInfo: 1000, diff --git a/Godeps/_workspace/src/github.com/gocql/gocql/conn.go b/Godeps/_workspace/src/github.com/gocql/gocql/conn.go index bb5edc30f..4ff390c88 100644 --- a/Godeps/_workspace/src/github.com/gocql/gocql/conn.go +++ b/Godeps/_workspace/src/github.com/gocql/gocql/conn.go @@ -99,6 +99,7 @@ type Conn struct { conn net.Conn r *bufio.Reader timeout time.Duration + cfg *ConnConfig headerBuf []byte @@ -121,7 +122,7 @@ type Conn struct { // Connect establishes a connection to a Cassandra node. // You must also call the Serve method before you can execute any queries. -func Connect(addr string, cfg ConnConfig, errorHandler ConnErrorHandler) (*Conn, error) { +func Connect(addr string, cfg *ConnConfig, errorHandler ConnErrorHandler) (*Conn, error) { var ( err error conn net.Conn @@ -166,6 +167,7 @@ func Connect(addr string, cfg ConnConfig, errorHandler ConnErrorHandler) (*Conn, c := &Conn{ conn: conn, r: bufio.NewReader(conn), + cfg: cfg, uniq: make(chan int, cfg.NumStreams), calls: make([]callReq, cfg.NumStreams), timeout: cfg.Timeout, @@ -191,7 +193,7 @@ func Connect(addr string, cfg ConnConfig, errorHandler ConnErrorHandler) (*Conn, go c.serve() - if err := c.startup(&cfg); err != nil { + if err := c.startup(); err != nil { conn.Close() return nil, err } @@ -231,16 +233,21 @@ func (c *Conn) Read(p []byte) (n int, err error) { return } -func (c *Conn) startup(cfg *ConnConfig) error { +func (c *Conn) startup() error { m := map[string]string{ - "CQL_VERSION": cfg.CQLVersion, + "CQL_VERSION": c.cfg.CQLVersion, } if c.compressor != nil { m["COMPRESSION"] = c.compressor.Name() } - frame, err := c.exec(&writeStartupFrame{opts: m}, nil) + framer, err := c.exec(&writeStartupFrame{opts: m}, nil) + if err != nil { + return err + } + + frame, err := framer.parseFrame() if err != nil { return err } @@ -270,7 +277,12 @@ func (c *Conn) authenticateHandshake(authFrame *authenticateFrame) error { req := &writeAuthResponseFrame{data: resp} for { - frame, err := c.exec(req, nil) + framer, err := c.exec(req, nil) + if err != nil { + return err + } + + frame, err := framer.parseFrame() if err != nil { return err } @@ -295,6 +307,8 @@ func (c *Conn) authenticateHandshake(authFrame *authenticateFrame) error { default: return fmt.Errorf("unknown frame response during authentication: %v", v) } + + framerPool.Put(framer) } } @@ -385,6 +399,7 @@ func (c *Conn) recv() error { if err := framer.readFrame(&head); err != nil { return err } + defer framerPool.Put(framer) frame, err := framer.parseFrame() if err != nil { @@ -435,7 +450,6 @@ type callReq struct { func (c *Conn) releaseStream(stream int) { call := &c.calls[stream] - framerPool.Put(call.framer) call.framer = nil select { @@ -450,7 +464,7 @@ func (c *Conn) handleTimeout() { } } -func (c *Conn) exec(req frameWriter, tracer Tracer) (frame, error) { +func (c *Conn) exec(req frameWriter, tracer Tracer) (*framer, error) { // TODO: move tracer onto conn var stream int select { @@ -512,19 +526,10 @@ func (c *Conn) exec(req frameWriter, tracer Tracer) (frame, error) { return nil, NewErrProtocol("unexpected protocol version in response: got %d expected %d", v, c.version) } - frame, err := framer.parseFrame() - if err != nil { - return nil, err - } - - if len(framer.traceID) > 0 { - tracer.Trace(framer.traceID) - } - - return frame, nil + return framer, nil } -func (c *Conn) prepareStatement(stmt string, trace Tracer) (*resultPreparedFrame, error) { +func (c *Conn) prepareStatement(stmt string, tracer Tracer) (*QueryInfo, error) { stmtsLRU.Lock() if stmtsLRU.lru == nil { initStmtsLRU(defaultMaxPreparedStmts) @@ -536,7 +541,7 @@ func (c *Conn) prepareStatement(stmt string, trace Tracer) (*resultPreparedFrame stmtsLRU.Unlock() flight := val.(*inflightPrepare) flight.wg.Wait() - return flight.info, flight.err + return &flight.info, flight.err } flight := new(inflightPrepare) @@ -548,16 +553,36 @@ func (c *Conn) prepareStatement(stmt string, trace Tracer) (*resultPreparedFrame statement: stmt, } - resp, err := c.exec(prep, trace) + framer, err := c.exec(prep, tracer) if err != nil { flight.err = err flight.wg.Done() return nil, err } - switch x := resp.(type) { + frame, err := framer.parseFrame() + if err != nil { + flight.err = err + flight.wg.Done() + return nil, err + } + + // TODO(zariel): tidy this up, simplify handling of frame parsing so its not duplicated + // everytime we need to parse a frame. + if len(framer.traceID) > 0 { + tracer.Trace(framer.traceID) + } + + switch x := frame.(type) { case *resultPreparedFrame: - flight.info = x + // defensivly copy as we will recycle the underlying buffer after we + // return. + flight.info.Id = copyBytes(x.preparedID) + // the type info's should _not_ have a reference to the framers read buffer, + // therefore we can just copy them directly. + flight.info.Args = x.reqMeta.columns + flight.info.PKeyColumns = x.reqMeta.pkeyColumns + flight.info.Rval = x.respMeta.columns case error: flight.err = x default: @@ -571,7 +596,9 @@ func (c *Conn) prepareStatement(stmt string, trace Tracer) (*resultPreparedFrame stmtsLRU.Unlock() } - return flight.info, flight.err + framerPool.Put(framer) + + return &flight.info, flight.err } func (c *Conn) executeQuery(qry *Query) *Iter { @@ -603,24 +630,19 @@ func (c *Conn) executeQuery(qry *Query) *Iter { if qry.binding == nil { values = qry.values } else { - binding := &QueryInfo{ - Id: info.preparedID, - Args: info.reqMeta.columns, - Rval: info.respMeta.columns, - } - - values, err = qry.binding(binding) + values, err = qry.binding(info) if err != nil { return &Iter{err: err} } } - if len(values) != len(info.reqMeta.columns) { + if len(values) != len(info.Args) { return &Iter{err: ErrQueryArgLength} } + params.values = make([]queryValues, len(values)) for i := 0; i < len(values); i++ { - val, err := Marshal(info.reqMeta.columns[i].TypeInfo, values[i]) + val, err := Marshal(info.Args[i].TypeInfo, values[i]) if err != nil { return &Iter{err: err} } @@ -631,7 +653,7 @@ func (c *Conn) executeQuery(qry *Query) *Iter { } frame = &writeExecuteFrame{ - preparedID: info.preparedID, + preparedID: info.Id, params: params, } } else { @@ -641,18 +663,28 @@ func (c *Conn) executeQuery(qry *Query) *Iter { } } - resp, err := c.exec(frame, qry.trace) + framer, err := c.exec(frame, qry.trace) if err != nil { return &Iter{err: err} } + resp, err := framer.parseFrame() + if err != nil { + return &Iter{err: err} + } + + if len(framer.traceID) > 0 { + qry.trace.Trace(framer.traceID) + } + switch x := resp.(type) { case *resultVoidFrame: - return &Iter{} + return &Iter{framer: framer} case *resultRowsFrame: iter := &Iter{ - meta: x.meta, - rows: x.rows, + meta: x.meta, + rows: x.rows, + framer: framer, } if len(x.meta.pagingState) > 0 && !qry.disableAutoPage { @@ -668,8 +700,8 @@ func (c *Conn) executeQuery(qry *Query) *Iter { } return iter - case *resultKeyspaceFrame, *resultSchemaChangeFrame, *schemaChangeKeyspace, *schemaChangeTable: - return &Iter{} + case *resultKeyspaceFrame, *resultSchemaChangeFrame, *schemaChangeKeyspace, *schemaChangeTable, *schemaChangeFunction: + return &Iter{framer: framer} case *RequestErrUnprepared: stmtsLRU.Lock() stmtCacheKey := c.addr + c.currentKeyspace + qry.stmt @@ -679,11 +711,14 @@ func (c *Conn) executeQuery(qry *Query) *Iter { return c.executeQuery(qry) } stmtsLRU.Unlock() - return &Iter{err: x} + return &Iter{err: x, framer: framer} case error: - return &Iter{err: x} + return &Iter{err: x, framer: framer} default: - return &Iter{err: NewErrProtocol("Unknown type in response to execute query (%T): %s", x, x)} + return &Iter{ + err: NewErrProtocol("Unknown type in response to execute query (%T): %s", x, x), + framer: framer, + } } } @@ -710,7 +745,12 @@ func (c *Conn) UseKeyspace(keyspace string) error { q := &writeQueryFrame{statement: `USE "` + keyspace + `"`} q.params.consistency = Any - resp, err := c.exec(q, nil) + framer, err := c.exec(q, nil) + if err != nil { + return err + } + + resp, err := framer.parseFrame() if err != nil { return err } @@ -728,9 +768,9 @@ func (c *Conn) UseKeyspace(keyspace string) error { return nil } -func (c *Conn) executeBatch(batch *Batch) error { +func (c *Conn) executeBatch(batch *Batch) (*Iter, error) { if c.version == protoVersion1 { - return ErrUnsupported + return nil, ErrUnsupported } n := len(batch.Entries) @@ -750,37 +790,32 @@ func (c *Conn) executeBatch(batch *Batch) error { if len(entry.Args) > 0 || entry.binding != nil { info, err := c.prepareStatement(entry.Stmt, nil) if err != nil { - return err + return nil, err } var args []interface{} if entry.binding == nil { args = entry.Args } else { - binding := &QueryInfo{ - Id: info.preparedID, - Args: info.reqMeta.columns, - Rval: info.respMeta.columns, - } - args, err = entry.binding(binding) + args, err = entry.binding(info) if err != nil { - return err + return nil, err } } - if len(args) != len(info.reqMeta.columns) { - return ErrQueryArgLength + if len(args) != len(info.Args) { + return nil, ErrQueryArgLength } - b.preparedID = info.preparedID - stmts[string(info.preparedID)] = entry.Stmt + b.preparedID = info.Id + stmts[string(info.Id)] = entry.Stmt - b.values = make([]queryValues, len(info.reqMeta.columns)) + b.values = make([]queryValues, len(info.Args)) - for j := 0; j < len(info.reqMeta.columns); j++ { - val, err := Marshal(info.reqMeta.columns[j].TypeInfo, args[j]) + for j := 0; j < len(info.Args); j++ { + val, err := Marshal(info.Args[j].TypeInfo, args[j]) if err != nil { - return err + return nil, err } b.values[j].value = val @@ -792,14 +827,20 @@ func (c *Conn) executeBatch(batch *Batch) error { } // TODO: should batch support tracing? - resp, err := c.exec(req, nil) + framer, err := c.exec(req, nil) if err != nil { - return err + return nil, err + } + + resp, err := framer.parseFrame() + if err != nil { + return nil, err } switch x := resp.(type) { case *resultVoidFrame: - return nil + framerPool.Put(framer) + return nil, nil case *RequestErrUnprepared: stmt, found := stmts[string(x.StatementId)] if found { @@ -807,15 +848,28 @@ func (c *Conn) executeBatch(batch *Batch) error { stmtsLRU.lru.Remove(c.addr + c.currentKeyspace + stmt) stmtsLRU.Unlock() } + + framerPool.Put(framer) + if found { return c.executeBatch(batch) } else { - return x + return nil, x } + case *resultRowsFrame: + iter := &Iter{ + meta: x.meta, + rows: x.rows, + framer: framer, + } + + return iter, nil case error: - return x + framerPool.Put(framer) + return nil, x default: - return NewErrProtocol("Unknown type in response to batch statement: %s", x) + framerPool.Put(framer) + return nil, NewErrProtocol("Unknown type in response to batch statement: %s", x) } } @@ -833,7 +887,7 @@ func (c *Conn) setKeepalive(d time.Duration) error { } type inflightPrepare struct { - info *resultPreparedFrame + info QueryInfo err error wg sync.WaitGroup } diff --git a/Godeps/_workspace/src/github.com/gocql/gocql/connectionpool.go b/Godeps/_workspace/src/github.com/gocql/gocql/connectionpool.go index 512206286..455f8c8f7 100644 --- a/Godeps/_workspace/src/github.com/gocql/gocql/connectionpool.go +++ b/Godeps/_workspace/src/github.com/gocql/gocql/connectionpool.go @@ -17,89 +17,6 @@ import ( "time" ) -/*ConnectionPool represents the interface gocql will use to work with a collection of connections. - -Purpose - -The connection pool in gocql opens and closes connections as well as selects an available connection -for gocql to execute a query against. The pool is also responsible for handling connection errors that -are caught by the connection experiencing the error. - -A connection pool should make a copy of the variables used from the ClusterConfig provided to the pool -upon creation. ClusterConfig is a pointer and can be modified after the creation of the pool. This can -lead to issues with variables being modified outside the expectations of the ConnectionPool type. - -Example of Single Connection Pool: - - type SingleConnection struct { - conn *Conn - cfg *ClusterConfig - } - - func NewSingleConnection(cfg *ClusterConfig) ConnectionPool { - addr := JoinHostPort(cfg.Hosts[0], cfg.Port) - - connCfg := ConnConfig{ - ProtoVersion: cfg.ProtoVersion, - CQLVersion: cfg.CQLVersion, - Timeout: cfg.Timeout, - NumStreams: cfg.NumStreams, - Compressor: cfg.Compressor, - Authenticator: cfg.Authenticator, - Keepalive: cfg.SocketKeepalive, - } - pool := SingleConnection{cfg:cfg} - pool.conn = Connect(addr,connCfg,pool) - return &pool - } - - func (s *SingleConnection) HandleError(conn *Conn, err error, closed bool) { - if closed { - connCfg := ConnConfig{ - ProtoVersion: cfg.ProtoVersion, - CQLVersion: cfg.CQLVersion, - Timeout: cfg.Timeout, - NumStreams: cfg.NumStreams, - Compressor: cfg.Compressor, - Authenticator: cfg.Authenticator, - Keepalive: cfg.SocketKeepalive, - } - s.conn = Connect(conn.Address(),connCfg,s) - } - } - - func (s *SingleConnection) Pick(qry *Query) *Conn { - if s.conn.isClosed { - return nil - } - return s.conn - } - - func (s *SingleConnection) Size() int { - return 1 - } - - func (s *SingleConnection) Close() { - s.conn.Close() - } - -This is a very simple example of a type that exposes the connection pool interface. To assign -this type as the connection pool to use you would assign it to the ClusterConfig like so: - - cluster := NewCluster("127.0.0.1") - cluster.ConnPoolType = NewSingleConnection - ... - session, err := cluster.CreateSession() - -To see a more complete example of a ConnectionPool implementation please see the SimplePool type. -*/ -type ConnectionPool interface { - SetHosts - Pick(*Query) *Conn - Size() int - Close() -} - // interface to implement to receive the host information type SetHosts interface { SetHosts(hosts []HostInfo) @@ -110,35 +27,6 @@ type SetPartitioner interface { SetPartitioner(partitioner string) } -//NewPoolFunc is the type used by ClusterConfig to create a pool of a specific type. -type NewPoolFunc func(*ClusterConfig) (ConnectionPool, error) - -//SimplePool is the current implementation of the connection pool inside gocql. This -//pool is meant to be a simple default used by gocql so users can get up and running -//quickly. -type SimplePool struct { - cfg *ClusterConfig - hostPool *RoundRobin - connPool map[string]*RoundRobin - conns map[*Conn]struct{} - keyspace string - - hostMu sync.RWMutex - // this is the set of current hosts which the pool will attempt to connect to - hosts map[string]*HostInfo - - // protects hostpool, connPoll, conns, quit - mu sync.Mutex - - cFillingPool chan int - - quit bool - quitWait chan bool - quitOnce sync.Once - - tlsConfig *tls.Config -} - func setupTLSConfig(sslOpts *SslOptions) (*tls.Config, error) { // ca cert is optional if sslOpts.CaPath != "" { @@ -169,313 +57,10 @@ func setupTLSConfig(sslOpts *SslOptions) (*tls.Config, error) { return &sslOpts.Config, nil } -//NewSimplePool is the function used by gocql to create the simple connection pool. -//This is the default if no other pool type is specified. -func NewSimplePool(cfg *ClusterConfig) (ConnectionPool, error) { - pool := &SimplePool{ - cfg: cfg, - hostPool: NewRoundRobin(), - connPool: make(map[string]*RoundRobin), - conns: make(map[*Conn]struct{}), - quitWait: make(chan bool), - cFillingPool: make(chan int, 1), - keyspace: cfg.Keyspace, - hosts: make(map[string]*HostInfo), - } - - for _, host := range cfg.Hosts { - // seed hosts have unknown topology - // TODO: Handle populating this during SetHosts - pool.hosts[host] = &HostInfo{Peer: host} - } - - if cfg.SslOpts != nil { - config, err := setupTLSConfig(cfg.SslOpts) - if err != nil { - return nil, err - } - pool.tlsConfig = config - } - - //Walk through connecting to hosts. As soon as one host connects - //defer the remaining connections to cluster.fillPool() - for i := 0; i < len(cfg.Hosts); i++ { - addr := JoinHostPort(cfg.Hosts[i], cfg.Port) - - if pool.connect(addr) == nil { - pool.cFillingPool <- 1 - go pool.fillPool() - break - } - } - - return pool, nil -} - -func (c *SimplePool) connect(addr string) error { - - cfg := ConnConfig{ - ProtoVersion: c.cfg.ProtoVersion, - CQLVersion: c.cfg.CQLVersion, - Timeout: c.cfg.Timeout, - NumStreams: c.cfg.NumStreams, - Compressor: c.cfg.Compressor, - Authenticator: c.cfg.Authenticator, - Keepalive: c.cfg.SocketKeepalive, - tlsConfig: c.tlsConfig, - } - - conn, err := Connect(addr, cfg, c) - if err != nil { - log.Printf("connect: failed to connect to %q: %v", addr, err) - return err - } - - return c.addConn(conn) -} - -func (c *SimplePool) addConn(conn *Conn) error { - c.mu.Lock() - defer c.mu.Unlock() - if c.quit { - conn.Close() - return nil - } - - //Set the connection's keyspace if any before adding it to the pool - if c.keyspace != "" { - if err := conn.UseKeyspace(c.keyspace); err != nil { - log.Printf("error setting connection keyspace. %v", err) - conn.Close() - return err - } - } - - connPool := c.connPool[conn.Address()] - if connPool == nil { - connPool = NewRoundRobin() - c.connPool[conn.Address()] = connPool - c.hostPool.AddNode(connPool) - } - - connPool.AddNode(conn) - c.conns[conn] = struct{}{} - - return nil -} - -//fillPool manages the pool of connections making sure that each host has the correct -//amount of connections defined. Also the method will test a host with one connection -//instead of flooding the host with number of connections defined in the cluster config -func (c *SimplePool) fillPool() { - //Debounce large amounts of requests to fill pool - select { - case <-time.After(1 * time.Millisecond): - return - case <-c.cFillingPool: - defer func() { c.cFillingPool <- 1 }() - } - - c.mu.Lock() - isClosed := c.quit - c.mu.Unlock() - //Exit if cluster(session) is closed - if isClosed { - return - } - - c.hostMu.RLock() - - //Walk through list of defined hosts - var wg sync.WaitGroup - for host := range c.hosts { - addr := JoinHostPort(host, c.cfg.Port) - - numConns := 1 - //See if the host already has connections in the pool - c.mu.Lock() - conns, ok := c.connPool[addr] - c.mu.Unlock() - - if ok { - //if the host has enough connections just exit - numConns = conns.Size() - if numConns >= c.cfg.NumConns { - continue - } - } else { - //See if the host is reachable - if err := c.connect(addr); err != nil { - continue - } - } - - //This is reached if the host is responsive and needs more connections - //Create connections for host synchronously to mitigate flooding the host. - wg.Add(1) - go func(a string, conns int) { - defer wg.Done() - for ; conns < c.cfg.NumConns; conns++ { - c.connect(a) - } - }(addr, numConns) - } - - c.hostMu.RUnlock() - - //Wait until we're finished connecting to each host before returning - wg.Wait() -} - -// Should only be called if c.mu is locked -func (c *SimplePool) removeConnLocked(conn *Conn) { - conn.Close() - connPool := c.connPool[conn.addr] - if connPool == nil { - return - } - connPool.RemoveNode(conn) - if connPool.Size() == 0 { - c.hostPool.RemoveNode(connPool) - delete(c.connPool, conn.addr) - } - delete(c.conns, conn) -} - -func (c *SimplePool) removeConn(conn *Conn) { - c.mu.Lock() - defer c.mu.Unlock() - c.removeConnLocked(conn) -} - -//HandleError is called by a Connection object to report to the pool an error has occured. -//Logic is then executed within the pool to clean up the erroroneous connection and try to -//top off the pool. -func (c *SimplePool) HandleError(conn *Conn, err error, closed bool) { - if !closed { - // ignore all non-fatal errors - return - } - c.removeConn(conn) - c.mu.Lock() - poolClosed := c.quit - c.mu.Unlock() - if !poolClosed { - go c.fillPool() // top off pool. - } -} - -//Pick selects a connection to be used by the query. -func (c *SimplePool) Pick(qry *Query) *Conn { - //Check if connections are available - c.mu.Lock() - conns := len(c.conns) - c.mu.Unlock() - - if conns == 0 { - //try to populate the pool before returning. - c.fillPool() - } - - return c.hostPool.Pick(qry) -} - -//Size returns the number of connections currently active in the pool -func (p *SimplePool) Size() int { - p.mu.Lock() - conns := len(p.conns) - p.mu.Unlock() - return conns -} - -//Close kills the pool and all associated connections. -func (c *SimplePool) Close() { - c.quitOnce.Do(func() { - c.mu.Lock() - defer c.mu.Unlock() - c.quit = true - close(c.quitWait) - for conn := range c.conns { - c.removeConnLocked(conn) - } - }) -} - -func (c *SimplePool) SetHosts(hosts []HostInfo) { - - c.hostMu.Lock() - toRemove := make(map[string]struct{}) - for k := range c.hosts { - toRemove[k] = struct{}{} - } - - for _, host := range hosts { - host := host - delete(toRemove, host.Peer) - // we already have it - if _, ok := c.hosts[host.Peer]; ok { - // TODO: Check rack, dc, token range is consistent, trigger topology change - // update stored host - continue - } - - c.hosts[host.Peer] = &host - } - - // can we hold c.mu whilst iterating this loop? - for addr := range toRemove { - c.removeHostLocked(addr) - } - c.hostMu.Unlock() - - c.fillPool() -} - -func (c *SimplePool) removeHostLocked(addr string) { - if _, ok := c.hosts[addr]; !ok { - return - } - delete(c.hosts, addr) - - c.mu.Lock() - defer c.mu.Unlock() - - if _, ok := c.connPool[addr]; !ok { - return - } - - for conn := range c.conns { - if conn.Address() == addr { - c.removeConnLocked(conn) - } - } -} - -//NewRoundRobinConnPool creates a connection pool which selects hosts by -//round-robin, and then selects a connection for that host by round-robin. -func NewRoundRobinConnPool(cfg *ClusterConfig) (ConnectionPool, error) { - return NewPolicyConnPool( - cfg, - NewRoundRobinHostPolicy(), - NewRoundRobinConnPolicy, - ) -} - -//NewTokenAwareConnPool creates a connection pool which selects hosts by -//a token aware policy, and then selects a connection for that host by -//round-robin. -func NewTokenAwareConnPool(cfg *ClusterConfig) (ConnectionPool, error) { - return NewPolicyConnPool( - cfg, - NewTokenAwareHostPolicy(NewRoundRobinHostPolicy()), - NewRoundRobinConnPolicy, - ) -} - type policyConnPool struct { port int numConns int - connCfg ConnConfig + connCfg *ConnConfig keyspace string mu sync.RWMutex @@ -484,18 +69,13 @@ type policyConnPool struct { hostConnPools map[string]*hostConnPool } -//Creates a policy based connection pool. This func isn't meant to be directly -//used as a NewPoolFunc in ClusterConfig, instead a func should be created -//which satisfies the NewPoolFunc type, which calls this func with the desired -//hostPolicy and connPolicy; see NewRoundRobinConnPool or NewTokenAwareConnPool -//for examples. -func NewPolicyConnPool( - cfg *ClusterConfig, - hostPolicy HostSelectionPolicy, - connPolicy func() ConnSelectionPolicy, -) (ConnectionPool, error) { - var err error - var tlsConfig *tls.Config +func newPolicyConnPool(cfg *ClusterConfig, hostPolicy HostSelectionPolicy, + connPolicy func() ConnSelectionPolicy) (*policyConnPool, error) { + + var ( + err error + tlsConfig *tls.Config + ) if cfg.SslOpts != nil { tlsConfig, err = setupTLSConfig(cfg.SslOpts) @@ -508,7 +88,7 @@ func NewPolicyConnPool( pool := &policyConnPool{ port: cfg.Port, numConns: cfg.NumConns, - connCfg: ConnConfig{ + connCfg: &ConnConfig{ ProtoVersion: cfg.ProtoVersion, CQLVersion: cfg.CQLVersion, Timeout: cfg.Timeout, @@ -594,9 +174,12 @@ func (p *policyConnPool) Size() int { func (p *policyConnPool) Pick(qry *Query) *Conn { nextHost := p.hostPolicy.Pick(qry) + var ( + host *HostInfo + conn *Conn + ) + p.mu.RLock() - var host *HostInfo - var conn *Conn for conn == nil { host = nextHost() if host == nil { @@ -629,7 +212,7 @@ type hostConnPool struct { port int addr string size int - connCfg ConnConfig + connCfg *ConnConfig keyspace string policy ConnSelectionPolicy // protection for conns, closed, filling @@ -639,14 +222,8 @@ type hostConnPool struct { filling bool } -func newHostConnPool( - host string, - port int, - size int, - connCfg ConnConfig, - keyspace string, - policy ConnSelectionPolicy, -) *hostConnPool { +func newHostConnPool(host string, port int, size int, connCfg *ConnConfig, + keyspace string, policy ConnSelectionPolicy) *hostConnPool { pool := &hostConnPool{ host: host, diff --git a/Godeps/_workspace/src/github.com/gocql/gocql/control.go b/Godeps/_workspace/src/github.com/gocql/gocql/control.go new file mode 100644 index 000000000..f46952458 --- /dev/null +++ b/Godeps/_workspace/src/github.com/gocql/gocql/control.go @@ -0,0 +1,220 @@ +package gocql + +import ( + "errors" + "fmt" + "sync/atomic" + "time" +) + +type controlConn struct { + session *Session + + conn atomic.Value + connecting uint64 + + retry RetryPolicy + + quit chan struct{} +} + +func createControlConn(session *Session) *controlConn { + control := &controlConn{ + session: session, + quit: make(chan struct{}), + retry: &SimpleRetryPolicy{NumRetries: 3}, + } + + control.conn.Store((*Conn)(nil)) + control.reconnect() + go control.heartBeat() + + return control +} + +func (c *controlConn) heartBeat() { + for { + select { + case <-c.quit: + return + case <-time.After(5 * time.Second): + } + + resp, err := c.writeFrame(&writeOptionsFrame{}) + if err != nil { + goto reconn + } + + switch resp.(type) { + case *supportedFrame: + continue + case error: + goto reconn + default: + panic(fmt.Sprintf("gocql: unknown frame in response to options: %T", resp)) + } + + reconn: + c.reconnect() + time.Sleep(5 * time.Second) + continue + + } +} + +func (c *controlConn) reconnect() { + if !atomic.CompareAndSwapUint64(&c.connecting, 0, 1) { + return + } + + success := false + defer func() { + // debounce reconnect a little + if success { + go func() { + time.Sleep(500 * time.Millisecond) + atomic.StoreUint64(&c.connecting, 0) + }() + } else { + atomic.StoreUint64(&c.connecting, 0) + } + }() + + oldConn := c.conn.Load().(*Conn) + + // TODO: should have our own roundrobbin for hosts so that we can try each + // in succession and guantee that we get a different host each time. + conn := c.session.pool.Pick(nil) + if conn == nil { + return + } + + newConn, err := Connect(conn.addr, conn.cfg, c) + if err != nil { + // TODO: add log handler for things like this + return + } + + c.conn.Store(newConn) + success = true + + if oldConn != nil { + oldConn.Close() + } +} + +func (c *controlConn) HandleError(conn *Conn, err error, closed bool) { + if !closed { + return + } + + oldConn := c.conn.Load().(*Conn) + if oldConn != conn { + return + } + + c.reconnect() +} + +func (c *controlConn) writeFrame(w frameWriter) (frame, error) { + conn := c.conn.Load().(*Conn) + if conn == nil { + return nil, errNoControl + } + + framer, err := conn.exec(w, nil) + if err != nil { + return nil, err + } + + return framer.parseFrame() +} + +// query will return nil if the connection is closed or nil +func (c *controlConn) query(statement string, values ...interface{}) (iter *Iter) { + q := c.session.Query(statement, values...).Consistency(One) + + const maxConnectAttempts = 5 + connectAttempts := 0 + + for { + conn := c.conn.Load().(*Conn) + if conn == nil { + if connectAttempts > maxConnectAttempts { + return &Iter{err: errNoControl} + } + + connectAttempts++ + + c.reconnect() + continue + } + + iter = conn.executeQuery(q) + q.attempts++ + if iter.err == nil || !c.retry.Attempt(q) { + break + } + } + + return +} + +func (c *controlConn) awaitSchemaAgreement() (err error) { + + const ( + // TODO(zariel): if we export this make this configurable + maxWaitTime = 60 * time.Second + + peerSchemas = "SELECT schema_version FROM system.peers" + localSchemas = "SELECT schema_version FROM system.local WHERE key='local'" + ) + + endDeadline := time.Now().Add(maxWaitTime) + + for time.Now().Before(endDeadline) { + iter := c.query(peerSchemas) + + versions := make(map[string]struct{}) + + var schemaVersion string + for iter.Scan(&schemaVersion) { + versions[schemaVersion] = struct{}{} + schemaVersion = "" + } + + if err = iter.Close(); err != nil { + goto cont + } + + iter = c.query(localSchemas) + for iter.Scan(&schemaVersion) { + versions[schemaVersion] = struct{}{} + schemaVersion = "" + } + + if err = iter.Close(); err != nil { + goto cont + } + + if len(versions) <= 1 { + return nil + } + + cont: + time.Sleep(200 * time.Millisecond) + } + + if err != nil { + return + } + + // not exported + return errors.New("gocql: cluster schema versions not consistent") +} +func (c *controlConn) close() { + // TODO: handle more gracefully + close(c.quit) +} + +var errNoControl = errors.New("gocql: no controll connection available") diff --git a/Godeps/_workspace/src/github.com/gocql/gocql/frame.go b/Godeps/_workspace/src/github.com/gocql/gocql/frame.go index 294c4fdf5..90abdee21 100644 --- a/Godeps/_workspace/src/github.com/gocql/gocql/frame.go +++ b/Godeps/_workspace/src/github.com/gocql/gocql/frame.go @@ -12,6 +12,7 @@ import ( "log" "net" "runtime" + "strings" "sync" "time" ) @@ -179,6 +180,31 @@ func (c Consistency) String() string { } } +func ParseConsistency(s string) Consistency { + switch strings.ToUpper(s) { + case "ANY": + return Any + case "ONE": + return One + case "TWO": + return Two + case "THREE": + return Three + case "QUORUM": + return Quorum + case "ALL": + return All + case "LOCAL_QUORUM": + return LocalQuorum + case "EACH_QUORUM": + return EachQuorum + case "LOCAL_ONE": + return LocalOne + default: + panic("invalid consistency: " + s) + } +} + type SerialConsistency uint16 const ( @@ -500,7 +526,7 @@ func (f *framer) parseErrorFrame() frame { stmtId := f.readShortBytes() return &RequestErrUnprepared{ errorFrame: errD, - StatementId: stmtId, + StatementId: copyBytes(stmtId), // defensivly copy } case errReadFailure: res := &RequestErrReadFailure{ @@ -1371,6 +1397,17 @@ func (f *framer) writeBatchFrame(streamID int, w *writeBatchFrame) error { return f.finishWrite() } +type writeOptionsFrame struct{} + +func (w *writeOptionsFrame) writeFrame(framer *framer, streamID int) error { + return framer.writeOptionsFrame(streamID, w) +} + +func (f *framer) writeOptionsFrame(stream int, _ *writeOptionsFrame) error { + f.writeHeader(f.flags, opOptions, stream) + return f.finishWrite() +} + func (f *framer) readByte() byte { if len(f.rbuf) < 1 { panic(fmt.Errorf("not enough bytes in buffer to read byte require 1 got: %d", len(f.rbuf))) @@ -1466,13 +1503,7 @@ func (f *framer) readBytes() []byte { panic(fmt.Errorf("not enough bytes in buffer to read bytes require %d got: %d", size, len(f.rbuf))) } - // we cant make assumptions about the length of the life of the supplied byte - // slice so we defensivly copy it out of the underlying buffer. This has the - // downside of increasing allocs per read but will provide much greater memory - // safety. The allocs can hopefully be improved in the future. - // TODO: dont copy into a new slice - l := make([]byte, size) - copy(l, f.rbuf[:size]) + l := f.rbuf[:size] f.rbuf = f.rbuf[size:] return l @@ -1484,8 +1515,7 @@ func (f *framer) readShortBytes() []byte { panic(fmt.Errorf("not enough bytes in buffer to read short bytes: require %d got %d", size, len(f.rbuf))) } - l := make([]byte, size) - copy(l, f.rbuf[:size]) + l := f.rbuf[:size] f.rbuf = f.rbuf[size:] return l diff --git a/Godeps/_workspace/src/github.com/gocql/gocql/helpers.go b/Godeps/_workspace/src/github.com/gocql/gocql/helpers.go index 08778a07e..4762048b1 100644 --- a/Godeps/_workspace/src/github.com/gocql/gocql/helpers.go +++ b/Godeps/_workspace/src/github.com/gocql/gocql/helpers.go @@ -180,3 +180,9 @@ func (iter *Iter) MapScan(m map[string]interface{}) bool { } return false } + +func copyBytes(p []byte) []byte { + b := make([]byte, len(p)) + copy(b, p) + return b +} diff --git a/Godeps/_workspace/src/github.com/gocql/gocql/host_source.go b/Godeps/_workspace/src/github.com/gocql/gocql/host_source.go index 801b6f914..ac40a4d30 100644 --- a/Godeps/_workspace/src/github.com/gocql/gocql/host_source.go +++ b/Godeps/_workspace/src/github.com/gocql/gocql/host_source.go @@ -24,20 +24,19 @@ type ringDescriber struct { closeChan chan bool } -func (r *ringDescriber) GetHosts() ( - hosts []HostInfo, - partitioner string, - err error, -) { +func (r *ringDescriber) GetHosts() (hosts []HostInfo, partitioner string, err error) { // we need conn to be the same because we need to query system.peers and system.local // on the same node to get the whole cluster - conn := r.session.Pool.Pick(nil) - if conn == nil { + + iter := r.session.control.query("SELECT data_center, rack, host_id, tokens, partitioner FROM system.local") + if iter == nil { return r.prevHosts, r.prevPartitioner, nil } - query := r.session.Query("SELECT data_center, rack, host_id, tokens, partitioner FROM system.local") - iter := conn.executeQuery(query) + conn := r.session.pool.Pick(nil) + if conn == nil { + return r.prevHosts, r.prevPartitioner, nil + } host := HostInfo{} iter.Scan(&host.DataCenter, &host.Rack, &host.HostId, &host.Tokens, &partitioner) @@ -57,8 +56,10 @@ func (r *ringDescriber) GetHosts() ( hosts = []HostInfo{host} - query = r.session.Query("SELECT peer, data_center, rack, host_id, tokens FROM system.peers") - iter = conn.executeQuery(query) + iter = r.session.control.query("SELECT peer, data_center, rack, host_id, tokens FROM system.peers") + if iter == nil { + return r.prevHosts, r.prevPartitioner, nil + } host = HostInfo{} for iter.Scan(&host.Peer, &host.DataCenter, &host.Rack, &host.HostId, &host.Tokens) { @@ -97,21 +98,21 @@ func (h *ringDescriber) run(sleep time.Duration) { } for { + // if we have 0 hosts this will return the previous list of hosts to + // attempt to reconnect to the cluster otherwise we would never find + // downed hosts again, could possibly have an optimisation to only + // try to add new hosts if GetHosts didnt error and the hosts didnt change. + hosts, partitioner, err := h.GetHosts() + if err != nil { + log.Println("RingDescriber: unable to get ring topology:", err) + continue + } + + h.session.pool.SetHosts(hosts) + h.session.pool.SetPartitioner(partitioner) + select { case <-time.After(sleep): - // if we have 0 hosts this will return the previous list of hosts to - // attempt to reconnect to the cluster otherwise we would never find - // downed hosts again, could possibly have an optimisation to only - // try to add new hosts if GetHosts didnt error and the hosts didnt change. - hosts, partitioner, err := h.GetHosts() - if err != nil { - log.Println("RingDescriber: unable to get ring topology:", err) - } else { - h.session.Pool.SetHosts(hosts) - if v, ok := h.session.Pool.(SetPartitioner); ok { - v.SetPartitioner(partitioner) - } - } case <-h.closeChan: return } diff --git a/Godeps/_workspace/src/github.com/gocql/gocql/integration.sh b/Godeps/_workspace/src/github.com/gocql/gocql/integration.sh index c5bf5d7bc..d317b53b2 100644 --- a/Godeps/_workspace/src/github.com/gocql/gocql/integration.sh +++ b/Godeps/_workspace/src/github.com/gocql/gocql/integration.sh @@ -40,10 +40,6 @@ function run_tests() { rm -rf $HOME/.ccm/test/node1/data/system_auth fi - ccm start -v - ccm status - ccm node1 nodetool status - local proto=2 if [[ $version == 1.2.* ]]; then proto=1 @@ -53,15 +49,20 @@ function run_tests() { proto=3 elif [[ $version == 2.2.* ]]; then proto=4 + ccm updateconf 'enable_user_defined_functions: true' fi + ccm start -v + ccm status + ccm node1 nodetool status + if [ "$auth" = true ] then sleep 30s go test -v . -timeout 15s -run=TestAuthentication -tags integration -runssl -runauth -proto=$proto -cluster=$(ccm liveset) -clusterSize=$clusterSize -autowait=1000ms else - go test -timeout 5m -tags integration -cover -v -runssl -proto=$proto -rf=3 -cluster=$(ccm liveset) -clusterSize=$clusterSize -autowait=2000ms -compressor=snappy ./... | tee results.txt + go test -timeout 5m -tags integration -v -gocql.timeout=10s -runssl -proto=$proto -rf=3 -cluster=$(ccm liveset) -clusterSize=$clusterSize -autowait=2000ms -compressor=snappy ./... if [ ${PIPESTATUS[0]} -ne 0 ]; then echo "--- FAIL: ccm status follows:" @@ -72,13 +73,6 @@ function run_tests() { echo "--- FAIL: Received a non-zero exit code from the go test execution, please investigate this" exit 1 fi - - cover=`cat results.txt | grep coverage: | grep -o "[0-9]\{1,3\}" | head -n 1` - - if [[ $cover -lt "55" ]]; then - echo "--- FAIL: expected coverage of at least 60 %, but coverage was $cover %" - exit 1 - fi fi ccm remove diff --git a/Godeps/_workspace/src/github.com/gocql/gocql/marshal.go b/Godeps/_workspace/src/github.com/gocql/gocql/marshal.go index fd3750258..c5727e70b 100644 --- a/Godeps/_workspace/src/github.com/gocql/gocql/marshal.go +++ b/Godeps/_workspace/src/github.com/gocql/gocql/marshal.go @@ -1356,7 +1356,16 @@ func marshalUDT(info TypeInfo, value interface{}) ([]byte, error) { if !f.IsValid() { return nil, marshalErrorf("cannot marshal %T into %s", value, info) } else if f.Kind() == reflect.Ptr { - f = f.Elem() + if f.IsNil() { + n := -1 + buf = append(buf, byte(n>>24), + byte(n>>16), + byte(n>>8), + byte(n)) + continue + } else { + f = f.Elem() + } } data, err := Marshal(e.Type, f.Interface()) diff --git a/Godeps/_workspace/src/github.com/gocql/gocql/metadata.go b/Godeps/_workspace/src/github.com/gocql/gocql/metadata.go index 92965c3a8..cfbe8cc49 100644 --- a/Godeps/_workspace/src/github.com/gocql/gocql/metadata.go +++ b/Godeps/_workspace/src/github.com/gocql/gocql/metadata.go @@ -335,30 +335,18 @@ func componentColumnCountOfType(columns map[string]*ColumnMetadata, kind string) } // query only for the keyspace metadata for the specified keyspace from system.schema_keyspace -func getKeyspaceMetadata( - session *Session, - keyspaceName string, -) (*KeyspaceMetadata, error) { - query := session.Query( - ` +func getKeyspaceMetadata(session *Session, keyspaceName string) (*KeyspaceMetadata, error) { + const stmt = ` SELECT durable_writes, strategy_class, strategy_options FROM system.schema_keyspaces - WHERE keyspace_name = ? - `, - keyspaceName, - ) - // Set a routing key to avoid GetRoutingKey from computing the routing key - // TODO use a separate connection (pool) for system keyspace queries. - query.RoutingKey([]byte{}) + WHERE keyspace_name = ?` keyspace := &KeyspaceMetadata{Name: keyspaceName} var strategyOptionsJSON []byte - err := query.Scan( - &keyspace.DurableWrites, - &keyspace.StrategyClass, - &strategyOptionsJSON, - ) + iter := session.control.query(stmt, keyspaceName) + iter.Scan(&keyspace.DurableWrites, &keyspace.StrategyClass, &strategyOptionsJSON) + err := iter.Close() if err != nil { return nil, fmt.Errorf("Error querying keyspace schema: %v", err) } @@ -431,11 +419,7 @@ func getTableMetadata(session *Session, keyspaceName string) ([]TableMetadata, e } } - // Set a routing key to avoid GetRoutingKey from computing the routing key - // TODO use a separate connection (pool) for system keyspace queries. - query := session.Query(stmt, keyspaceName) - query.RoutingKey([]byte{}) - iter := query.Iter() + iter := session.control.query(stmt, keyspaceName) tables := []TableMetadata{} table := TableMetadata{Keyspace: keyspaceName} @@ -560,11 +544,7 @@ func getColumnMetadata( var indexOptionsJSON []byte - query := session.Query(stmt, keyspaceName) - // Set a routing key to avoid GetRoutingKey from computing the routing key - // TODO use a separate connection (pool) for system keyspace queries. - query.RoutingKey([]byte{}) - iter := query.Iter() + iter := session.control.query(stmt, keyspaceName) for scan(iter, &column, &indexOptionsJSON) { var err error diff --git a/Godeps/_workspace/src/github.com/gocql/gocql/policies.go b/Godeps/_workspace/src/github.com/gocql/gocql/policies.go index 37ac28cff..ed3e606cb 100644 --- a/Godeps/_workspace/src/github.com/gocql/gocql/policies.go +++ b/Godeps/_workspace/src/github.com/gocql/gocql/policies.go @@ -10,8 +10,8 @@ import ( "sync/atomic" ) -//RetryableQuery is an interface that represents a query or batch statement that -//exposes the correct functions for the retry policy logic to evaluate correctly. +// RetryableQuery is an interface that represents a query or batch statement that +// exposes the correct functions for the retry policy logic to evaluate correctly. type RetryableQuery interface { Attempts() int GetConsistency() Consistency @@ -48,8 +48,8 @@ func (s *SimpleRetryPolicy) Attempt(q RetryableQuery) bool { return q.Attempts() <= s.NumRetries } -//HostSelectionPolicy is an interface for selecting -//the most appropriate host to execute a given query. +// HostSelectionPolicy is an interface for selecting +// the most appropriate host to execute a given query. type HostSelectionPolicy interface { SetHosts SetPartitioner @@ -57,11 +57,12 @@ type HostSelectionPolicy interface { Pick(*Query) NextHost } -//NextHost is an iteration function over picked hosts +// NextHost is an iteration function over picked hosts type NextHost func() *HostInfo -//NewRoundRobinHostPolicy is a round-robin load balancing policy -func NewRoundRobinHostPolicy() HostSelectionPolicy { +// RoundRobinHostPolicy is a round-robin load balancing policy, where each host +// is tried sequentially for each query. +func RoundRobinHostPolicy() HostSelectionPolicy { return &roundRobinHostPolicy{hosts: []HostInfo{}} } @@ -105,8 +106,10 @@ func (r *roundRobinHostPolicy) Pick(qry *Query) NextHost { } } -//NewTokenAwareHostPolicy is a token aware host selection policy -func NewTokenAwareHostPolicy(fallback HostSelectionPolicy) HostSelectionPolicy { +// TokenAwareHostPolicy is a token aware host selection policy, where hosts are +// selected based on the partition key, so queries are sent to the host which +// owns the partition. Fallback is used when routing information is not available. +func TokenAwareHostPolicy(fallback HostSelectionPolicy) HostSelectionPolicy { return &tokenAwareHostPolicy{fallback: fallback, hosts: []HostInfo{}} } @@ -227,8 +230,10 @@ type roundRobinConnPolicy struct { mu sync.RWMutex } -func NewRoundRobinConnPolicy() ConnSelectionPolicy { - return &roundRobinConnPolicy{} +func RoundRobinConnPolicy() func() ConnSelectionPolicy { + return func() ConnSelectionPolicy { + return &roundRobinConnPolicy{} + } } func (r *roundRobinConnPolicy) SetConns(conns []*Conn) { diff --git a/Godeps/_workspace/src/github.com/gocql/gocql/session.go b/Godeps/_workspace/src/github.com/gocql/gocql/session.go index 71d70e57f..799f099ce 100644 --- a/Godeps/_workspace/src/github.com/gocql/gocql/session.go +++ b/Godeps/_workspace/src/github.com/gocql/gocql/session.go @@ -28,7 +28,7 @@ import ( // and automatically sets a default consinstency level on all operations // that do not have a consistency level set. type Session struct { - Pool ConnectionPool + pool *policyConnPool cons Consistency pageSize int prefetch float64 @@ -38,6 +38,8 @@ type Session struct { hostSource *ringDescriber mu sync.RWMutex + control *controlConn + cfg ClusterConfig closeMu sync.RWMutex @@ -60,47 +62,48 @@ func NewSession(cfg ClusterConfig) (*Session, error) { cfg.NumStreams = maxStreams } - pool, err := cfg.ConnPoolType(&cfg) - if err != nil { - return nil, err - } - //Adjust the size of the prepared statements cache to match the latest configuration stmtsLRU.Lock() initStmtsLRU(cfg.MaxPreparedStmts) stmtsLRU.Unlock() s := &Session{ - Pool: pool, cons: cfg.Consistency, prefetch: 0.25, cfg: cfg, + pageSize: cfg.PageSize, } + pool, err := cfg.PoolConfig.buildPool(&s.cfg) + if err != nil { + return nil, err + } + s.pool = pool + //See if there are any connections in the pool - if pool.Size() > 0 { - s.routingKeyInfoCache.lru = lru.New(cfg.MaxRoutingKeyInfo) - - s.SetConsistency(cfg.Consistency) - s.SetPageSize(cfg.PageSize) - - if cfg.DiscoverHosts { - s.hostSource = &ringDescriber{ - session: s, - dcFilter: cfg.Discovery.DcFilter, - rackFilter: cfg.Discovery.RackFilter, - closeChan: make(chan bool), - } - - go s.hostSource.run(cfg.Discovery.Sleep) - } - - return s, nil + if pool.Size() == 0 { + s.Close() + return nil, ErrNoConnectionsStarted } - s.Close() + s.routingKeyInfoCache.lru = lru.New(cfg.MaxRoutingKeyInfo) - return nil, ErrNoConnectionsStarted + if !cfg.disableControlConn { + s.control = createControlConn(s) + } + + if cfg.DiscoverHosts { + s.hostSource = &ringDescriber{ + session: s, + dcFilter: cfg.Discovery.DcFilter, + rackFilter: cfg.Discovery.RackFilter, + closeChan: make(chan bool), + } + + go s.hostSource.run(cfg.Discovery.Sleep) + } + + return s, nil } // SetConsistency sets the default consistency level for this session. This @@ -154,9 +157,10 @@ func (s *Session) Query(stmt string, values ...interface{}) *Query { } type QueryInfo struct { - Id []byte - Args []ColumnInfo - Rval []ColumnInfo + Id []byte + Args []ColumnInfo + Rval []ColumnInfo + PKeyColumns []int } // Bind generates a new query object based on the query statement passed in. @@ -185,11 +189,15 @@ func (s *Session) Close() { } s.isClosed = true - s.Pool.Close() + s.pool.Close() if s.hostSource != nil { close(s.hostSource.closeChan) } + + if s.control != nil { + s.control.close() + } } func (s *Session) Closed() bool { @@ -210,12 +218,16 @@ func (s *Session) executeQuery(qry *Query) *Iter { qry.attempts = 0 qry.totalLatency = 0 for { - conn := s.Pool.Pick(qry) + conn := s.pool.Pick(qry) //Assign the error unavailable to the iterator if conn == nil { - iter = &Iter{err: ErrNoConnections} - break + if qry.rt == nil || !qry.rt.Attempt(qry) { + iter = &Iter{err: ErrNoConnections} + break + } + + continue } t := time.Now() @@ -289,12 +301,12 @@ func (s *Session) routingKeyInfo(stmt string) (*routingKeyInfo, error) { s.routingKeyInfoCache.mu.Unlock() var ( - prepared *resultPreparedFrame + info *QueryInfo partitionKey []*ColumnMetadata ) // get the query info for the statement - conn := s.Pool.Pick(nil) + conn := s.pool.Pick(nil) if conn == nil { // no connections inflight.err = ErrNoConnections @@ -303,20 +315,20 @@ func (s *Session) routingKeyInfo(stmt string) (*routingKeyInfo, error) { return nil, inflight.err } - prepared, inflight.err = conn.prepareStatement(stmt, nil) + info, inflight.err = conn.prepareStatement(stmt, nil) if inflight.err != nil { // don't cache this error s.routingKeyInfoCache.Remove(stmt) return nil, inflight.err } - if len(prepared.reqMeta.columns) == 0 { + if len(info.Args) == 0 { // no arguments, no routing key, and no error return nil, nil } // get the table metadata - table := prepared.reqMeta.columns[0].Table + table := info.Args[0].Table var keyspaceMetadata *KeyspaceMetadata keyspaceMetadata, inflight.err = s.KeyspaceMetadata(s.cfg.Keyspace) @@ -349,7 +361,7 @@ func (s *Session) routingKeyInfo(stmt string) (*routingKeyInfo, error) { routingKeyInfo.indexes[keyIndex] = -1 // find the column in the query info - for argIndex, boundColumn := range prepared.reqMeta.columns { + for argIndex, boundColumn := range info.Args { if keyColumn.Name == boundColumn.Name { // there may be many such bound columns, pick the first routingKeyInfo.indexes[keyIndex] = argIndex @@ -371,26 +383,25 @@ func (s *Session) routingKeyInfo(stmt string) (*routingKeyInfo, error) { return routingKeyInfo, nil } -// ExecuteBatch executes a batch operation and returns nil if successful -// otherwise an error is returned describing the failure. -func (s *Session) ExecuteBatch(batch *Batch) error { +func (s *Session) executeBatch(batch *Batch) (*Iter, error) { // fail fast if s.Closed() { - return ErrSessionClosed + return nil, ErrSessionClosed } // Prevent the execution of the batch if greater than the limit // Currently batches have a limit of 65536 queries. // https://datastax-oss.atlassian.net/browse/JAVA-229 if batch.Size() > BatchSizeMaximum { - return ErrTooManyStmts + return nil, ErrTooManyStmts } var err error + var iter *Iter batch.attempts = 0 batch.totalLatency = 0 for { - conn := s.Pool.Pick(nil) + conn := s.pool.Pick(nil) //Assign the error unavailable and break loop if conn == nil { @@ -398,12 +409,12 @@ func (s *Session) ExecuteBatch(batch *Batch) error { break } t := time.Now() - err = conn.executeBatch(batch) + iter, err = conn.executeBatch(batch) batch.totalLatency += time.Now().Sub(t).Nanoseconds() batch.attempts++ //Exit loop if operation executed correctly if err == nil { - return nil + return iter, err } if batch.rt == nil || !batch.rt.Attempt(batch) { @@ -411,9 +422,59 @@ func (s *Session) ExecuteBatch(batch *Batch) error { } } + return nil, err +} + +// ExecuteBatch executes a batch operation and returns nil if successful +// otherwise an error is returned describing the failure. +func (s *Session) ExecuteBatch(batch *Batch) error { + _, err := s.executeBatch(batch) return err } +// ExecuteBatchCAS executes a batch operation and returns nil if successful and +// an iterator (to scan aditional rows if more than one conditional statement) +// was sent, otherwise an error is returned describing the failure. +// Further scans on the interator must also remember to include +// the applied boolean as the first argument to *Iter.Scan +func (s *Session) ExecuteBatchCAS(batch *Batch, dest ...interface{}) (applied bool, iter *Iter, err error) { + if iter, err := s.executeBatch(batch); err == nil { + if err := iter.checkErrAndNotFound(); err != nil { + return false, nil, err + } + if len(iter.Columns()) > 1 { + dest = append([]interface{}{&applied}, dest...) + iter.Scan(dest...) + } else { + iter.Scan(&applied) + } + return applied, iter, nil + } else { + return false, nil, err + } +} + +// MapExecuteBatchCAS executes a batch operation much like ExecuteBatchCAS, +// however it accepts a map rather than a list of arguments for the initial +// scan. +func (s *Session) MapExecuteBatchCAS(batch *Batch, dest map[string]interface{}) (applied bool, iter *Iter, err error) { + if iter, err := s.executeBatch(batch); err == nil { + if err := iter.checkErrAndNotFound(); err != nil { + return false, nil, err + } + iter.MapScan(dest) + applied = dest["[applied]"].(bool) + delete(dest, "[applied]") + + // we usually close here, but instead of closing, just returin an error + // if MapScan failed. Although Close just returns err, using Close + // here might be confusing as we are not actually closing the iter + return applied, iter, iter.err + } else { + return false, nil, err + } +} + // Query represents a CQL statement that can be executed. type Query struct { stmt string @@ -717,6 +778,9 @@ type Iter struct { rows [][][]byte meta resultMetadata next *nextIter + + framer *framer + once sync.Once } // Columns returns the name and type of the selected columns. @@ -790,6 +854,13 @@ func (iter *Iter) Scan(dest ...interface{}) bool { // Close closes the iterator and returns any errors that happened during // the query or the iteration. func (iter *Iter) Close() error { + iter.once.Do(func() { + if iter.framer != nil { + framerPool.Put(iter.framer) + iter.framer = nil + } + }) + return iter.err } @@ -998,29 +1069,40 @@ func (t *traceWriter) Trace(traceId []byte) { coordinator string duration int ) - t.session.Query(`SELECT coordinator, duration + iter := t.session.control.query(`SELECT coordinator, duration FROM system_traces.sessions - WHERE session_id = ?`, traceId). - Consistency(One).Scan(&coordinator, &duration) + WHERE session_id = ?`, traceId) + + iter.Scan(&coordinator, &duration) + if err := iter.Close(); err != nil { + t.mu.Lock() + fmt.Fprintln(t.w, "Error:", err) + t.mu.Unlock() + return + } - iter := t.session.Query(`SELECT event_id, activity, source, source_elapsed - FROM system_traces.events - WHERE session_id = ?`, traceId). - Consistency(One).Iter() var ( timestamp time.Time activity string source string elapsed int ) - t.mu.Lock() - defer t.mu.Unlock() + fmt.Fprintf(t.w, "Tracing session %016x (coordinator: %s, duration: %v):\n", traceId, coordinator, time.Duration(duration)*time.Microsecond) + + t.mu.Lock() + defer t.mu.Unlock() + + iter = t.session.control.query(`SELECT event_id, activity, source, source_elapsed + FROM system_traces.events + WHERE session_id = ?`, traceId) + for iter.Scan(×tamp, &activity, &source, &elapsed) { fmt.Fprintf(t.w, "%s: %s (source: %s, elapsed: %d)\n", timestamp.Format("2006/01/02 15:04:05.999999"), activity, source, elapsed) } + if err := iter.Close(); err != nil { fmt.Fprintln(t.w, "Error:", err) } diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_releases.go b/Godeps/_workspace/src/github.com/google/go-github/github/repos_releases.go index 629b32131..4e4e2abbf 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/repos_releases.go +++ b/Godeps/_workspace/src/github.com/google/go-github/github/repos_releases.go @@ -8,6 +8,7 @@ package github import ( "errors" "fmt" + "io" "mime" "os" "path/filepath" @@ -211,6 +212,29 @@ func (s *RepositoriesService) GetReleaseAsset(owner, repo string, id int) (*Rele return asset, resp, err } +// DownloadReleaseAsset downloads a release asset. +// +// DownloadReleaseAsset returns an io.ReadCloser that reads the contents of the +// specified release asset. It is the caller's responsibility to close the ReadCloser. +// +// GitHub API docs : http://developer.github.com/v3/repos/releases/#get-a-single-release-asset +func (s *RepositoriesService) DownloadReleaseAsset(owner, repo string, id int) (io.ReadCloser, error) { + u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, err + } + req.Header.Set("Accept", defaultMediaType) + + resp, err := s.client.client.Do(req) + if err != nil { + return nil, err + } + + return resp.Body, nil +} + // EditReleaseAsset edits a repository release asset. // // GitHub API docs : http://developer.github.com/v3/repos/releases/#edit-a-release-asset diff --git a/Godeps/_workspace/src/github.com/hashicorp/consul/api/api.go b/Godeps/_workspace/src/github.com/hashicorp/consul/api/api.go index 0d248f655..7123c8a68 100644 --- a/Godeps/_workspace/src/github.com/hashicorp/consul/api/api.go +++ b/Godeps/_workspace/src/github.com/hashicorp/consul/api/api.go @@ -14,6 +14,8 @@ import ( "strconv" "strings" "time" + + "github.com/hashicorp/go-cleanhttp" ) // QueryOptions are used to parameterize a query @@ -119,7 +121,7 @@ func DefaultConfig() *Config { config := &Config{ Address: "127.0.0.1:8500", Scheme: "http", - HttpClient: &http.Client{}, + HttpClient: cleanhttp.DefaultClient(), } if addr := os.Getenv("CONSUL_HTTP_ADDR"); addr != "" { @@ -198,12 +200,12 @@ func NewClient(config *Config) (*Client, error) { } if parts := strings.SplitN(config.Address, "unix://", 2); len(parts) == 2 { + trans := cleanhttp.DefaultTransport() + trans.Dial = func(_, _ string) (net.Conn, error) { + return net.Dial("unix", parts[1]) + } config.HttpClient = &http.Client{ - Transport: &http.Transport{ - Dial: func(_, _ string) (net.Conn, error) { - return net.Dial("unix", parts[1]) - }, - }, + Transport: trans, } config.Address = parts[1] } diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-cleanhttp/LICENSE b/Godeps/_workspace/src/github.com/hashicorp/go-cleanhttp/LICENSE new file mode 100644 index 000000000..e87a115e4 --- /dev/null +++ b/Godeps/_workspace/src/github.com/hashicorp/go-cleanhttp/LICENSE @@ -0,0 +1,363 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. "Contributor" + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. "Contributor Version" + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the terms of + a Secondary License. + +1.6. "Executable Form" + + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + + means a work that combines Covered Software with other material, in a + separate file or files, that is not Covered Software. + +1.8. "License" + + means this document. + +1.9. "Licensable" + + means having the right to grant, to the maximum extent possible, whether + at the time of the initial grant or subsequently, any and all of the + rights conveyed by this License. + +1.10. "Modifications" + + means any of the following: + + a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. "Patent Claims" of a Contributor + + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the License, + by the making, using, selling, offering for sale, having made, import, + or transfer of either its Contributions or its Contributor Version. + +1.12. "Secondary License" + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. "Source Code Form" + + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, "control" means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. + + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights to + grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter the + recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, or + limitations of liability) contained within the Source Code Form of the + Covered Software, except that You may alter any license notices to the + extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, + judicial order, or regulation then You must: (a) comply with the terms of + this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be placed in a + text file included with all distributions of the Covered Software under + this License. Except to the extent prohibited by statute or regulation, + such description must be sufficiently detailed for a recipient of ordinary + skill to be able to understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing + basis, if such Contributor fails to notify You of the non-compliance by + some reasonable means prior to 60 days after You have come back into + compliance. Moreover, Your grants from a particular Contributor are + reinstated on an ongoing basis if such Contributor notifies You of the + non-compliance by some reasonable means, this is the first time You have + received notice of non-compliance with this License from such + Contributor, and You become compliant prior to 30 days after Your receipt + of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an "as is" basis, + without warranty of any kind, either expressed, implied, or statutory, + including, without limitation, warranties that the Covered Software is free + of defects, merchantable, fit for a particular purpose or non-infringing. + The entire risk as to the quality and performance of the Covered Software + is with You. Should any Covered Software prove defective in any respect, + You (not any Contributor) assume the cost of any necessary servicing, + repair, or correction. This disclaimer of warranty constitutes an essential + part of this License. No use of any Covered Software is authorized under + this License except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from + such party's negligence to the extent applicable law prohibits such + limitation. Some jurisdictions do not allow the exclusion or limitation of + incidental or consequential damages, so this exclusion and limitation may + not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts + of a jurisdiction where the defendant maintains its principal place of + business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. Nothing + in this Section shall prevent a party's ability to bring cross-claims or + counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides that + the language of a contract shall be construed against the drafter shall not + be used to construe this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses If You choose to distribute Source Code Form that is + Incompatible With Secondary Licenses under the terms of this version of + the License, the notice described in Exhibit B of this License must be + attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, +then You may include the notice in a location (such as a LICENSE file in a +relevant directory) where a recipient would be likely to look for such a +notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice + + This Source Code Form is "Incompatible + With Secondary Licenses", as defined by + the Mozilla Public License, v. 2.0. + diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-cleanhttp/README.md b/Godeps/_workspace/src/github.com/hashicorp/go-cleanhttp/README.md new file mode 100644 index 000000000..036e5313f --- /dev/null +++ b/Godeps/_workspace/src/github.com/hashicorp/go-cleanhttp/README.md @@ -0,0 +1,30 @@ +# cleanhttp + +Functions for accessing "clean" Go http.Client values + +------------- + +The Go standard library contains a default `http.Client` called +`http.DefaultClient`. It is a common idiom in Go code to start with +`http.DefaultClient` and tweak it as necessary, and in fact, this is +encouraged; from the `http` package documentation: + +> The Client's Transport typically has internal state (cached TCP connections), +so Clients should be reused instead of created as needed. Clients are safe for +concurrent use by multiple goroutines. + +Unfortunately, this is a shared value, and it is not uncommon for libraries to +assume that they are free to modify it at will. With enough dependencies, it +can be very easy to encounter strange problems and race conditions due to +manipulation of this shared value across libraries and goroutines (clients are +safe for concurrent use, but writing values to the client struct itself is not +protected). + +Making things worse is the fact that a bare `http.Client` will use a default +`http.Transport` called `http.DefaultTransport`, which is another global value +that behaves the same way. So it is not simply enough to replace +`http.DefaultClient` with `&http.Client{}`. + +This repository provides some simple functions to get a "clean" `http.Client` +-- one that uses the same default values as the Go standard library, but +returns a client that does not share any state with other clients. diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-cleanhttp/cleanhttp.go b/Godeps/_workspace/src/github.com/hashicorp/go-cleanhttp/cleanhttp.go new file mode 100644 index 000000000..1676d79cb --- /dev/null +++ b/Godeps/_workspace/src/github.com/hashicorp/go-cleanhttp/cleanhttp.go @@ -0,0 +1,28 @@ +package cleanhttp + +import ( + "net" + "net/http" + "time" +) + +// DefaultTransport returns a new http.Transport with the same default values +// as http.DefaultTransport +func DefaultTransport() *http.Transport { + return &http.Transport{ + Proxy: http.ProxyFromEnvironment, + Dial: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).Dial, + TLSHandshakeTimeout: 10 * time.Second, + } +} + +// DefaultClient returns a new http.Client with the same default values as +// http.Client, but with a non-shared Transport +func DefaultClient() *http.Client { + return &http.Client{ + Transport: DefaultTransport(), + } +} diff --git a/Godeps/_workspace/src/github.com/lib/pq/copy.go b/Godeps/_workspace/src/github.com/lib/pq/copy.go index e44fa48a5..101f11133 100644 --- a/Godeps/_workspace/src/github.com/lib/pq/copy.go +++ b/Godeps/_workspace/src/github.com/lib/pq/copy.go @@ -215,9 +215,7 @@ func (ci *copyin) Exec(v []driver.Value) (r driver.Result, err error) { } if len(v) == 0 { - err = ci.Close() - ci.closed = true - return nil, err + return nil, ci.Close() } numValues := len(v) @@ -240,9 +238,10 @@ func (ci *copyin) Exec(v []driver.Value) (r driver.Result, err error) { } func (ci *copyin) Close() (err error) { - if ci.closed { - return errCopyInClosed + if ci.closed { // Don't do anything, we're already closed + return nil } + ci.closed = true if ci.cn.bad { return driver.ErrBadConn diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/client_appengine.go b/Godeps/_workspace/src/golang.org/x/oauth2/client_appengine.go index 52f8d1dd6..8962c49d1 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/client_appengine.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/client_appengine.go @@ -1,4 +1,4 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/clientcredentials/clientcredentials.go b/Godeps/_workspace/src/golang.org/x/oauth2/clientcredentials/clientcredentials.go index fb55bcac8..a47e46559 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/clientcredentials/clientcredentials.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/clientcredentials/clientcredentials.go @@ -1,4 +1,4 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/facebook/facebook.go b/Godeps/_workspace/src/golang.org/x/oauth2/facebook/facebook.go index 9c816ff80..51c1480bd 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/facebook/facebook.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/facebook/facebook.go @@ -1,4 +1,4 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. +// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/github/github.go b/Godeps/_workspace/src/golang.org/x/oauth2/github/github.go index 82ca623dd..26502a368 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/github/github.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/github/github.go @@ -1,4 +1,4 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/google/appengine.go b/Godeps/_workspace/src/golang.org/x/oauth2/google/appengine.go index 855422154..dc993efb5 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/google/appengine.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/google/appengine.go @@ -1,4 +1,4 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/google/appengine_hook.go b/Godeps/_workspace/src/golang.org/x/oauth2/google/appengine_hook.go index 362766fdd..4f42c8b34 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/google/appengine_hook.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/google/appengine_hook.go @@ -1,4 +1,4 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. +// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/google/default.go b/Godeps/_workspace/src/golang.org/x/oauth2/google/default.go index 66daeefd5..b95236297 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/google/default.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/google/default.go @@ -1,4 +1,4 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. +// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/google/google.go b/Godeps/_workspace/src/golang.org/x/oauth2/google/google.go index 2077d9866..0bed73866 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/google/google.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/google/google.go @@ -1,4 +1,4 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/google/jwt.go b/Godeps/_workspace/src/golang.org/x/oauth2/google/jwt.go index 6f7ec3a1a..b91991786 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/google/jwt.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/google/jwt.go @@ -1,4 +1,4 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. +// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/google/sdk.go b/Godeps/_workspace/src/golang.org/x/oauth2/google/sdk.go index 01ba0ecb0..d29a3bb9b 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/google/sdk.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/google/sdk.go @@ -1,4 +1,4 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. +// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/internal/oauth2.go b/Godeps/_workspace/src/golang.org/x/oauth2/internal/oauth2.go index dc8ebfc4f..fbe1028d6 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/internal/oauth2.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/internal/oauth2.go @@ -1,4 +1,4 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/internal/token.go b/Godeps/_workspace/src/golang.org/x/oauth2/internal/token.go index db209d8e0..909d52a12 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/internal/token.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/internal/token.go @@ -1,4 +1,4 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/internal/transport.go b/Godeps/_workspace/src/golang.org/x/oauth2/internal/transport.go index 521e7b49e..33d366916 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/internal/transport.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/internal/transport.go @@ -1,4 +1,4 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/jws/jws.go b/Godeps/_workspace/src/golang.org/x/oauth2/jws/jws.go index a4595eb5e..797e2f3e1 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/jws/jws.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/jws/jws.go @@ -1,4 +1,4 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/jwt/jwt.go b/Godeps/_workspace/src/golang.org/x/oauth2/jwt/jwt.go index 11a2687ef..2ffad21a6 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/jwt/jwt.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/jwt/jwt.go @@ -1,4 +1,4 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/linkedin/linkedin.go b/Godeps/_workspace/src/golang.org/x/oauth2/linkedin/linkedin.go index d93fded6a..30c212b10 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/linkedin/linkedin.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/linkedin/linkedin.go @@ -1,4 +1,4 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. +// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/oauth2.go b/Godeps/_workspace/src/golang.org/x/oauth2/oauth2.go index dfcf238d2..b349276e6 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/oauth2.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/oauth2.go @@ -1,4 +1,4 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go b/Godeps/_workspace/src/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go index f0b66f97d..60741ce9d 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go @@ -1,4 +1,4 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. +// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/paypal/paypal.go b/Godeps/_workspace/src/golang.org/x/oauth2/paypal/paypal.go index a99366b6e..32308322f 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/paypal/paypal.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/paypal/paypal.go @@ -1,4 +1,4 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. +// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/token.go b/Godeps/_workspace/src/golang.org/x/oauth2/token.go index 4e596f0fc..7a3167f15 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/token.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/token.go @@ -1,4 +1,4 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/transport.go b/Godeps/_workspace/src/golang.org/x/oauth2/transport.go index 90db08833..92ac7e253 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/transport.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/transport.go @@ -1,4 +1,4 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/vk/vk.go b/Godeps/_workspace/src/golang.org/x/oauth2/vk/vk.go index 00e929357..6463482cf 100644 --- a/Godeps/_workspace/src/golang.org/x/oauth2/vk/vk.go +++ b/Godeps/_workspace/src/golang.org/x/oauth2/vk/vk.go @@ -1,4 +1,4 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. +// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file.