func TestConvertFromListError(t *testing.T) { // Test that we get an error using ConvertFromList to convert to a map. var actual map[string]interface{} expected := awserr.New("SerializationError", `v must be a non-nil pointer to an array or slice, got *map[string]interface {}`, nil).Error() if err := ConvertFromList(nil, &actual); err == nil { t.Errorf("ConvertFromList with input %#v returned no error, expected error `%s`", nil, expected) } else if err.Error() != expected { t.Errorf("ConvertFromList with input %#v returned error `%s`, expected error `%s`", nil, err, expected) } // Test that we get an error using ConvertFromList to convert to a struct. var actual2 myComplexStruct expected = awserr.New("SerializationError", `v must be a non-nil pointer to an array or slice, got *dynamodbattribute.myComplexStruct`, nil).Error() if err := ConvertFromList(nil, &actual2); err == nil { t.Errorf("ConvertFromList with input %#v returned no error, expected error `%s`", nil, expected) } else if err.Error() != expected { t.Errorf("ConvertFromList with input %#v returned error `%s`, expected error `%s`", nil, err, expected) } // Test that we get an error using ConvertFromList to convert to an interface{}. var actual3 interface{} expected = awserr.New("SerializationError", `v must be a non-nil pointer to an array or slice, got *interface {}`, nil).Error() if err := ConvertFromList(nil, &actual3); err == nil { t.Errorf("ConvertFromList with input %#v returned no error, expected error `%s`", nil, expected) } else if err.Error() != expected { t.Errorf("ConvertFromList with input %#v returned error `%s`, expected error `%s`", nil, err, expected) } }
func unmarshalError(r *request.Request) { defer r.HTTPResponse.Body.Close() if r.HTTPResponse.ContentLength == int64(0) { // No body, use status code to generate an awserr.Error r.Error = awserr.NewRequestFailure( awserr.New(strings.Replace(r.HTTPResponse.Status, " ", "", -1), r.HTTPResponse.Status, nil), r.HTTPResponse.StatusCode, "", ) return } resp := &xmlErrorResponse{} err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp) if err != nil && err != io.EOF { r.Error = awserr.New("SerializationError", "failed to decode SimpleDB XML error response", nil) } else if len(resp.Errors) == 0 { r.Error = awserr.New("MissingError", "missing error code in SimpleDB XML error response", nil) } else { // If there are multiple error codes, return only the first as the aws.Error interface only supports // one error code. r.Error = awserr.NewRequestFailure( awserr.New(resp.Errors[0].Code, resp.Errors[0].Message, nil), r.HTTPResponse.StatusCode, resp.RequestID, ) } }
func TestAfterRetryRefreshCreds(t *testing.T) { os.Clearenv() credProvider := &mockCredsProvider{} svc := awstesting.NewClient(&aws.Config{ Credentials: credentials.NewCredentials(credProvider), MaxRetries: aws.Int(1), }) svc.Handlers.Clear() svc.Handlers.ValidateResponse.PushBack(func(r *request.Request) { r.Error = awserr.New("UnknownError", "", nil) r.HTTPResponse = &http.Response{StatusCode: 400} }) svc.Handlers.UnmarshalError.PushBack(func(r *request.Request) { r.Error = awserr.New("ExpiredTokenException", "", nil) }) svc.Handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler) assert.True(t, svc.Config.Credentials.IsExpired(), "Expect to start out expired") assert.False(t, credProvider.retrieveCalled) req := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) req.Send() assert.True(t, svc.Config.Credentials.IsExpired()) assert.False(t, credProvider.retrieveCalled) _, err := svc.Config.Credentials.Get() assert.NoError(t, err) assert.True(t, credProvider.retrieveCalled) }
func unmarshalError(req *request.Request) { bodyBytes, err := ioutil.ReadAll(req.HTTPResponse.Body) if err != nil { req.Error = awserr.New("UnmarshaleError", req.HTTPResponse.Status, err) return } if len(bodyBytes) == 0 { req.Error = awserr.NewRequestFailure( awserr.New("UnmarshaleError", req.HTTPResponse.Status, fmt.Errorf("empty body")), req.HTTPResponse.StatusCode, "", ) return } var jsonErr jsonErrorResponse if err := json.Unmarshal(bodyBytes, &jsonErr); err != nil { req.Error = awserr.New("UnmarshaleError", "JSON unmarshal", err) return } req.Error = awserr.NewRequestFailure( awserr.New(jsonErr.Code, jsonErr.Message, nil), req.HTTPResponse.StatusCode, "", ) }
// loadProfiles loads from the file pointed to by shared credentials filename for profile. // The credentials retrieved from the profile will be returned or error. Error will be // returned if it fails to read from the file, or the data is invalid. func loadProfile(filename, profile string) (Value, error) { config, err := ini.Load(filename) if err != nil { return Value{}, awserr.New("SharedCredsLoad", "failed to load shared credentials file", err) } iniProfile, err := config.GetSection(profile) if err != nil { return Value{}, awserr.New("SharedCredsLoad", "failed to get profile", err) } id, err := iniProfile.GetKey("aws_access_key_id") if err != nil { return Value{}, awserr.New("SharedCredsAccessKey", fmt.Sprintf("shared credentials %s in %s did not contain aws_access_key_id", profile, filename), err) } secret, err := iniProfile.GetKey("aws_secret_access_key") if err != nil { return Value{}, awserr.New("SharedCredsSecret", fmt.Sprintf("shared credentials %s in %s did not contain aws_secret_access_key", profile, filename), nil) } // Default to empty string if not found token := iniProfile.Key("aws_session_token") return Value{ AccessKeyID: id.String(), SecretAccessKey: secret.String(), SessionToken: token.String(), }, nil }
// UnmarshalError unmarshals an error response for a JSON RPC service. func UnmarshalError(req *request.Request) { defer req.HTTPResponse.Body.Close() bodyBytes, err := ioutil.ReadAll(req.HTTPResponse.Body) if err != nil { req.Error = awserr.New("SerializationError", "failed reading JSON RPC error response", err) return } if len(bodyBytes) == 0 { req.Error = awserr.NewRequestFailure( awserr.New("SerializationError", req.HTTPResponse.Status, nil), req.HTTPResponse.StatusCode, "", ) return } var jsonErr jsonErrorResponse if err := json.Unmarshal(bodyBytes, &jsonErr); err != nil { req.Error = awserr.New("SerializationError", "failed decoding JSON RPC error response", err) return } codes := strings.SplitN(jsonErr.Code, "#", 2) req.Error = awserr.NewRequestFailure( awserr.New(codes[len(codes)-1], jsonErr.Message, nil), req.HTTPResponse.StatusCode, req.RequestID, ) }
// UnmarshalError unmarshals a response error for the REST JSON protocol. func UnmarshalError(r *request.Request) { code := r.HTTPResponse.Header.Get("X-Amzn-Errortype") bodyBytes, err := ioutil.ReadAll(r.HTTPResponse.Body) if err != nil { r.Error = awserr.New("SerializationError", "failed reading REST JSON error response", err) return } if len(bodyBytes) == 0 { r.Error = awserr.NewRequestFailure( awserr.New("SerializationError", r.HTTPResponse.Status, nil), r.HTTPResponse.StatusCode, "", ) return } var jsonErr jsonErrorResponse if err := json.Unmarshal(bodyBytes, &jsonErr); err != nil { r.Error = awserr.New("SerializationError", "failed decoding REST JSON error response", err) return } if code == "" { code = jsonErr.Code } code = strings.SplitN(code, ":", 2)[0] r.Error = awserr.NewRequestFailure( awserr.New(code, jsonErr.Message, nil), r.HTTPResponse.StatusCode, r.RequestID, ) }
// UnmarshalError unmarshals a response error for the EC2 protocol. func UnmarshalError(r *request.Request) { defer r.HTTPResponse.Body.Close() resp := &xmlErrorResponse{} err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp) if err != nil && err != io.EOF { r.Error = awserr.New("SerializationError", "failed decoding EC2 Query error response", err) } else { r.Error = awserr.NewRequestFailure( awserr.New(resp.Code, resp.Message, nil), r.HTTPResponse.StatusCode, resp.RequestID, ) } }
func buildQueryString(query url.Values, v reflect.Value, name string) error { switch value := v.Interface().(type) { case []*string: for _, item := range value { query.Add(name, *item) } case map[string]*string: for key, item := range value { query.Add(key, *item) } case map[string][]*string: for key, items := range value { for _, item := range items { query.Add(key, *item) } } default: str, err := convertType(v) if err == errValueNotSet { return nil } else if err != nil { return awserr.New("SerializationError", "failed to encode REST request", err) } query.Set(name, str) } return nil }
// Build builds a JSON payload for a JSON RPC request. func Build(req *request.Request) { var buf []byte var err error if req.ParamsFilled() { buf, err = jsonutil.BuildJSON(req.Params) if err != nil { req.Error = awserr.New("SerializationError", "failed encoding JSON RPC request", err) return } } else { buf = emptyJSON } if req.ClientInfo.TargetPrefix != "" || string(buf) != "{}" { req.SetBufferBody(buf) } if req.ClientInfo.TargetPrefix != "" { target := req.ClientInfo.TargetPrefix + "." + req.Operation.Name req.HTTPRequest.Header.Add("X-Amz-Target", target) } if req.ClientInfo.JSONVersion != "" { jsonVersion := req.ClientInfo.JSONVersion req.HTTPRequest.Header.Add("Content-Type", "application/x-amz-json-"+jsonVersion) } }
func unmarshalError(r *request.Request) { defer r.HTTPResponse.Body.Close() _, err := ioutil.ReadAll(r.HTTPResponse.Body) if err != nil { r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata error respose", err) } // TODO extract the error... }
// requestCredList requests a list of credentials from the EC2 service. // If there are no credentials, or there is an error making or receiving the request func requestCredList(client *ec2metadata.EC2Metadata) ([]string, error) { resp, err := client.GetMetadata(iamSecurityCredsPath) if err != nil { return nil, awserr.New("EC2RoleRequestError", "failed to list EC2 Roles", err) } credsList := []string{} s := bufio.NewScanner(strings.NewReader(resp)) for s.Scan() { credsList = append(credsList, s.Text()) } if err := s.Err(); err != nil { return nil, awserr.New("SerializationError", "failed to read list of EC2 Roles", err) } return credsList, nil }
func TestConvertFromMapError(t *testing.T) { // Test that we get an error using ConvertFromMap to convert to an interface{}. var actual interface{} expected := awserr.New("SerializationError", `v must be a non-nil pointer to a map[string]interface{} or struct, got *interface {}`, nil).Error() if err := ConvertFromMap(nil, &actual); err == nil { t.Errorf("ConvertFromMap with input %#v returned no error, expected error `%s`", nil, expected) } else if err.Error() != expected { t.Errorf("ConvertFromMap with input %#v returned error `%s`, expected error `%s`", nil, err, expected) } // Test that we get an error using ConvertFromMap to convert to a slice. var actual2 []interface{} expected = awserr.New("SerializationError", `v must be a non-nil pointer to a map[string]interface{} or struct, got *[]interface {}`, nil).Error() if err := ConvertFromMap(nil, &actual2); err == nil { t.Errorf("ConvertFromMap with input %#v returned no error, expected error `%s`", nil, expected) } else if err.Error() != expected { t.Errorf("ConvertFromMap with input %#v returned error `%s`, expected error `%s`", nil, err, expected) } }
// internal logic for deciding whether to upload a single part or use a // multipart upload. func (u *uploader) upload() (*UploadOutput, error) { u.init() if u.ctx.PartSize < MinUploadPartSize { msg := fmt.Sprintf("part size must be at least %d bytes", MinUploadPartSize) return nil, awserr.New("ConfigError", msg, nil) } // Do one read to determine if we have more than one part buf, err := u.nextReader() if err == io.EOF || err == io.ErrUnexpectedEOF { // single part return u.singlePart(buf) } else if err != nil { return nil, awserr.New("ReadRequestBody", "read upload data failed", err) } mu := multiuploader{uploader: u} return mu.upload(buf) }
// Unmarshal unmarshals a response for a JSON RPC service. func Unmarshal(req *request.Request) { defer req.HTTPResponse.Body.Close() if req.DataFilled() { err := jsonutil.UnmarshalJSON(req.Data, req.HTTPResponse.Body) if err != nil { req.Error = awserr.New("SerializationError", "failed decoding JSON RPC response", err) } } return }
func unmarshalHandler(r *request.Request) { defer r.HTTPResponse.Body.Close() b, err := ioutil.ReadAll(r.HTTPResponse.Body) if err != nil { r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata respose", err) } data := r.Data.(*metadataOutput) data.Content = string(b) }
func TestChainProviderWithNoValidProvider(t *testing.T) { errs := []error{ awserr.New("FirstError", "first provider error", nil), awserr.New("SecondError", "second provider error", nil), } p := &ChainProvider{ Providers: []Provider{ &stubProvider{err: errs[0]}, &stubProvider{err: errs[1]}, }, } assert.True(t, p.IsExpired(), "Expect expired with no providers") _, err := p.Retrieve() assert.Equal(t, ErrNoValidProvidersFoundInChain, err, "Expect no providers error returned") }
// Unmarshal unmarshals a response for an AWS Query service. func Unmarshal(r *request.Request) { defer r.HTTPResponse.Body.Close() if r.DataFilled() { decoder := xml.NewDecoder(r.HTTPResponse.Body) err := xmlutil.UnmarshalXML(r.Data, decoder, r.Operation.Name+"Result") if err != nil { r.Error = awserr.New("SerializationError", "failed decoding Query response", err) return } } }
// ConvertFromList accepts a []*dynamodb.AttributeValue and converts it to an array or // slice. // // If v contains any structs, the result is first converted it to a // []interface{}, then JSON encoded/decoded it to convert to a typed array or // slice, so `json` struct tags are respected. func ConvertFromList(item []*dynamodb.AttributeValue, v interface{}) (err error) { defer func() { if r := recover(); r != nil { if e, ok := r.(runtime.Error); ok { err = e } else if s, ok := r.(string); ok { err = fmt.Errorf(s) } else { err = r.(error) } item = nil } }() rv := reflect.ValueOf(v) if rv.Kind() != reflect.Ptr || rv.IsNil() { return awserr.New("SerializationError", fmt.Sprintf("v must be a non-nil pointer to an array or slice, got %s", rv.Type()), nil) } if rv.Elem().Kind() != reflect.Array && rv.Elem().Kind() != reflect.Slice { return awserr.New("SerializationError", fmt.Sprintf("v must be a non-nil pointer to an array or slice, got %s", rv.Type()), nil) } l := make([]interface{}, 0, len(item)) for _, v := range item { l = append(l, convertFrom(v)) } if isTyped(reflect.TypeOf(v)) { err = convertToTyped(l, v) } else { rv.Elem().Set(reflect.ValueOf(l)) } return err }
// ConvertFromMap accepts a map[string]*dynamodb.AttributeValue and converts it to a // map[string]interface{} or struct. // // If v points to a struct, the result is first converted it to a // map[string]interface{}, then JSON encoded/decoded it to convert to a struct, // so `json` struct tags are respected. func ConvertFromMap(item map[string]*dynamodb.AttributeValue, v interface{}) (err error) { defer func() { if r := recover(); r != nil { if e, ok := r.(runtime.Error); ok { err = e } else if s, ok := r.(string); ok { err = fmt.Errorf(s) } else { err = r.(error) } item = nil } }() rv := reflect.ValueOf(v) if rv.Kind() != reflect.Ptr || rv.IsNil() { return awserr.New("SerializationError", fmt.Sprintf("v must be a non-nil pointer to a map[string]interface{} or struct, got %s", rv.Type()), nil) } if rv.Elem().Kind() != reflect.Struct && !(rv.Elem().Kind() == reflect.Map && rv.Elem().Type().Key().Kind() == reflect.String) { return awserr.New("SerializationError", fmt.Sprintf("v must be a non-nil pointer to a map[string]interface{} or struct, got %s", rv.Type()), nil) } m := make(map[string]interface{}) for k, v := range item { m[k] = convertFrom(v) } if isTyped(reflect.TypeOf(v)) { err = convertToTyped(m, v) } else { rv.Elem().Set(reflect.ValueOf(m)) } return err }
func buildHeader(header *http.Header, v reflect.Value, name string) error { str, err := convertType(v) if err == errValueNotSet { return nil } else if err != nil { return awserr.New("SerializationError", "failed to encode REST request", err) } header.Add(name, str) return nil }
func TestChainProviderGet(t *testing.T) { p := &ChainProvider{ Providers: []Provider{ &stubProvider{err: awserr.New("FirstError", "first provider error", nil)}, &stubProvider{err: awserr.New("SecondError", "second provider error", nil)}, &stubProvider{ creds: Value{ AccessKeyID: "AKID", SecretAccessKey: "SECRET", SessionToken: "", }, }, }, } creds, err := p.Retrieve() assert.Nil(t, err, "Expect no error") assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match") assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match") assert.Empty(t, creds.SessionToken, "Expect session token to be empty") }
func TestChainProviderWithNoValidProviderWithVerboseEnabled(t *testing.T) { errs := []error{ awserr.New("FirstError", "first provider error", nil), awserr.New("SecondError", "second provider error", nil), } p := &ChainProvider{ VerboseErrors: true, Providers: []Provider{ &stubProvider{err: errs[0]}, &stubProvider{err: errs[1]}, }, } assert.True(t, p.IsExpired(), "Expect expired with no providers") _, err := p.Retrieve() assert.Equal(t, awserr.NewBatchError("NoCredentialProviders", "no valid providers in chain", errs), err, "Expect no providers error returned") }
// ConvertToList accepts an array or slice and converts it to a // []*dynamodb.AttributeValue. // // If in contains any structs, it is first JSON encoded/decoded it to convert it // to a []interface{}, so `json` struct tags are respected. func ConvertToList(in interface{}) (item []*dynamodb.AttributeValue, err error) { defer func() { if r := recover(); r != nil { if e, ok := r.(runtime.Error); ok { err = e } else if s, ok := r.(string); ok { err = fmt.Errorf(s) } else { err = r.(error) } item = nil } }() if in == nil { return nil, awserr.New("SerializationError", "in must be an array or slice, got <nil>", nil) } v := reflect.ValueOf(in) if v.Kind() != reflect.Array && v.Kind() != reflect.Slice { return nil, awserr.New("SerializationError", fmt.Sprintf("in must be an array or slice, got %s", v.Type().String()), nil) } if isTyped(reflect.TypeOf(in)) { var out []interface{} in = convertToUntyped(in, out) } item = make([]*dynamodb.AttributeValue, 0, len(in.([]interface{}))) for _, v := range in.([]interface{}) { item = append(item, convertTo(v)) } return item, nil }
func unmarshalBody(r *request.Request, v reflect.Value) { if field, ok := v.Type().FieldByName("_"); ok { if payloadName := field.Tag.Get("payload"); payloadName != "" { pfield, _ := v.Type().FieldByName(payloadName) if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" { payload := v.FieldByName(payloadName) if payload.IsValid() { switch payload.Interface().(type) { case []byte: b, err := ioutil.ReadAll(r.HTTPResponse.Body) if err != nil { r.Error = awserr.New("SerializationError", "failed to decode REST response", err) } else { payload.Set(reflect.ValueOf(b)) } case *string: b, err := ioutil.ReadAll(r.HTTPResponse.Body) if err != nil { r.Error = awserr.New("SerializationError", "failed to decode REST response", err) } else { str := string(b) payload.Set(reflect.ValueOf(&str)) } default: switch payload.Type().String() { case "io.ReadSeeker": payload.Set(reflect.ValueOf(aws.ReadSeekCloser(r.HTTPResponse.Body))) case "aws.ReadSeekCloser", "io.ReadCloser": payload.Set(reflect.ValueOf(r.HTTPResponse.Body)) default: r.Error = awserr.New("SerializationError", "failed to decode REST response", fmt.Errorf("unknown payload type %s", payload.Type())) } } } } } } }
// ConvertToMap accepts a map[string]interface{} or struct and converts it to a // map[string]*dynamodb.AttributeValue. // // If in contains any structs, it is first JSON encoded/decoded it to convert it // to a map[string]interface{}, so `json` struct tags are respected. func ConvertToMap(in interface{}) (item map[string]*dynamodb.AttributeValue, err error) { defer func() { if r := recover(); r != nil { if e, ok := r.(runtime.Error); ok { err = e } else if s, ok := r.(string); ok { err = fmt.Errorf(s) } else { err = r.(error) } item = nil } }() if in == nil { return nil, awserr.New("SerializationError", "in must be a map[string]interface{} or struct, got <nil>", nil) } v := reflect.ValueOf(in) if v.Kind() != reflect.Struct && !(v.Kind() == reflect.Map && v.Type().Key().Kind() == reflect.String) { return nil, awserr.New("SerializationError", fmt.Sprintf("in must be a map[string]interface{} or struct, got %s", v.Type().String()), nil) } if isTyped(reflect.TypeOf(in)) { var out map[string]interface{} in = convertToUntyped(in, out) } item = make(map[string]*dynamodb.AttributeValue) for k, v := range in.(map[string]interface{}) { item[k] = convertTo(v) } return item, nil }
// Build builds a request payload for the REST XML protocol. func Build(r *request.Request) { rest.Build(r) if t := rest.PayloadType(r.Params); t == "structure" || t == "" { var buf bytes.Buffer err := xmlutil.BuildXML(r.Params, xml.NewEncoder(&buf)) if err != nil { r.Error = awserr.New("SerializationError", "failed to encode rest XML request", err) return } r.SetBufferBody(buf.Bytes()) } }
// Unmarshal unmarshals a payload response for the REST XML protocol. func Unmarshal(r *request.Request) { if t := rest.PayloadType(r.Data); t == "structure" || t == "" { defer r.HTTPResponse.Body.Close() decoder := xml.NewDecoder(r.HTTPResponse.Body) err := xmlutil.UnmarshalXML(r.Data, decoder, "") if err != nil { r.Error = awserr.New("SerializationError", "failed to decode REST XML response", err) return } } else { rest.Unmarshal(r) } }
// ConvertFrom accepts a *dynamodb.AttributeValue and converts it to any interface{}. // // If v contains any structs, the result is first converted it to a interface{}, // then JSON encoded/decoded it to convert to a struct, so `json` struct tags // are respected. func ConvertFrom(item *dynamodb.AttributeValue, v interface{}) (err error) { defer func() { if r := recover(); r != nil { if e, ok := r.(runtime.Error); ok { err = e } else if s, ok := r.(string); ok { err = fmt.Errorf(s) } else { err = r.(error) } item = nil } }() rv := reflect.ValueOf(v) if rv.Kind() != reflect.Ptr || rv.IsNil() { return awserr.New("SerializationError", fmt.Sprintf("v must be a non-nil pointer to an interface{} or struct, got %s", rv.Type()), nil) } if rv.Elem().Kind() != reflect.Interface && rv.Elem().Kind() != reflect.Struct { return awserr.New("SerializationError", fmt.Sprintf("v must be a non-nil pointer to an interface{} or struct, got %s", rv.Type()), nil) } res := convertFrom(item) if isTyped(reflect.TypeOf(v)) { err = convertToTyped(res, v) } else if res != nil { rv.Elem().Set(reflect.ValueOf(res)) } return err }
// contentMD5 computes and sets the HTTP Content-MD5 header for requests that // require it. func contentMD5(r *request.Request) { h := md5.New() // hash the body. seek back to the first position after reading to reset // the body for transmission. copy errors may be assumed to be from the // body. _, err := io.Copy(h, r.Body) if err != nil { r.Error = awserr.New("ContentMD5", "failed to read body", err) return } _, err = r.Body.Seek(0, 0) if err != nil { r.Error = awserr.New("ContentMD5", "failed to seek body", err) return } // encode the md5 checksum in base64 and set the request header. sum := h.Sum(nil) sum64 := make([]byte, base64.StdEncoding.EncodedLen(len(sum))) base64.StdEncoding.Encode(sum64, sum) r.HTTPRequest.Header.Set("Content-MD5", string(sum64)) }