Update Go AWS SDK to the latest version

This commit is contained in:
Andrey Smirnov
2019-07-13 00:03:55 +03:00
committed by Andrey Smirnov
parent d08be990ef
commit 94a72b23ff
2183 changed files with 885887 additions and 228114 deletions
+21 -11
View File
@@ -13,9 +13,13 @@ import (
"github.com/aws/aws-sdk-go/private/protocol"
)
// BuildXML will serialize params into an xml.Encoder.
// Error will be returned if the serialization of any of the params or nested values fails.
// BuildXML will serialize params into an xml.Encoder. Error will be returned
// if the serialization of any of the params or nested values fails.
func BuildXML(params interface{}, e *xml.Encoder) error {
return buildXML(params, e, false)
}
func buildXML(params interface{}, e *xml.Encoder, sorted bool) error {
b := xmlBuilder{encoder: e, namespaces: map[string]string{}}
root := NewXMLElement(xml.Name{})
if err := b.buildValue(reflect.ValueOf(params), root, ""); err != nil {
@@ -23,7 +27,7 @@ func BuildXML(params interface{}, e *xml.Encoder) error {
}
for _, c := range root.Children {
for _, v := range c {
return StructToXML(e, v, false)
return StructToXML(e, v, sorted)
}
}
return nil
@@ -83,15 +87,13 @@ func (b *xmlBuilder) buildValue(value reflect.Value, current *XMLNode, tag refle
}
}
// buildStruct adds a struct and its fields to the current XMLNode. All fields any any nested
// buildStruct adds a struct and its fields to the current XMLNode. All fields and any nested
// types are converted to XMLNodes also.
func (b *xmlBuilder) buildStruct(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
if !value.IsValid() {
return nil
}
fieldAdded := false
// unwrap payloads
if payload := tag.Get("payload"); payload != "" {
field, _ := value.Type().FieldByName(payload)
@@ -119,6 +121,8 @@ func (b *xmlBuilder) buildStruct(value reflect.Value, current *XMLNode, tag refl
child.Attr = append(child.Attr, ns)
}
var payloadFields, nonPayloadFields int
t := value.Type()
for i := 0; i < value.NumField(); i++ {
member := elemOf(value.Field(i))
@@ -133,8 +137,10 @@ func (b *xmlBuilder) buildStruct(value reflect.Value, current *XMLNode, tag refl
mTag := field.Tag
if mTag.Get("location") != "" { // skip non-body members
nonPayloadFields++
continue
}
payloadFields++
if protocol.CanSetIdempotencyToken(value.Field(i), field) {
token := protocol.GetIdempotencyToken()
@@ -149,11 +155,11 @@ func (b *xmlBuilder) buildStruct(value reflect.Value, current *XMLNode, tag refl
if err := b.buildValue(member, child, mTag); err != nil {
return err
}
fieldAdded = true
}
if fieldAdded { // only append this child if we have one ore more valid members
// Only case where the child shape is not added is if the shape only contains
// non-payload fields, e.g headers/query.
if !(payloadFields == 0 && nonPayloadFields > 0) {
current.AddChild(child)
}
@@ -278,8 +284,12 @@ func (b *xmlBuilder) buildScalar(value reflect.Value, current *XMLNode, tag refl
case float32:
str = strconv.FormatFloat(float64(converted), 'f', -1, 32)
case time.Time:
const ISO8601UTC = "2006-01-02T15:04:05Z"
str = converted.UTC().Format(ISO8601UTC)
format := tag.Get("timestampFormat")
if len(format) == 0 {
format = protocol.ISO8601TimeFormatName
}
str = protocol.FormatTime(format, converted)
default:
return fmt.Errorf("unsupported value for param %s: %v (%s)",
tag.Get("locationName"), value.Interface(), value.Type().Name())
@@ -0,0 +1,170 @@
// +build go1.7
package xmlutil
import (
"bytes"
"encoding/xml"
"testing"
"github.com/aws/aws-sdk-go/aws"
)
type implicitPayload struct {
_ struct{} `type:"structure"`
StrVal *string `type:"string"`
Second *nestedType `type:"structure"`
Third *nestedType `type:"structure"`
}
type namedImplicitPayload struct {
_ struct{} `type:"structure" locationName:"namedPayload"`
StrVal *string `type:"string"`
Second *nestedType `type:"structure"`
Third *nestedType `type:"structure"`
}
type explicitPayload struct {
_ struct{} `type:"structure" payload:"Second"`
Second *nestedType `type:"structure" locationName:"Second"`
}
type useEmptyNested struct {
_ struct{} `type:"structure" locationName:"useEmptyNested"`
StrVal *string `type:"string"`
Empty *emptyType `type:"structure"`
}
type useIgnoreNested struct {
_ struct{} `type:"structure" locationName:"useIgnoreNested"`
StrVal *string `type:"string"`
Ignore *ignoreNested `type:"structure"`
}
type skipNonPayload struct {
_ struct{} `type:"structure" locationName:"skipNonPayload"`
Field *string `type:"string" location:"header"`
}
type namedEmptyPayload struct {
_ struct{} `type:"structure" locationName:"namedEmptyPayload"`
}
type nestedType struct {
_ struct{} `type:"structure"`
IntVal *int64 `type:"integer"`
StrVal *string `type:"string"`
}
type emptyType struct {
_ struct{} `type:"structure"`
}
type ignoreNested struct {
_ struct{} `type:"structure"`
IgnoreMe *string `type:"string" ignore:"true"`
}
func TestBuildXML(t *testing.T) {
cases := map[string]struct {
Input interface{}
Expect string
}{
"explicit payload": {
Input: &explicitPayload{
Second: &nestedType{
IntVal: aws.Int64(1234),
StrVal: aws.String("string value"),
},
},
Expect: `<Second><IntVal>1234</IntVal><StrVal>string value</StrVal></Second>`,
},
"implicit payload": {
Input: &implicitPayload{
StrVal: aws.String("string value"),
Second: &nestedType{
IntVal: aws.Int64(1111),
StrVal: aws.String("second string"),
},
Third: &nestedType{
IntVal: aws.Int64(2222),
StrVal: aws.String("third string"),
},
},
Expect: `<Second><IntVal>1111</IntVal><StrVal>second string</StrVal></Second><StrVal>string value</StrVal><Third><IntVal>2222</IntVal><StrVal>third string</StrVal></Third>`,
},
"named implicit payload": {
Input: &namedImplicitPayload{
StrVal: aws.String("string value"),
Second: &nestedType{
IntVal: aws.Int64(1111),
StrVal: aws.String("second string"),
},
Third: &nestedType{
IntVal: aws.Int64(2222),
StrVal: aws.String("third string"),
},
},
Expect: `<namedPayload><Second><IntVal>1111</IntVal><StrVal>second string</StrVal></Second><StrVal>string value</StrVal><Third><IntVal>2222</IntVal><StrVal>third string</StrVal></Third></namedPayload>`,
},
"empty with fields nested type": {
Input: &namedImplicitPayload{
StrVal: aws.String("string value"),
Second: &nestedType{},
Third: &nestedType{
IntVal: aws.Int64(2222),
StrVal: aws.String("third string"),
},
},
Expect: `<namedPayload><Second></Second><StrVal>string value</StrVal><Third><IntVal>2222</IntVal><StrVal>third string</StrVal></Third></namedPayload>`,
},
"empty no fields nested type": {
Input: &useEmptyNested{
StrVal: aws.String("string value"),
Empty: &emptyType{},
},
Expect: `<useEmptyNested><Empty></Empty><StrVal>string value</StrVal></useEmptyNested>`,
},
"ignored nested field": {
Input: &useIgnoreNested{
StrVal: aws.String("string value"),
Ignore: &ignoreNested{
IgnoreMe: aws.String("abc123"),
},
},
Expect: `<useIgnoreNested><Ignore></Ignore><StrVal>string value</StrVal></useIgnoreNested>`,
},
"skip non payload root": {
Input: &skipNonPayload{
Field: aws.String("value"),
},
Expect: "",
},
"skip empty root": {
Input: &emptyType{},
Expect: "",
},
"named empty payload": {
Input: &namedEmptyPayload{},
Expect: "<namedEmptyPayload></namedEmptyPayload>",
},
}
for name, c := range cases {
t.Run(name, func(t *testing.T) {
var w bytes.Buffer
if err := buildXML(c.Input, xml.NewEncoder(&w), true); err != nil {
t.Fatalf("expect no error, %v", err)
}
if e, a := c.Expect, w.String(); e != a {
t.Errorf("expect:\n%s\nactual:\n%s\n", e, a)
}
})
}
}
+35 -4
View File
@@ -1,6 +1,7 @@
package xmlutil
import (
"bytes"
"encoding/base64"
"encoding/xml"
"fmt"
@@ -9,8 +10,28 @@ import (
"strconv"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/private/protocol"
)
// UnmarshalXMLError unmarshals the XML error from the stream into the value
// type specified. The value must be a pointer. If the message fails to
// unmarshal, the message content will be included in the returned error as a
// awserr.UnmarshalError.
func UnmarshalXMLError(v interface{}, stream io.Reader) error {
var errBuf bytes.Buffer
body := io.TeeReader(stream, &errBuf)
err := xml.NewDecoder(body).Decode(v)
if err != nil && err != io.EOF {
return awserr.NewUnmarshalError(err,
"failed to unmarshal error message", errBuf.Bytes())
}
return nil
}
// UnmarshalXML deserializes an xml.Decoder into the container v. V
// needs to match the shape of the XML expected to be decoded.
// If the shape doesn't match unmarshaling will fail.
@@ -52,9 +73,15 @@ func parse(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
if t == "" {
switch rtype.Kind() {
case reflect.Struct:
t = "structure"
// also it can't be a time object
if _, ok := r.Interface().(*time.Time); !ok {
t = "structure"
}
case reflect.Slice:
t = "list"
// also it can't be a byte slice
if _, ok := r.Interface().([]byte); !ok {
t = "list"
}
case reflect.Map:
t = "map"
}
@@ -247,8 +274,12 @@ func parseScalar(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
}
r.Set(reflect.ValueOf(&v))
case *time.Time:
const ISO8601UTC = "2006-01-02T15:04:05Z"
t, err := time.Parse(ISO8601UTC, node.Text)
format := tag.Get("timestampFormat")
if len(format) == 0 {
format = protocol.ISO8601TimeFormatName
}
t, err := protocol.ParseTime(format, node.Text)
if err != nil {
return err
}
@@ -29,6 +29,7 @@ func NewXMLElement(name xml.Name) *XMLNode {
// AddChild adds child to the XMLNode.
func (n *XMLNode) AddChild(child *XMLNode) {
child.parent = n
if _, ok := n.Children[child.Name.Local]; !ok {
n.Children[child.Name.Local] = []*XMLNode{}
}