mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
* Added registrar support to Route53 provider * ran gofmt on route53Provider * Caveat: If you use r53 is a Registrar but not as a Dns Service Provider, DNSControl may be DNS-related API calls that you do not have IAM permissions to do.
This commit is contained in:
committed by
Tom Limoncelli
parent
8cff3128ea
commit
7f01a8c9ad
@ -3,6 +3,7 @@ package route53
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -12,20 +13,34 @@ import (
|
|||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
|
"github.com/aws/aws-sdk-go/private/waiter"
|
||||||
r53 "github.com/aws/aws-sdk-go/service/route53"
|
r53 "github.com/aws/aws-sdk-go/service/route53"
|
||||||
|
r53d "github.com/aws/aws-sdk-go/service/route53domains"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type route53Provider struct {
|
type route53Provider struct {
|
||||||
client *r53.Route53
|
client *r53.Route53
|
||||||
|
registrar *r53d.Route53Domains
|
||||||
zones map[string]*r53.HostedZone
|
zones map[string]*r53.HostedZone
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRoute53(m map[string]string, metadata json.RawMessage) (providers.DNSServiceProvider, error) {
|
func newRoute53Reg(conf map[string]string) (providers.Registrar, error) {
|
||||||
|
return newRoute53(conf, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRoute53Dsp(conf map[string]string, metadata json.RawMessage) (providers.DNSServiceProvider, error) {
|
||||||
|
return newRoute53(conf, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRoute53(m map[string]string, metadata json.RawMessage) (*route53Provider, error) {
|
||||||
keyId, secretKey := m["KeyId"], m["SecretKey"]
|
keyId, secretKey := m["KeyId"], m["SecretKey"]
|
||||||
|
|
||||||
|
// Route53 uses a global endpoint and route53domains
|
||||||
|
// currently only has a single regional endpoint in us-east-1
|
||||||
|
// http://docs.aws.amazon.com/general/latest/gr/rande.html#r53_region
|
||||||
config := &aws.Config{
|
config := &aws.Config{
|
||||||
Region: aws.String("us-west-2"),
|
Region: aws.String("us-east-1"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if keyId != "" || secretKey != "" {
|
if keyId != "" || secretKey != "" {
|
||||||
@ -33,7 +48,7 @@ func newRoute53(m map[string]string, metadata json.RawMessage) (providers.DNSSer
|
|||||||
}
|
}
|
||||||
sess := session.New(config)
|
sess := session.New(config)
|
||||||
|
|
||||||
api := &route53Provider{client: r53.New(sess)}
|
api := &route53Provider{client: r53.New(sess), registrar: r53d.New(sess)}
|
||||||
err := api.getZones()
|
err := api.getZones()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -42,8 +57,10 @@ func newRoute53(m map[string]string, metadata json.RawMessage) (providers.DNSSer
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
providers.RegisterDomainServiceProviderType("ROUTE53", newRoute53, providers.CanUsePTR, providers.CanUseSRV)
|
providers.RegisterDomainServiceProviderType("ROUTE53", newRoute53Dsp, providers.CanUsePTR, providers.CanUseSRV)
|
||||||
|
providers.RegisterRegistrarType("ROUTE53", newRoute53Reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sPtr(s string) *string {
|
func sPtr(s string) *string {
|
||||||
return &s
|
return &s
|
||||||
}
|
}
|
||||||
@ -249,6 +266,69 @@ func (r *route53Provider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *route53Provider) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||||
|
corrections := []*models.Correction{}
|
||||||
|
actualSet, err := r.getRegistrarNameservers(&dc.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sort.Strings(actualSet)
|
||||||
|
actual := strings.Join(actualSet, ",")
|
||||||
|
|
||||||
|
expectedSet := []string{}
|
||||||
|
for _, ns := range dc.Nameservers {
|
||||||
|
expectedSet = append(expectedSet, ns.Name)
|
||||||
|
}
|
||||||
|
sort.Strings(expectedSet)
|
||||||
|
expected := strings.Join(expectedSet, ",")
|
||||||
|
|
||||||
|
if actual != expected {
|
||||||
|
return []*models.Correction{
|
||||||
|
{
|
||||||
|
Msg: fmt.Sprintf("Update nameservers %s -> %s", actual, expected),
|
||||||
|
F: func() error {
|
||||||
|
operationId, err := r.updateRegistrarNameservers(dc.Name, expectedSet)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.waitUntilNameserversUpdate(operationId)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return corrections, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *route53Provider) getRegistrarNameservers(domainName *string) ([]string, error) {
|
||||||
|
domainDetail, err := r.registrar.GetDomainDetail(&r53d.GetDomainDetailInput{DomainName: domainName})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nameservers := []string{}
|
||||||
|
for _, ns := range domainDetail.Nameservers {
|
||||||
|
nameservers = append(nameservers, *ns.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nameservers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *route53Provider) updateRegistrarNameservers(domainName string, nameservers []string) (*string, error) {
|
||||||
|
servers := []*r53d.Nameserver{}
|
||||||
|
for i := range nameservers {
|
||||||
|
servers = append(servers, &r53d.Nameserver{Name: &nameservers[i]})
|
||||||
|
}
|
||||||
|
|
||||||
|
domainUpdate, err := r.registrar.UpdateDomainNameservers(&r53d.UpdateDomainNameserversInput{DomainName: &domainName, Nameservers: servers})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return domainUpdate.OperationId, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *route53Provider) fetchRecordSets(zoneID *string) ([]*r53.ResourceRecordSet, error) {
|
func (r *route53Provider) fetchRecordSets(zoneID *string) ([]*r53.ResourceRecordSet, error) {
|
||||||
if zoneID == nil || *zoneID == "" {
|
if zoneID == nil || *zoneID == "" {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -301,3 +381,31 @@ func (r *route53Provider) EnsureDomainExists(domain string) error {
|
|||||||
return err
|
return err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *route53Provider) waitUntilNameserversUpdate(operationId *string) error {
|
||||||
|
fmt.Print("Waiting for registrar update to complete...")
|
||||||
|
|
||||||
|
waiterCfg := waiter.Config{
|
||||||
|
Operation: "GetOperationDetail",
|
||||||
|
Delay: 30,
|
||||||
|
MaxAttempts: 10,
|
||||||
|
Acceptors: []waiter.WaitAcceptor{
|
||||||
|
{
|
||||||
|
State: "success",
|
||||||
|
Matcher: "path",
|
||||||
|
Argument: "Status",
|
||||||
|
Expected: "SUCCESSFUL",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
w := waiter.Waiter{
|
||||||
|
Client: r.registrar,
|
||||||
|
Input: &r53d.GetOperationDetailInput{
|
||||||
|
OperationId: operationId,
|
||||||
|
},
|
||||||
|
Config: waiterCfg,
|
||||||
|
}
|
||||||
|
|
||||||
|
return w.Wait()
|
||||||
|
}
|
||||||
|
279
vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go
generated
vendored
Normal file
279
vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go
generated
vendored
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
// Package jsonutil provides JSON serialization of AWS requests and responses.
|
||||||
|
package jsonutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/private/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
var timeType = reflect.ValueOf(time.Time{}).Type()
|
||||||
|
var byteSliceType = reflect.ValueOf([]byte{}).Type()
|
||||||
|
|
||||||
|
// BuildJSON builds a JSON string for a given object v.
|
||||||
|
func BuildJSON(v interface{}) ([]byte, error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
err := buildAny(reflect.ValueOf(v), &buf, "")
|
||||||
|
return buf.Bytes(), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildAny(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
|
||||||
|
origVal := value
|
||||||
|
value = reflect.Indirect(value)
|
||||||
|
if !value.IsValid() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
vtype := value.Type()
|
||||||
|
|
||||||
|
t := tag.Get("type")
|
||||||
|
if t == "" {
|
||||||
|
switch vtype.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
// also it can't be a time object
|
||||||
|
if value.Type() != timeType {
|
||||||
|
t = "structure"
|
||||||
|
}
|
||||||
|
case reflect.Slice:
|
||||||
|
// also it can't be a byte slice
|
||||||
|
if _, ok := value.Interface().([]byte); !ok {
|
||||||
|
t = "list"
|
||||||
|
}
|
||||||
|
case reflect.Map:
|
||||||
|
t = "map"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t {
|
||||||
|
case "structure":
|
||||||
|
if field, ok := vtype.FieldByName("_"); ok {
|
||||||
|
tag = field.Tag
|
||||||
|
}
|
||||||
|
return buildStruct(value, buf, tag)
|
||||||
|
case "list":
|
||||||
|
return buildList(value, buf, tag)
|
||||||
|
case "map":
|
||||||
|
return buildMap(value, buf, tag)
|
||||||
|
default:
|
||||||
|
return buildScalar(origVal, buf, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildStruct(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
|
||||||
|
if !value.IsValid() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// unwrap payloads
|
||||||
|
if payload := tag.Get("payload"); payload != "" {
|
||||||
|
field, _ := value.Type().FieldByName(payload)
|
||||||
|
tag = field.Tag
|
||||||
|
value = elemOf(value.FieldByName(payload))
|
||||||
|
|
||||||
|
if !value.IsValid() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteByte('{')
|
||||||
|
|
||||||
|
t := value.Type()
|
||||||
|
first := true
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
member := value.Field(i)
|
||||||
|
|
||||||
|
// This allocates the most memory.
|
||||||
|
// Additionally, we cannot skip nil fields due to
|
||||||
|
// idempotency auto filling.
|
||||||
|
field := t.Field(i)
|
||||||
|
|
||||||
|
if field.PkgPath != "" {
|
||||||
|
continue // ignore unexported fields
|
||||||
|
}
|
||||||
|
if field.Tag.Get("json") == "-" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if field.Tag.Get("location") != "" {
|
||||||
|
continue // ignore non-body elements
|
||||||
|
}
|
||||||
|
if field.Tag.Get("ignore") != "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if protocol.CanSetIdempotencyToken(member, field) {
|
||||||
|
token := protocol.GetIdempotencyToken()
|
||||||
|
member = reflect.ValueOf(&token)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (member.Kind() == reflect.Ptr || member.Kind() == reflect.Slice || member.Kind() == reflect.Map) && member.IsNil() {
|
||||||
|
continue // ignore unset fields
|
||||||
|
}
|
||||||
|
|
||||||
|
if first {
|
||||||
|
first = false
|
||||||
|
} else {
|
||||||
|
buf.WriteByte(',')
|
||||||
|
}
|
||||||
|
|
||||||
|
// figure out what this field is called
|
||||||
|
name := field.Name
|
||||||
|
if locName := field.Tag.Get("locationName"); locName != "" {
|
||||||
|
name = locName
|
||||||
|
}
|
||||||
|
|
||||||
|
writeString(name, buf)
|
||||||
|
buf.WriteString(`:`)
|
||||||
|
|
||||||
|
err := buildAny(member, buf, field.Tag)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString("}")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildList(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
|
||||||
|
buf.WriteString("[")
|
||||||
|
|
||||||
|
for i := 0; i < value.Len(); i++ {
|
||||||
|
buildAny(value.Index(i), buf, "")
|
||||||
|
|
||||||
|
if i < value.Len()-1 {
|
||||||
|
buf.WriteString(",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString("]")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type sortedValues []reflect.Value
|
||||||
|
|
||||||
|
func (sv sortedValues) Len() int { return len(sv) }
|
||||||
|
func (sv sortedValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
|
||||||
|
func (sv sortedValues) Less(i, j int) bool { return sv[i].String() < sv[j].String() }
|
||||||
|
|
||||||
|
func buildMap(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
|
||||||
|
buf.WriteString("{")
|
||||||
|
|
||||||
|
sv := sortedValues(value.MapKeys())
|
||||||
|
sort.Sort(sv)
|
||||||
|
|
||||||
|
for i, k := range sv {
|
||||||
|
if i > 0 {
|
||||||
|
buf.WriteByte(',')
|
||||||
|
}
|
||||||
|
|
||||||
|
writeString(k.String(), buf)
|
||||||
|
buf.WriteString(`:`)
|
||||||
|
|
||||||
|
buildAny(value.MapIndex(k), buf, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString("}")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildScalar(v reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
|
||||||
|
// prevents allocation on the heap.
|
||||||
|
scratch := [64]byte{}
|
||||||
|
switch value := reflect.Indirect(v); value.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
writeString(value.String(), buf)
|
||||||
|
case reflect.Bool:
|
||||||
|
if value.Bool() {
|
||||||
|
buf.WriteString("true")
|
||||||
|
} else {
|
||||||
|
buf.WriteString("false")
|
||||||
|
}
|
||||||
|
case reflect.Int64:
|
||||||
|
buf.Write(strconv.AppendInt(scratch[:0], value.Int(), 10))
|
||||||
|
case reflect.Float64:
|
||||||
|
f := value.Float()
|
||||||
|
if math.IsInf(f, 0) || math.IsNaN(f) {
|
||||||
|
return &json.UnsupportedValueError{Value: v, Str: strconv.FormatFloat(f, 'f', -1, 64)}
|
||||||
|
}
|
||||||
|
buf.Write(strconv.AppendFloat(scratch[:0], f, 'f', -1, 64))
|
||||||
|
default:
|
||||||
|
switch value.Type() {
|
||||||
|
case timeType:
|
||||||
|
converted := v.Interface().(*time.Time)
|
||||||
|
|
||||||
|
buf.Write(strconv.AppendInt(scratch[:0], converted.UTC().Unix(), 10))
|
||||||
|
case byteSliceType:
|
||||||
|
if !value.IsNil() {
|
||||||
|
converted := value.Interface().([]byte)
|
||||||
|
buf.WriteByte('"')
|
||||||
|
if len(converted) < 1024 {
|
||||||
|
// for small buffers, using Encode directly is much faster.
|
||||||
|
dst := make([]byte, base64.StdEncoding.EncodedLen(len(converted)))
|
||||||
|
base64.StdEncoding.Encode(dst, converted)
|
||||||
|
buf.Write(dst)
|
||||||
|
} else {
|
||||||
|
// for large buffers, avoid unnecessary extra temporary
|
||||||
|
// buffer space.
|
||||||
|
enc := base64.NewEncoder(base64.StdEncoding, buf)
|
||||||
|
enc.Write(converted)
|
||||||
|
enc.Close()
|
||||||
|
}
|
||||||
|
buf.WriteByte('"')
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported JSON value %v (%s)", value.Interface(), value.Type())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var hex = "0123456789abcdef"
|
||||||
|
|
||||||
|
func writeString(s string, buf *bytes.Buffer) {
|
||||||
|
buf.WriteByte('"')
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if s[i] == '"' {
|
||||||
|
buf.WriteString(`\"`)
|
||||||
|
} else if s[i] == '\\' {
|
||||||
|
buf.WriteString(`\\`)
|
||||||
|
} else if s[i] == '\b' {
|
||||||
|
buf.WriteString(`\b`)
|
||||||
|
} else if s[i] == '\f' {
|
||||||
|
buf.WriteString(`\f`)
|
||||||
|
} else if s[i] == '\r' {
|
||||||
|
buf.WriteString(`\r`)
|
||||||
|
} else if s[i] == '\t' {
|
||||||
|
buf.WriteString(`\t`)
|
||||||
|
} else if s[i] == '\n' {
|
||||||
|
buf.WriteString(`\n`)
|
||||||
|
} else if s[i] < 32 {
|
||||||
|
buf.WriteString("\\u00")
|
||||||
|
buf.WriteByte(hex[s[i]>>4])
|
||||||
|
buf.WriteByte(hex[s[i]&0xF])
|
||||||
|
} else {
|
||||||
|
buf.WriteByte(s[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.WriteByte('"')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the reflection element of a value, if it is a pointer.
|
||||||
|
func elemOf(value reflect.Value) reflect.Value {
|
||||||
|
for value.Kind() == reflect.Ptr {
|
||||||
|
value = value.Elem()
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
213
vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go
generated
vendored
Normal file
213
vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go
generated
vendored
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
package jsonutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UnmarshalJSON reads a stream and unmarshals the results in object v.
|
||||||
|
func UnmarshalJSON(v interface{}, stream io.Reader) error {
|
||||||
|
var out interface{}
|
||||||
|
|
||||||
|
b, err := ioutil.ReadAll(stream)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(b) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(b, &out); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return unmarshalAny(reflect.ValueOf(v), out, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalAny(value reflect.Value, data interface{}, tag reflect.StructTag) error {
|
||||||
|
vtype := value.Type()
|
||||||
|
if vtype.Kind() == reflect.Ptr {
|
||||||
|
vtype = vtype.Elem() // check kind of actual element type
|
||||||
|
}
|
||||||
|
|
||||||
|
t := tag.Get("type")
|
||||||
|
if t == "" {
|
||||||
|
switch vtype.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
// also it can't be a time object
|
||||||
|
if _, ok := value.Interface().(*time.Time); !ok {
|
||||||
|
t = "structure"
|
||||||
|
}
|
||||||
|
case reflect.Slice:
|
||||||
|
// also it can't be a byte slice
|
||||||
|
if _, ok := value.Interface().([]byte); !ok {
|
||||||
|
t = "list"
|
||||||
|
}
|
||||||
|
case reflect.Map:
|
||||||
|
t = "map"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t {
|
||||||
|
case "structure":
|
||||||
|
if field, ok := vtype.FieldByName("_"); ok {
|
||||||
|
tag = field.Tag
|
||||||
|
}
|
||||||
|
return unmarshalStruct(value, data, tag)
|
||||||
|
case "list":
|
||||||
|
return unmarshalList(value, data, tag)
|
||||||
|
case "map":
|
||||||
|
return unmarshalMap(value, data, tag)
|
||||||
|
default:
|
||||||
|
return unmarshalScalar(value, data, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalStruct(value reflect.Value, data interface{}, tag reflect.StructTag) error {
|
||||||
|
if data == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
mapData, ok := data.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("JSON value is not a structure (%#v)", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
t := value.Type()
|
||||||
|
if value.Kind() == reflect.Ptr {
|
||||||
|
if value.IsNil() { // create the structure if it's nil
|
||||||
|
s := reflect.New(value.Type().Elem())
|
||||||
|
value.Set(s)
|
||||||
|
value = s
|
||||||
|
}
|
||||||
|
|
||||||
|
value = value.Elem()
|
||||||
|
t = t.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
// unwrap any payloads
|
||||||
|
if payload := tag.Get("payload"); payload != "" {
|
||||||
|
field, _ := t.FieldByName(payload)
|
||||||
|
return unmarshalAny(value.FieldByName(payload), data, field.Tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
field := t.Field(i)
|
||||||
|
if field.PkgPath != "" {
|
||||||
|
continue // ignore unexported fields
|
||||||
|
}
|
||||||
|
|
||||||
|
// figure out what this field is called
|
||||||
|
name := field.Name
|
||||||
|
if locName := field.Tag.Get("locationName"); locName != "" {
|
||||||
|
name = locName
|
||||||
|
}
|
||||||
|
|
||||||
|
member := value.FieldByIndex(field.Index)
|
||||||
|
err := unmarshalAny(member, mapData[name], field.Tag)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalList(value reflect.Value, data interface{}, tag reflect.StructTag) error {
|
||||||
|
if data == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
listData, ok := data.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("JSON value is not a list (%#v)", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.IsNil() {
|
||||||
|
l := len(listData)
|
||||||
|
value.Set(reflect.MakeSlice(value.Type(), l, l))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, c := range listData {
|
||||||
|
err := unmarshalAny(value.Index(i), c, "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalMap(value reflect.Value, data interface{}, tag reflect.StructTag) error {
|
||||||
|
if data == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
mapData, ok := data.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("JSON value is not a map (%#v)", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.IsNil() {
|
||||||
|
value.Set(reflect.MakeMap(value.Type()))
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range mapData {
|
||||||
|
kvalue := reflect.ValueOf(k)
|
||||||
|
vvalue := reflect.New(value.Type().Elem()).Elem()
|
||||||
|
|
||||||
|
unmarshalAny(vvalue, v, "")
|
||||||
|
value.SetMapIndex(kvalue, vvalue)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalScalar(value reflect.Value, data interface{}, tag reflect.StructTag) error {
|
||||||
|
errf := func() error {
|
||||||
|
return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
switch d := data.(type) {
|
||||||
|
case nil:
|
||||||
|
return nil // nothing to do here
|
||||||
|
case string:
|
||||||
|
switch value.Interface().(type) {
|
||||||
|
case *string:
|
||||||
|
value.Set(reflect.ValueOf(&d))
|
||||||
|
case []byte:
|
||||||
|
b, err := base64.StdEncoding.DecodeString(d)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
value.Set(reflect.ValueOf(b))
|
||||||
|
default:
|
||||||
|
return errf()
|
||||||
|
}
|
||||||
|
case float64:
|
||||||
|
switch value.Interface().(type) {
|
||||||
|
case *int64:
|
||||||
|
di := int64(d)
|
||||||
|
value.Set(reflect.ValueOf(&di))
|
||||||
|
case *float64:
|
||||||
|
value.Set(reflect.ValueOf(&d))
|
||||||
|
case *time.Time:
|
||||||
|
t := time.Unix(int64(d), 0).UTC()
|
||||||
|
value.Set(reflect.ValueOf(&t))
|
||||||
|
default:
|
||||||
|
return errf()
|
||||||
|
}
|
||||||
|
case bool:
|
||||||
|
switch value.Interface().(type) {
|
||||||
|
case *bool:
|
||||||
|
value.Set(reflect.ValueOf(&d))
|
||||||
|
default:
|
||||||
|
return errf()
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported JSON value (%v)", data)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
111
vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/jsonrpc.go
generated
vendored
Normal file
111
vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/jsonrpc.go
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// Package jsonrpc provides JSON RPC utilities for serialization of AWS
|
||||||
|
// requests and responses.
|
||||||
|
package jsonrpc
|
||||||
|
|
||||||
|
//go:generate go run -tags codegen ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/input/json.json build_test.go
|
||||||
|
//go:generate go run -tags codegen ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/output/json.json unmarshal_test.go
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
"github.com/aws/aws-sdk-go/private/protocol/json/jsonutil"
|
||||||
|
"github.com/aws/aws-sdk-go/private/protocol/rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
var emptyJSON = []byte("{}")
|
||||||
|
|
||||||
|
// BuildHandler is a named request handler for building jsonrpc protocol requests
|
||||||
|
var BuildHandler = request.NamedHandler{Name: "awssdk.jsonrpc.Build", Fn: Build}
|
||||||
|
|
||||||
|
// UnmarshalHandler is a named request handler for unmarshaling jsonrpc protocol requests
|
||||||
|
var UnmarshalHandler = request.NamedHandler{Name: "awssdk.jsonrpc.Unmarshal", Fn: Unmarshal}
|
||||||
|
|
||||||
|
// UnmarshalMetaHandler is a named request handler for unmarshaling jsonrpc protocol request metadata
|
||||||
|
var UnmarshalMetaHandler = request.NamedHandler{Name: "awssdk.jsonrpc.UnmarshalMeta", Fn: UnmarshalMeta}
|
||||||
|
|
||||||
|
// UnmarshalErrorHandler is a named request handler for unmarshaling jsonrpc protocol request errors
|
||||||
|
var UnmarshalErrorHandler = request.NamedHandler{Name: "awssdk.jsonrpc.UnmarshalError", Fn: UnmarshalError}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalMeta unmarshals headers from a response for a JSON RPC service.
|
||||||
|
func UnmarshalMeta(req *request.Request) {
|
||||||
|
rest.UnmarshalMeta(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type jsonErrorResponse struct {
|
||||||
|
Code string `json:"__type"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
4472
vendor/github.com/aws/aws-sdk-go/service/route53domains/api.go
generated
vendored
Normal file
4472
vendor/github.com/aws/aws-sdk-go/service/route53domains/api.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
88
vendor/github.com/aws/aws-sdk-go/service/route53domains/service.go
generated
vendored
Normal file
88
vendor/github.com/aws/aws-sdk-go/service/route53domains/service.go
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||||
|
|
||||||
|
package route53domains
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/client"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/client/metadata"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/signer/v4"
|
||||||
|
"github.com/aws/aws-sdk-go/private/protocol/jsonrpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Route53Domains is a client for Amazon Route 53 Domains.
|
||||||
|
//The service client's operations are safe to be used concurrently.
|
||||||
|
// It is not safe to mutate any of the client's properties though.
|
||||||
|
type Route53Domains struct {
|
||||||
|
*client.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for custom client initialization logic
|
||||||
|
var initClient func(*client.Client)
|
||||||
|
|
||||||
|
// Used for custom request initialization logic
|
||||||
|
var initRequest func(*request.Request)
|
||||||
|
|
||||||
|
// A ServiceName is the name of the service the client will make API calls to.
|
||||||
|
const ServiceName = "route53domains"
|
||||||
|
|
||||||
|
// New creates a new instance of the Route53Domains client with a session.
|
||||||
|
// If additional configuration is needed for the client instance use the optional
|
||||||
|
// aws.Config parameter to add your extra config.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// // Create a Route53Domains client from just a session.
|
||||||
|
// svc := route53domains.New(mySession)
|
||||||
|
//
|
||||||
|
// // Create a Route53Domains client with additional configuration
|
||||||
|
// svc := route53domains.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
|
||||||
|
func New(p client.ConfigProvider, cfgs ...*aws.Config) *Route53Domains {
|
||||||
|
c := p.ClientConfig(ServiceName, cfgs...)
|
||||||
|
return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
|
||||||
|
}
|
||||||
|
|
||||||
|
// newClient creates, initializes and returns a new service client instance.
|
||||||
|
func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *Route53Domains {
|
||||||
|
svc := &Route53Domains{
|
||||||
|
Client: client.New(
|
||||||
|
cfg,
|
||||||
|
metadata.ClientInfo{
|
||||||
|
ServiceName: ServiceName,
|
||||||
|
SigningRegion: signingRegion,
|
||||||
|
Endpoint: endpoint,
|
||||||
|
APIVersion: "2014-05-15",
|
||||||
|
JSONVersion: "1.1",
|
||||||
|
TargetPrefix: "Route53Domains_v20140515",
|
||||||
|
},
|
||||||
|
handlers,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handlers
|
||||||
|
svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
|
||||||
|
svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler)
|
||||||
|
svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler)
|
||||||
|
svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler)
|
||||||
|
svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler)
|
||||||
|
|
||||||
|
// Run custom client initialization if present
|
||||||
|
if initClient != nil {
|
||||||
|
initClient(svc.Client)
|
||||||
|
}
|
||||||
|
|
||||||
|
return svc
|
||||||
|
}
|
||||||
|
|
||||||
|
// newRequest creates a new request for a Route53Domains operation and runs any
|
||||||
|
// custom request initialization.
|
||||||
|
func (c *Route53Domains) newRequest(op *request.Operation, params, data interface{}) *request.Request {
|
||||||
|
req := c.NewRequest(op, params, data)
|
||||||
|
|
||||||
|
// Run custom request initialization if present
|
||||||
|
if initRequest != nil {
|
||||||
|
initRequest(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
return req
|
||||||
|
}
|
18
vendor/vendor.json
vendored
18
vendor/vendor.json
vendored
@ -133,6 +133,18 @@
|
|||||||
"revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346",
|
"revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346",
|
||||||
"revisionTime": "2016-08-11T16:24:59Z"
|
"revisionTime": "2016-08-11T16:24:59Z"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "O6hcK24yI6w7FA+g4Pbr+eQ7pys=",
|
||||||
|
"path": "github.com/aws/aws-sdk-go/private/protocol/json/jsonutil",
|
||||||
|
"revision": "aafdacd0d6e625a7a2782bef5f9942d6fc4c9f30",
|
||||||
|
"revisionTime": "2017-07-14T21:00:53Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "R00RL5jJXRYq1iiK1+PGvMfvXyM=",
|
||||||
|
"path": "github.com/aws/aws-sdk-go/private/protocol/jsonrpc",
|
||||||
|
"revision": "aafdacd0d6e625a7a2782bef5f9942d6fc4c9f30",
|
||||||
|
"revisionTime": "2017-07-14T21:00:53Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "isoix7lTx4qIq2zI2xFADtti5SI=",
|
"checksumSHA1": "isoix7lTx4qIq2zI2xFADtti5SI=",
|
||||||
"path": "github.com/aws/aws-sdk-go/private/protocol/query",
|
"path": "github.com/aws/aws-sdk-go/private/protocol/query",
|
||||||
@ -181,6 +193,12 @@
|
|||||||
"revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346",
|
"revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346",
|
||||||
"revisionTime": "2016-08-11T16:24:59Z"
|
"revisionTime": "2016-08-11T16:24:59Z"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "qS3eZZfhdDM6haTZp7OeyhMDlV8=",
|
||||||
|
"path": "github.com/aws/aws-sdk-go/service/route53domains",
|
||||||
|
"revision": "f80e7d0182a463dff0c0da6bbed57f21369d4346",
|
||||||
|
"revisionTime": "2016-08-11T16:24:59Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "nH/itbdeFHpl4ysegdtgww9bFSA=",
|
"checksumSHA1": "nH/itbdeFHpl4ysegdtgww9bFSA=",
|
||||||
"path": "github.com/aws/aws-sdk-go/service/sts",
|
"path": "github.com/aws/aws-sdk-go/service/sts",
|
||||||
|
Reference in New Issue
Block a user