mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-05-07 22:20:24 +00:00
Update Go AWS SDK to the latest version
This commit is contained in:
committed by
Andrey Smirnov
parent
d08be990ef
commit
94a72b23ff
+21
-11
@@ -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())
|
||||
|
||||
+170
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
+1
@@ -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{}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user