mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-05-06 22:18:28 +00:00
Update Go AWS SDK to the latest version
This commit is contained in:
committed by
Andrey Smirnov
parent
d08be990ef
commit
94a72b23ff
+144
-68
@@ -5,17 +5,18 @@ package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// SDKImportRoot is the root import path of the SDK.
|
||||
const SDKImportRoot = "github.com/aws/aws-sdk-go"
|
||||
|
||||
// An API defines a service API's definition. and logic to serialize the definition.
|
||||
type API struct {
|
||||
Metadata Metadata
|
||||
@@ -24,6 +25,7 @@ type API struct {
|
||||
Waiters []Waiter
|
||||
Documentation string
|
||||
Examples Examples
|
||||
SmokeTests SmokeTestSuite
|
||||
|
||||
// Set to true to avoid removing unused shapes
|
||||
NoRemoveUnusedShapes bool
|
||||
@@ -46,7 +48,7 @@ type API struct {
|
||||
// Set to true to not generate struct field accessors
|
||||
NoGenStructFieldAccessors bool
|
||||
|
||||
SvcClientImportPath string
|
||||
BaseImportPath string
|
||||
|
||||
initialized bool
|
||||
imports map[string]bool
|
||||
@@ -54,6 +56,10 @@ type API struct {
|
||||
path string
|
||||
|
||||
BaseCrosslinkURL string
|
||||
|
||||
HasEventStream bool `json:"-"`
|
||||
|
||||
EndpointDiscoveryOp *Operation
|
||||
}
|
||||
|
||||
// A Metadata is the metadata about an API's definition.
|
||||
@@ -67,21 +73,18 @@ type Metadata struct {
|
||||
JSONVersion string
|
||||
TargetPrefix string
|
||||
Protocol string
|
||||
ProtocolSettings ProtocolSettings
|
||||
UID string
|
||||
EndpointsID string
|
||||
ServiceID string
|
||||
|
||||
NoResolveEndpoint bool
|
||||
}
|
||||
|
||||
var serviceAliases map[string]string
|
||||
|
||||
func Bootstrap() error {
|
||||
b, err := ioutil.ReadFile(filepath.Join("..", "models", "customizations", "service-aliases.json"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return json.Unmarshal(b, &serviceAliases)
|
||||
// ProtocolSettings define how the SDK should handle requests in the context
|
||||
// of of a protocol.
|
||||
type ProtocolSettings struct {
|
||||
HTTP2 string `json:"h2,omitempty"`
|
||||
}
|
||||
|
||||
// PackageName name of the API package
|
||||
@@ -89,6 +92,11 @@ func (a *API) PackageName() string {
|
||||
return strings.ToLower(a.StructName())
|
||||
}
|
||||
|
||||
// ImportPath returns the client's full import path
|
||||
func (a *API) ImportPath() string {
|
||||
return path.Join(a.BaseImportPath, a.PackageName())
|
||||
}
|
||||
|
||||
// InterfacePackageName returns the package name for the interface.
|
||||
func (a *API) InterfacePackageName() string {
|
||||
return a.PackageName() + "iface"
|
||||
@@ -135,11 +143,6 @@ func (a *API) StructName() string {
|
||||
// Strip out spaces.
|
||||
name = strings.Replace(name, " ", "", -1)
|
||||
|
||||
// Swap out for alias name if one is defined.
|
||||
if alias, ok := serviceAliases[strings.ToLower(name)]; ok {
|
||||
name = alias
|
||||
}
|
||||
|
||||
a.name = name
|
||||
return a.name
|
||||
}
|
||||
@@ -217,8 +220,8 @@ func (a *API) ShapeNames() []string {
|
||||
func (a *API) ShapeList() []*Shape {
|
||||
list := make([]*Shape, 0, len(a.Shapes))
|
||||
for _, n := range a.ShapeNames() {
|
||||
// Ignore error shapes in list
|
||||
if s := a.Shapes[n]; !s.IsError {
|
||||
// Ignore non-eventstream exception shapes in list.
|
||||
if s := a.Shapes[n]; !(s.Exception && len(s.EventFor) == 0) {
|
||||
list = append(list, s)
|
||||
}
|
||||
}
|
||||
@@ -230,7 +233,7 @@ func (a *API) ShapeListErrors() []*Shape {
|
||||
list := []*Shape{}
|
||||
for _, n := range a.ShapeNames() {
|
||||
// Ignore error shapes in list
|
||||
if s := a.Shapes[n]; s.IsError {
|
||||
if s := a.Shapes[n]; s.Exception {
|
||||
list = append(list, s)
|
||||
}
|
||||
}
|
||||
@@ -239,9 +242,7 @@ func (a *API) ShapeListErrors() []*Shape {
|
||||
|
||||
// resetImports resets the import map to default values.
|
||||
func (a *API) resetImports() {
|
||||
a.imports = map[string]bool{
|
||||
"github.com/aws/aws-sdk-go/aws": true,
|
||||
}
|
||||
a.imports = map[string]bool{}
|
||||
}
|
||||
|
||||
// importsGoCode returns the generated Go import code.
|
||||
@@ -293,22 +294,28 @@ var tplAPI = template.Must(template.New("api").Parse(`
|
||||
{{ end }}
|
||||
`))
|
||||
|
||||
// AddImport adds the import path to the generated file's import.
|
||||
func (a *API) AddImport(v string) error {
|
||||
a.imports[v] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddSDKImport adds a SDK package import to the generated file's import.
|
||||
func (a *API) AddSDKImport(v ...string) error {
|
||||
e := make([]string, 0, 5)
|
||||
e = append(e, SDKImportRoot)
|
||||
e = append(e, v...)
|
||||
|
||||
a.imports[path.Join(e...)] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// APIGoCode renders the API in Go code. Returning it as a string
|
||||
func (a *API) APIGoCode() string {
|
||||
a.resetImports()
|
||||
a.imports["github.com/aws/aws-sdk-go/aws/awsutil"] = true
|
||||
a.imports["github.com/aws/aws-sdk-go/aws/request"] = true
|
||||
if a.OperationHasOutputPlaceholder() {
|
||||
a.imports["github.com/aws/aws-sdk-go/private/protocol/"+a.ProtocolPackage()] = true
|
||||
a.imports["github.com/aws/aws-sdk-go/private/protocol"] = true
|
||||
}
|
||||
|
||||
for _, op := range a.Operations {
|
||||
if op.AuthType == "none" {
|
||||
a.imports["github.com/aws/aws-sdk-go/aws/credentials"] = true
|
||||
break
|
||||
}
|
||||
}
|
||||
a.AddSDKImport("aws")
|
||||
a.AddSDKImport("aws/awsutil")
|
||||
a.AddSDKImport("aws/request")
|
||||
|
||||
var buf bytes.Buffer
|
||||
err := tplAPI.Execute(&buf, a)
|
||||
@@ -407,7 +414,7 @@ var tplServiceDoc = template.Must(template.New("service docs").Funcs(template.Fu
|
||||
//
|
||||
// See the SDK's documentation for more information on how to use the SDK.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/
|
||||
//
|
||||
//
|
||||
// See aws.Config documentation for more information on configuring SDK clients.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config
|
||||
//
|
||||
@@ -416,30 +423,62 @@ var tplServiceDoc = template.Must(template.New("service docs").Funcs(template.Fu
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/service/{{ .PackageName }}/#New
|
||||
`))
|
||||
|
||||
var serviceIDRegex = regexp.MustCompile("[^a-zA-Z0-9 ]+")
|
||||
var prefixDigitRegex = regexp.MustCompile("^[0-9]+")
|
||||
|
||||
// ServiceID will return a unique identifier specific to a service.
|
||||
func ServiceID(a *API) string {
|
||||
if len(a.Metadata.ServiceID) > 0 {
|
||||
return a.Metadata.ServiceID
|
||||
}
|
||||
|
||||
name := a.Metadata.ServiceAbbreviation
|
||||
if len(name) == 0 {
|
||||
name = a.Metadata.ServiceFullName
|
||||
}
|
||||
|
||||
name = strings.Replace(name, "Amazon", "", -1)
|
||||
name = strings.Replace(name, "AWS", "", -1)
|
||||
name = serviceIDRegex.ReplaceAllString(name, "")
|
||||
name = prefixDigitRegex.ReplaceAllString(name, "")
|
||||
name = strings.TrimSpace(name)
|
||||
return name
|
||||
}
|
||||
|
||||
// A tplService defines the template for the service generated code.
|
||||
var tplService = template.Must(template.New("service").Funcs(template.FuncMap{
|
||||
"ServiceNameConstValue": ServiceName,
|
||||
"ServiceNameValue": func(a *API) string {
|
||||
if a.NoConstServiceNames {
|
||||
return fmt.Sprintf("%q", a.Metadata.EndpointPrefix)
|
||||
if !a.NoConstServiceNames {
|
||||
return "ServiceName"
|
||||
}
|
||||
return "ServiceName"
|
||||
return fmt.Sprintf("%q", ServiceName(a))
|
||||
},
|
||||
"EndpointsIDConstValue": func(a *API) string {
|
||||
if a.NoConstServiceNames {
|
||||
return fmt.Sprintf("%q", a.Metadata.EndpointPrefix)
|
||||
return fmt.Sprintf("%q", a.Metadata.EndpointsID)
|
||||
}
|
||||
if a.Metadata.EndpointPrefix == a.Metadata.EndpointsID {
|
||||
if a.Metadata.EndpointsID == ServiceName(a) {
|
||||
return "ServiceName"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%q", a.Metadata.EndpointsID)
|
||||
},
|
||||
"EndpointsIDValue": func(a *API) string {
|
||||
if a.NoConstServiceNames {
|
||||
return fmt.Sprintf("%q", a.Metadata.EndpointPrefix)
|
||||
return fmt.Sprintf("%q", a.Metadata.EndpointsID)
|
||||
}
|
||||
|
||||
return "EndpointsID"
|
||||
},
|
||||
"ServiceIDVar": func(a *API) string {
|
||||
if a.NoConstServiceNames {
|
||||
return fmt.Sprintf("%q", ServiceID(a))
|
||||
}
|
||||
|
||||
return "ServiceID"
|
||||
},
|
||||
"ServiceID": ServiceID,
|
||||
}).Parse(`
|
||||
// {{ .StructName }} provides the API operation methods for making requests to
|
||||
// {{ .Metadata.ServiceFullName }}. See this package's package overview docs
|
||||
@@ -449,6 +488,9 @@ var tplService = template.Must(template.New("service").Funcs(template.FuncMap{
|
||||
// modify mutate any of the struct's properties though.
|
||||
type {{ .StructName }} struct {
|
||||
*client.Client
|
||||
{{- if .EndpointDiscoveryOp }}
|
||||
endpointCache *crr.EndpointCache
|
||||
{{ end -}}
|
||||
}
|
||||
|
||||
{{ if .UseInitMethods }}// Used for custom client initialization logic
|
||||
@@ -462,8 +504,9 @@ var initRequest func(*request.Request)
|
||||
{{ if not .NoConstServiceNames -}}
|
||||
// Service information constants
|
||||
const (
|
||||
ServiceName = "{{ .Metadata.EndpointPrefix }}" // Service endpoint prefix API calls made to.
|
||||
EndpointsID = {{ EndpointsIDConstValue . }} // Service ID for Regions and Endpoints metadata.
|
||||
ServiceName = "{{ ServiceNameConstValue . }}" // Name of service.
|
||||
EndpointsID = {{ EndpointsIDConstValue . }} // ID to lookup a service endpoint with.
|
||||
ServiceID = "{{ ServiceID . }}" // ServiceID is a unique identifer of a specific service.
|
||||
)
|
||||
{{- end }}
|
||||
|
||||
@@ -504,14 +547,15 @@ func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegio
|
||||
cfg,
|
||||
metadata.ClientInfo{
|
||||
ServiceName: {{ ServiceNameValue . }},
|
||||
ServiceID : {{ ServiceIDVar . }},
|
||||
SigningName: signingName,
|
||||
SigningRegion: signingRegion,
|
||||
Endpoint: endpoint,
|
||||
APIVersion: "{{ .Metadata.APIVersion }}",
|
||||
{{ if .Metadata.JSONVersion -}}
|
||||
{{ if and (.Metadata.JSONVersion) (eq .Metadata.Protocol "json") -}}
|
||||
JSONVersion: "{{ .Metadata.JSONVersion }}",
|
||||
{{- end }}
|
||||
{{ if .Metadata.TargetPrefix -}}
|
||||
{{ if and (.Metadata.TargetPrefix) (eq .Metadata.Protocol "json") -}}
|
||||
TargetPrefix: "{{ .Metadata.TargetPrefix }}",
|
||||
{{- end }}
|
||||
},
|
||||
@@ -519,8 +563,22 @@ func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegio
|
||||
),
|
||||
}
|
||||
|
||||
{{- if .EndpointDiscoveryOp }}
|
||||
svc.endpointCache = crr.NewEndpointCache(10)
|
||||
{{- end }}
|
||||
|
||||
// Handlers
|
||||
svc.Handlers.Sign.PushBackNamed({{if eq .Metadata.SignatureVersion "v2"}}v2{{else}}v4{{end}}.SignRequestHandler)
|
||||
svc.Handlers.Sign.PushBackNamed(
|
||||
{{- if eq .Metadata.SignatureVersion "v2" -}}
|
||||
v2.SignRequestHandler
|
||||
{{- else if or (eq .Metadata.SignatureVersion "s3") (eq .Metadata.SignatureVersion "s3v4") -}}
|
||||
v4.BuildNamedHandler(v4.SignRequestHandler.Name, func(s *v4.Signer) {
|
||||
s.DisableURIPathEscaping = true
|
||||
})
|
||||
{{- else -}}
|
||||
v4.SignRequestHandler
|
||||
{{- end -}}
|
||||
)
|
||||
{{- if eq .Metadata.SignatureVersion "v2" }}
|
||||
svc.Handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler)
|
||||
{{- end }}
|
||||
@@ -528,6 +586,9 @@ func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegio
|
||||
svc.Handlers.Unmarshal.PushBackNamed({{ .ProtocolPackage }}.UnmarshalHandler)
|
||||
svc.Handlers.UnmarshalMeta.PushBackNamed({{ .ProtocolPackage }}.UnmarshalMetaHandler)
|
||||
svc.Handlers.UnmarshalError.PushBackNamed({{ .ProtocolPackage }}.UnmarshalErrorHandler)
|
||||
{{ if .HasEventStream }}
|
||||
svc.Handlers.UnmarshalStream.PushBackNamed({{ .ProtocolPackage }}.UnmarshalHandler)
|
||||
{{ end }}
|
||||
|
||||
{{ if .UseInitMethods }}// Run custom client initialization if present
|
||||
if initClient != nil {
|
||||
@@ -570,16 +631,20 @@ func (a *API) ServicePackageDoc() string {
|
||||
// ServiceGoCode renders service go code. Returning it as a string.
|
||||
func (a *API) ServiceGoCode() string {
|
||||
a.resetImports()
|
||||
a.imports["github.com/aws/aws-sdk-go/aws/client"] = true
|
||||
a.imports["github.com/aws/aws-sdk-go/aws/client/metadata"] = true
|
||||
a.imports["github.com/aws/aws-sdk-go/aws/request"] = true
|
||||
a.AddSDKImport("aws")
|
||||
a.AddSDKImport("aws/client")
|
||||
a.AddSDKImport("aws/client/metadata")
|
||||
a.AddSDKImport("aws/request")
|
||||
if a.Metadata.SignatureVersion == "v2" {
|
||||
a.imports["github.com/aws/aws-sdk-go/private/signer/v2"] = true
|
||||
a.imports["github.com/aws/aws-sdk-go/aws/corehandlers"] = true
|
||||
a.AddSDKImport("private/signer/v2")
|
||||
a.AddSDKImport("aws/corehandlers")
|
||||
} else {
|
||||
a.imports["github.com/aws/aws-sdk-go/aws/signer/v4"] = true
|
||||
a.AddSDKImport("aws/signer/v4")
|
||||
}
|
||||
a.AddSDKImport("private/protocol", a.ProtocolPackage())
|
||||
if a.EndpointDiscoveryOp != nil {
|
||||
a.AddSDKImport("aws/crr")
|
||||
}
|
||||
a.imports["github.com/aws/aws-sdk-go/private/protocol/"+a.ProtocolPackage()] = true
|
||||
|
||||
var buf bytes.Buffer
|
||||
err := tplService.Execute(&buf, a)
|
||||
@@ -607,9 +672,9 @@ func (a *API) ExampleGoCode() string {
|
||||
"bytes",
|
||||
"fmt",
|
||||
"time",
|
||||
"github.com/aws/aws-sdk-go/aws",
|
||||
"github.com/aws/aws-sdk-go/aws/session",
|
||||
path.Join(a.SvcClientImportPath, a.PackageName()),
|
||||
SDKImportRoot+"/aws",
|
||||
SDKImportRoot+"/aws/session",
|
||||
a.ImportPath(),
|
||||
)
|
||||
for k := range imports {
|
||||
code += fmt.Sprintf("%q\n", k)
|
||||
@@ -665,7 +730,7 @@ var tplInterface = template.Must(template.New("interface").Parse(`
|
||||
//
|
||||
// It is important to note that this interface will have breaking changes
|
||||
// when the service model is updated and adds new API operations, paginators,
|
||||
// and waiters. Its suggested to use the pattern above for testing, or using
|
||||
// and waiters. Its suggested to use the pattern above for testing, or using
|
||||
// tooling to generate mocks to satisfy the interfaces.
|
||||
type {{ .StructName }}API interface {
|
||||
{{ range $_, $o := .OperationList }}
|
||||
@@ -684,11 +749,9 @@ var _ {{ .StructName }}API = (*{{ .PackageName }}.{{ .StructName }})(nil)
|
||||
// package than the service API's package.
|
||||
func (a *API) InterfaceGoCode() string {
|
||||
a.resetImports()
|
||||
a.imports = map[string]bool{
|
||||
"github.com/aws/aws-sdk-go/aws": true,
|
||||
"github.com/aws/aws-sdk-go/aws/request": true,
|
||||
path.Join(a.SvcClientImportPath, a.PackageName()): true,
|
||||
}
|
||||
a.AddSDKImport("aws")
|
||||
a.AddSDKImport("aws/request")
|
||||
a.AddImport(a.ImportPath())
|
||||
|
||||
var buf bytes.Buffer
|
||||
err := tplInterface.Execute(&buf, a)
|
||||
@@ -726,7 +789,6 @@ func resolveShapeValidations(s *Shape, ancestry ...*Shape) {
|
||||
children := []string{}
|
||||
for _, name := range s.MemberNames() {
|
||||
ref := s.MemberRefs[name]
|
||||
|
||||
if s.IsRequired(name) && !s.Validations.Has(ref, ShapeValidationRequired) {
|
||||
s.Validations = append(s.Validations, ShapeValidation{
|
||||
Name: name, Ref: ref, Type: ShapeValidationRequired,
|
||||
@@ -739,6 +801,12 @@ func resolveShapeValidations(s *Shape, ancestry ...*Shape) {
|
||||
})
|
||||
}
|
||||
|
||||
if !ref.CanBeEmpty() && !s.Validations.Has(ref, ShapeValidationMinVal) {
|
||||
s.Validations = append(s.Validations, ShapeValidation{
|
||||
Name: name, Ref: ref, Type: ShapeValidationMinVal,
|
||||
})
|
||||
}
|
||||
|
||||
switch ref.Shape.Type {
|
||||
case "map", "list", "structure":
|
||||
children = append(children, name)
|
||||
@@ -806,7 +874,7 @@ func (a *API) APIErrorsGoCode() string {
|
||||
// removeOperation removes an operation, its input/output shapes, as well as
|
||||
// any references/shapes that are unique to this operation.
|
||||
func (a *API) removeOperation(name string) {
|
||||
fmt.Println("removing operation,", name)
|
||||
debugLogger.Logln("removing operation,", name)
|
||||
op := a.Operations[name]
|
||||
|
||||
delete(a.Operations, name)
|
||||
@@ -820,7 +888,7 @@ func (a *API) removeOperation(name string) {
|
||||
// shapes. Will also remove member reference targeted shapes if those shapes do
|
||||
// not have any additional references.
|
||||
func (a *API) removeShape(s *Shape) {
|
||||
fmt.Println("removing shape,", s.ShapeName)
|
||||
debugLogger.Logln("removing shape,", s.ShapeName)
|
||||
|
||||
delete(a.Shapes, s.ShapeName)
|
||||
|
||||
@@ -851,3 +919,11 @@ func (a *API) removeShapeRef(ref *ShapeRef) {
|
||||
a.removeShape(ref.Shape)
|
||||
}
|
||||
}
|
||||
|
||||
func getDeprecatedMessage(msg string, name string) string {
|
||||
if len(msg) == 0 {
|
||||
return name + " has been deprecated"
|
||||
}
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
+5
-3
@@ -7,8 +7,8 @@ import (
|
||||
)
|
||||
|
||||
func TestAPI_StructName(t *testing.T) {
|
||||
origAliases := serviceAliases
|
||||
defer func() { serviceAliases = origAliases }()
|
||||
origAliases := serviceAliaseNames
|
||||
defer func() { serviceAliaseNames = origAliases }()
|
||||
|
||||
cases := map[string]struct {
|
||||
Aliases map[string]string
|
||||
@@ -57,12 +57,14 @@ func TestAPI_StructName(t *testing.T) {
|
||||
|
||||
for k, c := range cases {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
serviceAliases = c.Aliases
|
||||
serviceAliaseNames = c.Aliases
|
||||
|
||||
a := API{
|
||||
Metadata: c.Metadata,
|
||||
}
|
||||
|
||||
a.Setup()
|
||||
|
||||
if e, o := c.StructName, a.StructName(); e != o {
|
||||
t.Errorf("expect %v structName, got %v", e, o)
|
||||
}
|
||||
|
||||
Generated
Vendored
+131
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"version":"2.0",
|
||||
"metadata":{
|
||||
"apiVersion":"2018-08-31",
|
||||
"endpointPrefix":"awsendpointdiscoverytestservice",
|
||||
"jsonVersion":"1.1",
|
||||
"protocol":"json",
|
||||
"serviceAbbreviation":"AwsEndpointDiscoveryTest",
|
||||
"serviceFullName":"AwsEndpointDiscoveryTest",
|
||||
"signatureVersion":"v4",
|
||||
"signingName":"awsendpointdiscoverytestservice",
|
||||
"targetPrefix":"AwsEndpointDiscoveryTestService"
|
||||
},
|
||||
"operations":{
|
||||
"DescribeEndpoints":{
|
||||
"name":"DescribeEndpoints",
|
||||
"http":{
|
||||
"method":"POST",
|
||||
"requestUri":"/"
|
||||
},
|
||||
"input":{"shape":"DescribeEndpointsRequest"},
|
||||
"output":{"shape":"DescribeEndpointsResponse"},
|
||||
"endpointoperation":true
|
||||
},
|
||||
"TestDiscoveryIdentifiersRequired":{
|
||||
"name":"TestDiscoveryIdentifiersRequired",
|
||||
"http":{
|
||||
"method":"POST",
|
||||
"requestUri":"/"
|
||||
},
|
||||
"input":{"shape":"TestDiscoveryIdentifiersRequiredRequest"},
|
||||
"output":{"shape":"TestDiscoveryIdentifiersRequiredResponse"},
|
||||
"endpointdiscovery":{"required":true}
|
||||
},
|
||||
"TestDiscoveryOptional":{
|
||||
"name":"TestDiscoveryOptional",
|
||||
"http":{
|
||||
"method":"POST",
|
||||
"requestUri":"/"
|
||||
},
|
||||
"input":{"shape":"TestDiscoveryOptionalRequest"},
|
||||
"output":{"shape":"TestDiscoveryOptionalResponse"},
|
||||
"endpointdiscovery":{
|
||||
}
|
||||
},
|
||||
"TestDiscoveryRequired":{
|
||||
"name":"TestDiscoveryRequired",
|
||||
"http":{
|
||||
"method":"POST",
|
||||
"requestUri":"/"
|
||||
},
|
||||
"input":{"shape":"TestDiscoveryRequiredRequest"},
|
||||
"output":{"shape":"TestDiscoveryRequiredResponse"},
|
||||
"endpointdiscovery":{
|
||||
}
|
||||
}
|
||||
},
|
||||
"shapes":{
|
||||
"Boolean":{"type":"boolean"},
|
||||
"DescribeEndpointsRequest":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"Operation": {"shape":"String"}
|
||||
}
|
||||
},
|
||||
"DescribeEndpointsResponse":{
|
||||
"type":"structure",
|
||||
"required":["Endpoints"],
|
||||
"members":{
|
||||
"Endpoints":{"shape":"Endpoints"}
|
||||
}
|
||||
},
|
||||
"Endpoint":{
|
||||
"type":"structure",
|
||||
"required":[
|
||||
"Address",
|
||||
"CachePeriodInMinutes"
|
||||
],
|
||||
"members":{
|
||||
"Address":{"shape":"String"},
|
||||
"CachePeriodInMinutes":{"shape":"Long"}
|
||||
}
|
||||
},
|
||||
"Endpoints":{
|
||||
"type":"list",
|
||||
"member":{"shape":"Endpoint"}
|
||||
},
|
||||
"Long":{"type":"long"},
|
||||
"String":{"type":"string"},
|
||||
"TestDiscoveryIdentifiersRequiredRequest":{
|
||||
"type":"structure",
|
||||
"required":["Sdk"],
|
||||
"members":{
|
||||
"Sdk":{
|
||||
"shape":"String",
|
||||
"endpointdiscoveryid":true
|
||||
}
|
||||
}
|
||||
},
|
||||
"TestDiscoveryIdentifiersRequiredResponse":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"RequestSuccessful":{"shape":"Boolean"}
|
||||
}
|
||||
},
|
||||
"TestDiscoveryOptionalRequest":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"Sdk":{"shape":"String"}
|
||||
}
|
||||
},
|
||||
"TestDiscoveryOptionalResponse":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"RequestSuccessful":{"shape":"Boolean"}
|
||||
}
|
||||
},
|
||||
"TestDiscoveryRequiredRequest":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"Sdk":{"shape":"String"}
|
||||
}
|
||||
},
|
||||
"TestDiscoveryRequiredResponse":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"RequestSuccessful":{"shape":"Boolean"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": "2.0",
|
||||
"service": null,
|
||||
"operations": {
|
||||
},
|
||||
"shapes":{}
|
||||
}
|
||||
Generated
Vendored
+228
@@ -0,0 +1,228 @@
|
||||
{
|
||||
"version":"2.0",
|
||||
"metadata":{
|
||||
"apiVersion":"0000-00-00",
|
||||
"endpointPrefix":"rpcservice",
|
||||
"jsonVersion":"1.1",
|
||||
"protocol":"json",
|
||||
"serviceAbbreviation":"RPCService",
|
||||
"serviceFullName":"RPC Service",
|
||||
"serviceId":"RPCService",
|
||||
"signatureVersion":"v4",
|
||||
"targetPrefix":"RPCService_00000000",
|
||||
"uid":"RPCService-0000-00-00"
|
||||
},
|
||||
"operations":{
|
||||
"GetEventStream":{
|
||||
"name":"GetEventStream",
|
||||
"http":{
|
||||
"method":"POST",
|
||||
"requestUri":"/"
|
||||
},
|
||||
"input":{"shape":"GetEventStreamRequest"},
|
||||
"output":{"shape":"GetEventStreamResponse"}
|
||||
},
|
||||
"EmptyStream":{
|
||||
"name":"EmptyStream",
|
||||
"http":{
|
||||
"method":"POST",
|
||||
"requestUri":"/"
|
||||
},
|
||||
"input":{"shape":"EmptyStreamRequest"},
|
||||
"output":{"shape":"EmptyStreamResponse"}
|
||||
},
|
||||
"OtherOperation":{
|
||||
"name":"OtherOperation",
|
||||
"http":{
|
||||
"method":"POST",
|
||||
"requestUri":"/"
|
||||
},
|
||||
"errors":[
|
||||
{"shape":"ExceptionEvent2"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"shapes":{
|
||||
"Bool":{"type":"boolean"},
|
||||
"Byte":{"type":"byte"},
|
||||
"Short":{"type":"short"},
|
||||
"Integer":{"type":"integer"},
|
||||
"Long":{"type":"long"},
|
||||
"Blob":{"type":"blob"},
|
||||
"String":{"type":"string"},
|
||||
"Time":{"type":"timestamp"},
|
||||
"GetEventStreamRequest":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"InputVal":{"shape":"String"}
|
||||
}
|
||||
},
|
||||
"GetEventStreamResponse":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"StrVal":{"shape":"String"},
|
||||
"IntVal":{"shape":"Integer"},
|
||||
"EventStream":{"shape":"EventStream"}
|
||||
}
|
||||
},
|
||||
"EventStream":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"Headers":{"shape":"HeaderOnlyEvent"},
|
||||
"ImplicitPayload":{"shape":"ImplicitPayloadEvent"},
|
||||
"ExplicitPayload":{"shape":"ExplicitPayloadEvent"},
|
||||
"PayloadOnly":{"shape":"PayloadOnlyEvent"},
|
||||
"PayloadOnlyBlob":{"shape":"PayloadOnlyBlobEvent"},
|
||||
"PayloadOnlyString":{"shape":"PayloadOnlyStringEvent"},
|
||||
"Empty":{"shape":"EmptyEvent"},
|
||||
"Exception":{"shape":"ExceptionEvent"},
|
||||
"Exception2":{"shape":"ExceptionEvent2"}
|
||||
},
|
||||
"eventstream":true
|
||||
},
|
||||
"EmptyStreamRequest":{
|
||||
"type":"structure",
|
||||
"members":{}
|
||||
},
|
||||
"EmptyStreamResponse":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"EventStream":{"shape":"EmptyEventStream"}
|
||||
}
|
||||
},
|
||||
"EmptyEventStream":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
},
|
||||
"eventstream":true
|
||||
},
|
||||
"HeaderOnlyEvent":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"BoolVal":{
|
||||
"shape":"Bool",
|
||||
"eventheader":true
|
||||
},
|
||||
"ByteVal":{
|
||||
"shape":"Byte",
|
||||
"eventheader":true
|
||||
},
|
||||
"ShortVal":{
|
||||
"shape":"Short",
|
||||
"eventheader":true
|
||||
},
|
||||
"IntegerVal":{
|
||||
"shape":"Integer",
|
||||
"eventheader":true
|
||||
},
|
||||
"LongVal":{
|
||||
"shape":"Long",
|
||||
"eventheader":true
|
||||
},
|
||||
"StringVal":{
|
||||
"shape":"String",
|
||||
"eventheader":true
|
||||
},
|
||||
"BlobVal":{
|
||||
"shape":"Blob",
|
||||
"eventheader":true
|
||||
},
|
||||
"TimeVal":{
|
||||
"shape":"Time",
|
||||
"eventheader":true
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"ImplicitPayloadEvent": {
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"ByteVal":{
|
||||
"shape":"Byte",
|
||||
"eventheader":true
|
||||
},
|
||||
"ShortVal":{
|
||||
"shape":"Short"
|
||||
},
|
||||
"IntegerVal":{
|
||||
"shape":"Integer"
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"ExplicitPayloadEvent": {
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"LongVal":{
|
||||
"shape":"Long",
|
||||
"eventheader":true
|
||||
},
|
||||
"StringVal":{
|
||||
"shape":"String",
|
||||
"eventheader":true
|
||||
},
|
||||
"NestedVal":{
|
||||
"shape":"NestedShape",
|
||||
"eventpayload":true
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"PayloadOnlyEvent":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"NestedVal":{
|
||||
"shape":"NestedShape",
|
||||
"eventpayload":true
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"PayloadOnlyBlobEvent":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"BlobPayload":{
|
||||
"shape":"Blob",
|
||||
"eventpayload":true
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"PayloadOnlyStringEvent":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"StringPayload":{
|
||||
"shape":"String",
|
||||
"eventpayload":true
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"EmptyEvent": {
|
||||
"type":"structure",
|
||||
"members":{},
|
||||
"event": true
|
||||
},
|
||||
"NestedShape": {
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"IntVal":{"shape":"Integer"},
|
||||
"StrVal":{"shape":"String"}
|
||||
}
|
||||
},
|
||||
"ExceptionEvent":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"IntVal":{"shape":"Integer"},
|
||||
"message":{"shape":"String"}
|
||||
},
|
||||
"exception":true
|
||||
},
|
||||
"ExceptionEvent2":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
},
|
||||
"exception":true
|
||||
}
|
||||
}
|
||||
}
|
||||
vendor/github.com/aws/aws-sdk-go/private/model/api/codegentest/models/jsonrpc/0000-00-00/docs-2.json
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": "2.0",
|
||||
"service": null,
|
||||
"operations": {
|
||||
},
|
||||
"shapes":{}
|
||||
}
|
||||
vendor/github.com/aws/aws-sdk-go/private/model/api/codegentest/models/restjson/0000-00-00/api-2.json
Generated
Vendored
+226
@@ -0,0 +1,226 @@
|
||||
{
|
||||
"version":"2.0",
|
||||
"metadata":{
|
||||
"apiVersion":"0000-00-00",
|
||||
"endpointPrefix":"restjsonservice",
|
||||
"protocol":"rest-json",
|
||||
"serviceAbbreviation":"RESTJSONService",
|
||||
"serviceFullName":"REST JSON Service",
|
||||
"serviceId":"RESTJSONService",
|
||||
"signatureVersion":"v4",
|
||||
"uid":"RESTJSONService-0000-00-00"
|
||||
},
|
||||
"operations":{
|
||||
"GetEventStream":{
|
||||
"name":"GetEventStream",
|
||||
"http":{
|
||||
"method":"POST",
|
||||
"requestUri":"/"
|
||||
},
|
||||
"input":{"shape":"GetEventStreamRequest"},
|
||||
"output":{"shape":"GetEventStreamResponse"}
|
||||
},
|
||||
"EmptyStream":{
|
||||
"name":"EmptyStream",
|
||||
"http":{
|
||||
"method":"POST",
|
||||
"requestUri":"/"
|
||||
},
|
||||
"input":{"shape":"EmptyStreamRequest"},
|
||||
"output":{"shape":"EmptyStreamResponse"}
|
||||
},
|
||||
"OtherOperation":{
|
||||
"name":"OtherOperation",
|
||||
"http":{
|
||||
"method":"POST",
|
||||
"requestUri":"/"
|
||||
},
|
||||
"errors":[
|
||||
{"shape":"ExceptionEvent2"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"shapes":{
|
||||
"Bool":{"type":"boolean"},
|
||||
"Byte":{"type":"byte"},
|
||||
"Short":{"type":"short"},
|
||||
"Integer":{"type":"integer"},
|
||||
"Long":{"type":"long"},
|
||||
"Blob":{"type":"blob"},
|
||||
"String":{"type":"string"},
|
||||
"Time":{"type":"timestamp"},
|
||||
"GetEventStreamRequest":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"InputVal":{"shape":"String"}
|
||||
}
|
||||
},
|
||||
"GetEventStreamResponse":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"StrVal":{"shape":"String"},
|
||||
"IntVal":{"shape":"Integer"},
|
||||
"EventStream":{"shape":"EventStream"}
|
||||
}
|
||||
},
|
||||
"EventStream":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"Headers":{"shape":"HeaderOnlyEvent"},
|
||||
"ImplicitPayload":{"shape":"ImplicitPayloadEvent"},
|
||||
"ExplicitPayload":{"shape":"ExplicitPayloadEvent"},
|
||||
"PayloadOnly":{"shape":"PayloadOnlyEvent"},
|
||||
"PayloadOnlyBlob":{"shape":"PayloadOnlyBlobEvent"},
|
||||
"PayloadOnlyString":{"shape":"PayloadOnlyStringEvent"},
|
||||
"Empty":{"shape":"EmptyEvent"},
|
||||
"Exception":{"shape":"ExceptionEvent"},
|
||||
"Exception2":{"shape":"ExceptionEvent2"}
|
||||
},
|
||||
"eventstream":true
|
||||
},
|
||||
"EmptyStreamRequest":{
|
||||
"type":"structure",
|
||||
"members":{}
|
||||
},
|
||||
"EmptyStreamResponse":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"EventStream":{"shape":"EmptyEventStream"}
|
||||
}
|
||||
},
|
||||
"EmptyEventStream":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
},
|
||||
"eventstream":true
|
||||
},
|
||||
"HeaderOnlyEvent":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"BoolVal":{
|
||||
"shape":"Bool",
|
||||
"eventheader":true
|
||||
},
|
||||
"ByteVal":{
|
||||
"shape":"Byte",
|
||||
"eventheader":true
|
||||
},
|
||||
"ShortVal":{
|
||||
"shape":"Short",
|
||||
"eventheader":true
|
||||
},
|
||||
"IntegerVal":{
|
||||
"shape":"Integer",
|
||||
"eventheader":true
|
||||
},
|
||||
"LongVal":{
|
||||
"shape":"Long",
|
||||
"eventheader":true
|
||||
},
|
||||
"StringVal":{
|
||||
"shape":"String",
|
||||
"eventheader":true
|
||||
},
|
||||
"BlobVal":{
|
||||
"shape":"Blob",
|
||||
"eventheader":true
|
||||
},
|
||||
"TimeVal":{
|
||||
"shape":"Time",
|
||||
"eventheader":true
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"ImplicitPayloadEvent": {
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"ByteVal":{
|
||||
"shape":"Byte",
|
||||
"eventheader":true
|
||||
},
|
||||
"ShortVal":{
|
||||
"shape":"Short"
|
||||
},
|
||||
"IntegerVal":{
|
||||
"shape":"Integer"
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"ExplicitPayloadEvent": {
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"LongVal":{
|
||||
"shape":"Long",
|
||||
"eventheader":true
|
||||
},
|
||||
"StringVal":{
|
||||
"shape":"String",
|
||||
"eventheader":true
|
||||
},
|
||||
"NestedVal":{
|
||||
"shape":"NestedShape",
|
||||
"eventpayload":true
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"PayloadOnlyEvent":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"NestedVal":{
|
||||
"shape":"NestedShape",
|
||||
"eventpayload":true
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"PayloadOnlyBlobEvent":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"BlobPayload":{
|
||||
"shape":"Blob",
|
||||
"eventpayload":true
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"PayloadOnlyStringEvent":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"StringPayload":{
|
||||
"shape":"String",
|
||||
"eventpayload":true
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"EmptyEvent": {
|
||||
"type":"structure",
|
||||
"members":{},
|
||||
"event": true
|
||||
},
|
||||
"NestedShape": {
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"IntVal":{"shape":"Integer"},
|
||||
"StrVal":{"shape":"String"}
|
||||
}
|
||||
},
|
||||
"ExceptionEvent":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"IntVal":{"shape":"Integer"},
|
||||
"message":{"shape":"String"}
|
||||
},
|
||||
"exception":true
|
||||
},
|
||||
"ExceptionEvent2":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
},
|
||||
"exception":true
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": "2.0",
|
||||
"service": null,
|
||||
"operations": {
|
||||
},
|
||||
"shapes":{}
|
||||
}
|
||||
Generated
Vendored
+226
@@ -0,0 +1,226 @@
|
||||
{
|
||||
"version":"2.0",
|
||||
"metadata":{
|
||||
"apiVersion":"0000-00-00",
|
||||
"endpointPrefix":"restxmlservice",
|
||||
"protocol":"rest-xml",
|
||||
"serviceAbbreviation":"RESTXMLService",
|
||||
"serviceFullName":"REST XML Service",
|
||||
"serviceId":"RESTXMLService",
|
||||
"signatureVersion":"v4",
|
||||
"uid":"RESTXMLService-0000-00-00"
|
||||
},
|
||||
"operations":{
|
||||
"GetEventStream":{
|
||||
"name":"GetEventStream",
|
||||
"http":{
|
||||
"method":"POST",
|
||||
"requestUri":"/"
|
||||
},
|
||||
"input":{"shape":"GetEventStreamRequest"},
|
||||
"output":{"shape":"GetEventStreamResponse"}
|
||||
},
|
||||
"EmptyStream":{
|
||||
"name":"EmptyStream",
|
||||
"http":{
|
||||
"method":"POST",
|
||||
"requestUri":"/"
|
||||
},
|
||||
"input":{"shape":"EmptyStreamRequest"},
|
||||
"output":{"shape":"EmptyStreamResponse"}
|
||||
},
|
||||
"OtherOperation":{
|
||||
"name":"OtherOperation",
|
||||
"http":{
|
||||
"method":"POST",
|
||||
"requestUri":"/"
|
||||
},
|
||||
"errors":[
|
||||
{"shape":"ExceptionEvent2"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"shapes":{
|
||||
"Bool":{"type":"boolean"},
|
||||
"Byte":{"type":"byte"},
|
||||
"Short":{"type":"short"},
|
||||
"Integer":{"type":"integer"},
|
||||
"Long":{"type":"long"},
|
||||
"Blob":{"type":"blob"},
|
||||
"String":{"type":"string"},
|
||||
"Time":{"type":"timestamp"},
|
||||
"GetEventStreamRequest":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"InputVal":{"shape":"String"}
|
||||
}
|
||||
},
|
||||
"GetEventStreamResponse":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"StrVal":{"shape":"String"},
|
||||
"IntVal":{"shape":"Integer"},
|
||||
"EventStream":{"shape":"EventStream"}
|
||||
}
|
||||
},
|
||||
"EventStream":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"Headers":{"shape":"HeaderOnlyEvent"},
|
||||
"ImplicitPayload":{"shape":"ImplicitPayloadEvent"},
|
||||
"ExplicitPayload":{"shape":"ExplicitPayloadEvent"},
|
||||
"PayloadOnly":{"shape":"PayloadOnlyEvent"},
|
||||
"PayloadOnlyBlob":{"shape":"PayloadOnlyBlobEvent"},
|
||||
"PayloadOnlyString":{"shape":"PayloadOnlyStringEvent"},
|
||||
"Empty":{"shape":"EmptyEvent"},
|
||||
"Exception":{"shape":"ExceptionEvent"},
|
||||
"Exception2":{"shape":"ExceptionEvent2"}
|
||||
},
|
||||
"eventstream":true
|
||||
},
|
||||
"EmptyStreamRequest":{
|
||||
"type":"structure",
|
||||
"members":{}
|
||||
},
|
||||
"EmptyStreamResponse":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"EventStream":{"shape":"EmptyEventStream"}
|
||||
}
|
||||
},
|
||||
"EmptyEventStream":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
},
|
||||
"eventstream":true
|
||||
},
|
||||
"HeaderOnlyEvent":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"BoolVal":{
|
||||
"shape":"Bool",
|
||||
"eventheader":true
|
||||
},
|
||||
"ByteVal":{
|
||||
"shape":"Byte",
|
||||
"eventheader":true
|
||||
},
|
||||
"ShortVal":{
|
||||
"shape":"Short",
|
||||
"eventheader":true
|
||||
},
|
||||
"IntegerVal":{
|
||||
"shape":"Integer",
|
||||
"eventheader":true
|
||||
},
|
||||
"LongVal":{
|
||||
"shape":"Long",
|
||||
"eventheader":true
|
||||
},
|
||||
"StringVal":{
|
||||
"shape":"String",
|
||||
"eventheader":true
|
||||
},
|
||||
"BlobVal":{
|
||||
"shape":"Blob",
|
||||
"eventheader":true
|
||||
},
|
||||
"TimeVal":{
|
||||
"shape":"Time",
|
||||
"eventheader":true
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"ImplicitPayloadEvent": {
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"ByteVal":{
|
||||
"shape":"Byte",
|
||||
"eventheader":true
|
||||
},
|
||||
"ShortVal":{
|
||||
"shape":"Short"
|
||||
},
|
||||
"IntegerVal":{
|
||||
"shape":"Integer"
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"ExplicitPayloadEvent": {
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"LongVal":{
|
||||
"shape":"Long",
|
||||
"eventheader":true
|
||||
},
|
||||
"StringVal":{
|
||||
"shape":"String",
|
||||
"eventheader":true
|
||||
},
|
||||
"NestedVal":{
|
||||
"shape":"NestedShape",
|
||||
"eventpayload":true
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"PayloadOnlyEvent":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"NestedVal":{
|
||||
"shape":"NestedShape",
|
||||
"eventpayload":true
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"PayloadOnlyBlobEvent":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"BlobPayload":{
|
||||
"shape":"Blob",
|
||||
"eventpayload":true
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"PayloadOnlyStringEvent":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"StringPayload":{
|
||||
"shape":"String",
|
||||
"eventpayload":true
|
||||
}
|
||||
},
|
||||
"event":true
|
||||
},
|
||||
"EmptyEvent": {
|
||||
"type":"structure",
|
||||
"members":{},
|
||||
"event": true
|
||||
},
|
||||
"NestedShape": {
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"IntVal":{"shape":"Integer"},
|
||||
"StrVal":{"shape":"String"}
|
||||
}
|
||||
},
|
||||
"ExceptionEvent":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
"IntVal":{"shape":"Integer"},
|
||||
"message":{"shape":"String"}
|
||||
},
|
||||
"exception":true
|
||||
},
|
||||
"ExceptionEvent2":{
|
||||
"type":"structure",
|
||||
"members":{
|
||||
},
|
||||
"exception":true
|
||||
}
|
||||
}
|
||||
}
|
||||
vendor/github.com/aws/aws-sdk-go/private/model/api/codegentest/models/restxml/0000-00-00/docs-2.json
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": "2.0",
|
||||
"service": null,
|
||||
"operations": {
|
||||
},
|
||||
"shapes":{}
|
||||
}
|
||||
Generated
Vendored
+635
@@ -0,0 +1,635 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
package awsendpointdiscoverytest
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||
"github.com/aws/aws-sdk-go/aws/crr"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
)
|
||||
|
||||
const opDescribeEndpoints = "DescribeEndpoints"
|
||||
|
||||
// DescribeEndpointsRequest generates a "aws/request.Request" representing the
|
||||
// client's request for the DescribeEndpoints operation. The "output" return
|
||||
// value will be populated with the request's response once the request completes
|
||||
// successfully.
|
||||
//
|
||||
// Use "Send" method on the returned Request to send the API call to the service.
|
||||
// the "output" return value is not valid until after Send returns without error.
|
||||
//
|
||||
// See DescribeEndpoints for more information on using the DescribeEndpoints
|
||||
// API call, and error handling.
|
||||
//
|
||||
// This method is useful when you want to inject custom logic or configuration
|
||||
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
|
||||
//
|
||||
//
|
||||
// // Example sending a request using the DescribeEndpointsRequest method.
|
||||
// req, resp := client.DescribeEndpointsRequest(params)
|
||||
//
|
||||
// err := req.Send()
|
||||
// if err == nil { // resp is now filled
|
||||
// fmt.Println(resp)
|
||||
// }
|
||||
func (c *AwsEndpointDiscoveryTest) DescribeEndpointsRequest(input *DescribeEndpointsInput) (req *request.Request, output *DescribeEndpointsOutput) {
|
||||
op := &request.Operation{
|
||||
Name: opDescribeEndpoints,
|
||||
HTTPMethod: "POST",
|
||||
HTTPPath: "/",
|
||||
}
|
||||
|
||||
if input == nil {
|
||||
input = &DescribeEndpointsInput{}
|
||||
}
|
||||
|
||||
output = &DescribeEndpointsOutput{}
|
||||
req = c.newRequest(op, input, output)
|
||||
return
|
||||
}
|
||||
|
||||
// DescribeEndpoints API operation for AwsEndpointDiscoveryTest.
|
||||
//
|
||||
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
|
||||
// with awserr.Error's Code and Message methods to get detailed information about
|
||||
// the error.
|
||||
//
|
||||
// See the AWS API reference guide for AwsEndpointDiscoveryTest's
|
||||
// API operation DescribeEndpoints for usage and error information.
|
||||
func (c *AwsEndpointDiscoveryTest) DescribeEndpoints(input *DescribeEndpointsInput) (*DescribeEndpointsOutput, error) {
|
||||
req, out := c.DescribeEndpointsRequest(input)
|
||||
return out, req.Send()
|
||||
}
|
||||
|
||||
// DescribeEndpointsWithContext is the same as DescribeEndpoints with the addition of
|
||||
// the ability to pass a context and additional request options.
|
||||
//
|
||||
// See DescribeEndpoints for details on how to use this API operation.
|
||||
//
|
||||
// The context must be non-nil and will be used for request cancellation. If
|
||||
// the context is nil a panic will occur. In the future the SDK may create
|
||||
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
|
||||
// for more information on using Contexts.
|
||||
func (c *AwsEndpointDiscoveryTest) DescribeEndpointsWithContext(ctx aws.Context, input *DescribeEndpointsInput, opts ...request.Option) (*DescribeEndpointsOutput, error) {
|
||||
req, out := c.DescribeEndpointsRequest(input)
|
||||
req.SetContext(ctx)
|
||||
req.ApplyOptions(opts...)
|
||||
return out, req.Send()
|
||||
}
|
||||
|
||||
type discovererDescribeEndpoints struct {
|
||||
Client *AwsEndpointDiscoveryTest
|
||||
Required bool
|
||||
EndpointCache *crr.EndpointCache
|
||||
Params map[string]*string
|
||||
Key string
|
||||
}
|
||||
|
||||
func (d *discovererDescribeEndpoints) Discover() (crr.Endpoint, error) {
|
||||
input := &DescribeEndpointsInput{
|
||||
Operation: d.Params["op"],
|
||||
}
|
||||
|
||||
resp, err := d.Client.DescribeEndpoints(input)
|
||||
if err != nil {
|
||||
return crr.Endpoint{}, err
|
||||
}
|
||||
|
||||
endpoint := crr.Endpoint{
|
||||
Key: d.Key,
|
||||
}
|
||||
|
||||
for _, e := range resp.Endpoints {
|
||||
if e.Address == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
cachedInMinutes := aws.Int64Value(e.CachePeriodInMinutes)
|
||||
u, err := url.Parse(*e.Address)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
addr := crr.WeightedAddress{
|
||||
URL: u,
|
||||
Expired: time.Now().Add(time.Duration(cachedInMinutes) * time.Minute),
|
||||
}
|
||||
|
||||
endpoint.Add(addr)
|
||||
}
|
||||
|
||||
d.EndpointCache.Add(endpoint)
|
||||
|
||||
return endpoint, nil
|
||||
}
|
||||
|
||||
func (d *discovererDescribeEndpoints) Handler(r *request.Request) {
|
||||
endpointKey := crr.BuildEndpointKey(d.Params)
|
||||
d.Key = endpointKey
|
||||
|
||||
endpoint, err := d.EndpointCache.Get(d, endpointKey, d.Required)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return
|
||||
}
|
||||
|
||||
if endpoint.URL != nil && len(endpoint.URL.String()) > 0 {
|
||||
r.HTTPRequest.URL = endpoint.URL
|
||||
}
|
||||
}
|
||||
|
||||
const opTestDiscoveryIdentifiersRequired = "TestDiscoveryIdentifiersRequired"
|
||||
|
||||
// TestDiscoveryIdentifiersRequiredRequest generates a "aws/request.Request" representing the
|
||||
// client's request for the TestDiscoveryIdentifiersRequired operation. The "output" return
|
||||
// value will be populated with the request's response once the request completes
|
||||
// successfully.
|
||||
//
|
||||
// Use "Send" method on the returned Request to send the API call to the service.
|
||||
// the "output" return value is not valid until after Send returns without error.
|
||||
//
|
||||
// See TestDiscoveryIdentifiersRequired for more information on using the TestDiscoveryIdentifiersRequired
|
||||
// API call, and error handling.
|
||||
//
|
||||
// This method is useful when you want to inject custom logic or configuration
|
||||
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
|
||||
//
|
||||
//
|
||||
// // Example sending a request using the TestDiscoveryIdentifiersRequiredRequest method.
|
||||
// req, resp := client.TestDiscoveryIdentifiersRequiredRequest(params)
|
||||
//
|
||||
// err := req.Send()
|
||||
// if err == nil { // resp is now filled
|
||||
// fmt.Println(resp)
|
||||
// }
|
||||
func (c *AwsEndpointDiscoveryTest) TestDiscoveryIdentifiersRequiredRequest(input *TestDiscoveryIdentifiersRequiredInput) (req *request.Request, output *TestDiscoveryIdentifiersRequiredOutput) {
|
||||
op := &request.Operation{
|
||||
Name: opTestDiscoveryIdentifiersRequired,
|
||||
HTTPMethod: "POST",
|
||||
HTTPPath: "/",
|
||||
}
|
||||
|
||||
if input == nil {
|
||||
input = &TestDiscoveryIdentifiersRequiredInput{}
|
||||
}
|
||||
|
||||
output = &TestDiscoveryIdentifiersRequiredOutput{}
|
||||
req = c.newRequest(op, input, output)
|
||||
de := discovererDescribeEndpoints{
|
||||
Required: true,
|
||||
EndpointCache: c.endpointCache,
|
||||
Params: map[string]*string{
|
||||
"op": aws.String(req.Operation.Name),
|
||||
"Sdk": input.Sdk,
|
||||
},
|
||||
Client: c,
|
||||
}
|
||||
|
||||
for k, v := range de.Params {
|
||||
if v == nil {
|
||||
delete(de.Params, k)
|
||||
}
|
||||
}
|
||||
|
||||
req.Handlers.Build.PushFrontNamed(request.NamedHandler{
|
||||
Name: "crr.endpointdiscovery",
|
||||
Fn: de.Handler,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// TestDiscoveryIdentifiersRequired API operation for AwsEndpointDiscoveryTest.
|
||||
//
|
||||
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
|
||||
// with awserr.Error's Code and Message methods to get detailed information about
|
||||
// the error.
|
||||
//
|
||||
// See the AWS API reference guide for AwsEndpointDiscoveryTest's
|
||||
// API operation TestDiscoveryIdentifiersRequired for usage and error information.
|
||||
func (c *AwsEndpointDiscoveryTest) TestDiscoveryIdentifiersRequired(input *TestDiscoveryIdentifiersRequiredInput) (*TestDiscoveryIdentifiersRequiredOutput, error) {
|
||||
req, out := c.TestDiscoveryIdentifiersRequiredRequest(input)
|
||||
return out, req.Send()
|
||||
}
|
||||
|
||||
// TestDiscoveryIdentifiersRequiredWithContext is the same as TestDiscoveryIdentifiersRequired with the addition of
|
||||
// the ability to pass a context and additional request options.
|
||||
//
|
||||
// See TestDiscoveryIdentifiersRequired for details on how to use this API operation.
|
||||
//
|
||||
// The context must be non-nil and will be used for request cancellation. If
|
||||
// the context is nil a panic will occur. In the future the SDK may create
|
||||
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
|
||||
// for more information on using Contexts.
|
||||
func (c *AwsEndpointDiscoveryTest) TestDiscoveryIdentifiersRequiredWithContext(ctx aws.Context, input *TestDiscoveryIdentifiersRequiredInput, opts ...request.Option) (*TestDiscoveryIdentifiersRequiredOutput, error) {
|
||||
req, out := c.TestDiscoveryIdentifiersRequiredRequest(input)
|
||||
req.SetContext(ctx)
|
||||
req.ApplyOptions(opts...)
|
||||
return out, req.Send()
|
||||
}
|
||||
|
||||
const opTestDiscoveryOptional = "TestDiscoveryOptional"
|
||||
|
||||
// TestDiscoveryOptionalRequest generates a "aws/request.Request" representing the
|
||||
// client's request for the TestDiscoveryOptional operation. The "output" return
|
||||
// value will be populated with the request's response once the request completes
|
||||
// successfully.
|
||||
//
|
||||
// Use "Send" method on the returned Request to send the API call to the service.
|
||||
// the "output" return value is not valid until after Send returns without error.
|
||||
//
|
||||
// See TestDiscoveryOptional for more information on using the TestDiscoveryOptional
|
||||
// API call, and error handling.
|
||||
//
|
||||
// This method is useful when you want to inject custom logic or configuration
|
||||
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
|
||||
//
|
||||
//
|
||||
// // Example sending a request using the TestDiscoveryOptionalRequest method.
|
||||
// req, resp := client.TestDiscoveryOptionalRequest(params)
|
||||
//
|
||||
// err := req.Send()
|
||||
// if err == nil { // resp is now filled
|
||||
// fmt.Println(resp)
|
||||
// }
|
||||
func (c *AwsEndpointDiscoveryTest) TestDiscoveryOptionalRequest(input *TestDiscoveryOptionalInput) (req *request.Request, output *TestDiscoveryOptionalOutput) {
|
||||
op := &request.Operation{
|
||||
Name: opTestDiscoveryOptional,
|
||||
HTTPMethod: "POST",
|
||||
HTTPPath: "/",
|
||||
}
|
||||
|
||||
if input == nil {
|
||||
input = &TestDiscoveryOptionalInput{}
|
||||
}
|
||||
|
||||
output = &TestDiscoveryOptionalOutput{}
|
||||
req = c.newRequest(op, input, output)
|
||||
if aws.BoolValue(req.Config.EnableEndpointDiscovery) {
|
||||
de := discovererDescribeEndpoints{
|
||||
Required: false,
|
||||
EndpointCache: c.endpointCache,
|
||||
Params: map[string]*string{
|
||||
"op": aws.String(req.Operation.Name),
|
||||
},
|
||||
Client: c,
|
||||
}
|
||||
|
||||
for k, v := range de.Params {
|
||||
if v == nil {
|
||||
delete(de.Params, k)
|
||||
}
|
||||
}
|
||||
|
||||
req.Handlers.Build.PushFrontNamed(request.NamedHandler{
|
||||
Name: "crr.endpointdiscovery",
|
||||
Fn: de.Handler,
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// TestDiscoveryOptional API operation for AwsEndpointDiscoveryTest.
|
||||
//
|
||||
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
|
||||
// with awserr.Error's Code and Message methods to get detailed information about
|
||||
// the error.
|
||||
//
|
||||
// See the AWS API reference guide for AwsEndpointDiscoveryTest's
|
||||
// API operation TestDiscoveryOptional for usage and error information.
|
||||
func (c *AwsEndpointDiscoveryTest) TestDiscoveryOptional(input *TestDiscoveryOptionalInput) (*TestDiscoveryOptionalOutput, error) {
|
||||
req, out := c.TestDiscoveryOptionalRequest(input)
|
||||
return out, req.Send()
|
||||
}
|
||||
|
||||
// TestDiscoveryOptionalWithContext is the same as TestDiscoveryOptional with the addition of
|
||||
// the ability to pass a context and additional request options.
|
||||
//
|
||||
// See TestDiscoveryOptional for details on how to use this API operation.
|
||||
//
|
||||
// The context must be non-nil and will be used for request cancellation. If
|
||||
// the context is nil a panic will occur. In the future the SDK may create
|
||||
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
|
||||
// for more information on using Contexts.
|
||||
func (c *AwsEndpointDiscoveryTest) TestDiscoveryOptionalWithContext(ctx aws.Context, input *TestDiscoveryOptionalInput, opts ...request.Option) (*TestDiscoveryOptionalOutput, error) {
|
||||
req, out := c.TestDiscoveryOptionalRequest(input)
|
||||
req.SetContext(ctx)
|
||||
req.ApplyOptions(opts...)
|
||||
return out, req.Send()
|
||||
}
|
||||
|
||||
const opTestDiscoveryRequired = "TestDiscoveryRequired"
|
||||
|
||||
// TestDiscoveryRequiredRequest generates a "aws/request.Request" representing the
|
||||
// client's request for the TestDiscoveryRequired operation. The "output" return
|
||||
// value will be populated with the request's response once the request completes
|
||||
// successfully.
|
||||
//
|
||||
// Use "Send" method on the returned Request to send the API call to the service.
|
||||
// the "output" return value is not valid until after Send returns without error.
|
||||
//
|
||||
// See TestDiscoveryRequired for more information on using the TestDiscoveryRequired
|
||||
// API call, and error handling.
|
||||
//
|
||||
// This method is useful when you want to inject custom logic or configuration
|
||||
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
|
||||
//
|
||||
//
|
||||
// // Example sending a request using the TestDiscoveryRequiredRequest method.
|
||||
// req, resp := client.TestDiscoveryRequiredRequest(params)
|
||||
//
|
||||
// err := req.Send()
|
||||
// if err == nil { // resp is now filled
|
||||
// fmt.Println(resp)
|
||||
// }
|
||||
func (c *AwsEndpointDiscoveryTest) TestDiscoveryRequiredRequest(input *TestDiscoveryRequiredInput) (req *request.Request, output *TestDiscoveryRequiredOutput) {
|
||||
op := &request.Operation{
|
||||
Name: opTestDiscoveryRequired,
|
||||
HTTPMethod: "POST",
|
||||
HTTPPath: "/",
|
||||
}
|
||||
|
||||
if input == nil {
|
||||
input = &TestDiscoveryRequiredInput{}
|
||||
}
|
||||
|
||||
output = &TestDiscoveryRequiredOutput{}
|
||||
req = c.newRequest(op, input, output)
|
||||
if aws.BoolValue(req.Config.EnableEndpointDiscovery) {
|
||||
de := discovererDescribeEndpoints{
|
||||
Required: false,
|
||||
EndpointCache: c.endpointCache,
|
||||
Params: map[string]*string{
|
||||
"op": aws.String(req.Operation.Name),
|
||||
},
|
||||
Client: c,
|
||||
}
|
||||
|
||||
for k, v := range de.Params {
|
||||
if v == nil {
|
||||
delete(de.Params, k)
|
||||
}
|
||||
}
|
||||
|
||||
req.Handlers.Build.PushFrontNamed(request.NamedHandler{
|
||||
Name: "crr.endpointdiscovery",
|
||||
Fn: de.Handler,
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// TestDiscoveryRequired API operation for AwsEndpointDiscoveryTest.
|
||||
//
|
||||
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
|
||||
// with awserr.Error's Code and Message methods to get detailed information about
|
||||
// the error.
|
||||
//
|
||||
// See the AWS API reference guide for AwsEndpointDiscoveryTest's
|
||||
// API operation TestDiscoveryRequired for usage and error information.
|
||||
func (c *AwsEndpointDiscoveryTest) TestDiscoveryRequired(input *TestDiscoveryRequiredInput) (*TestDiscoveryRequiredOutput, error) {
|
||||
req, out := c.TestDiscoveryRequiredRequest(input)
|
||||
return out, req.Send()
|
||||
}
|
||||
|
||||
// TestDiscoveryRequiredWithContext is the same as TestDiscoveryRequired with the addition of
|
||||
// the ability to pass a context and additional request options.
|
||||
//
|
||||
// See TestDiscoveryRequired for details on how to use this API operation.
|
||||
//
|
||||
// The context must be non-nil and will be used for request cancellation. If
|
||||
// the context is nil a panic will occur. In the future the SDK may create
|
||||
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
|
||||
// for more information on using Contexts.
|
||||
func (c *AwsEndpointDiscoveryTest) TestDiscoveryRequiredWithContext(ctx aws.Context, input *TestDiscoveryRequiredInput, opts ...request.Option) (*TestDiscoveryRequiredOutput, error) {
|
||||
req, out := c.TestDiscoveryRequiredRequest(input)
|
||||
req.SetContext(ctx)
|
||||
req.ApplyOptions(opts...)
|
||||
return out, req.Send()
|
||||
}
|
||||
|
||||
type DescribeEndpointsInput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
Operation *string `type:"string"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s DescribeEndpointsInput) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s DescribeEndpointsInput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// SetOperation sets the Operation field's value.
|
||||
func (s *DescribeEndpointsInput) SetOperation(v string) *DescribeEndpointsInput {
|
||||
s.Operation = &v
|
||||
return s
|
||||
}
|
||||
|
||||
type DescribeEndpointsOutput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
// Endpoints is a required field
|
||||
Endpoints []*Endpoint `type:"list" required:"true"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s DescribeEndpointsOutput) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s DescribeEndpointsOutput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// SetEndpoints sets the Endpoints field's value.
|
||||
func (s *DescribeEndpointsOutput) SetEndpoints(v []*Endpoint) *DescribeEndpointsOutput {
|
||||
s.Endpoints = v
|
||||
return s
|
||||
}
|
||||
|
||||
type Endpoint struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
// Address is a required field
|
||||
Address *string `type:"string" required:"true"`
|
||||
|
||||
// CachePeriodInMinutes is a required field
|
||||
CachePeriodInMinutes *int64 `type:"long" required:"true"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s Endpoint) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s Endpoint) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// SetAddress sets the Address field's value.
|
||||
func (s *Endpoint) SetAddress(v string) *Endpoint {
|
||||
s.Address = &v
|
||||
return s
|
||||
}
|
||||
|
||||
// SetCachePeriodInMinutes sets the CachePeriodInMinutes field's value.
|
||||
func (s *Endpoint) SetCachePeriodInMinutes(v int64) *Endpoint {
|
||||
s.CachePeriodInMinutes = &v
|
||||
return s
|
||||
}
|
||||
|
||||
type TestDiscoveryIdentifiersRequiredInput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
// Sdk is a required field
|
||||
Sdk *string `type:"string" required:"true"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s TestDiscoveryIdentifiersRequiredInput) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s TestDiscoveryIdentifiersRequiredInput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// Validate inspects the fields of the type to determine if they are valid.
|
||||
func (s *TestDiscoveryIdentifiersRequiredInput) Validate() error {
|
||||
invalidParams := request.ErrInvalidParams{Context: "TestDiscoveryIdentifiersRequiredInput"}
|
||||
if s.Sdk == nil {
|
||||
invalidParams.Add(request.NewErrParamRequired("Sdk"))
|
||||
}
|
||||
|
||||
if invalidParams.Len() > 0 {
|
||||
return invalidParams
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetSdk sets the Sdk field's value.
|
||||
func (s *TestDiscoveryIdentifiersRequiredInput) SetSdk(v string) *TestDiscoveryIdentifiersRequiredInput {
|
||||
s.Sdk = &v
|
||||
return s
|
||||
}
|
||||
|
||||
type TestDiscoveryIdentifiersRequiredOutput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
RequestSuccessful *bool `type:"boolean"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s TestDiscoveryIdentifiersRequiredOutput) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s TestDiscoveryIdentifiersRequiredOutput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// SetRequestSuccessful sets the RequestSuccessful field's value.
|
||||
func (s *TestDiscoveryIdentifiersRequiredOutput) SetRequestSuccessful(v bool) *TestDiscoveryIdentifiersRequiredOutput {
|
||||
s.RequestSuccessful = &v
|
||||
return s
|
||||
}
|
||||
|
||||
type TestDiscoveryOptionalInput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
Sdk *string `type:"string"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s TestDiscoveryOptionalInput) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s TestDiscoveryOptionalInput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// SetSdk sets the Sdk field's value.
|
||||
func (s *TestDiscoveryOptionalInput) SetSdk(v string) *TestDiscoveryOptionalInput {
|
||||
s.Sdk = &v
|
||||
return s
|
||||
}
|
||||
|
||||
type TestDiscoveryOptionalOutput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
RequestSuccessful *bool `type:"boolean"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s TestDiscoveryOptionalOutput) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s TestDiscoveryOptionalOutput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// SetRequestSuccessful sets the RequestSuccessful field's value.
|
||||
func (s *TestDiscoveryOptionalOutput) SetRequestSuccessful(v bool) *TestDiscoveryOptionalOutput {
|
||||
s.RequestSuccessful = &v
|
||||
return s
|
||||
}
|
||||
|
||||
type TestDiscoveryRequiredInput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
Sdk *string `type:"string"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s TestDiscoveryRequiredInput) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s TestDiscoveryRequiredInput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// SetSdk sets the Sdk field's value.
|
||||
func (s *TestDiscoveryRequiredInput) SetSdk(v string) *TestDiscoveryRequiredInput {
|
||||
s.Sdk = &v
|
||||
return s
|
||||
}
|
||||
|
||||
type TestDiscoveryRequiredOutput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
RequestSuccessful *bool `type:"boolean"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s TestDiscoveryRequiredOutput) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s TestDiscoveryRequiredOutput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// SetRequestSuccessful sets the RequestSuccessful field's value.
|
||||
func (s *TestDiscoveryRequiredOutput) SetRequestSuccessful(v bool) *TestDiscoveryRequiredOutput {
|
||||
s.RequestSuccessful = &v
|
||||
return s
|
||||
}
|
||||
Generated
Vendored
+80
@@ -0,0 +1,80 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
// Package awsendpointdiscoverytestiface provides an interface to enable mocking the AwsEndpointDiscoveryTest service client
|
||||
// for testing your code.
|
||||
//
|
||||
// It is important to note that this interface will have breaking changes
|
||||
// when the service model is updated and adds new API operations, paginators,
|
||||
// and waiters.
|
||||
package awsendpointdiscoverytestiface
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/private/model/api/codegentest/service/awsendpointdiscoverytest"
|
||||
)
|
||||
|
||||
// AwsEndpointDiscoveryTestAPI provides an interface to enable mocking the
|
||||
// awsendpointdiscoverytest.AwsEndpointDiscoveryTest service client's API operation,
|
||||
// paginators, and waiters. This make unit testing your code that calls out
|
||||
// to the SDK's service client's calls easier.
|
||||
//
|
||||
// The best way to use this interface is so the SDK's service client's calls
|
||||
// can be stubbed out for unit testing your code with the SDK without needing
|
||||
// to inject custom request handlers into the SDK's request pipeline.
|
||||
//
|
||||
// // myFunc uses an SDK service client to make a request to
|
||||
// // AwsEndpointDiscoveryTest.
|
||||
// func myFunc(svc awsendpointdiscoverytestiface.AwsEndpointDiscoveryTestAPI) bool {
|
||||
// // Make svc.DescribeEndpoints request
|
||||
// }
|
||||
//
|
||||
// func main() {
|
||||
// sess := session.New()
|
||||
// svc := awsendpointdiscoverytest.New(sess)
|
||||
//
|
||||
// myFunc(svc)
|
||||
// }
|
||||
//
|
||||
// In your _test.go file:
|
||||
//
|
||||
// // Define a mock struct to be used in your unit tests of myFunc.
|
||||
// type mockAwsEndpointDiscoveryTestClient struct {
|
||||
// awsendpointdiscoverytestiface.AwsEndpointDiscoveryTestAPI
|
||||
// }
|
||||
// func (m *mockAwsEndpointDiscoveryTestClient) DescribeEndpoints(input *awsendpointdiscoverytest.DescribeEndpointsInput) (*awsendpointdiscoverytest.DescribeEndpointsOutput, error) {
|
||||
// // mock response/functionality
|
||||
// }
|
||||
//
|
||||
// func TestMyFunc(t *testing.T) {
|
||||
// // Setup Test
|
||||
// mockSvc := &mockAwsEndpointDiscoveryTestClient{}
|
||||
//
|
||||
// myfunc(mockSvc)
|
||||
//
|
||||
// // Verify myFunc's functionality
|
||||
// }
|
||||
//
|
||||
// It is important to note that this interface will have breaking changes
|
||||
// when the service model is updated and adds new API operations, paginators,
|
||||
// and waiters. Its suggested to use the pattern above for testing, or using
|
||||
// tooling to generate mocks to satisfy the interfaces.
|
||||
type AwsEndpointDiscoveryTestAPI interface {
|
||||
DescribeEndpoints(*awsendpointdiscoverytest.DescribeEndpointsInput) (*awsendpointdiscoverytest.DescribeEndpointsOutput, error)
|
||||
DescribeEndpointsWithContext(aws.Context, *awsendpointdiscoverytest.DescribeEndpointsInput, ...request.Option) (*awsendpointdiscoverytest.DescribeEndpointsOutput, error)
|
||||
DescribeEndpointsRequest(*awsendpointdiscoverytest.DescribeEndpointsInput) (*request.Request, *awsendpointdiscoverytest.DescribeEndpointsOutput)
|
||||
|
||||
TestDiscoveryIdentifiersRequired(*awsendpointdiscoverytest.TestDiscoveryIdentifiersRequiredInput) (*awsendpointdiscoverytest.TestDiscoveryIdentifiersRequiredOutput, error)
|
||||
TestDiscoveryIdentifiersRequiredWithContext(aws.Context, *awsendpointdiscoverytest.TestDiscoveryIdentifiersRequiredInput, ...request.Option) (*awsendpointdiscoverytest.TestDiscoveryIdentifiersRequiredOutput, error)
|
||||
TestDiscoveryIdentifiersRequiredRequest(*awsendpointdiscoverytest.TestDiscoveryIdentifiersRequiredInput) (*request.Request, *awsendpointdiscoverytest.TestDiscoveryIdentifiersRequiredOutput)
|
||||
|
||||
TestDiscoveryOptional(*awsendpointdiscoverytest.TestDiscoveryOptionalInput) (*awsendpointdiscoverytest.TestDiscoveryOptionalOutput, error)
|
||||
TestDiscoveryOptionalWithContext(aws.Context, *awsendpointdiscoverytest.TestDiscoveryOptionalInput, ...request.Option) (*awsendpointdiscoverytest.TestDiscoveryOptionalOutput, error)
|
||||
TestDiscoveryOptionalRequest(*awsendpointdiscoverytest.TestDiscoveryOptionalInput) (*request.Request, *awsendpointdiscoverytest.TestDiscoveryOptionalOutput)
|
||||
|
||||
TestDiscoveryRequired(*awsendpointdiscoverytest.TestDiscoveryRequiredInput) (*awsendpointdiscoverytest.TestDiscoveryRequiredOutput, error)
|
||||
TestDiscoveryRequiredWithContext(aws.Context, *awsendpointdiscoverytest.TestDiscoveryRequiredInput, ...request.Option) (*awsendpointdiscoverytest.TestDiscoveryRequiredOutput, error)
|
||||
TestDiscoveryRequiredRequest(*awsendpointdiscoverytest.TestDiscoveryRequiredInput) (*request.Request, *awsendpointdiscoverytest.TestDiscoveryRequiredOutput)
|
||||
}
|
||||
|
||||
var _ AwsEndpointDiscoveryTestAPI = (*awsendpointdiscoverytest.AwsEndpointDiscoveryTest)(nil)
|
||||
Generated
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
// Package awsendpointdiscoverytest provides the client and types for making API
|
||||
// requests to AwsEndpointDiscoveryTest.
|
||||
//
|
||||
// See awsendpointdiscoverytest package documentation for more information.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/service/awsendpointdiscoverytest/
|
||||
//
|
||||
// Using the Client
|
||||
//
|
||||
// To contact AwsEndpointDiscoveryTest with the SDK use the New function to create
|
||||
// a new service client. With that client you can make API requests to the service.
|
||||
// These clients are safe to use concurrently.
|
||||
//
|
||||
// See the SDK's documentation for more information on how to use the SDK.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/
|
||||
//
|
||||
// See aws.Config documentation for more information on configuring SDK clients.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config
|
||||
//
|
||||
// See the AwsEndpointDiscoveryTest client AwsEndpointDiscoveryTest for more
|
||||
// information on creating client for this service.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/service/awsendpointdiscoverytest/#New
|
||||
package awsendpointdiscoverytest
|
||||
Generated
Vendored
+136
@@ -0,0 +1,136 @@
|
||||
package awsendpointdiscoverytest
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||
)
|
||||
|
||||
func TestEndpointDiscovery(t *testing.T) {
|
||||
svc := New(unit.Session, &aws.Config{
|
||||
EnableEndpointDiscovery: aws.Bool(true),
|
||||
})
|
||||
svc.Handlers.Clear()
|
||||
svc.Handlers.Send.PushBack(mockSendDescEndpoint)
|
||||
|
||||
var descCount int32
|
||||
svc.Handlers.Complete.PushBack(func(r *request.Request) {
|
||||
if r.Operation.Name != opDescribeEndpoints {
|
||||
return
|
||||
}
|
||||
atomic.AddInt32(&descCount, 1)
|
||||
})
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
req, _ := svc.TestDiscoveryIdentifiersRequiredRequest(
|
||||
&TestDiscoveryIdentifiersRequiredInput{
|
||||
Sdk: aws.String("sdk"),
|
||||
},
|
||||
)
|
||||
req.Handlers.Send.PushBack(func(r *request.Request) {
|
||||
if e, a := "http://foo", r.HTTPRequest.URL.String(); e != a {
|
||||
t.Errorf("expected %q, but received %q", e, a)
|
||||
}
|
||||
})
|
||||
if err := req.Send(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if e, a := int32(1), atomic.LoadInt32(&descCount); e != a {
|
||||
t.Errorf("expect desc endpoint called %d, got %d", e, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAsyncEndpointDiscovery(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
svc := New(unit.Session, &aws.Config{
|
||||
EnableEndpointDiscovery: aws.Bool(true),
|
||||
})
|
||||
svc.Handlers.Clear()
|
||||
|
||||
var firstAsyncReq sync.WaitGroup
|
||||
firstAsyncReq.Add(1)
|
||||
svc.Handlers.Build.PushBack(func(r *request.Request) {
|
||||
if r.Operation.Name == opDescribeEndpoints {
|
||||
firstAsyncReq.Wait()
|
||||
}
|
||||
})
|
||||
svc.Handlers.Send.PushBack(mockSendDescEndpoint)
|
||||
|
||||
req, _ := svc.TestDiscoveryOptionalRequest(&TestDiscoveryOptionalInput{
|
||||
Sdk: aws.String("sdk"),
|
||||
})
|
||||
const clientHost = "awsendpointdiscoverytestservice.mock-region.amazonaws.com"
|
||||
req.Handlers.Send.PushBack(func(r *request.Request) {
|
||||
if e, a := clientHost, r.HTTPRequest.URL.Host; e != a {
|
||||
t.Errorf("expected %q, but received %q", e, a)
|
||||
}
|
||||
})
|
||||
req.Handlers.Complete.PushBack(func(r *request.Request) {
|
||||
firstAsyncReq.Done()
|
||||
})
|
||||
if err := req.Send(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var cacheUpdated bool
|
||||
for s := time.Now().Add(10 * time.Second); s.After(time.Now()); {
|
||||
// Wait for the cache to be updated before making second request.
|
||||
if svc.endpointCache.Has(req.Operation.Name) {
|
||||
cacheUpdated = true
|
||||
break
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
if !cacheUpdated {
|
||||
t.Fatalf("expect endpoint cache to be updated, was not")
|
||||
}
|
||||
|
||||
req, _ = svc.TestDiscoveryOptionalRequest(&TestDiscoveryOptionalInput{
|
||||
Sdk: aws.String("sdk"),
|
||||
})
|
||||
req.Handlers.Send.PushBack(func(r *request.Request) {
|
||||
if e, a := "http://foo", r.HTTPRequest.URL.String(); e != a {
|
||||
t.Errorf("expected %q, but received %q", e, a)
|
||||
}
|
||||
})
|
||||
if err := req.Send(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func removeHandlers(h request.Handlers, removeSendHandlers bool) request.Handlers {
|
||||
if removeSendHandlers {
|
||||
h.Send.Clear()
|
||||
}
|
||||
h.Unmarshal.Clear()
|
||||
h.UnmarshalStream.Clear()
|
||||
h.UnmarshalMeta.Clear()
|
||||
h.UnmarshalError.Clear()
|
||||
h.Validate.Clear()
|
||||
h.Complete.Clear()
|
||||
h.ValidateResponse.Clear()
|
||||
return h
|
||||
}
|
||||
|
||||
func mockSendDescEndpoint(r *request.Request) {
|
||||
if r.Operation.Name != opDescribeEndpoints {
|
||||
return
|
||||
}
|
||||
|
||||
out, _ := r.Data.(*DescribeEndpointsOutput)
|
||||
out.Endpoints = []*Endpoint{
|
||||
{
|
||||
Address: aws.String("http://foo"),
|
||||
CachePeriodInMinutes: aws.Int64(5),
|
||||
},
|
||||
}
|
||||
r.Data = out
|
||||
}
|
||||
Generated
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
package awsendpointdiscoverytest
|
||||
Generated
Vendored
+103
@@ -0,0 +1,103 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
package awsendpointdiscoverytest
|
||||
|
||||
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/crr"
|
||||
"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"
|
||||
)
|
||||
|
||||
// AwsEndpointDiscoveryTest provides the API operation methods for making requests to
|
||||
// AwsEndpointDiscoveryTest. See this package's package overview docs
|
||||
// for details on the service.
|
||||
//
|
||||
// AwsEndpointDiscoveryTest methods are safe to use concurrently. It is not safe to
|
||||
// modify mutate any of the struct's properties though.
|
||||
type AwsEndpointDiscoveryTest struct {
|
||||
*client.Client
|
||||
endpointCache *crr.EndpointCache
|
||||
}
|
||||
|
||||
// Used for custom client initialization logic
|
||||
var initClient func(*client.Client)
|
||||
|
||||
// Used for custom request initialization logic
|
||||
var initRequest func(*request.Request)
|
||||
|
||||
// Service information constants
|
||||
const (
|
||||
ServiceName = "AwsEndpointDiscoveryTest" // Name of service.
|
||||
EndpointsID = "awsendpointdiscoverytestservice" // ID to lookup a service endpoint with.
|
||||
ServiceID = "AwsEndpointDiscoveryTest" // ServiceID is a unique identifer of a specific service.
|
||||
)
|
||||
|
||||
// New creates a new instance of the AwsEndpointDiscoveryTest 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 AwsEndpointDiscoveryTest client from just a session.
|
||||
// svc := awsendpointdiscoverytest.New(mySession)
|
||||
//
|
||||
// // Create a AwsEndpointDiscoveryTest client with additional configuration
|
||||
// svc := awsendpointdiscoverytest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
|
||||
func New(p client.ConfigProvider, cfgs ...*aws.Config) *AwsEndpointDiscoveryTest {
|
||||
c := p.ClientConfig(EndpointsID, cfgs...)
|
||||
if c.SigningNameDerived || len(c.SigningName) == 0 {
|
||||
c.SigningName = "awsendpointdiscoverytestservice"
|
||||
}
|
||||
return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName)
|
||||
}
|
||||
|
||||
// newClient creates, initializes and returns a new service client instance.
|
||||
func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *AwsEndpointDiscoveryTest {
|
||||
svc := &AwsEndpointDiscoveryTest{
|
||||
Client: client.New(
|
||||
cfg,
|
||||
metadata.ClientInfo{
|
||||
ServiceName: ServiceName,
|
||||
ServiceID: ServiceID,
|
||||
SigningName: signingName,
|
||||
SigningRegion: signingRegion,
|
||||
Endpoint: endpoint,
|
||||
APIVersion: "2018-08-31",
|
||||
JSONVersion: "1.1",
|
||||
TargetPrefix: "AwsEndpointDiscoveryTestService",
|
||||
},
|
||||
handlers,
|
||||
),
|
||||
}
|
||||
svc.endpointCache = crr.NewEndpointCache(10)
|
||||
|
||||
// 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 AwsEndpointDiscoveryTest operation and runs any
|
||||
// custom request initialization.
|
||||
func (c *AwsEndpointDiscoveryTest) 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
|
||||
}
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
// Package service contains automatically generated AWS clients.
|
||||
package service
|
||||
|
||||
//go:generate go run -tags codegen ../../../cli/gen-api/main.go -path=../service -svc-import-path "github.com/aws/aws-sdk-go/private/model/api/codegentest/service" ../models/*/*/api-2.json
|
||||
//go:generate gofmt -s -w ../service
|
||||
Generated
Vendored
+1355
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
// Package restjsonservice provides the client and types for making API
|
||||
// requests to REST JSON Service.
|
||||
//
|
||||
// See https://docs.aws.amazon.com/goto/WebAPI/RESTJSONService-0000-00-00 for more information on this service.
|
||||
//
|
||||
// See restjsonservice package documentation for more information.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/service/restjsonservice/
|
||||
//
|
||||
// Using the Client
|
||||
//
|
||||
// To contact REST JSON Service with the SDK use the New function to create
|
||||
// a new service client. With that client you can make API requests to the service.
|
||||
// These clients are safe to use concurrently.
|
||||
//
|
||||
// See the SDK's documentation for more information on how to use the SDK.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/
|
||||
//
|
||||
// See aws.Config documentation for more information on configuring SDK clients.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config
|
||||
//
|
||||
// See the REST JSON Service client RESTJSONService for more
|
||||
// information on creating client for this service.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/service/restjsonservice/#New
|
||||
package restjsonservice
|
||||
Generated
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
package restjsonservice
|
||||
|
||||
const (
|
||||
|
||||
// ErrCodeExceptionEvent for service response error code
|
||||
// "ExceptionEvent".
|
||||
ErrCodeExceptionEvent = "ExceptionEvent"
|
||||
|
||||
// ErrCodeExceptionEvent2 for service response error code
|
||||
// "ExceptionEvent2".
|
||||
ErrCodeExceptionEvent2 = "ExceptionEvent2"
|
||||
)
|
||||
Generated
Vendored
+526
@@ -0,0 +1,526 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
// +build go1.6
|
||||
|
||||
package restjsonservice
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/corehandlers"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||
"github.com/aws/aws-sdk-go/private/protocol"
|
||||
"github.com/aws/aws-sdk-go/private/protocol/eventstream"
|
||||
"github.com/aws/aws-sdk-go/private/protocol/eventstream/eventstreamapi"
|
||||
"github.com/aws/aws-sdk-go/private/protocol/eventstream/eventstreamtest"
|
||||
"github.com/aws/aws-sdk-go/private/protocol/restjson"
|
||||
)
|
||||
|
||||
var _ time.Time
|
||||
var _ awserr.Error
|
||||
|
||||
func TestEmptyStream_Read(t *testing.T) {
|
||||
expectEvents, eventMsgs := mockEmptyStreamReadEvents()
|
||||
sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
|
||||
eventstreamtest.ServeEventStream{
|
||||
T: t,
|
||||
Events: eventMsgs,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error, %v", err)
|
||||
}
|
||||
defer cleanupFn()
|
||||
|
||||
svc := New(sess)
|
||||
resp, err := svc.EmptyStream(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error got, %v", err)
|
||||
}
|
||||
defer resp.EventStream.Close()
|
||||
|
||||
var i int
|
||||
for event := range resp.EventStream.Events() {
|
||||
if event == nil {
|
||||
t.Errorf("%d, expect event, got nil", i)
|
||||
}
|
||||
if e, a := expectEvents[i], event; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("%d, expect %T %v, got %T %v", i, e, e, a, a)
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
if err := resp.EventStream.Err(); err != nil {
|
||||
t.Errorf("expect no error, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyStream_ReadClose(t *testing.T) {
|
||||
_, eventMsgs := mockEmptyStreamReadEvents()
|
||||
sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
|
||||
eventstreamtest.ServeEventStream{
|
||||
T: t,
|
||||
Events: eventMsgs,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error, %v", err)
|
||||
}
|
||||
defer cleanupFn()
|
||||
|
||||
svc := New(sess)
|
||||
resp, err := svc.EmptyStream(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error got, %v", err)
|
||||
}
|
||||
|
||||
resp.EventStream.Close()
|
||||
<-resp.EventStream.Events()
|
||||
|
||||
if err := resp.EventStream.Err(); err != nil {
|
||||
t.Errorf("expect no error, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEmptyStream_Read(b *testing.B) {
|
||||
_, eventMsgs := mockEmptyStreamReadEvents()
|
||||
var buf bytes.Buffer
|
||||
encoder := eventstream.NewEncoder(&buf)
|
||||
for _, msg := range eventMsgs {
|
||||
if err := encoder.Encode(msg); err != nil {
|
||||
b.Fatalf("failed to encode message, %v", err)
|
||||
}
|
||||
}
|
||||
stream := &loopReader{source: bytes.NewReader(buf.Bytes())}
|
||||
|
||||
sess := unit.Session
|
||||
svc := New(sess, &aws.Config{
|
||||
Endpoint: aws.String("https://example.com"),
|
||||
DisableParamValidation: aws.Bool(true),
|
||||
})
|
||||
svc.Handlers.Send.Swap(corehandlers.SendHandler.Name,
|
||||
request.NamedHandler{Name: "mockSend",
|
||||
Fn: func(r *request.Request) {
|
||||
r.HTTPResponse = &http.Response{
|
||||
Status: "200 OK",
|
||||
StatusCode: 200,
|
||||
Header: http.Header{},
|
||||
Body: ioutil.NopCloser(stream),
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
resp, err := svc.EmptyStream(nil)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to create request, %v", err)
|
||||
}
|
||||
defer resp.EventStream.Close()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err = resp.EventStream.Err(); err != nil {
|
||||
b.Fatalf("expect no error, got %v", err)
|
||||
}
|
||||
event := <-resp.EventStream.Events()
|
||||
if event == nil {
|
||||
b.Fatalf("expect event, got nil, %v, %d", resp.EventStream.Err(), i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mockEmptyStreamReadEvents() (
|
||||
[]EmptyEventStreamEvent,
|
||||
[]eventstream.Message,
|
||||
) {
|
||||
expectEvents := []EmptyEventStreamEvent{}
|
||||
|
||||
var marshalers request.HandlerList
|
||||
marshalers.PushBackNamed(restjson.BuildHandler)
|
||||
payloadMarshaler := protocol.HandlerPayloadMarshal{
|
||||
Marshalers: marshalers,
|
||||
}
|
||||
_ = payloadMarshaler
|
||||
|
||||
eventMsgs := []eventstream.Message{}
|
||||
|
||||
return expectEvents, eventMsgs
|
||||
}
|
||||
|
||||
func TestGetEventStream_Read(t *testing.T) {
|
||||
expectEvents, eventMsgs := mockGetEventStreamReadEvents()
|
||||
sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
|
||||
eventstreamtest.ServeEventStream{
|
||||
T: t,
|
||||
Events: eventMsgs,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error, %v", err)
|
||||
}
|
||||
defer cleanupFn()
|
||||
|
||||
svc := New(sess)
|
||||
resp, err := svc.GetEventStream(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error got, %v", err)
|
||||
}
|
||||
defer resp.EventStream.Close()
|
||||
|
||||
var i int
|
||||
for event := range resp.EventStream.Events() {
|
||||
if event == nil {
|
||||
t.Errorf("%d, expect event, got nil", i)
|
||||
}
|
||||
if e, a := expectEvents[i], event; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("%d, expect %T %v, got %T %v", i, e, e, a, a)
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
if err := resp.EventStream.Err(); err != nil {
|
||||
t.Errorf("expect no error, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetEventStream_ReadClose(t *testing.T) {
|
||||
_, eventMsgs := mockGetEventStreamReadEvents()
|
||||
sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
|
||||
eventstreamtest.ServeEventStream{
|
||||
T: t,
|
||||
Events: eventMsgs,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error, %v", err)
|
||||
}
|
||||
defer cleanupFn()
|
||||
|
||||
svc := New(sess)
|
||||
resp, err := svc.GetEventStream(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error got, %v", err)
|
||||
}
|
||||
|
||||
resp.EventStream.Close()
|
||||
<-resp.EventStream.Events()
|
||||
|
||||
if err := resp.EventStream.Err(); err != nil {
|
||||
t.Errorf("expect no error, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGetEventStream_Read(b *testing.B) {
|
||||
_, eventMsgs := mockGetEventStreamReadEvents()
|
||||
var buf bytes.Buffer
|
||||
encoder := eventstream.NewEncoder(&buf)
|
||||
for _, msg := range eventMsgs {
|
||||
if err := encoder.Encode(msg); err != nil {
|
||||
b.Fatalf("failed to encode message, %v", err)
|
||||
}
|
||||
}
|
||||
stream := &loopReader{source: bytes.NewReader(buf.Bytes())}
|
||||
|
||||
sess := unit.Session
|
||||
svc := New(sess, &aws.Config{
|
||||
Endpoint: aws.String("https://example.com"),
|
||||
DisableParamValidation: aws.Bool(true),
|
||||
})
|
||||
svc.Handlers.Send.Swap(corehandlers.SendHandler.Name,
|
||||
request.NamedHandler{Name: "mockSend",
|
||||
Fn: func(r *request.Request) {
|
||||
r.HTTPResponse = &http.Response{
|
||||
Status: "200 OK",
|
||||
StatusCode: 200,
|
||||
Header: http.Header{},
|
||||
Body: ioutil.NopCloser(stream),
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
resp, err := svc.GetEventStream(nil)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to create request, %v", err)
|
||||
}
|
||||
defer resp.EventStream.Close()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err = resp.EventStream.Err(); err != nil {
|
||||
b.Fatalf("expect no error, got %v", err)
|
||||
}
|
||||
event := <-resp.EventStream.Events()
|
||||
if event == nil {
|
||||
b.Fatalf("expect event, got nil, %v, %d", resp.EventStream.Err(), i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mockGetEventStreamReadEvents() (
|
||||
[]EventStreamEvent,
|
||||
[]eventstream.Message,
|
||||
) {
|
||||
expectEvents := []EventStreamEvent{
|
||||
&EmptyEvent{},
|
||||
&ExplicitPayloadEvent{
|
||||
LongVal: aws.Int64(1234),
|
||||
NestedVal: &NestedShape{
|
||||
IntVal: aws.Int64(123),
|
||||
StrVal: aws.String("string value goes here"),
|
||||
},
|
||||
StringVal: aws.String("string value goes here"),
|
||||
},
|
||||
&HeaderOnlyEvent{
|
||||
BlobVal: []byte("blob value goes here"),
|
||||
BoolVal: aws.Bool(true),
|
||||
ByteVal: aws.Int64(1),
|
||||
IntegerVal: aws.Int64(123),
|
||||
LongVal: aws.Int64(1234),
|
||||
ShortVal: aws.Int64(12),
|
||||
StringVal: aws.String("string value goes here"),
|
||||
TimeVal: aws.Time(time.Unix(1396594860, 0).UTC()),
|
||||
},
|
||||
&ImplicitPayloadEvent{
|
||||
ByteVal: aws.Int64(1),
|
||||
IntegerVal: aws.Int64(123),
|
||||
ShortVal: aws.Int64(12),
|
||||
},
|
||||
&PayloadOnlyEvent{
|
||||
NestedVal: &NestedShape{
|
||||
IntVal: aws.Int64(123),
|
||||
StrVal: aws.String("string value goes here"),
|
||||
},
|
||||
},
|
||||
&PayloadOnlyBlobEvent{
|
||||
BlobPayload: []byte("blob value goes here"),
|
||||
},
|
||||
&PayloadOnlyStringEvent{
|
||||
StringPayload: aws.String("string value goes here"),
|
||||
},
|
||||
}
|
||||
|
||||
var marshalers request.HandlerList
|
||||
marshalers.PushBackNamed(restjson.BuildHandler)
|
||||
payloadMarshaler := protocol.HandlerPayloadMarshal{
|
||||
Marshalers: marshalers,
|
||||
}
|
||||
_ = payloadMarshaler
|
||||
|
||||
eventMsgs := []eventstream.Message{
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("Empty"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("ExplicitPayload"),
|
||||
},
|
||||
{
|
||||
Name: "LongVal",
|
||||
Value: eventstream.Int64Value(*expectEvents[1].(*ExplicitPayloadEvent).LongVal),
|
||||
},
|
||||
{
|
||||
Name: "StringVal",
|
||||
Value: eventstream.StringValue(*expectEvents[1].(*ExplicitPayloadEvent).StringVal),
|
||||
},
|
||||
},
|
||||
Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[1]),
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("Headers"),
|
||||
},
|
||||
{
|
||||
Name: "BlobVal",
|
||||
Value: eventstream.BytesValue(expectEvents[2].(*HeaderOnlyEvent).BlobVal),
|
||||
},
|
||||
{
|
||||
Name: "BoolVal",
|
||||
Value: eventstream.BoolValue(*expectEvents[2].(*HeaderOnlyEvent).BoolVal),
|
||||
},
|
||||
{
|
||||
Name: "ByteVal",
|
||||
Value: eventstream.Int8Value(int8(*expectEvents[2].(*HeaderOnlyEvent).ByteVal)),
|
||||
},
|
||||
{
|
||||
Name: "IntegerVal",
|
||||
Value: eventstream.Int32Value(int32(*expectEvents[2].(*HeaderOnlyEvent).IntegerVal)),
|
||||
},
|
||||
{
|
||||
Name: "LongVal",
|
||||
Value: eventstream.Int64Value(*expectEvents[2].(*HeaderOnlyEvent).LongVal),
|
||||
},
|
||||
{
|
||||
Name: "ShortVal",
|
||||
Value: eventstream.Int16Value(int16(*expectEvents[2].(*HeaderOnlyEvent).ShortVal)),
|
||||
},
|
||||
{
|
||||
Name: "StringVal",
|
||||
Value: eventstream.StringValue(*expectEvents[2].(*HeaderOnlyEvent).StringVal),
|
||||
},
|
||||
{
|
||||
Name: "TimeVal",
|
||||
Value: eventstream.TimestampValue(*expectEvents[2].(*HeaderOnlyEvent).TimeVal),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("ImplicitPayload"),
|
||||
},
|
||||
{
|
||||
Name: "ByteVal",
|
||||
Value: eventstream.Int8Value(int8(*expectEvents[3].(*ImplicitPayloadEvent).ByteVal)),
|
||||
},
|
||||
},
|
||||
Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[3]),
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("PayloadOnly"),
|
||||
},
|
||||
},
|
||||
Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[4]),
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("PayloadOnlyBlob"),
|
||||
},
|
||||
},
|
||||
Payload: expectEvents[5].(*PayloadOnlyBlobEvent).BlobPayload,
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("PayloadOnlyString"),
|
||||
},
|
||||
},
|
||||
Payload: []byte(*expectEvents[6].(*PayloadOnlyStringEvent).StringPayload),
|
||||
},
|
||||
}
|
||||
|
||||
return expectEvents, eventMsgs
|
||||
}
|
||||
func TestGetEventStream_ReadException(t *testing.T) {
|
||||
expectEvents := []EventStreamEvent{
|
||||
&ExceptionEvent{
|
||||
IntVal: aws.Int64(123),
|
||||
Message_: aws.String("string value goes here"),
|
||||
},
|
||||
}
|
||||
|
||||
var marshalers request.HandlerList
|
||||
marshalers.PushBackNamed(restjson.BuildHandler)
|
||||
payloadMarshaler := protocol.HandlerPayloadMarshal{
|
||||
Marshalers: marshalers,
|
||||
}
|
||||
|
||||
eventMsgs := []eventstream.Message{
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventExceptionTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.ExceptionTypeHeader,
|
||||
Value: eventstream.StringValue("Exception"),
|
||||
},
|
||||
},
|
||||
Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[0]),
|
||||
},
|
||||
}
|
||||
|
||||
sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
|
||||
eventstreamtest.ServeEventStream{
|
||||
T: t,
|
||||
Events: eventMsgs,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error, %v", err)
|
||||
}
|
||||
defer cleanupFn()
|
||||
|
||||
svc := New(sess)
|
||||
resp, err := svc.GetEventStream(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error got, %v", err)
|
||||
}
|
||||
|
||||
defer resp.EventStream.Close()
|
||||
|
||||
<-resp.EventStream.Events()
|
||||
|
||||
err = resp.EventStream.Err()
|
||||
if err == nil {
|
||||
t.Fatalf("expect err, got none")
|
||||
}
|
||||
|
||||
expectErr := &ExceptionEvent{
|
||||
IntVal: aws.Int64(123),
|
||||
Message_: aws.String("string value goes here"),
|
||||
}
|
||||
aerr, ok := err.(awserr.Error)
|
||||
if !ok {
|
||||
t.Errorf("expect exception, got %T, %#v", err, err)
|
||||
}
|
||||
if e, a := expectErr.Code(), aerr.Code(); e != a {
|
||||
t.Errorf("expect %v, got %v", e, a)
|
||||
}
|
||||
if e, a := expectErr.Message(), aerr.Message(); e != a {
|
||||
t.Errorf("expect %v, got %v", e, a)
|
||||
}
|
||||
|
||||
if e, a := expectErr, aerr; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("expect %#v, got %#v", e, a)
|
||||
}
|
||||
}
|
||||
|
||||
var _ awserr.Error = (*ExceptionEvent)(nil)
|
||||
var _ awserr.Error = (*ExceptionEvent2)(nil)
|
||||
|
||||
type loopReader struct {
|
||||
source *bytes.Reader
|
||||
}
|
||||
|
||||
func (c *loopReader) Read(p []byte) (int, error) {
|
||||
if c.source.Len() == 0 {
|
||||
c.source.Seek(0, 0)
|
||||
}
|
||||
|
||||
return c.source.Read(p)
|
||||
}
|
||||
Generated
Vendored
+76
@@ -0,0 +1,76 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
// Package restjsonserviceiface provides an interface to enable mocking the REST JSON Service service client
|
||||
// for testing your code.
|
||||
//
|
||||
// It is important to note that this interface will have breaking changes
|
||||
// when the service model is updated and adds new API operations, paginators,
|
||||
// and waiters.
|
||||
package restjsonserviceiface
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/private/model/api/codegentest/service/restjsonservice"
|
||||
)
|
||||
|
||||
// RESTJSONServiceAPI provides an interface to enable mocking the
|
||||
// restjsonservice.RESTJSONService service client's API operation,
|
||||
// paginators, and waiters. This make unit testing your code that calls out
|
||||
// to the SDK's service client's calls easier.
|
||||
//
|
||||
// The best way to use this interface is so the SDK's service client's calls
|
||||
// can be stubbed out for unit testing your code with the SDK without needing
|
||||
// to inject custom request handlers into the SDK's request pipeline.
|
||||
//
|
||||
// // myFunc uses an SDK service client to make a request to
|
||||
// // REST JSON Service.
|
||||
// func myFunc(svc restjsonserviceiface.RESTJSONServiceAPI) bool {
|
||||
// // Make svc.EmptyStream request
|
||||
// }
|
||||
//
|
||||
// func main() {
|
||||
// sess := session.New()
|
||||
// svc := restjsonservice.New(sess)
|
||||
//
|
||||
// myFunc(svc)
|
||||
// }
|
||||
//
|
||||
// In your _test.go file:
|
||||
//
|
||||
// // Define a mock struct to be used in your unit tests of myFunc.
|
||||
// type mockRESTJSONServiceClient struct {
|
||||
// restjsonserviceiface.RESTJSONServiceAPI
|
||||
// }
|
||||
// func (m *mockRESTJSONServiceClient) EmptyStream(input *restjsonservice.EmptyStreamInput) (*restjsonservice.EmptyStreamOutput, error) {
|
||||
// // mock response/functionality
|
||||
// }
|
||||
//
|
||||
// func TestMyFunc(t *testing.T) {
|
||||
// // Setup Test
|
||||
// mockSvc := &mockRESTJSONServiceClient{}
|
||||
//
|
||||
// myfunc(mockSvc)
|
||||
//
|
||||
// // Verify myFunc's functionality
|
||||
// }
|
||||
//
|
||||
// It is important to note that this interface will have breaking changes
|
||||
// when the service model is updated and adds new API operations, paginators,
|
||||
// and waiters. Its suggested to use the pattern above for testing, or using
|
||||
// tooling to generate mocks to satisfy the interfaces.
|
||||
type RESTJSONServiceAPI interface {
|
||||
EmptyStream(*restjsonservice.EmptyStreamInput) (*restjsonservice.EmptyStreamOutput, error)
|
||||
EmptyStreamWithContext(aws.Context, *restjsonservice.EmptyStreamInput, ...request.Option) (*restjsonservice.EmptyStreamOutput, error)
|
||||
EmptyStreamRequest(*restjsonservice.EmptyStreamInput) (*request.Request, *restjsonservice.EmptyStreamOutput)
|
||||
|
||||
GetEventStream(*restjsonservice.GetEventStreamInput) (*restjsonservice.GetEventStreamOutput, error)
|
||||
GetEventStreamWithContext(aws.Context, *restjsonservice.GetEventStreamInput, ...request.Option) (*restjsonservice.GetEventStreamOutput, error)
|
||||
GetEventStreamRequest(*restjsonservice.GetEventStreamInput) (*request.Request, *restjsonservice.GetEventStreamOutput)
|
||||
|
||||
OtherOperation(*restjsonservice.OtherOperationInput) (*restjsonservice.OtherOperationOutput, error)
|
||||
OtherOperationWithContext(aws.Context, *restjsonservice.OtherOperationInput, ...request.Option) (*restjsonservice.OtherOperationOutput, error)
|
||||
OtherOperationRequest(*restjsonservice.OtherOperationInput) (*request.Request, *restjsonservice.OtherOperationOutput)
|
||||
}
|
||||
|
||||
var _ RESTJSONServiceAPI = (*restjsonservice.RESTJSONService)(nil)
|
||||
Generated
Vendored
+97
@@ -0,0 +1,97 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
package restjsonservice
|
||||
|
||||
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/restjson"
|
||||
)
|
||||
|
||||
// RESTJSONService provides the API operation methods for making requests to
|
||||
// REST JSON Service. See this package's package overview docs
|
||||
// for details on the service.
|
||||
//
|
||||
// RESTJSONService methods are safe to use concurrently. It is not safe to
|
||||
// modify mutate any of the struct's properties though.
|
||||
type RESTJSONService 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)
|
||||
|
||||
// Service information constants
|
||||
const (
|
||||
ServiceName = "RESTJSONService" // Name of service.
|
||||
EndpointsID = "restjsonservice" // ID to lookup a service endpoint with.
|
||||
ServiceID = "RESTJSONService" // ServiceID is a unique identifer of a specific service.
|
||||
)
|
||||
|
||||
// New creates a new instance of the RESTJSONService 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 RESTJSONService client from just a session.
|
||||
// svc := restjsonservice.New(mySession)
|
||||
//
|
||||
// // Create a RESTJSONService client with additional configuration
|
||||
// svc := restjsonservice.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
|
||||
func New(p client.ConfigProvider, cfgs ...*aws.Config) *RESTJSONService {
|
||||
c := p.ClientConfig(EndpointsID, cfgs...)
|
||||
return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName)
|
||||
}
|
||||
|
||||
// newClient creates, initializes and returns a new service client instance.
|
||||
func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *RESTJSONService {
|
||||
svc := &RESTJSONService{
|
||||
Client: client.New(
|
||||
cfg,
|
||||
metadata.ClientInfo{
|
||||
ServiceName: ServiceName,
|
||||
ServiceID: ServiceID,
|
||||
SigningName: signingName,
|
||||
SigningRegion: signingRegion,
|
||||
Endpoint: endpoint,
|
||||
APIVersion: "0000-00-00",
|
||||
},
|
||||
handlers,
|
||||
),
|
||||
}
|
||||
|
||||
// Handlers
|
||||
svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
|
||||
svc.Handlers.Build.PushBackNamed(restjson.BuildHandler)
|
||||
svc.Handlers.Unmarshal.PushBackNamed(restjson.UnmarshalHandler)
|
||||
svc.Handlers.UnmarshalMeta.PushBackNamed(restjson.UnmarshalMetaHandler)
|
||||
svc.Handlers.UnmarshalError.PushBackNamed(restjson.UnmarshalErrorHandler)
|
||||
|
||||
svc.Handlers.UnmarshalStream.PushBackNamed(restjson.UnmarshalHandler)
|
||||
|
||||
// Run custom client initialization if present
|
||||
if initClient != nil {
|
||||
initClient(svc.Client)
|
||||
}
|
||||
|
||||
return svc
|
||||
}
|
||||
|
||||
// newRequest creates a new request for a RESTJSONService operation and runs any
|
||||
// custom request initialization.
|
||||
func (c *RESTJSONService) 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
|
||||
}
|
||||
Generated
Vendored
+1355
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
// Package restxmlservice provides the client and types for making API
|
||||
// requests to REST XML Service.
|
||||
//
|
||||
// See https://docs.aws.amazon.com/goto/WebAPI/RESTXMLService-0000-00-00 for more information on this service.
|
||||
//
|
||||
// See restxmlservice package documentation for more information.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/service/restxmlservice/
|
||||
//
|
||||
// Using the Client
|
||||
//
|
||||
// To contact REST XML Service with the SDK use the New function to create
|
||||
// a new service client. With that client you can make API requests to the service.
|
||||
// These clients are safe to use concurrently.
|
||||
//
|
||||
// See the SDK's documentation for more information on how to use the SDK.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/
|
||||
//
|
||||
// See aws.Config documentation for more information on configuring SDK clients.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config
|
||||
//
|
||||
// See the REST XML Service client RESTXMLService for more
|
||||
// information on creating client for this service.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/service/restxmlservice/#New
|
||||
package restxmlservice
|
||||
Generated
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
package restxmlservice
|
||||
|
||||
const (
|
||||
|
||||
// ErrCodeExceptionEvent for service response error code
|
||||
// "ExceptionEvent".
|
||||
ErrCodeExceptionEvent = "ExceptionEvent"
|
||||
|
||||
// ErrCodeExceptionEvent2 for service response error code
|
||||
// "ExceptionEvent2".
|
||||
ErrCodeExceptionEvent2 = "ExceptionEvent2"
|
||||
)
|
||||
Generated
Vendored
+526
@@ -0,0 +1,526 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
// +build go1.6
|
||||
|
||||
package restxmlservice
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/corehandlers"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||
"github.com/aws/aws-sdk-go/private/protocol"
|
||||
"github.com/aws/aws-sdk-go/private/protocol/eventstream"
|
||||
"github.com/aws/aws-sdk-go/private/protocol/eventstream/eventstreamapi"
|
||||
"github.com/aws/aws-sdk-go/private/protocol/eventstream/eventstreamtest"
|
||||
"github.com/aws/aws-sdk-go/private/protocol/restxml"
|
||||
)
|
||||
|
||||
var _ time.Time
|
||||
var _ awserr.Error
|
||||
|
||||
func TestEmptyStream_Read(t *testing.T) {
|
||||
expectEvents, eventMsgs := mockEmptyStreamReadEvents()
|
||||
sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
|
||||
eventstreamtest.ServeEventStream{
|
||||
T: t,
|
||||
Events: eventMsgs,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error, %v", err)
|
||||
}
|
||||
defer cleanupFn()
|
||||
|
||||
svc := New(sess)
|
||||
resp, err := svc.EmptyStream(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error got, %v", err)
|
||||
}
|
||||
defer resp.EventStream.Close()
|
||||
|
||||
var i int
|
||||
for event := range resp.EventStream.Events() {
|
||||
if event == nil {
|
||||
t.Errorf("%d, expect event, got nil", i)
|
||||
}
|
||||
if e, a := expectEvents[i], event; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("%d, expect %T %v, got %T %v", i, e, e, a, a)
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
if err := resp.EventStream.Err(); err != nil {
|
||||
t.Errorf("expect no error, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyStream_ReadClose(t *testing.T) {
|
||||
_, eventMsgs := mockEmptyStreamReadEvents()
|
||||
sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
|
||||
eventstreamtest.ServeEventStream{
|
||||
T: t,
|
||||
Events: eventMsgs,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error, %v", err)
|
||||
}
|
||||
defer cleanupFn()
|
||||
|
||||
svc := New(sess)
|
||||
resp, err := svc.EmptyStream(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error got, %v", err)
|
||||
}
|
||||
|
||||
resp.EventStream.Close()
|
||||
<-resp.EventStream.Events()
|
||||
|
||||
if err := resp.EventStream.Err(); err != nil {
|
||||
t.Errorf("expect no error, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEmptyStream_Read(b *testing.B) {
|
||||
_, eventMsgs := mockEmptyStreamReadEvents()
|
||||
var buf bytes.Buffer
|
||||
encoder := eventstream.NewEncoder(&buf)
|
||||
for _, msg := range eventMsgs {
|
||||
if err := encoder.Encode(msg); err != nil {
|
||||
b.Fatalf("failed to encode message, %v", err)
|
||||
}
|
||||
}
|
||||
stream := &loopReader{source: bytes.NewReader(buf.Bytes())}
|
||||
|
||||
sess := unit.Session
|
||||
svc := New(sess, &aws.Config{
|
||||
Endpoint: aws.String("https://example.com"),
|
||||
DisableParamValidation: aws.Bool(true),
|
||||
})
|
||||
svc.Handlers.Send.Swap(corehandlers.SendHandler.Name,
|
||||
request.NamedHandler{Name: "mockSend",
|
||||
Fn: func(r *request.Request) {
|
||||
r.HTTPResponse = &http.Response{
|
||||
Status: "200 OK",
|
||||
StatusCode: 200,
|
||||
Header: http.Header{},
|
||||
Body: ioutil.NopCloser(stream),
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
resp, err := svc.EmptyStream(nil)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to create request, %v", err)
|
||||
}
|
||||
defer resp.EventStream.Close()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err = resp.EventStream.Err(); err != nil {
|
||||
b.Fatalf("expect no error, got %v", err)
|
||||
}
|
||||
event := <-resp.EventStream.Events()
|
||||
if event == nil {
|
||||
b.Fatalf("expect event, got nil, %v, %d", resp.EventStream.Err(), i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mockEmptyStreamReadEvents() (
|
||||
[]EmptyEventStreamEvent,
|
||||
[]eventstream.Message,
|
||||
) {
|
||||
expectEvents := []EmptyEventStreamEvent{}
|
||||
|
||||
var marshalers request.HandlerList
|
||||
marshalers.PushBackNamed(restxml.BuildHandler)
|
||||
payloadMarshaler := protocol.HandlerPayloadMarshal{
|
||||
Marshalers: marshalers,
|
||||
}
|
||||
_ = payloadMarshaler
|
||||
|
||||
eventMsgs := []eventstream.Message{}
|
||||
|
||||
return expectEvents, eventMsgs
|
||||
}
|
||||
|
||||
func TestGetEventStream_Read(t *testing.T) {
|
||||
expectEvents, eventMsgs := mockGetEventStreamReadEvents()
|
||||
sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
|
||||
eventstreamtest.ServeEventStream{
|
||||
T: t,
|
||||
Events: eventMsgs,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error, %v", err)
|
||||
}
|
||||
defer cleanupFn()
|
||||
|
||||
svc := New(sess)
|
||||
resp, err := svc.GetEventStream(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error got, %v", err)
|
||||
}
|
||||
defer resp.EventStream.Close()
|
||||
|
||||
var i int
|
||||
for event := range resp.EventStream.Events() {
|
||||
if event == nil {
|
||||
t.Errorf("%d, expect event, got nil", i)
|
||||
}
|
||||
if e, a := expectEvents[i], event; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("%d, expect %T %v, got %T %v", i, e, e, a, a)
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
if err := resp.EventStream.Err(); err != nil {
|
||||
t.Errorf("expect no error, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetEventStream_ReadClose(t *testing.T) {
|
||||
_, eventMsgs := mockGetEventStreamReadEvents()
|
||||
sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
|
||||
eventstreamtest.ServeEventStream{
|
||||
T: t,
|
||||
Events: eventMsgs,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error, %v", err)
|
||||
}
|
||||
defer cleanupFn()
|
||||
|
||||
svc := New(sess)
|
||||
resp, err := svc.GetEventStream(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error got, %v", err)
|
||||
}
|
||||
|
||||
resp.EventStream.Close()
|
||||
<-resp.EventStream.Events()
|
||||
|
||||
if err := resp.EventStream.Err(); err != nil {
|
||||
t.Errorf("expect no error, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGetEventStream_Read(b *testing.B) {
|
||||
_, eventMsgs := mockGetEventStreamReadEvents()
|
||||
var buf bytes.Buffer
|
||||
encoder := eventstream.NewEncoder(&buf)
|
||||
for _, msg := range eventMsgs {
|
||||
if err := encoder.Encode(msg); err != nil {
|
||||
b.Fatalf("failed to encode message, %v", err)
|
||||
}
|
||||
}
|
||||
stream := &loopReader{source: bytes.NewReader(buf.Bytes())}
|
||||
|
||||
sess := unit.Session
|
||||
svc := New(sess, &aws.Config{
|
||||
Endpoint: aws.String("https://example.com"),
|
||||
DisableParamValidation: aws.Bool(true),
|
||||
})
|
||||
svc.Handlers.Send.Swap(corehandlers.SendHandler.Name,
|
||||
request.NamedHandler{Name: "mockSend",
|
||||
Fn: func(r *request.Request) {
|
||||
r.HTTPResponse = &http.Response{
|
||||
Status: "200 OK",
|
||||
StatusCode: 200,
|
||||
Header: http.Header{},
|
||||
Body: ioutil.NopCloser(stream),
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
resp, err := svc.GetEventStream(nil)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to create request, %v", err)
|
||||
}
|
||||
defer resp.EventStream.Close()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err = resp.EventStream.Err(); err != nil {
|
||||
b.Fatalf("expect no error, got %v", err)
|
||||
}
|
||||
event := <-resp.EventStream.Events()
|
||||
if event == nil {
|
||||
b.Fatalf("expect event, got nil, %v, %d", resp.EventStream.Err(), i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mockGetEventStreamReadEvents() (
|
||||
[]EventStreamEvent,
|
||||
[]eventstream.Message,
|
||||
) {
|
||||
expectEvents := []EventStreamEvent{
|
||||
&EmptyEvent{},
|
||||
&ExplicitPayloadEvent{
|
||||
LongVal: aws.Int64(1234),
|
||||
NestedVal: &NestedShape{
|
||||
IntVal: aws.Int64(123),
|
||||
StrVal: aws.String("string value goes here"),
|
||||
},
|
||||
StringVal: aws.String("string value goes here"),
|
||||
},
|
||||
&HeaderOnlyEvent{
|
||||
BlobVal: []byte("blob value goes here"),
|
||||
BoolVal: aws.Bool(true),
|
||||
ByteVal: aws.Int64(1),
|
||||
IntegerVal: aws.Int64(123),
|
||||
LongVal: aws.Int64(1234),
|
||||
ShortVal: aws.Int64(12),
|
||||
StringVal: aws.String("string value goes here"),
|
||||
TimeVal: aws.Time(time.Unix(1396594860, 0).UTC()),
|
||||
},
|
||||
&ImplicitPayloadEvent{
|
||||
ByteVal: aws.Int64(1),
|
||||
IntegerVal: aws.Int64(123),
|
||||
ShortVal: aws.Int64(12),
|
||||
},
|
||||
&PayloadOnlyEvent{
|
||||
NestedVal: &NestedShape{
|
||||
IntVal: aws.Int64(123),
|
||||
StrVal: aws.String("string value goes here"),
|
||||
},
|
||||
},
|
||||
&PayloadOnlyBlobEvent{
|
||||
BlobPayload: []byte("blob value goes here"),
|
||||
},
|
||||
&PayloadOnlyStringEvent{
|
||||
StringPayload: aws.String("string value goes here"),
|
||||
},
|
||||
}
|
||||
|
||||
var marshalers request.HandlerList
|
||||
marshalers.PushBackNamed(restxml.BuildHandler)
|
||||
payloadMarshaler := protocol.HandlerPayloadMarshal{
|
||||
Marshalers: marshalers,
|
||||
}
|
||||
_ = payloadMarshaler
|
||||
|
||||
eventMsgs := []eventstream.Message{
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("Empty"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("ExplicitPayload"),
|
||||
},
|
||||
{
|
||||
Name: "LongVal",
|
||||
Value: eventstream.Int64Value(*expectEvents[1].(*ExplicitPayloadEvent).LongVal),
|
||||
},
|
||||
{
|
||||
Name: "StringVal",
|
||||
Value: eventstream.StringValue(*expectEvents[1].(*ExplicitPayloadEvent).StringVal),
|
||||
},
|
||||
},
|
||||
Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[1]),
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("Headers"),
|
||||
},
|
||||
{
|
||||
Name: "BlobVal",
|
||||
Value: eventstream.BytesValue(expectEvents[2].(*HeaderOnlyEvent).BlobVal),
|
||||
},
|
||||
{
|
||||
Name: "BoolVal",
|
||||
Value: eventstream.BoolValue(*expectEvents[2].(*HeaderOnlyEvent).BoolVal),
|
||||
},
|
||||
{
|
||||
Name: "ByteVal",
|
||||
Value: eventstream.Int8Value(int8(*expectEvents[2].(*HeaderOnlyEvent).ByteVal)),
|
||||
},
|
||||
{
|
||||
Name: "IntegerVal",
|
||||
Value: eventstream.Int32Value(int32(*expectEvents[2].(*HeaderOnlyEvent).IntegerVal)),
|
||||
},
|
||||
{
|
||||
Name: "LongVal",
|
||||
Value: eventstream.Int64Value(*expectEvents[2].(*HeaderOnlyEvent).LongVal),
|
||||
},
|
||||
{
|
||||
Name: "ShortVal",
|
||||
Value: eventstream.Int16Value(int16(*expectEvents[2].(*HeaderOnlyEvent).ShortVal)),
|
||||
},
|
||||
{
|
||||
Name: "StringVal",
|
||||
Value: eventstream.StringValue(*expectEvents[2].(*HeaderOnlyEvent).StringVal),
|
||||
},
|
||||
{
|
||||
Name: "TimeVal",
|
||||
Value: eventstream.TimestampValue(*expectEvents[2].(*HeaderOnlyEvent).TimeVal),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("ImplicitPayload"),
|
||||
},
|
||||
{
|
||||
Name: "ByteVal",
|
||||
Value: eventstream.Int8Value(int8(*expectEvents[3].(*ImplicitPayloadEvent).ByteVal)),
|
||||
},
|
||||
},
|
||||
Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[3]),
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("PayloadOnly"),
|
||||
},
|
||||
},
|
||||
Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[4]),
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("PayloadOnlyBlob"),
|
||||
},
|
||||
},
|
||||
Payload: expectEvents[5].(*PayloadOnlyBlobEvent).BlobPayload,
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("PayloadOnlyString"),
|
||||
},
|
||||
},
|
||||
Payload: []byte(*expectEvents[6].(*PayloadOnlyStringEvent).StringPayload),
|
||||
},
|
||||
}
|
||||
|
||||
return expectEvents, eventMsgs
|
||||
}
|
||||
func TestGetEventStream_ReadException(t *testing.T) {
|
||||
expectEvents := []EventStreamEvent{
|
||||
&ExceptionEvent{
|
||||
IntVal: aws.Int64(123),
|
||||
Message_: aws.String("string value goes here"),
|
||||
},
|
||||
}
|
||||
|
||||
var marshalers request.HandlerList
|
||||
marshalers.PushBackNamed(restxml.BuildHandler)
|
||||
payloadMarshaler := protocol.HandlerPayloadMarshal{
|
||||
Marshalers: marshalers,
|
||||
}
|
||||
|
||||
eventMsgs := []eventstream.Message{
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventExceptionTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.ExceptionTypeHeader,
|
||||
Value: eventstream.StringValue("Exception"),
|
||||
},
|
||||
},
|
||||
Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[0]),
|
||||
},
|
||||
}
|
||||
|
||||
sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
|
||||
eventstreamtest.ServeEventStream{
|
||||
T: t,
|
||||
Events: eventMsgs,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error, %v", err)
|
||||
}
|
||||
defer cleanupFn()
|
||||
|
||||
svc := New(sess)
|
||||
resp, err := svc.GetEventStream(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error got, %v", err)
|
||||
}
|
||||
|
||||
defer resp.EventStream.Close()
|
||||
|
||||
<-resp.EventStream.Events()
|
||||
|
||||
err = resp.EventStream.Err()
|
||||
if err == nil {
|
||||
t.Fatalf("expect err, got none")
|
||||
}
|
||||
|
||||
expectErr := &ExceptionEvent{
|
||||
IntVal: aws.Int64(123),
|
||||
Message_: aws.String("string value goes here"),
|
||||
}
|
||||
aerr, ok := err.(awserr.Error)
|
||||
if !ok {
|
||||
t.Errorf("expect exception, got %T, %#v", err, err)
|
||||
}
|
||||
if e, a := expectErr.Code(), aerr.Code(); e != a {
|
||||
t.Errorf("expect %v, got %v", e, a)
|
||||
}
|
||||
if e, a := expectErr.Message(), aerr.Message(); e != a {
|
||||
t.Errorf("expect %v, got %v", e, a)
|
||||
}
|
||||
|
||||
if e, a := expectErr, aerr; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("expect %#v, got %#v", e, a)
|
||||
}
|
||||
}
|
||||
|
||||
var _ awserr.Error = (*ExceptionEvent)(nil)
|
||||
var _ awserr.Error = (*ExceptionEvent2)(nil)
|
||||
|
||||
type loopReader struct {
|
||||
source *bytes.Reader
|
||||
}
|
||||
|
||||
func (c *loopReader) Read(p []byte) (int, error) {
|
||||
if c.source.Len() == 0 {
|
||||
c.source.Seek(0, 0)
|
||||
}
|
||||
|
||||
return c.source.Read(p)
|
||||
}
|
||||
Generated
Vendored
+76
@@ -0,0 +1,76 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
// Package restxmlserviceiface provides an interface to enable mocking the REST XML Service service client
|
||||
// for testing your code.
|
||||
//
|
||||
// It is important to note that this interface will have breaking changes
|
||||
// when the service model is updated and adds new API operations, paginators,
|
||||
// and waiters.
|
||||
package restxmlserviceiface
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/private/model/api/codegentest/service/restxmlservice"
|
||||
)
|
||||
|
||||
// RESTXMLServiceAPI provides an interface to enable mocking the
|
||||
// restxmlservice.RESTXMLService service client's API operation,
|
||||
// paginators, and waiters. This make unit testing your code that calls out
|
||||
// to the SDK's service client's calls easier.
|
||||
//
|
||||
// The best way to use this interface is so the SDK's service client's calls
|
||||
// can be stubbed out for unit testing your code with the SDK without needing
|
||||
// to inject custom request handlers into the SDK's request pipeline.
|
||||
//
|
||||
// // myFunc uses an SDK service client to make a request to
|
||||
// // REST XML Service.
|
||||
// func myFunc(svc restxmlserviceiface.RESTXMLServiceAPI) bool {
|
||||
// // Make svc.EmptyStream request
|
||||
// }
|
||||
//
|
||||
// func main() {
|
||||
// sess := session.New()
|
||||
// svc := restxmlservice.New(sess)
|
||||
//
|
||||
// myFunc(svc)
|
||||
// }
|
||||
//
|
||||
// In your _test.go file:
|
||||
//
|
||||
// // Define a mock struct to be used in your unit tests of myFunc.
|
||||
// type mockRESTXMLServiceClient struct {
|
||||
// restxmlserviceiface.RESTXMLServiceAPI
|
||||
// }
|
||||
// func (m *mockRESTXMLServiceClient) EmptyStream(input *restxmlservice.EmptyStreamInput) (*restxmlservice.EmptyStreamOutput, error) {
|
||||
// // mock response/functionality
|
||||
// }
|
||||
//
|
||||
// func TestMyFunc(t *testing.T) {
|
||||
// // Setup Test
|
||||
// mockSvc := &mockRESTXMLServiceClient{}
|
||||
//
|
||||
// myfunc(mockSvc)
|
||||
//
|
||||
// // Verify myFunc's functionality
|
||||
// }
|
||||
//
|
||||
// It is important to note that this interface will have breaking changes
|
||||
// when the service model is updated and adds new API operations, paginators,
|
||||
// and waiters. Its suggested to use the pattern above for testing, or using
|
||||
// tooling to generate mocks to satisfy the interfaces.
|
||||
type RESTXMLServiceAPI interface {
|
||||
EmptyStream(*restxmlservice.EmptyStreamInput) (*restxmlservice.EmptyStreamOutput, error)
|
||||
EmptyStreamWithContext(aws.Context, *restxmlservice.EmptyStreamInput, ...request.Option) (*restxmlservice.EmptyStreamOutput, error)
|
||||
EmptyStreamRequest(*restxmlservice.EmptyStreamInput) (*request.Request, *restxmlservice.EmptyStreamOutput)
|
||||
|
||||
GetEventStream(*restxmlservice.GetEventStreamInput) (*restxmlservice.GetEventStreamOutput, error)
|
||||
GetEventStreamWithContext(aws.Context, *restxmlservice.GetEventStreamInput, ...request.Option) (*restxmlservice.GetEventStreamOutput, error)
|
||||
GetEventStreamRequest(*restxmlservice.GetEventStreamInput) (*request.Request, *restxmlservice.GetEventStreamOutput)
|
||||
|
||||
OtherOperation(*restxmlservice.OtherOperationInput) (*restxmlservice.OtherOperationOutput, error)
|
||||
OtherOperationWithContext(aws.Context, *restxmlservice.OtherOperationInput, ...request.Option) (*restxmlservice.OtherOperationOutput, error)
|
||||
OtherOperationRequest(*restxmlservice.OtherOperationInput) (*request.Request, *restxmlservice.OtherOperationOutput)
|
||||
}
|
||||
|
||||
var _ RESTXMLServiceAPI = (*restxmlservice.RESTXMLService)(nil)
|
||||
Generated
Vendored
+97
@@ -0,0 +1,97 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
package restxmlservice
|
||||
|
||||
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/restxml"
|
||||
)
|
||||
|
||||
// RESTXMLService provides the API operation methods for making requests to
|
||||
// REST XML Service. See this package's package overview docs
|
||||
// for details on the service.
|
||||
//
|
||||
// RESTXMLService methods are safe to use concurrently. It is not safe to
|
||||
// modify mutate any of the struct's properties though.
|
||||
type RESTXMLService 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)
|
||||
|
||||
// Service information constants
|
||||
const (
|
||||
ServiceName = "RESTXMLService" // Name of service.
|
||||
EndpointsID = "restxmlservice" // ID to lookup a service endpoint with.
|
||||
ServiceID = "RESTXMLService" // ServiceID is a unique identifer of a specific service.
|
||||
)
|
||||
|
||||
// New creates a new instance of the RESTXMLService 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 RESTXMLService client from just a session.
|
||||
// svc := restxmlservice.New(mySession)
|
||||
//
|
||||
// // Create a RESTXMLService client with additional configuration
|
||||
// svc := restxmlservice.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
|
||||
func New(p client.ConfigProvider, cfgs ...*aws.Config) *RESTXMLService {
|
||||
c := p.ClientConfig(EndpointsID, cfgs...)
|
||||
return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName)
|
||||
}
|
||||
|
||||
// newClient creates, initializes and returns a new service client instance.
|
||||
func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *RESTXMLService {
|
||||
svc := &RESTXMLService{
|
||||
Client: client.New(
|
||||
cfg,
|
||||
metadata.ClientInfo{
|
||||
ServiceName: ServiceName,
|
||||
ServiceID: ServiceID,
|
||||
SigningName: signingName,
|
||||
SigningRegion: signingRegion,
|
||||
Endpoint: endpoint,
|
||||
APIVersion: "0000-00-00",
|
||||
},
|
||||
handlers,
|
||||
),
|
||||
}
|
||||
|
||||
// Handlers
|
||||
svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
|
||||
svc.Handlers.Build.PushBackNamed(restxml.BuildHandler)
|
||||
svc.Handlers.Unmarshal.PushBackNamed(restxml.UnmarshalHandler)
|
||||
svc.Handlers.UnmarshalMeta.PushBackNamed(restxml.UnmarshalMetaHandler)
|
||||
svc.Handlers.UnmarshalError.PushBackNamed(restxml.UnmarshalErrorHandler)
|
||||
|
||||
svc.Handlers.UnmarshalStream.PushBackNamed(restxml.UnmarshalHandler)
|
||||
|
||||
// Run custom client initialization if present
|
||||
if initClient != nil {
|
||||
initClient(svc.Client)
|
||||
}
|
||||
|
||||
return svc
|
||||
}
|
||||
|
||||
// newRequest creates a new request for a RESTXMLService operation and runs any
|
||||
// custom request initialization.
|
||||
func (c *RESTXMLService) 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
|
||||
}
|
||||
Generated
Vendored
+1452
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
// Package rpcservice provides the client and types for making API
|
||||
// requests to RPC Service.
|
||||
//
|
||||
// See https://docs.aws.amazon.com/goto/WebAPI/RPCService-0000-00-00 for more information on this service.
|
||||
//
|
||||
// See rpcservice package documentation for more information.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/service/rpcservice/
|
||||
//
|
||||
// Using the Client
|
||||
//
|
||||
// To contact RPC Service with the SDK use the New function to create
|
||||
// a new service client. With that client you can make API requests to the service.
|
||||
// These clients are safe to use concurrently.
|
||||
//
|
||||
// See the SDK's documentation for more information on how to use the SDK.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/
|
||||
//
|
||||
// See aws.Config documentation for more information on configuring SDK clients.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config
|
||||
//
|
||||
// See the RPC Service client RPCService for more
|
||||
// information on creating client for this service.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/service/rpcservice/#New
|
||||
package rpcservice
|
||||
Generated
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
package rpcservice
|
||||
|
||||
const (
|
||||
|
||||
// ErrCodeExceptionEvent for service response error code
|
||||
// "ExceptionEvent".
|
||||
ErrCodeExceptionEvent = "ExceptionEvent"
|
||||
|
||||
// ErrCodeExceptionEvent2 for service response error code
|
||||
// "ExceptionEvent2".
|
||||
ErrCodeExceptionEvent2 = "ExceptionEvent2"
|
||||
)
|
||||
Generated
Vendored
+578
@@ -0,0 +1,578 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
// +build go1.6
|
||||
|
||||
package rpcservice
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/corehandlers"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||
"github.com/aws/aws-sdk-go/private/protocol"
|
||||
"github.com/aws/aws-sdk-go/private/protocol/eventstream"
|
||||
"github.com/aws/aws-sdk-go/private/protocol/eventstream/eventstreamapi"
|
||||
"github.com/aws/aws-sdk-go/private/protocol/eventstream/eventstreamtest"
|
||||
"github.com/aws/aws-sdk-go/private/protocol/jsonrpc"
|
||||
)
|
||||
|
||||
var _ time.Time
|
||||
var _ awserr.Error
|
||||
|
||||
func TestEmptyStream_Read(t *testing.T) {
|
||||
expectEvents, eventMsgs := mockEmptyStreamReadEvents()
|
||||
sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
|
||||
eventstreamtest.ServeEventStream{
|
||||
T: t,
|
||||
Events: eventMsgs,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error, %v", err)
|
||||
}
|
||||
defer cleanupFn()
|
||||
|
||||
svc := New(sess)
|
||||
resp, err := svc.EmptyStream(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error got, %v", err)
|
||||
}
|
||||
defer resp.EventStream.Close()
|
||||
// Trim off response output type pseudo event so only event messages remain.
|
||||
expectEvents = expectEvents[1:]
|
||||
|
||||
var i int
|
||||
for event := range resp.EventStream.Events() {
|
||||
if event == nil {
|
||||
t.Errorf("%d, expect event, got nil", i)
|
||||
}
|
||||
if e, a := expectEvents[i], event; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("%d, expect %T %v, got %T %v", i, e, e, a, a)
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
if err := resp.EventStream.Err(); err != nil {
|
||||
t.Errorf("expect no error, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyStream_ReadClose(t *testing.T) {
|
||||
_, eventMsgs := mockEmptyStreamReadEvents()
|
||||
sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
|
||||
eventstreamtest.ServeEventStream{
|
||||
T: t,
|
||||
Events: eventMsgs,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error, %v", err)
|
||||
}
|
||||
defer cleanupFn()
|
||||
|
||||
svc := New(sess)
|
||||
resp, err := svc.EmptyStream(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error got, %v", err)
|
||||
}
|
||||
|
||||
resp.EventStream.Close()
|
||||
<-resp.EventStream.Events()
|
||||
|
||||
if err := resp.EventStream.Err(); err != nil {
|
||||
t.Errorf("expect no error, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEmptyStream_Read(b *testing.B) {
|
||||
_, eventMsgs := mockEmptyStreamReadEvents()
|
||||
var buf bytes.Buffer
|
||||
encoder := eventstream.NewEncoder(&buf)
|
||||
for _, msg := range eventMsgs {
|
||||
if err := encoder.Encode(msg); err != nil {
|
||||
b.Fatalf("failed to encode message, %v", err)
|
||||
}
|
||||
}
|
||||
stream := &loopReader{source: bytes.NewReader(buf.Bytes())}
|
||||
|
||||
sess := unit.Session
|
||||
svc := New(sess, &aws.Config{
|
||||
Endpoint: aws.String("https://example.com"),
|
||||
DisableParamValidation: aws.Bool(true),
|
||||
})
|
||||
svc.Handlers.Send.Swap(corehandlers.SendHandler.Name,
|
||||
request.NamedHandler{Name: "mockSend",
|
||||
Fn: func(r *request.Request) {
|
||||
r.HTTPResponse = &http.Response{
|
||||
Status: "200 OK",
|
||||
StatusCode: 200,
|
||||
Header: http.Header{},
|
||||
Body: ioutil.NopCloser(stream),
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
resp, err := svc.EmptyStream(nil)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to create request, %v", err)
|
||||
}
|
||||
defer resp.EventStream.Close()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err = resp.EventStream.Err(); err != nil {
|
||||
b.Fatalf("expect no error, got %v", err)
|
||||
}
|
||||
event := <-resp.EventStream.Events()
|
||||
if event == nil {
|
||||
b.Fatalf("expect event, got nil, %v, %d", resp.EventStream.Err(), i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mockEmptyStreamReadEvents() (
|
||||
[]EmptyEventStreamEvent,
|
||||
[]eventstream.Message,
|
||||
) {
|
||||
expectEvents := []EmptyEventStreamEvent{
|
||||
&EmptyStreamOutput{},
|
||||
}
|
||||
|
||||
var marshalers request.HandlerList
|
||||
marshalers.PushBackNamed(jsonrpc.BuildHandler)
|
||||
payloadMarshaler := protocol.HandlerPayloadMarshal{
|
||||
Marshalers: marshalers,
|
||||
}
|
||||
_ = payloadMarshaler
|
||||
|
||||
eventMsgs := []eventstream.Message{
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("initial-response"),
|
||||
},
|
||||
},
|
||||
Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[0]),
|
||||
},
|
||||
}
|
||||
|
||||
return expectEvents, eventMsgs
|
||||
}
|
||||
|
||||
func TestGetEventStream_Read(t *testing.T) {
|
||||
expectEvents, eventMsgs := mockGetEventStreamReadEvents()
|
||||
sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
|
||||
eventstreamtest.ServeEventStream{
|
||||
T: t,
|
||||
Events: eventMsgs,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error, %v", err)
|
||||
}
|
||||
defer cleanupFn()
|
||||
|
||||
svc := New(sess)
|
||||
resp, err := svc.GetEventStream(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error got, %v", err)
|
||||
}
|
||||
defer resp.EventStream.Close()
|
||||
expectResp := expectEvents[0].(*GetEventStreamOutput)
|
||||
if e, a := expectResp.IntVal, resp.IntVal; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("expect %v, got %v", e, a)
|
||||
}
|
||||
if e, a := expectResp.StrVal, resp.StrVal; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("expect %v, got %v", e, a)
|
||||
}
|
||||
// Trim off response output type pseudo event so only event messages remain.
|
||||
expectEvents = expectEvents[1:]
|
||||
|
||||
var i int
|
||||
for event := range resp.EventStream.Events() {
|
||||
if event == nil {
|
||||
t.Errorf("%d, expect event, got nil", i)
|
||||
}
|
||||
if e, a := expectEvents[i], event; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("%d, expect %T %v, got %T %v", i, e, e, a, a)
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
if err := resp.EventStream.Err(); err != nil {
|
||||
t.Errorf("expect no error, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetEventStream_ReadClose(t *testing.T) {
|
||||
_, eventMsgs := mockGetEventStreamReadEvents()
|
||||
sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
|
||||
eventstreamtest.ServeEventStream{
|
||||
T: t,
|
||||
Events: eventMsgs,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error, %v", err)
|
||||
}
|
||||
defer cleanupFn()
|
||||
|
||||
svc := New(sess)
|
||||
resp, err := svc.GetEventStream(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error got, %v", err)
|
||||
}
|
||||
|
||||
resp.EventStream.Close()
|
||||
<-resp.EventStream.Events()
|
||||
|
||||
if err := resp.EventStream.Err(); err != nil {
|
||||
t.Errorf("expect no error, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGetEventStream_Read(b *testing.B) {
|
||||
_, eventMsgs := mockGetEventStreamReadEvents()
|
||||
var buf bytes.Buffer
|
||||
encoder := eventstream.NewEncoder(&buf)
|
||||
for _, msg := range eventMsgs {
|
||||
if err := encoder.Encode(msg); err != nil {
|
||||
b.Fatalf("failed to encode message, %v", err)
|
||||
}
|
||||
}
|
||||
stream := &loopReader{source: bytes.NewReader(buf.Bytes())}
|
||||
|
||||
sess := unit.Session
|
||||
svc := New(sess, &aws.Config{
|
||||
Endpoint: aws.String("https://example.com"),
|
||||
DisableParamValidation: aws.Bool(true),
|
||||
})
|
||||
svc.Handlers.Send.Swap(corehandlers.SendHandler.Name,
|
||||
request.NamedHandler{Name: "mockSend",
|
||||
Fn: func(r *request.Request) {
|
||||
r.HTTPResponse = &http.Response{
|
||||
Status: "200 OK",
|
||||
StatusCode: 200,
|
||||
Header: http.Header{},
|
||||
Body: ioutil.NopCloser(stream),
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
resp, err := svc.GetEventStream(nil)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to create request, %v", err)
|
||||
}
|
||||
defer resp.EventStream.Close()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err = resp.EventStream.Err(); err != nil {
|
||||
b.Fatalf("expect no error, got %v", err)
|
||||
}
|
||||
event := <-resp.EventStream.Events()
|
||||
if event == nil {
|
||||
b.Fatalf("expect event, got nil, %v, %d", resp.EventStream.Err(), i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mockGetEventStreamReadEvents() (
|
||||
[]EventStreamEvent,
|
||||
[]eventstream.Message,
|
||||
) {
|
||||
expectEvents := []EventStreamEvent{
|
||||
&GetEventStreamOutput{
|
||||
IntVal: aws.Int64(123),
|
||||
StrVal: aws.String("string value goes here"),
|
||||
},
|
||||
&EmptyEvent{},
|
||||
&ExplicitPayloadEvent{
|
||||
LongVal: aws.Int64(1234),
|
||||
NestedVal: &NestedShape{
|
||||
IntVal: aws.Int64(123),
|
||||
StrVal: aws.String("string value goes here"),
|
||||
},
|
||||
StringVal: aws.String("string value goes here"),
|
||||
},
|
||||
&HeaderOnlyEvent{
|
||||
BlobVal: []byte("blob value goes here"),
|
||||
BoolVal: aws.Bool(true),
|
||||
ByteVal: aws.Int64(1),
|
||||
IntegerVal: aws.Int64(123),
|
||||
LongVal: aws.Int64(1234),
|
||||
ShortVal: aws.Int64(12),
|
||||
StringVal: aws.String("string value goes here"),
|
||||
TimeVal: aws.Time(time.Unix(1396594860, 0).UTC()),
|
||||
},
|
||||
&ImplicitPayloadEvent{
|
||||
ByteVal: aws.Int64(1),
|
||||
IntegerVal: aws.Int64(123),
|
||||
ShortVal: aws.Int64(12),
|
||||
},
|
||||
&PayloadOnlyEvent{
|
||||
NestedVal: &NestedShape{
|
||||
IntVal: aws.Int64(123),
|
||||
StrVal: aws.String("string value goes here"),
|
||||
},
|
||||
},
|
||||
&PayloadOnlyBlobEvent{
|
||||
BlobPayload: []byte("blob value goes here"),
|
||||
},
|
||||
&PayloadOnlyStringEvent{
|
||||
StringPayload: aws.String("string value goes here"),
|
||||
},
|
||||
}
|
||||
|
||||
var marshalers request.HandlerList
|
||||
marshalers.PushBackNamed(jsonrpc.BuildHandler)
|
||||
payloadMarshaler := protocol.HandlerPayloadMarshal{
|
||||
Marshalers: marshalers,
|
||||
}
|
||||
_ = payloadMarshaler
|
||||
|
||||
eventMsgs := []eventstream.Message{
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("initial-response"),
|
||||
},
|
||||
},
|
||||
Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[0]),
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("Empty"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("ExplicitPayload"),
|
||||
},
|
||||
{
|
||||
Name: "LongVal",
|
||||
Value: eventstream.Int64Value(*expectEvents[2].(*ExplicitPayloadEvent).LongVal),
|
||||
},
|
||||
{
|
||||
Name: "StringVal",
|
||||
Value: eventstream.StringValue(*expectEvents[2].(*ExplicitPayloadEvent).StringVal),
|
||||
},
|
||||
},
|
||||
Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[2]),
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("Headers"),
|
||||
},
|
||||
{
|
||||
Name: "BlobVal",
|
||||
Value: eventstream.BytesValue(expectEvents[3].(*HeaderOnlyEvent).BlobVal),
|
||||
},
|
||||
{
|
||||
Name: "BoolVal",
|
||||
Value: eventstream.BoolValue(*expectEvents[3].(*HeaderOnlyEvent).BoolVal),
|
||||
},
|
||||
{
|
||||
Name: "ByteVal",
|
||||
Value: eventstream.Int8Value(int8(*expectEvents[3].(*HeaderOnlyEvent).ByteVal)),
|
||||
},
|
||||
{
|
||||
Name: "IntegerVal",
|
||||
Value: eventstream.Int32Value(int32(*expectEvents[3].(*HeaderOnlyEvent).IntegerVal)),
|
||||
},
|
||||
{
|
||||
Name: "LongVal",
|
||||
Value: eventstream.Int64Value(*expectEvents[3].(*HeaderOnlyEvent).LongVal),
|
||||
},
|
||||
{
|
||||
Name: "ShortVal",
|
||||
Value: eventstream.Int16Value(int16(*expectEvents[3].(*HeaderOnlyEvent).ShortVal)),
|
||||
},
|
||||
{
|
||||
Name: "StringVal",
|
||||
Value: eventstream.StringValue(*expectEvents[3].(*HeaderOnlyEvent).StringVal),
|
||||
},
|
||||
{
|
||||
Name: "TimeVal",
|
||||
Value: eventstream.TimestampValue(*expectEvents[3].(*HeaderOnlyEvent).TimeVal),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("ImplicitPayload"),
|
||||
},
|
||||
{
|
||||
Name: "ByteVal",
|
||||
Value: eventstream.Int8Value(int8(*expectEvents[4].(*ImplicitPayloadEvent).ByteVal)),
|
||||
},
|
||||
},
|
||||
Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[4]),
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("PayloadOnly"),
|
||||
},
|
||||
},
|
||||
Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[5]),
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("PayloadOnlyBlob"),
|
||||
},
|
||||
},
|
||||
Payload: expectEvents[6].(*PayloadOnlyBlobEvent).BlobPayload,
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("PayloadOnlyString"),
|
||||
},
|
||||
},
|
||||
Payload: []byte(*expectEvents[7].(*PayloadOnlyStringEvent).StringPayload),
|
||||
},
|
||||
}
|
||||
|
||||
return expectEvents, eventMsgs
|
||||
}
|
||||
func TestGetEventStream_ReadException(t *testing.T) {
|
||||
expectEvents := []EventStreamEvent{
|
||||
&GetEventStreamOutput{
|
||||
IntVal: aws.Int64(123),
|
||||
StrVal: aws.String("string value goes here"),
|
||||
},
|
||||
&ExceptionEvent{
|
||||
IntVal: aws.Int64(123),
|
||||
Message_: aws.String("string value goes here"),
|
||||
},
|
||||
}
|
||||
|
||||
var marshalers request.HandlerList
|
||||
marshalers.PushBackNamed(jsonrpc.BuildHandler)
|
||||
payloadMarshaler := protocol.HandlerPayloadMarshal{
|
||||
Marshalers: marshalers,
|
||||
}
|
||||
|
||||
eventMsgs := []eventstream.Message{
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventMessageTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.EventTypeHeader,
|
||||
Value: eventstream.StringValue("initial-response"),
|
||||
},
|
||||
},
|
||||
Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[0]),
|
||||
},
|
||||
{
|
||||
Headers: eventstream.Headers{
|
||||
eventstreamtest.EventExceptionTypeHeader,
|
||||
{
|
||||
Name: eventstreamapi.ExceptionTypeHeader,
|
||||
Value: eventstream.StringValue("Exception"),
|
||||
},
|
||||
},
|
||||
Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[1]),
|
||||
},
|
||||
}
|
||||
|
||||
sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
|
||||
eventstreamtest.ServeEventStream{
|
||||
T: t,
|
||||
Events: eventMsgs,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error, %v", err)
|
||||
}
|
||||
defer cleanupFn()
|
||||
|
||||
svc := New(sess)
|
||||
resp, err := svc.GetEventStream(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error got, %v", err)
|
||||
}
|
||||
|
||||
defer resp.EventStream.Close()
|
||||
|
||||
<-resp.EventStream.Events()
|
||||
|
||||
err = resp.EventStream.Err()
|
||||
if err == nil {
|
||||
t.Fatalf("expect err, got none")
|
||||
}
|
||||
|
||||
expectErr := &ExceptionEvent{
|
||||
IntVal: aws.Int64(123),
|
||||
Message_: aws.String("string value goes here"),
|
||||
}
|
||||
aerr, ok := err.(awserr.Error)
|
||||
if !ok {
|
||||
t.Errorf("expect exception, got %T, %#v", err, err)
|
||||
}
|
||||
if e, a := expectErr.Code(), aerr.Code(); e != a {
|
||||
t.Errorf("expect %v, got %v", e, a)
|
||||
}
|
||||
if e, a := expectErr.Message(), aerr.Message(); e != a {
|
||||
t.Errorf("expect %v, got %v", e, a)
|
||||
}
|
||||
|
||||
if e, a := expectErr, aerr; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("expect %#v, got %#v", e, a)
|
||||
}
|
||||
}
|
||||
|
||||
var _ awserr.Error = (*ExceptionEvent)(nil)
|
||||
var _ awserr.Error = (*ExceptionEvent2)(nil)
|
||||
|
||||
type loopReader struct {
|
||||
source *bytes.Reader
|
||||
}
|
||||
|
||||
func (c *loopReader) Read(p []byte) (int, error) {
|
||||
if c.source.Len() == 0 {
|
||||
c.source.Seek(0, 0)
|
||||
}
|
||||
|
||||
return c.source.Read(p)
|
||||
}
|
||||
Generated
Vendored
+76
@@ -0,0 +1,76 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
// Package rpcserviceiface provides an interface to enable mocking the RPC Service service client
|
||||
// for testing your code.
|
||||
//
|
||||
// It is important to note that this interface will have breaking changes
|
||||
// when the service model is updated and adds new API operations, paginators,
|
||||
// and waiters.
|
||||
package rpcserviceiface
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/private/model/api/codegentest/service/rpcservice"
|
||||
)
|
||||
|
||||
// RPCServiceAPI provides an interface to enable mocking the
|
||||
// rpcservice.RPCService service client's API operation,
|
||||
// paginators, and waiters. This make unit testing your code that calls out
|
||||
// to the SDK's service client's calls easier.
|
||||
//
|
||||
// The best way to use this interface is so the SDK's service client's calls
|
||||
// can be stubbed out for unit testing your code with the SDK without needing
|
||||
// to inject custom request handlers into the SDK's request pipeline.
|
||||
//
|
||||
// // myFunc uses an SDK service client to make a request to
|
||||
// // RPC Service.
|
||||
// func myFunc(svc rpcserviceiface.RPCServiceAPI) bool {
|
||||
// // Make svc.EmptyStream request
|
||||
// }
|
||||
//
|
||||
// func main() {
|
||||
// sess := session.New()
|
||||
// svc := rpcservice.New(sess)
|
||||
//
|
||||
// myFunc(svc)
|
||||
// }
|
||||
//
|
||||
// In your _test.go file:
|
||||
//
|
||||
// // Define a mock struct to be used in your unit tests of myFunc.
|
||||
// type mockRPCServiceClient struct {
|
||||
// rpcserviceiface.RPCServiceAPI
|
||||
// }
|
||||
// func (m *mockRPCServiceClient) EmptyStream(input *rpcservice.EmptyStreamInput) (*rpcservice.EmptyStreamOutput, error) {
|
||||
// // mock response/functionality
|
||||
// }
|
||||
//
|
||||
// func TestMyFunc(t *testing.T) {
|
||||
// // Setup Test
|
||||
// mockSvc := &mockRPCServiceClient{}
|
||||
//
|
||||
// myfunc(mockSvc)
|
||||
//
|
||||
// // Verify myFunc's functionality
|
||||
// }
|
||||
//
|
||||
// It is important to note that this interface will have breaking changes
|
||||
// when the service model is updated and adds new API operations, paginators,
|
||||
// and waiters. Its suggested to use the pattern above for testing, or using
|
||||
// tooling to generate mocks to satisfy the interfaces.
|
||||
type RPCServiceAPI interface {
|
||||
EmptyStream(*rpcservice.EmptyStreamInput) (*rpcservice.EmptyStreamOutput, error)
|
||||
EmptyStreamWithContext(aws.Context, *rpcservice.EmptyStreamInput, ...request.Option) (*rpcservice.EmptyStreamOutput, error)
|
||||
EmptyStreamRequest(*rpcservice.EmptyStreamInput) (*request.Request, *rpcservice.EmptyStreamOutput)
|
||||
|
||||
GetEventStream(*rpcservice.GetEventStreamInput) (*rpcservice.GetEventStreamOutput, error)
|
||||
GetEventStreamWithContext(aws.Context, *rpcservice.GetEventStreamInput, ...request.Option) (*rpcservice.GetEventStreamOutput, error)
|
||||
GetEventStreamRequest(*rpcservice.GetEventStreamInput) (*request.Request, *rpcservice.GetEventStreamOutput)
|
||||
|
||||
OtherOperation(*rpcservice.OtherOperationInput) (*rpcservice.OtherOperationOutput, error)
|
||||
OtherOperationWithContext(aws.Context, *rpcservice.OtherOperationInput, ...request.Option) (*rpcservice.OtherOperationOutput, error)
|
||||
OtherOperationRequest(*rpcservice.OtherOperationInput) (*request.Request, *rpcservice.OtherOperationOutput)
|
||||
}
|
||||
|
||||
var _ RPCServiceAPI = (*rpcservice.RPCService)(nil)
|
||||
Generated
Vendored
+99
@@ -0,0 +1,99 @@
|
||||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
package rpcservice
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
// RPCService provides the API operation methods for making requests to
|
||||
// RPC Service. See this package's package overview docs
|
||||
// for details on the service.
|
||||
//
|
||||
// RPCService methods are safe to use concurrently. It is not safe to
|
||||
// modify mutate any of the struct's properties though.
|
||||
type RPCService 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)
|
||||
|
||||
// Service information constants
|
||||
const (
|
||||
ServiceName = "RPCService" // Name of service.
|
||||
EndpointsID = "rpcservice" // ID to lookup a service endpoint with.
|
||||
ServiceID = "RPCService" // ServiceID is a unique identifer of a specific service.
|
||||
)
|
||||
|
||||
// New creates a new instance of the RPCService 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 RPCService client from just a session.
|
||||
// svc := rpcservice.New(mySession)
|
||||
//
|
||||
// // Create a RPCService client with additional configuration
|
||||
// svc := rpcservice.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
|
||||
func New(p client.ConfigProvider, cfgs ...*aws.Config) *RPCService {
|
||||
c := p.ClientConfig(EndpointsID, cfgs...)
|
||||
return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName)
|
||||
}
|
||||
|
||||
// newClient creates, initializes and returns a new service client instance.
|
||||
func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *RPCService {
|
||||
svc := &RPCService{
|
||||
Client: client.New(
|
||||
cfg,
|
||||
metadata.ClientInfo{
|
||||
ServiceName: ServiceName,
|
||||
ServiceID: ServiceID,
|
||||
SigningName: signingName,
|
||||
SigningRegion: signingRegion,
|
||||
Endpoint: endpoint,
|
||||
APIVersion: "0000-00-00",
|
||||
JSONVersion: "1.1",
|
||||
TargetPrefix: "RPCService_00000000",
|
||||
},
|
||||
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)
|
||||
|
||||
svc.Handlers.UnmarshalStream.PushBackNamed(jsonrpc.UnmarshalHandler)
|
||||
|
||||
// Run custom client initialization if present
|
||||
if initClient != nil {
|
||||
initClient(svc.Client)
|
||||
}
|
||||
|
||||
return svc
|
||||
}
|
||||
|
||||
// newRequest creates a new request for a RPCService operation and runs any
|
||||
// custom request initialization.
|
||||
func (c *RPCService) 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
|
||||
}
|
||||
+90
-4
@@ -3,7 +3,9 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
@@ -27,10 +29,24 @@ var mergeServices = map[string]service{
|
||||
},
|
||||
}
|
||||
|
||||
var serviceAliaseNames = map[string]string{
|
||||
"costandusagereportservice": "CostandUsageReportService",
|
||||
"elasticloadbalancing": "ELB",
|
||||
"elasticloadbalancingv2": "ELBV2",
|
||||
"config": "ConfigService",
|
||||
}
|
||||
|
||||
func (a *API) setServiceAliaseName() {
|
||||
if newName, ok := serviceAliaseNames[a.PackageName()]; ok {
|
||||
a.name = newName
|
||||
}
|
||||
}
|
||||
|
||||
// customizationPasses Executes customization logic for the API by package name.
|
||||
func (a *API) customizationPasses() {
|
||||
var svcCustomizations = map[string]func(*API){
|
||||
"s3": s3Customizations,
|
||||
"s3control": s3ControlCustomizations,
|
||||
"cloudfront": cloudfrontCustomizations,
|
||||
"rds": rdsCustomizations,
|
||||
|
||||
@@ -38,6 +54,23 @@ func (a *API) customizationPasses() {
|
||||
// to provide endpoint them selves.
|
||||
"cloudsearchdomain": disableEndpointResolving,
|
||||
"iotdataplane": disableEndpointResolving,
|
||||
|
||||
// MTurk smoke test is invalid. The service requires AWS account to be
|
||||
// linked to Amazon Mechanical Turk Account.
|
||||
"mturk": supressSmokeTest,
|
||||
|
||||
// Backfill the authentication type for cognito identity and sts.
|
||||
// Removes the need for the customizations in these services.
|
||||
"cognitoidentity": backfillAuthType(NoneAuthType,
|
||||
"GetId",
|
||||
"GetOpenIdToken",
|
||||
"UnlinkIdentity",
|
||||
"GetCredentialsForIdentity",
|
||||
),
|
||||
"sts": backfillAuthType(NoneAuthType,
|
||||
"AssumeRoleWithSAML",
|
||||
"AssumeRoleWithWebIdentity",
|
||||
),
|
||||
}
|
||||
|
||||
for k := range mergeServices {
|
||||
@@ -49,13 +82,17 @@ func (a *API) customizationPasses() {
|
||||
}
|
||||
}
|
||||
|
||||
func supressSmokeTest(a *API) {
|
||||
a.SmokeTests.TestCases = []SmokeTestCase{}
|
||||
}
|
||||
|
||||
// s3Customizations customizes the API generation to replace values specific to S3.
|
||||
func s3Customizations(a *API) {
|
||||
var strExpires *Shape
|
||||
|
||||
var keepContentMD5Ref = map[string]struct{}{
|
||||
"PutObjectInput": struct{}{},
|
||||
"UploadPartInput": struct{}{},
|
||||
"PutObjectInput": {},
|
||||
"UploadPartInput": {},
|
||||
}
|
||||
|
||||
for name, s := range a.Shapes {
|
||||
@@ -73,6 +110,22 @@ func s3Customizations(a *API) {
|
||||
}
|
||||
}
|
||||
|
||||
// Decorate member references that are modeled with the wrong type.
|
||||
// Specifically the case where a member was modeled as a string, but is
|
||||
// expected to sent across the wire as a base64 value.
|
||||
//
|
||||
// e.g. S3's SSECustomerKey and CopySourceSSECustomerKey
|
||||
for _, refName := range []string{
|
||||
"SSECustomerKey",
|
||||
"CopySourceSSECustomerKey",
|
||||
} {
|
||||
if ref, ok := s.MemberRefs[refName]; ok {
|
||||
ref.CustomTags = append(ref.CustomTags, ShapeTag{
|
||||
"marshal-as", "blob",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Expires should be a string not time.Time since the format is not
|
||||
// enforced by S3, and any value can be set to this field outside of the SDK.
|
||||
if strings.HasSuffix(name, "Output") {
|
||||
@@ -110,6 +163,22 @@ func s3CustRemoveHeadObjectModeledErrors(a *API) {
|
||||
op.ErrorRefs = []ShapeRef{}
|
||||
}
|
||||
|
||||
// S3 service operations with an AccountId need accessors to be generated for
|
||||
// them so the fields can be dynamically accessed without reflection.
|
||||
func s3ControlCustomizations(a *API) {
|
||||
for opName, op := range a.Operations {
|
||||
// Add moving AccountId into the hostname instead of header.
|
||||
if ref, ok := op.InputRef.Shape.MemberRefs["AccountId"]; ok {
|
||||
if op.Endpoint != nil {
|
||||
fmt.Fprintf(os.Stderr, "S3 Control, %s, model already defining endpoint trait, remove this customization.\n", opName)
|
||||
}
|
||||
|
||||
op.Endpoint = &EndpointTrait{HostPrefix: "{AccountId}."}
|
||||
ref.HostLabel = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cloudfrontCustomizations customized the API generation to replace values
|
||||
// specific to CloudFront.
|
||||
func cloudfrontCustomizations(a *API) {
|
||||
@@ -129,7 +198,7 @@ func mergeServicesCustomizations(a *API) {
|
||||
p := strings.Replace(a.path, info.srcName, info.dstName, -1)
|
||||
|
||||
if info.serviceVersion != "" {
|
||||
index := strings.LastIndex(p, "/")
|
||||
index := strings.LastIndex(p, string(filepath.Separator))
|
||||
files, _ := ioutil.ReadDir(p[:index])
|
||||
if len(files) > 1 {
|
||||
panic("New version was introduced")
|
||||
@@ -145,7 +214,7 @@ func mergeServicesCustomizations(a *API) {
|
||||
|
||||
for n := range a.Shapes {
|
||||
if _, ok := serviceAPI.Shapes[n]; ok {
|
||||
a.Shapes[n].resolvePkg = "github.com/aws/aws-sdk-go/service/" + info.dstName
|
||||
a.Shapes[n].resolvePkg = SDKImportRoot + "/service/" + info.dstName
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,3 +247,20 @@ func rdsCustomizations(a *API) {
|
||||
func disableEndpointResolving(a *API) {
|
||||
a.Metadata.NoResolveEndpoint = true
|
||||
}
|
||||
|
||||
func backfillAuthType(typ AuthType, opNames ...string) func(*API) {
|
||||
return func(a *API) {
|
||||
for _, opName := range opNames {
|
||||
op, ok := a.Operations[opName]
|
||||
if !ok {
|
||||
panic("unable to backfill auth-type for unknown operation " + opName)
|
||||
}
|
||||
if v := op.AuthType; len(v) != 0 {
|
||||
fmt.Fprintf(os.Stderr, "unable to backfill auth-type for %s, already set, %s", opName, v)
|
||||
continue
|
||||
}
|
||||
|
||||
op.AuthType = typ
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+372
-239
@@ -3,15 +3,17 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html"
|
||||
"io"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
xhtml "golang.org/x/net/html"
|
||||
"golang.org/x/net/html/atom"
|
||||
)
|
||||
|
||||
type apiDocumentation struct {
|
||||
@@ -47,8 +49,13 @@ func (a *API) AttachDocs(filename string) {
|
||||
func (d *apiDocumentation) setup() {
|
||||
d.API.Documentation = docstring(d.Service)
|
||||
|
||||
for op, doc := range d.Operations {
|
||||
d.API.Operations[op].Documentation = docstring(doc)
|
||||
for opName, doc := range d.Operations {
|
||||
if _, ok := d.API.Operations[opName]; !ok {
|
||||
panic(fmt.Sprintf("%s, doc op %q not found in API op set",
|
||||
d.API.name, opName),
|
||||
)
|
||||
}
|
||||
d.API.Operations[opName].Documentation = docstring(doc)
|
||||
}
|
||||
|
||||
for shape, info := range d.Shapes {
|
||||
@@ -108,7 +115,6 @@ func docstring(doc string) string {
|
||||
doc = html.UnescapeString(doc)
|
||||
|
||||
// Replace doc with full name if doc is empty.
|
||||
doc = strings.TrimSpace(doc)
|
||||
if len(doc) == 0 {
|
||||
doc = fullname
|
||||
}
|
||||
@@ -120,17 +126,6 @@ const (
|
||||
indent = " "
|
||||
)
|
||||
|
||||
// style is what we want to prefix a string with.
|
||||
// For instance, <li>Foo</li><li>Bar</li>, will generate
|
||||
// * Foo
|
||||
// * Bar
|
||||
var style = map[string]string{
|
||||
"ul": indent + "* ",
|
||||
"li": indent + "* ",
|
||||
"code": indent,
|
||||
"pre": indent,
|
||||
}
|
||||
|
||||
// commentify converts a string to a Go comment
|
||||
func commentify(doc string) string {
|
||||
if len(doc) == 0 {
|
||||
@@ -155,257 +150,395 @@ func commentify(doc string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// wrap returns a rewritten version of text to have line breaks
|
||||
// at approximately length characters. Line breaks will only be
|
||||
// inserted into whitespace.
|
||||
func wrap(text string, length int, isIndented bool) string {
|
||||
var buf bytes.Buffer
|
||||
var last rune
|
||||
var lastNL bool
|
||||
var col int
|
||||
func wrap(text string, length int) string {
|
||||
var b strings.Builder
|
||||
|
||||
for _, c := range text {
|
||||
switch c {
|
||||
case '\r': // ignore this
|
||||
continue // and also don't track `last`
|
||||
case '\n': // ignore this too, but reset col
|
||||
if col >= length || last == '\n' {
|
||||
buf.WriteString("\n")
|
||||
s := bufio.NewScanner(strings.NewReader(text))
|
||||
for s.Scan() {
|
||||
line := s.Text()
|
||||
|
||||
// cleanup the line's spaces
|
||||
var i int
|
||||
for i = 0; i < len(line); i++ {
|
||||
c := line[i]
|
||||
// Ignore leading spaces, e.g indents.
|
||||
if !(c == ' ' || c == '\t') {
|
||||
break
|
||||
}
|
||||
buf.WriteString("\n")
|
||||
col = 0
|
||||
case ' ', '\t': // opportunity to split
|
||||
if col >= length {
|
||||
buf.WriteByte('\n')
|
||||
col = 0
|
||||
if isIndented {
|
||||
buf.WriteString(indent)
|
||||
col += 3
|
||||
}
|
||||
} else {
|
||||
// We only want to write a leading space if the col is greater than zero.
|
||||
// This will provide the proper spacing for documentation.
|
||||
buf.WriteRune(c)
|
||||
col++ // count column
|
||||
}
|
||||
default:
|
||||
buf.WriteRune(c)
|
||||
col++
|
||||
}
|
||||
lastNL = c == '\n'
|
||||
_ = lastNL
|
||||
last = c
|
||||
line = line[:i] + strings.Join(strings.Fields(line[i:]), " ")
|
||||
splitLine(&b, line, length)
|
||||
}
|
||||
return buf.String()
|
||||
|
||||
return strings.TrimRight(b.String(), "\n")
|
||||
}
|
||||
|
||||
type tagInfo struct {
|
||||
tag string
|
||||
key string
|
||||
val string
|
||||
txt string
|
||||
raw string
|
||||
closingTag bool
|
||||
func splitLine(w stringWriter, line string, length int) {
|
||||
leading := getLeadingWhitespace(line)
|
||||
|
||||
line = line[len(leading):]
|
||||
length -= len(leading)
|
||||
|
||||
const splitOn = " "
|
||||
for len(line) > length {
|
||||
// Find the next whitespace to the length
|
||||
idx := strings.Index(line[length:], splitOn)
|
||||
if idx == -1 {
|
||||
break
|
||||
}
|
||||
offset := length + idx
|
||||
|
||||
if v := line[offset+len(splitOn):]; len(v) == 1 && strings.ContainsAny(v, `,.!?'"`) {
|
||||
// Workaround for long lines with space before the punctuation mark.
|
||||
break
|
||||
}
|
||||
|
||||
w.WriteString(leading)
|
||||
w.WriteString(line[:offset])
|
||||
w.WriteByte('\n')
|
||||
line = strings.TrimLeft(line[offset+len(splitOn):], " \t")
|
||||
}
|
||||
|
||||
if len(line) > 0 {
|
||||
w.WriteString(leading)
|
||||
w.WriteString(line)
|
||||
}
|
||||
// Add the newline back in that was stripped out by scanner.
|
||||
w.WriteByte('\n')
|
||||
}
|
||||
|
||||
func getLeadingWhitespace(v string) string {
|
||||
var o strings.Builder
|
||||
for _, c := range v {
|
||||
if c == ' ' || c == '\t' {
|
||||
o.WriteRune(c)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return o.String()
|
||||
}
|
||||
|
||||
// generateDoc will generate the proper doc string for html encoded or plain text doc entries.
|
||||
func generateDoc(htmlSrc string) string {
|
||||
tokenizer := xhtml.NewTokenizer(strings.NewReader(htmlSrc))
|
||||
tokens := buildTokenArray(tokenizer)
|
||||
scopes := findScopes(tokens)
|
||||
return walk(scopes)
|
||||
var builder strings.Builder
|
||||
if err := encodeHTMLToText(&builder, tokenizer); err != nil {
|
||||
panic(fmt.Sprintf("failed to generated docs, %v", err))
|
||||
}
|
||||
|
||||
return wrap(strings.Trim(builder.String(), "\n"), 72)
|
||||
}
|
||||
|
||||
func buildTokenArray(tokenizer *xhtml.Tokenizer) []tagInfo {
|
||||
tokens := []tagInfo{}
|
||||
for tt := tokenizer.Next(); tt != xhtml.ErrorToken; tt = tokenizer.Next() {
|
||||
switch tt {
|
||||
case xhtml.TextToken:
|
||||
txt := string(tokenizer.Text())
|
||||
if len(tokens) == 0 {
|
||||
info := tagInfo{
|
||||
raw: txt,
|
||||
}
|
||||
tokens = append(tokens, info)
|
||||
}
|
||||
tn, _ := tokenizer.TagName()
|
||||
key, val, _ := tokenizer.TagAttr()
|
||||
info := tagInfo{
|
||||
tag: string(tn),
|
||||
key: string(key),
|
||||
val: string(val),
|
||||
txt: txt,
|
||||
}
|
||||
tokens = append(tokens, info)
|
||||
case xhtml.StartTagToken:
|
||||
tn, _ := tokenizer.TagName()
|
||||
key, val, _ := tokenizer.TagAttr()
|
||||
info := tagInfo{
|
||||
tag: string(tn),
|
||||
key: string(key),
|
||||
val: string(val),
|
||||
}
|
||||
tokens = append(tokens, info)
|
||||
case xhtml.SelfClosingTagToken, xhtml.EndTagToken:
|
||||
tn, _ := tokenizer.TagName()
|
||||
key, val, _ := tokenizer.TagAttr()
|
||||
info := tagInfo{
|
||||
tag: string(tn),
|
||||
key: string(key),
|
||||
val: string(val),
|
||||
closingTag: true,
|
||||
}
|
||||
tokens = append(tokens, info)
|
||||
}
|
||||
}
|
||||
return tokens
|
||||
type stringWriter interface {
|
||||
Write([]byte) (int, error)
|
||||
WriteByte(byte) error
|
||||
WriteRune(rune) (int, error)
|
||||
WriteString(string) (int, error)
|
||||
}
|
||||
|
||||
// walk is used to traverse each scoped block. These scoped
|
||||
// blocks will act as blocked text where we do most of our
|
||||
// text manipulation.
|
||||
func walk(scopes [][]tagInfo) string {
|
||||
doc := ""
|
||||
// Documentation will be chunked by scopes.
|
||||
// Meaning, for each scope will be divided by one or more newlines.
|
||||
for _, scope := range scopes {
|
||||
indentStr, isIndented := priorityIndentation(scope)
|
||||
block := ""
|
||||
href := ""
|
||||
after := false
|
||||
level := 0
|
||||
lastTag := ""
|
||||
for _, token := range scope {
|
||||
if token.closingTag {
|
||||
endl := closeTag(token, level)
|
||||
block += endl
|
||||
level--
|
||||
lastTag = ""
|
||||
} else if token.txt == "" {
|
||||
if token.val != "" {
|
||||
href, after = formatText(token, "")
|
||||
}
|
||||
if level == 1 && isIndented {
|
||||
block += indentStr
|
||||
}
|
||||
level++
|
||||
lastTag = token.tag
|
||||
} else {
|
||||
if token.txt != " " {
|
||||
str, _ := formatText(token, lastTag)
|
||||
block += str
|
||||
if after {
|
||||
block += href
|
||||
after = false
|
||||
}
|
||||
} else {
|
||||
fmt.Println(token.tag)
|
||||
str, _ := formatText(tagInfo{}, lastTag)
|
||||
block += str
|
||||
}
|
||||
func encodeHTMLToText(w stringWriter, z *xhtml.Tokenizer) error {
|
||||
encoder := newHTMLTokenEncoder(w)
|
||||
defer encoder.Flush()
|
||||
|
||||
for {
|
||||
tt := z.Next()
|
||||
if tt == xhtml.ErrorToken {
|
||||
if err := z.Err(); err == io.EOF {
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if !isIndented {
|
||||
block = strings.TrimPrefix(block, " ")
|
||||
|
||||
if err := encoder.Encode(z.Token()); err != nil {
|
||||
return err
|
||||
}
|
||||
block = wrap(block, 72, isIndented)
|
||||
doc += block
|
||||
}
|
||||
return doc
|
||||
}
|
||||
|
||||
// closeTag will divide up the blocks of documentation to be formated properly.
|
||||
func closeTag(token tagInfo, level int) string {
|
||||
switch token.tag {
|
||||
case "pre", "li", "div":
|
||||
return "\n"
|
||||
case "p", "h1", "h2", "h3", "h4", "h5", "h6":
|
||||
return "\n\n"
|
||||
case "code":
|
||||
// indented code is only at the 0th level.
|
||||
if level == 0 {
|
||||
return "\n"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
type htmlTokenHandler interface {
|
||||
OnStartTagToken(xhtml.Token) htmlTokenHandler
|
||||
OnEndTagToken(xhtml.Token, bool)
|
||||
OnSelfClosingTagToken(xhtml.Token)
|
||||
OnTextTagToken(xhtml.Token)
|
||||
}
|
||||
|
||||
// formatText will format any sort of text based off of a tag. It will also return
|
||||
// a boolean to add the string after the text token.
|
||||
func formatText(token tagInfo, lastTag string) (string, bool) {
|
||||
switch token.tag {
|
||||
case "a":
|
||||
if token.val != "" {
|
||||
return fmt.Sprintf(" (%s)", token.val), true
|
||||
}
|
||||
}
|
||||
|
||||
// We don't care about a single space nor no text.
|
||||
if len(token.txt) == 0 || token.txt == " " {
|
||||
return "", false
|
||||
}
|
||||
|
||||
// Here we want to indent code blocks that are newlines
|
||||
if lastTag == "code" {
|
||||
// Greater than one, because we don't care about newlines in the beginning
|
||||
block := ""
|
||||
if lines := strings.Split(token.txt, "\n"); len(lines) > 1 {
|
||||
for _, line := range lines {
|
||||
block += indent + line
|
||||
}
|
||||
block += "\n"
|
||||
return block, false
|
||||
}
|
||||
}
|
||||
return token.txt, false
|
||||
type htmlTokenEncoder struct {
|
||||
w stringWriter
|
||||
depth int
|
||||
handlers []tokenHandlerItem
|
||||
baseHandler tokenHandlerItem
|
||||
}
|
||||
|
||||
// This is a parser to check what type of indention is needed.
|
||||
func priorityIndentation(blocks []tagInfo) (string, bool) {
|
||||
if len(blocks) == 0 {
|
||||
return "", false
|
||||
}
|
||||
|
||||
v, ok := style[blocks[0].tag]
|
||||
return v, ok
|
||||
type tokenHandlerItem struct {
|
||||
handler htmlTokenHandler
|
||||
depth int
|
||||
}
|
||||
|
||||
// Divides into scopes based off levels.
|
||||
// For instance,
|
||||
// <p>Testing<code>123</code></p><ul><li>Foo</li></ul>
|
||||
// This has 2 scopes, the <p> and <ul>
|
||||
func findScopes(tokens []tagInfo) [][]tagInfo {
|
||||
level := 0
|
||||
scope := []tagInfo{}
|
||||
scopes := [][]tagInfo{}
|
||||
for _, token := range tokens {
|
||||
// we will clear empty tagged tokens from the array
|
||||
txt := strings.TrimSpace(token.txt)
|
||||
tag := strings.TrimSpace(token.tag)
|
||||
if len(txt) == 0 && len(tag) == 0 {
|
||||
continue
|
||||
}
|
||||
func newHTMLTokenEncoder(w stringWriter) *htmlTokenEncoder {
|
||||
baseHandler := newBlockTokenHandler(w)
|
||||
baseHandler.rootBlock = true
|
||||
|
||||
scope = append(scope, token)
|
||||
|
||||
// If it is a closing tag then we check what level
|
||||
// we are on. If it is 0, then that means we have found a
|
||||
// scoped block.
|
||||
if token.closingTag {
|
||||
level--
|
||||
if level == 0 {
|
||||
scopes = append(scopes, scope)
|
||||
scope = []tagInfo{}
|
||||
}
|
||||
// Check opening tags and increment the level
|
||||
} else if token.txt == "" {
|
||||
level++
|
||||
}
|
||||
return &htmlTokenEncoder{
|
||||
w: w,
|
||||
baseHandler: tokenHandlerItem{
|
||||
handler: baseHandler,
|
||||
},
|
||||
}
|
||||
// In this case, we did not run into a closing tag. This would mean
|
||||
// we have plaintext for documentation.
|
||||
if len(scopes) == 0 {
|
||||
scopes = append(scopes, scope)
|
||||
}
|
||||
return scopes
|
||||
}
|
||||
|
||||
func (e *htmlTokenEncoder) Flush() error {
|
||||
e.baseHandler.handler.OnEndTagToken(xhtml.Token{Type: xhtml.TextToken}, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *htmlTokenEncoder) Encode(token xhtml.Token) error {
|
||||
h := e.baseHandler
|
||||
if len(e.handlers) != 0 {
|
||||
h = e.handlers[len(e.handlers)-1]
|
||||
}
|
||||
|
||||
switch token.Type {
|
||||
case xhtml.StartTagToken:
|
||||
e.depth++
|
||||
|
||||
next := h.handler.OnStartTagToken(token)
|
||||
if next != nil {
|
||||
e.handlers = append(e.handlers, tokenHandlerItem{
|
||||
handler: next,
|
||||
depth: e.depth,
|
||||
})
|
||||
}
|
||||
|
||||
case xhtml.EndTagToken:
|
||||
handlerBlockClosing := e.depth == h.depth
|
||||
|
||||
h.handler.OnEndTagToken(token, handlerBlockClosing)
|
||||
|
||||
// Remove all but the root handler as the handler is no longer needed.
|
||||
if handlerBlockClosing {
|
||||
e.handlers = e.handlers[:len(e.handlers)-1]
|
||||
}
|
||||
e.depth--
|
||||
|
||||
case xhtml.SelfClosingTagToken:
|
||||
h.handler.OnSelfClosingTagToken(token)
|
||||
|
||||
case xhtml.TextToken:
|
||||
h.handler.OnTextTagToken(token)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type baseTokenHandler struct {
|
||||
w stringWriter
|
||||
}
|
||||
|
||||
func (e *baseTokenHandler) OnStartTagToken(token xhtml.Token) htmlTokenHandler { return nil }
|
||||
func (e *baseTokenHandler) OnEndTagToken(token xhtml.Token, blockClosing bool) {}
|
||||
func (e *baseTokenHandler) OnSelfClosingTagToken(token xhtml.Token) {}
|
||||
func (e *baseTokenHandler) OnTextTagToken(token xhtml.Token) {
|
||||
e.w.WriteString(token.Data)
|
||||
}
|
||||
|
||||
type blockTokenHandler struct {
|
||||
baseTokenHandler
|
||||
|
||||
rootBlock bool
|
||||
origWriter stringWriter
|
||||
strBuilder *strings.Builder
|
||||
|
||||
started bool
|
||||
newlineBeforeNextBlock bool
|
||||
}
|
||||
|
||||
func newBlockTokenHandler(w stringWriter) *blockTokenHandler {
|
||||
strBuilder := &strings.Builder{}
|
||||
return &blockTokenHandler{
|
||||
origWriter: w,
|
||||
strBuilder: strBuilder,
|
||||
baseTokenHandler: baseTokenHandler{
|
||||
w: strBuilder,
|
||||
},
|
||||
}
|
||||
}
|
||||
func (e *blockTokenHandler) OnStartTagToken(token xhtml.Token) htmlTokenHandler {
|
||||
e.started = true
|
||||
if e.newlineBeforeNextBlock {
|
||||
e.w.WriteString("\n")
|
||||
e.newlineBeforeNextBlock = false
|
||||
}
|
||||
|
||||
switch token.DataAtom {
|
||||
case atom.A:
|
||||
return newLinkTokenHandler(e.w, token)
|
||||
case atom.Ul:
|
||||
e.w.WriteString("\n")
|
||||
e.newlineBeforeNextBlock = true
|
||||
return newListTokenHandler(e.w)
|
||||
|
||||
case atom.Div, atom.Dt, atom.P, atom.H1, atom.H2, atom.H3, atom.H4, atom.H5, atom.H6:
|
||||
e.w.WriteString("\n")
|
||||
e.newlineBeforeNextBlock = true
|
||||
return newBlockTokenHandler(e.w)
|
||||
|
||||
case atom.Pre, atom.Code:
|
||||
if e.rootBlock {
|
||||
e.w.WriteString("\n")
|
||||
e.w.WriteString(indent)
|
||||
e.newlineBeforeNextBlock = true
|
||||
}
|
||||
return newBlockTokenHandler(e.w)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
func (e *blockTokenHandler) OnEndTagToken(token xhtml.Token, blockClosing bool) {
|
||||
if !blockClosing {
|
||||
return
|
||||
}
|
||||
|
||||
e.origWriter.WriteString(e.strBuilder.String())
|
||||
if e.newlineBeforeNextBlock {
|
||||
e.origWriter.WriteString("\n")
|
||||
e.newlineBeforeNextBlock = false
|
||||
}
|
||||
|
||||
e.strBuilder.Reset()
|
||||
}
|
||||
|
||||
func (e *blockTokenHandler) OnTextTagToken(token xhtml.Token) {
|
||||
if e.newlineBeforeNextBlock {
|
||||
e.w.WriteString("\n")
|
||||
e.newlineBeforeNextBlock = false
|
||||
}
|
||||
if !e.started {
|
||||
token.Data = strings.TrimLeft(token.Data, " \t\n")
|
||||
}
|
||||
if len(token.Data) != 0 {
|
||||
e.started = true
|
||||
}
|
||||
e.baseTokenHandler.OnTextTagToken(token)
|
||||
}
|
||||
|
||||
type linkTokenHandler struct {
|
||||
baseTokenHandler
|
||||
linkToken xhtml.Token
|
||||
}
|
||||
|
||||
func newLinkTokenHandler(w stringWriter, token xhtml.Token) *linkTokenHandler {
|
||||
return &linkTokenHandler{
|
||||
baseTokenHandler: baseTokenHandler{
|
||||
w: w,
|
||||
},
|
||||
linkToken: token,
|
||||
}
|
||||
}
|
||||
func (e *linkTokenHandler) OnEndTagToken(token xhtml.Token, blockClosing bool) {
|
||||
if !blockClosing {
|
||||
return
|
||||
}
|
||||
|
||||
if href, ok := getHTMLTokenAttr(e.linkToken.Attr, "href"); ok && len(href) != 0 {
|
||||
fmt.Fprintf(e.w, " (%s)", strings.TrimSpace(href))
|
||||
}
|
||||
}
|
||||
|
||||
type listTokenHandler struct {
|
||||
baseTokenHandler
|
||||
|
||||
items int
|
||||
}
|
||||
|
||||
func newListTokenHandler(w stringWriter) *listTokenHandler {
|
||||
return &listTokenHandler{
|
||||
baseTokenHandler: baseTokenHandler{
|
||||
w: w,
|
||||
},
|
||||
}
|
||||
}
|
||||
func (e *listTokenHandler) OnStartTagToken(token xhtml.Token) htmlTokenHandler {
|
||||
switch token.DataAtom {
|
||||
case atom.Li:
|
||||
if e.items >= 1 {
|
||||
e.w.WriteString("\n\n")
|
||||
}
|
||||
e.items++
|
||||
return newListItemTokenHandler(e.w)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *listTokenHandler) OnTextTagToken(token xhtml.Token) {
|
||||
// Squash whitespace between list and items
|
||||
}
|
||||
|
||||
type listItemTokenHandler struct {
|
||||
baseTokenHandler
|
||||
|
||||
origWriter stringWriter
|
||||
strBuilder *strings.Builder
|
||||
}
|
||||
|
||||
func newListItemTokenHandler(w stringWriter) *listItemTokenHandler {
|
||||
strBuilder := &strings.Builder{}
|
||||
return &listItemTokenHandler{
|
||||
origWriter: w,
|
||||
strBuilder: strBuilder,
|
||||
baseTokenHandler: baseTokenHandler{
|
||||
w: strBuilder,
|
||||
},
|
||||
}
|
||||
}
|
||||
func (e *listItemTokenHandler) OnStartTagToken(token xhtml.Token) htmlTokenHandler {
|
||||
switch token.DataAtom {
|
||||
case atom.P:
|
||||
return newBlockTokenHandler(e.w)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (e *listItemTokenHandler) OnEndTagToken(token xhtml.Token, blockClosing bool) {
|
||||
if !blockClosing {
|
||||
return
|
||||
}
|
||||
|
||||
e.origWriter.WriteString(indent + "* ")
|
||||
e.origWriter.WriteString(strings.TrimSpace(e.strBuilder.String()))
|
||||
}
|
||||
|
||||
type trimSpaceTokenHandler struct {
|
||||
baseTokenHandler
|
||||
|
||||
origWriter stringWriter
|
||||
strBuilder *strings.Builder
|
||||
}
|
||||
|
||||
func newTrimSpaceTokenHandler(w stringWriter) *trimSpaceTokenHandler {
|
||||
strBuilder := &strings.Builder{}
|
||||
return &trimSpaceTokenHandler{
|
||||
origWriter: w,
|
||||
strBuilder: strBuilder,
|
||||
baseTokenHandler: baseTokenHandler{
|
||||
w: strBuilder,
|
||||
},
|
||||
}
|
||||
}
|
||||
func (e *trimSpaceTokenHandler) OnEndTagToken(token xhtml.Token, blockClosing bool) {
|
||||
if !blockClosing {
|
||||
return
|
||||
}
|
||||
|
||||
e.origWriter.WriteString(strings.TrimSpace(e.strBuilder.String()))
|
||||
}
|
||||
|
||||
func getHTMLTokenAttr(attr []xhtml.Attribute, name string) (string, bool) {
|
||||
for _, a := range attr {
|
||||
if strings.EqualFold(a.Key, name) {
|
||||
return a.Val, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
+71
-90
@@ -1,4 +1,4 @@
|
||||
// +build 1.6,codegen
|
||||
// +build go1.8,codegen
|
||||
|
||||
package api
|
||||
|
||||
@@ -6,95 +6,76 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNonHTMLDocGen(t *testing.T) {
|
||||
doc := "Testing 1 2 3"
|
||||
expected := "// Testing 1 2 3\n"
|
||||
doc = docstring(doc)
|
||||
func TestDocstring(t *testing.T) {
|
||||
cases := map[string]struct {
|
||||
In string
|
||||
Expect string
|
||||
}{
|
||||
"non HTML": {
|
||||
In: "Testing 1 2 3",
|
||||
Expect: "// Testing 1 2 3",
|
||||
},
|
||||
"link": {
|
||||
In: `<a href="https://example.com">a link</a>`,
|
||||
Expect: "// a link (https://example.com)",
|
||||
},
|
||||
"link with space": {
|
||||
In: `<a href=" https://example.com">a link</a>`,
|
||||
Expect: "// a link (https://example.com)",
|
||||
},
|
||||
"list HTML 01": {
|
||||
In: "<ul><li>Testing 1 2 3</li> <li>FooBar</li></ul>",
|
||||
Expect: "// * Testing 1 2 3\n// \n// * FooBar",
|
||||
},
|
||||
"list HTML 02": {
|
||||
In: "<ul> <li>Testing 1 2 3</li> <li>FooBar</li> </ul>",
|
||||
Expect: "// * Testing 1 2 3\n// \n// * FooBar",
|
||||
},
|
||||
"list HTML leading spaces": {
|
||||
In: " <ul> <li>Testing 1 2 3</li> <li>FooBar</li> </ul>",
|
||||
Expect: "// * Testing 1 2 3\n// \n// * FooBar",
|
||||
},
|
||||
"list HTML paragraph": {
|
||||
In: "<ul> <li> <p>Testing 1 2 3</p> </li><li> <p>FooBar</p></li></ul>",
|
||||
Expect: "// * Testing 1 2 3\n// \n// * FooBar",
|
||||
},
|
||||
"inline code HTML": {
|
||||
In: "<ul> <li><code>Testing</code>: 1 2 3</li> <li>FooBar</li> </ul>",
|
||||
Expect: "// * Testing: 1 2 3\n// \n// * FooBar",
|
||||
},
|
||||
"complex list paragraph": {
|
||||
In: "<ul> <li><p><code>FOO</code> Bar</p></li><li><p><code>Xyz</code> ABC</p></li></ul>",
|
||||
Expect: "// * FOO Bar\n// \n// * Xyz ABC",
|
||||
},
|
||||
"inline code in paragraph": {
|
||||
In: "<p><code>Testing</code>: 1 2 3</p>",
|
||||
Expect: "// Testing: 1 2 3",
|
||||
},
|
||||
"root pre": {
|
||||
In: "<pre><code>Testing</code></pre>",
|
||||
Expect: "// Testing",
|
||||
},
|
||||
"paragraph": {
|
||||
In: "<p>Testing 1 2 3</p>",
|
||||
Expect: "// Testing 1 2 3",
|
||||
},
|
||||
"wrap lines": {
|
||||
In: "<span data-target-type=\"operation\" data-service=\"secretsmanager\" data-target=\"CreateSecret\">CreateSecret</span> <span data-target-type=\"structure\" data-service=\"secretsmanager\" data-target=\"SecretListEntry\">SecretListEntry</span> <span data-target-type=\"structure\" data-service=\"secretsmanager\" data-target=\"CreateSecret$SecretName\">SecretName</span> <span data-target-type=\"structure\" data-service=\"secretsmanager\" data-target=\"SecretListEntry$KmsKeyId\">KmsKeyId</span>",
|
||||
Expect: "// CreateSecret SecretListEntry SecretName KmsKeyId",
|
||||
},
|
||||
"links with spaces": {
|
||||
In: "<p> Deletes the replication configuration from the bucket. For information about replication configuration, see <a href=\" https://docs.aws.amazon.com/AmazonS3/latest/dev/crr.html\">Cross-Region Replication (CRR)</a> in the <i>Amazon S3 Developer Guide</i>. </p>",
|
||||
Expect: "// Deletes the replication configuration from the bucket. For information about\n// replication configuration, see Cross-Region Replication (CRR) (https://docs.aws.amazon.com/AmazonS3/latest/dev/crr.html)\n// in the Amazon S3 Developer Guide.",
|
||||
},
|
||||
}
|
||||
|
||||
if expected != doc {
|
||||
t.Errorf("Expected %s, but received %s", expected, doc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListsHTMLDocGen(t *testing.T) {
|
||||
doc := "<ul><li>Testing 1 2 3</li> <li>FooBar</li></ul>"
|
||||
expected := "// * Testing 1 2 3\n// * FooBar\n"
|
||||
doc = docstring(doc)
|
||||
|
||||
if expected != doc {
|
||||
t.Errorf("Expected %s, but received %s", expected, doc)
|
||||
}
|
||||
|
||||
doc = "<ul> <li>Testing 1 2 3</li> <li>FooBar</li> </ul>"
|
||||
expected = "// * Testing 1 2 3\n// * FooBar\n"
|
||||
doc = docstring(doc)
|
||||
|
||||
if expected != doc {
|
||||
t.Errorf("Expected %s, but received %s", expected, doc)
|
||||
}
|
||||
|
||||
// Test leading spaces
|
||||
doc = " <ul> <li>Testing 1 2 3</li> <li>FooBar</li> </ul>"
|
||||
doc = docstring(doc)
|
||||
if expected != doc {
|
||||
t.Errorf("Expected %s, but received %s", expected, doc)
|
||||
}
|
||||
|
||||
// Paragraph check
|
||||
doc = "<ul> <li> <p>Testing 1 2 3</p> </li><li> <p>FooBar</p></li></ul>"
|
||||
expected = "// * Testing 1 2 3\n// \n// * FooBar\n"
|
||||
doc = docstring(doc)
|
||||
if expected != doc {
|
||||
t.Errorf("Expected %s, but received %s", expected, doc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInlineCodeHTMLDocGen(t *testing.T) {
|
||||
doc := "<ul> <li><code>Testing</code>: 1 2 3</li> <li>FooBar</li> </ul>"
|
||||
expected := "// * Testing: 1 2 3\n// * FooBar\n"
|
||||
doc = docstring(doc)
|
||||
|
||||
if expected != doc {
|
||||
t.Errorf("Expected %s, but received %s", expected, doc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInlineCodeInParagraphHTMLDocGen(t *testing.T) {
|
||||
doc := "<p><code>Testing</code>: 1 2 3</p>"
|
||||
expected := "// Testing: 1 2 3\n"
|
||||
doc = docstring(doc)
|
||||
|
||||
if expected != doc {
|
||||
t.Errorf("Expected %s, but received %s", expected, doc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyPREInlineCodeHTMLDocGen(t *testing.T) {
|
||||
doc := "<pre><code>Testing</code></pre>"
|
||||
expected := "// Testing\n"
|
||||
doc = docstring(doc)
|
||||
|
||||
if expected != doc {
|
||||
t.Errorf("Expected %s, but received %s", expected, doc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParagraph(t *testing.T) {
|
||||
doc := "<p>Testing 1 2 3</p>"
|
||||
expected := "// Testing 1 2 3\n"
|
||||
doc = docstring(doc)
|
||||
|
||||
if expected != doc {
|
||||
t.Errorf("Expected %s, but received %s", expected, doc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestComplexListParagraphCode(t *testing.T) {
|
||||
doc := "<ul> <li><p><code>FOO</code> Bar</p></li><li><p><code>Xyz</code> ABC</p></li></ul>"
|
||||
expected := "// * FOO Bar\n// \n// * Xyz ABC\n"
|
||||
doc = docstring(doc)
|
||||
|
||||
if expected != doc {
|
||||
t.Errorf("Expected %s, but received %s", expected, doc)
|
||||
for name, c := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Log("Input", c.In)
|
||||
actual := docstring(c.In)
|
||||
if e, a := c.Expect, actual; e != a {
|
||||
t.Errorf("expect %q, got %q", e, a)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// +build codegen
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
func setupEndpointHostPrefix(op *Operation) {
|
||||
op.API.AddSDKImport("private/protocol")
|
||||
|
||||
buildHandler := fmt.Sprintf("protocol.NewHostPrefixHandler(%q, ",
|
||||
op.Endpoint.HostPrefix)
|
||||
|
||||
if op.InputRef.Shape.HasHostLabelMembers() {
|
||||
buildHandler += "input.hostLabels"
|
||||
} else {
|
||||
buildHandler += "nil"
|
||||
}
|
||||
|
||||
buildHandler += ")"
|
||||
|
||||
op.CustomBuildHandlers = append(op.CustomBuildHandlers,
|
||||
buildHandler,
|
||||
"protocol.ValidateEndpointHostHandler",
|
||||
)
|
||||
}
|
||||
|
||||
// HasHostLabelMembers returns true if the shape contains any members which are
|
||||
// decorated with the hostLabel trait.
|
||||
func (s *Shape) HasHostLabelMembers() bool {
|
||||
for _, ref := range s.MemberRefs {
|
||||
if ref.HostLabel {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
var hostLabelsShapeTmpl = template.Must(
|
||||
template.New("hostLabelsShapeTmpl").
|
||||
Parse(hostLabelsShapeTmplDef),
|
||||
)
|
||||
|
||||
const hostLabelsShapeTmplDef = `
|
||||
{{- define "hostLabelsShapeTmpl" }}
|
||||
func (s *{{ $.ShapeName }}) hostLabels() map[string]string {
|
||||
return map[string]string{
|
||||
{{- range $name, $ref := $.MemberRefs }}
|
||||
{{- if $ref.HostLabel }}
|
||||
"{{ $name }}": aws.StringValue(s.{{ $name }}),
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
`
|
||||
+1165
-9
File diff suppressed because it is too large
Load Diff
-79
@@ -1,79 +0,0 @@
|
||||
// +build go1.6,codegen
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSuppressEventStream(t *testing.T) {
|
||||
cases := []struct {
|
||||
API *API
|
||||
Ops []string
|
||||
Shapes []string
|
||||
}{
|
||||
{
|
||||
API: &API{
|
||||
Operations: map[string]*Operation{
|
||||
"abc": {
|
||||
InputRef: ShapeRef{
|
||||
ShapeName: "abcRequest",
|
||||
},
|
||||
OutputRef: ShapeRef{
|
||||
ShapeName: "abcResponse",
|
||||
},
|
||||
},
|
||||
"eventStreamOp": {
|
||||
InputRef: ShapeRef{
|
||||
ShapeName: "eventStreamOpRequest",
|
||||
},
|
||||
OutputRef: ShapeRef{
|
||||
ShapeName: "eventStreamOpResponse",
|
||||
},
|
||||
},
|
||||
},
|
||||
Shapes: map[string]*Shape{
|
||||
"abcRequest": {},
|
||||
"abcResponse": {},
|
||||
"eventStreamOpRequest": {},
|
||||
"eventStreamOpResponse": {
|
||||
MemberRefs: map[string]*ShapeRef{
|
||||
"eventStreamShape": {
|
||||
ShapeName: "eventStreamShape",
|
||||
},
|
||||
},
|
||||
},
|
||||
"eventStreamShape": {
|
||||
IsEventStream: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Ops: []string{"Abc"},
|
||||
Shapes: []string{"AbcInput", "AbcOutput"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
c.API.Setup()
|
||||
if e, a := c.Ops, c.API.OperationNames(); !stringsEqual(e, a) {
|
||||
t.Errorf("expect %v ops, got %v", e, a)
|
||||
}
|
||||
|
||||
if e, a := c.Shapes, c.API.ShapeNames(); !stringsEqual(e, a) {
|
||||
t.Errorf("expect %v ops, got %v", e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func stringsEqual(a, b []string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 0; i < len(a); i++ {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
+7
-6
@@ -54,14 +54,12 @@ var exampleCustomizations = map[string]template.FuncMap{}
|
||||
|
||||
var exampleTmpls = template.Must(template.New("example").Funcs(exampleFuncMap).Parse(`
|
||||
{{ generateTypes . }}
|
||||
{{ commentify (wrap .Title 80 false) }}
|
||||
{{ commentify (wrap .Title 80) }}
|
||||
//
|
||||
{{ commentify (wrap .Description 80 false) }}
|
||||
{{ commentify (wrap .Description 80) }}
|
||||
func Example{{ .API.StructName }}_{{ .MethodName }}() {
|
||||
svc := {{ .API.PackageName }}.New(session.New())
|
||||
input := &{{ .Operation.InputRef.Shape.GoTypeWithPkgNameElem }} {
|
||||
{{ generateExampleInput . -}}
|
||||
}
|
||||
input := {{ generateExampleInput . }}
|
||||
|
||||
result, err := svc.{{ .OperationName }}(input)
|
||||
if err != nil {
|
||||
@@ -130,7 +128,10 @@ func (ex Example) GoCode() string {
|
||||
|
||||
func generateExampleInput(ex Example) string {
|
||||
if ex.Operation.HasInput() {
|
||||
return ex.Builder.BuildShape(&ex.Operation.InputRef, ex.Input, false)
|
||||
return fmt.Sprintf("&%s{\n%s\n}",
|
||||
ex.Builder.GoType(&ex.Operation.InputRef, true),
|
||||
ex.Builder.BuildShape(&ex.Operation.InputRef, ex.Input, false),
|
||||
)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
+4
-4
@@ -220,10 +220,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/fooservice"
|
||||
"` + SDKImportRoot + `/aws"
|
||||
"` + SDKImportRoot + `/aws/awserr"
|
||||
"` + SDKImportRoot + `/aws/session"
|
||||
"` + SDKImportRoot + `/service/fooservice"
|
||||
)
|
||||
|
||||
var _ time.Duration
|
||||
|
||||
+9
-204
@@ -2,221 +2,26 @@
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type examplesBuilder interface {
|
||||
BuildShape(*ShapeRef, map[string]interface{}, bool) string
|
||||
BuildList(string, string, *ShapeRef, []interface{}) string
|
||||
BuildComplex(string, string, *ShapeRef, map[string]interface{}) string
|
||||
GoType(*ShapeRef, bool) string
|
||||
Imports(*API) string
|
||||
}
|
||||
|
||||
type defaultExamplesBuilder struct{}
|
||||
|
||||
// BuildShape will recursively build the referenced shape based on the json object
|
||||
// provided.
|
||||
// isMap will dictate how the field name is specified. If isMap is true, we will expect
|
||||
// the member name to be quotes like "Foo".
|
||||
func (builder defaultExamplesBuilder) BuildShape(ref *ShapeRef, shapes map[string]interface{}, isMap bool) string {
|
||||
order := make([]string, len(shapes))
|
||||
for k := range shapes {
|
||||
order = append(order, k)
|
||||
}
|
||||
sort.Strings(order)
|
||||
|
||||
ret := ""
|
||||
for _, name := range order {
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
shape := shapes[name]
|
||||
|
||||
// If the shape isn't a map, we want to export the value, since every field
|
||||
// defined in our shapes are exported.
|
||||
if len(name) > 0 && !isMap && strings.ToLower(name[0:1]) == name[0:1] {
|
||||
name = strings.Title(name)
|
||||
}
|
||||
|
||||
memName := name
|
||||
passRef := ref.Shape.MemberRefs[name]
|
||||
|
||||
if isMap {
|
||||
memName = fmt.Sprintf("%q", memName)
|
||||
passRef = &ref.Shape.ValueRef
|
||||
}
|
||||
|
||||
switch v := shape.(type) {
|
||||
case map[string]interface{}:
|
||||
ret += builder.BuildComplex(name, memName, passRef, v)
|
||||
case []interface{}:
|
||||
ret += builder.BuildList(name, memName, passRef, v)
|
||||
default:
|
||||
ret += builder.BuildScalar(name, memName, passRef, v, ref.Shape.Payload == name)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// BuildList will construct a list shape based off the service's definition
|
||||
// of that list.
|
||||
func (builder defaultExamplesBuilder) BuildList(name, memName string, ref *ShapeRef, v []interface{}) string {
|
||||
ret := ""
|
||||
|
||||
if len(v) == 0 || ref == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
passRef := &ref.Shape.MemberRef
|
||||
ret += fmt.Sprintf("%s: %s {\n", memName, builder.GoType(ref, false))
|
||||
ret += builder.buildListElements(passRef, v)
|
||||
ret += "},\n"
|
||||
return ret
|
||||
}
|
||||
|
||||
func (builder defaultExamplesBuilder) buildListElements(ref *ShapeRef, v []interface{}) string {
|
||||
if len(v) == 0 || ref == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
ret := ""
|
||||
format := ""
|
||||
isComplex := false
|
||||
isList := false
|
||||
|
||||
// get format for atomic type. If it is not an atomic type,
|
||||
// get the element.
|
||||
switch v[0].(type) {
|
||||
case string:
|
||||
format = "%s"
|
||||
case bool:
|
||||
format = "%t"
|
||||
case float64:
|
||||
switch ref.Shape.Type {
|
||||
case "integer", "int64", "long":
|
||||
format = "%d"
|
||||
default:
|
||||
format = "%f"
|
||||
}
|
||||
case []interface{}:
|
||||
isList = true
|
||||
case map[string]interface{}:
|
||||
isComplex = true
|
||||
}
|
||||
|
||||
for _, elem := range v {
|
||||
if isComplex {
|
||||
ret += fmt.Sprintf("{\n%s\n},\n", builder.BuildShape(ref, elem.(map[string]interface{}), ref.Shape.Type == "map"))
|
||||
} else if isList {
|
||||
ret += fmt.Sprintf("{\n%s\n},\n", builder.buildListElements(&ref.Shape.MemberRef, elem.([]interface{})))
|
||||
} else {
|
||||
switch ref.Shape.Type {
|
||||
case "integer", "int64", "long":
|
||||
elem = int(elem.(float64))
|
||||
}
|
||||
ret += fmt.Sprintf("%s,\n", getValue(ref.Shape.Type, fmt.Sprintf(format, elem)))
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// BuildScalar will build atomic Go types.
|
||||
func (builder defaultExamplesBuilder) BuildScalar(name, memName string, ref *ShapeRef, shape interface{}, isPayload bool) string {
|
||||
if ref == nil || ref.Shape == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch v := shape.(type) {
|
||||
case bool:
|
||||
return convertToCorrectType(memName, ref.Shape.Type, fmt.Sprintf("%t", v))
|
||||
case int:
|
||||
if ref.Shape.Type == "timestamp" {
|
||||
return parseTimeString(ref, memName, fmt.Sprintf("%d", v))
|
||||
}
|
||||
return convertToCorrectType(memName, ref.Shape.Type, fmt.Sprintf("%d", v))
|
||||
case float64:
|
||||
dataType := ref.Shape.Type
|
||||
if dataType == "integer" || dataType == "int64" || dataType == "long" {
|
||||
return convertToCorrectType(memName, ref.Shape.Type, fmt.Sprintf("%d", int(shape.(float64))))
|
||||
}
|
||||
return convertToCorrectType(memName, ref.Shape.Type, fmt.Sprintf("%f", v))
|
||||
case string:
|
||||
t := ref.Shape.Type
|
||||
switch t {
|
||||
case "timestamp":
|
||||
return parseTimeString(ref, memName, fmt.Sprintf("%s", v))
|
||||
case "blob":
|
||||
if (ref.Streaming || ref.Shape.Streaming) && isPayload {
|
||||
return fmt.Sprintf("%s: aws.ReadSeekCloser(strings.NewReader(%q)),\n", memName, v)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s: []byte(%q),\n", memName, v)
|
||||
default:
|
||||
return convertToCorrectType(memName, t, v)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("Unsupported scalar type: %v", reflect.TypeOf(v)))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (builder defaultExamplesBuilder) BuildComplex(name, memName string, ref *ShapeRef, v map[string]interface{}) string {
|
||||
switch ref.Shape.Type {
|
||||
case "structure":
|
||||
return fmt.Sprintf(`%s: &%s{
|
||||
%s
|
||||
},
|
||||
`, memName, builder.GoType(ref, true), builder.BuildShape(ref, v, false))
|
||||
case "map":
|
||||
return fmt.Sprintf(`%s: %s{
|
||||
%s
|
||||
},
|
||||
`, name, builder.GoType(ref, false), builder.BuildShape(ref, v, true))
|
||||
default:
|
||||
panic(fmt.Sprintf("Expected complex type but recieved %q", ref.Shape.Type))
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (builder defaultExamplesBuilder) GoType(ref *ShapeRef, elem bool) string {
|
||||
if ref.Shape.Type != "structure" && ref.Shape.Type != "list" && ref.Shape.Type != "map" {
|
||||
return ref.GoTypeWithPkgName()
|
||||
}
|
||||
|
||||
prefix := ""
|
||||
if ref.Shape.Type == "list" {
|
||||
ref = &ref.Shape.MemberRef
|
||||
prefix = "[]"
|
||||
}
|
||||
|
||||
name := ref.GoTypeWithPkgName()
|
||||
if elem {
|
||||
name = ref.GoTypeElem()
|
||||
if !strings.Contains(name, ".") {
|
||||
name = strings.Join([]string{ref.API.PackageName(), name}, ".")
|
||||
}
|
||||
}
|
||||
|
||||
return prefix + name
|
||||
type defaultExamplesBuilder struct {
|
||||
ShapeValueBuilder
|
||||
}
|
||||
|
||||
func (builder defaultExamplesBuilder) Imports(a *API) string {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
buf.WriteString(`"fmt"
|
||||
return `"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
`)
|
||||
|
||||
buf.WriteString(fmt.Sprintf("\"%s/%s\"", "github.com/aws/aws-sdk-go/service", a.PackageName()))
|
||||
return buf.String()
|
||||
"` + SDKImportRoot + `/aws"
|
||||
"` + SDKImportRoot + `/aws/awserr"
|
||||
"` + SDKImportRoot + `/aws/session"
|
||||
"` + a.ImportPath() + `"
|
||||
`
|
||||
}
|
||||
|
||||
Generated
Vendored
+7
-15
@@ -2,27 +2,19 @@
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type wafregionalExamplesBuilder struct {
|
||||
defaultExamplesBuilder
|
||||
}
|
||||
|
||||
func (builder wafregionalExamplesBuilder) Imports(a *API) string {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
buf.WriteString(`"fmt"
|
||||
return `"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/waf"
|
||||
`)
|
||||
|
||||
buf.WriteString(fmt.Sprintf("\"%s/%s\"", "github.com/aws/aws-sdk-go/service", a.PackageName()))
|
||||
return buf.String()
|
||||
"` + SDKImportRoot + `/aws"
|
||||
"` + SDKImportRoot + `/aws/awserr"
|
||||
"` + SDKImportRoot + `/aws/session"
|
||||
"` + SDKImportRoot + `/service/waf"
|
||||
"` + SDKImportRoot + `/service/` + a.PackageName() + `"
|
||||
`
|
||||
}
|
||||
|
||||
+92
-4
@@ -1,13 +1,34 @@
|
||||
package api
|
||||
|
||||
type persistAPIType struct {
|
||||
output bool
|
||||
input bool
|
||||
}
|
||||
|
||||
type persistAPITypes map[string]map[string]persistAPIType
|
||||
|
||||
func (ts persistAPITypes) Lookup(serviceName, opName string) persistAPIType {
|
||||
service, ok := shamelist[serviceName]
|
||||
if !ok {
|
||||
return persistAPIType{}
|
||||
}
|
||||
|
||||
return service[opName]
|
||||
}
|
||||
|
||||
func (ts persistAPITypes) Input(serviceName, opName string) bool {
|
||||
return ts.Lookup(serviceName, opName).input
|
||||
}
|
||||
|
||||
func (ts persistAPITypes) Output(serviceName, opName string) bool {
|
||||
return ts.Lookup(serviceName, opName).output
|
||||
}
|
||||
|
||||
// shamelist is used to not rename certain operation's input and output shapes.
|
||||
// We need to maintain backwards compatibility with pre-existing services. Since
|
||||
// not generating unique input/output shapes is not desired, we will generate
|
||||
// unique input/output shapes for new operations.
|
||||
var shamelist = map[string]map[string]struct {
|
||||
input bool
|
||||
output bool
|
||||
}{
|
||||
var shamelist = persistAPITypes{
|
||||
"APIGateway": {
|
||||
"CreateApiKey": {
|
||||
output: true,
|
||||
@@ -352,6 +373,11 @@ var shamelist = map[string]map[string]struct {
|
||||
output: true,
|
||||
},
|
||||
},
|
||||
"ElasticTranscoder": {
|
||||
"CreateJob": {
|
||||
output: true,
|
||||
},
|
||||
},
|
||||
"Glacier": {
|
||||
"DescribeJob": {
|
||||
output: true,
|
||||
@@ -431,6 +457,54 @@ var shamelist = map[string]map[string]struct {
|
||||
output: true,
|
||||
},
|
||||
},
|
||||
"MQ": {
|
||||
"CreateBroker": {
|
||||
input: true,
|
||||
output: true,
|
||||
},
|
||||
"CreateConfiguration": {
|
||||
input: true,
|
||||
output: true,
|
||||
},
|
||||
"CreateUser": {
|
||||
input: true,
|
||||
},
|
||||
"DeleteBroker": {
|
||||
output: true,
|
||||
},
|
||||
"DescribeBroker": {
|
||||
output: true,
|
||||
},
|
||||
"DescribeUser": {
|
||||
output: true,
|
||||
},
|
||||
"DescribeConfigurationRevision": {
|
||||
output: true,
|
||||
},
|
||||
"ListBrokers": {
|
||||
output: true,
|
||||
},
|
||||
"ListConfigurations": {
|
||||
output: true,
|
||||
},
|
||||
"ListConfigurationRevisions": {
|
||||
output: true,
|
||||
},
|
||||
"ListUsers": {
|
||||
output: true,
|
||||
},
|
||||
"UpdateBroker": {
|
||||
input: true,
|
||||
output: true,
|
||||
},
|
||||
"UpdateConfiguration": {
|
||||
input: true,
|
||||
output: true,
|
||||
},
|
||||
"UpdateUser": {
|
||||
input: true,
|
||||
},
|
||||
},
|
||||
"RDS": {
|
||||
"ModifyDBClusterParameterGroup": {
|
||||
output: true,
|
||||
@@ -472,6 +546,20 @@ var shamelist = map[string]map[string]struct {
|
||||
output: true,
|
||||
},
|
||||
},
|
||||
"ServerlessApplicationRepository": {
|
||||
"CreateApplication": {
|
||||
input: true,
|
||||
},
|
||||
"CreateApplicationVersion": {
|
||||
input: true,
|
||||
},
|
||||
"CreateCloudFormationChangeSet": {
|
||||
input: true,
|
||||
},
|
||||
"UpdateApplication": {
|
||||
input: true,
|
||||
},
|
||||
},
|
||||
"SWF": {
|
||||
"CountClosedWorkflowExecutions": {
|
||||
output: true,
|
||||
|
||||
+140
-6
@@ -7,8 +7,136 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// APIs provides a set of API models loaded by API package name.
|
||||
type APIs map[string]*API
|
||||
|
||||
// LoadAPIs loads the API model files from disk returning the map of API
|
||||
// package. Returns error if multiple API model resolve to the same package
|
||||
// name.
|
||||
func LoadAPIs(modelPaths []string, baseImport string) (APIs, error) {
|
||||
apis := APIs{}
|
||||
for _, modelPath := range modelPaths {
|
||||
a, err := loadAPI(modelPath, baseImport)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load API, %v, %v", modelPath, err)
|
||||
}
|
||||
importPath := a.ImportPath()
|
||||
if _, ok := apis[importPath]; ok {
|
||||
return nil, fmt.Errorf(
|
||||
"package names must be unique attempted to load %v twice. Second model file: %v",
|
||||
importPath, modelPath)
|
||||
}
|
||||
apis[importPath] = a
|
||||
}
|
||||
|
||||
return apis, nil
|
||||
}
|
||||
|
||||
func loadAPI(modelPath, baseImport string) (*API, error) {
|
||||
a := &API{
|
||||
BaseImportPath: baseImport,
|
||||
BaseCrosslinkURL: "https://docs.aws.amazon.com",
|
||||
}
|
||||
|
||||
modelFile := filepath.Base(modelPath)
|
||||
modelDir := filepath.Dir(modelPath)
|
||||
err := attachModelFiles(modelDir,
|
||||
modelLoader{modelFile, a.Attach, true},
|
||||
modelLoader{"docs-2.json", a.AttachDocs, false},
|
||||
modelLoader{"paginators-1.json", a.AttachPaginators, false},
|
||||
modelLoader{"waiters-2.json", a.AttachWaiters, false},
|
||||
modelLoader{"examples-1.json", a.AttachExamples, false},
|
||||
modelLoader{"smoke.json", a.AttachSmokeTests, false},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
a.Setup()
|
||||
|
||||
return a, nil
|
||||
}
|
||||
|
||||
type modelLoader struct {
|
||||
Filename string
|
||||
Loader func(string)
|
||||
Required bool
|
||||
}
|
||||
|
||||
func attachModelFiles(modelPath string, modelFiles ...modelLoader) error {
|
||||
for _, m := range modelFiles {
|
||||
filepath := filepath.Join(modelPath, m.Filename)
|
||||
_, err := os.Stat(filepath)
|
||||
if os.IsNotExist(err) && !m.Required {
|
||||
continue
|
||||
} else if err != nil {
|
||||
return fmt.Errorf("failed to load model file %v, %v", m.Filename, err)
|
||||
}
|
||||
|
||||
m.Loader(filepath)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExpandModelGlobPath returns a slice of model paths expanded from the glob
|
||||
// pattern passed in. Returns the path of the model file to be loaded. Includes
|
||||
// all versions of a service model.
|
||||
//
|
||||
// e.g:
|
||||
// models/apis/*/*/api-2.json
|
||||
//
|
||||
// Or with specific model file:
|
||||
// models/apis/service/version/api-2.json
|
||||
func ExpandModelGlobPath(globs ...string) ([]string, error) {
|
||||
modelPaths := []string{}
|
||||
|
||||
for _, g := range globs {
|
||||
filepaths, err := filepath.Glob(g)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, p := range filepaths {
|
||||
modelPaths = append(modelPaths, p)
|
||||
}
|
||||
}
|
||||
|
||||
return modelPaths, nil
|
||||
}
|
||||
|
||||
// TrimModelServiceVersions sorts the model paths by service version then
|
||||
// returns recent model versions, and model version excluded.
|
||||
//
|
||||
// Uses the third from last path element to determine unique service. Only one
|
||||
// service version will be included.
|
||||
//
|
||||
// models/apis/service/version/api-2.json
|
||||
func TrimModelServiceVersions(modelPaths []string) (include, exclude []string) {
|
||||
sort.Strings(modelPaths)
|
||||
|
||||
// Remove old API versions from list
|
||||
m := map[string]struct{}{}
|
||||
for i := len(modelPaths) - 1; i >= 0; i-- {
|
||||
// service name is 2nd-to-last component
|
||||
parts := strings.Split(modelPaths[i], string(filepath.Separator))
|
||||
svc := parts[len(parts)-3]
|
||||
|
||||
if _, ok := m[svc]; ok {
|
||||
// Removed unused service version
|
||||
exclude = append(exclude, modelPaths[i])
|
||||
continue
|
||||
}
|
||||
include = append(include, modelPaths[i])
|
||||
m[svc] = struct{}{}
|
||||
}
|
||||
|
||||
return include, exclude
|
||||
}
|
||||
|
||||
// Attach opens a file by name, and unmarshal its JSON data.
|
||||
// Will proceed to setup the API if not already done so.
|
||||
func (a *API) Attach(filename string) {
|
||||
@@ -35,19 +163,25 @@ func (a *API) AttachString(str string) {
|
||||
|
||||
// Setup initializes the API.
|
||||
func (a *API) Setup() {
|
||||
a.setServiceAliaseName()
|
||||
a.setMetadataEndpointsKey()
|
||||
a.writeShapeNames()
|
||||
a.resolveReferences()
|
||||
a.fixStutterNames()
|
||||
a.renameExportable()
|
||||
if !a.NoRenameToplevelShapes {
|
||||
a.renameToplevelShapes()
|
||||
|
||||
if !a.NoRemoveUnusedShapes {
|
||||
a.removeUnusedShapes()
|
||||
}
|
||||
|
||||
a.fixStutterNames()
|
||||
a.renameExportable()
|
||||
a.applyShapeNameAliases()
|
||||
a.createInputOutputShapes()
|
||||
a.renameAPIPayloadShapes()
|
||||
a.renameCollidingFields()
|
||||
a.updateTopLevelShapeReferences()
|
||||
a.createInputOutputShapes()
|
||||
a.suppressEventStreams()
|
||||
a.setupEventStreams()
|
||||
a.findEndpointDiscoveryOp()
|
||||
a.injectUnboundedOutputStreaming()
|
||||
a.customizationPasses()
|
||||
|
||||
if !a.NoRemoveUnusedShapes {
|
||||
|
||||
+45
-1
@@ -1,8 +1,11 @@
|
||||
// +build 1.6,codegen
|
||||
// +build codegen
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -30,3 +33,44 @@ func TestResolvedReferences(t *testing.T) {
|
||||
t.Errorf("Expected %d, but received %d", 2, len(a.Shapes["OtherTest"].refs))
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrimModelServiceVersions(t *testing.T) {
|
||||
cases := []struct {
|
||||
Paths []string
|
||||
Include []string
|
||||
Exclude []string
|
||||
}{
|
||||
{
|
||||
Paths: []string{
|
||||
filepath.Join("foo", "baz", "2018-01-02", "api-2.json"),
|
||||
filepath.Join("foo", "baz", "2019-01-02", "api-2.json"),
|
||||
filepath.Join("foo", "baz", "2017-01-02", "api-2.json"),
|
||||
filepath.Join("foo", "bar", "2019-01-02", "api-2.json"),
|
||||
filepath.Join("foo", "bar", "2013-04-02", "api-2.json"),
|
||||
filepath.Join("foo", "bar", "2019-01-03", "api-2.json"),
|
||||
},
|
||||
Include: []string{
|
||||
filepath.Join("foo", "baz", "2019-01-02", "api-2.json"),
|
||||
filepath.Join("foo", "bar", "2019-01-03", "api-2.json"),
|
||||
},
|
||||
Exclude: []string{
|
||||
filepath.Join("foo", "baz", "2018-01-02", "api-2.json"),
|
||||
filepath.Join("foo", "baz", "2017-01-02", "api-2.json"),
|
||||
filepath.Join("foo", "bar", "2019-01-02", "api-2.json"),
|
||||
filepath.Join("foo", "bar", "2013-04-02", "api-2.json"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||
include, exclude := TrimModelServiceVersions(c.Paths)
|
||||
if e, a := c.Include, include; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("expect include %v, got %v", e, a)
|
||||
}
|
||||
if e, a := c.Exclude, exclude; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("expect exclude %v, got %v", e, a)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// +build codegen
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var debugLogger *logger
|
||||
var initDebugLoggerOnce sync.Once
|
||||
|
||||
// logger provides a basic logging
|
||||
type logger struct {
|
||||
w io.Writer
|
||||
}
|
||||
|
||||
// LogDebug initialize's the debug logger for the components in the api
|
||||
// package to log debug lines to.
|
||||
//
|
||||
// Panics if called multiple times.
|
||||
//
|
||||
// Must be used prior to any model loading or code gen.
|
||||
func LogDebug(w io.Writer) {
|
||||
var initialized bool
|
||||
initDebugLoggerOnce.Do(func() {
|
||||
debugLogger = &logger{
|
||||
w: w,
|
||||
}
|
||||
initialized = true
|
||||
})
|
||||
|
||||
if !initialized && debugLogger != nil {
|
||||
panic("LogDebug called multiple times. Can only be called once")
|
||||
}
|
||||
}
|
||||
|
||||
// Logf logs using the fmt printf pattern. Appends a new line to the end of the
|
||||
// logged statement.
|
||||
func (l *logger) Logf(format string, args ...interface{}) {
|
||||
if l == nil {
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(l.w, format+"\n", args...)
|
||||
}
|
||||
|
||||
// Logln logs using the fmt println pattern.
|
||||
func (l *logger) Logln(args ...interface{}) {
|
||||
if l == nil {
|
||||
return
|
||||
}
|
||||
fmt.Fprintln(l.w, args...)
|
||||
}
|
||||
+261
-32
@@ -13,18 +13,58 @@ import (
|
||||
|
||||
// An Operation defines a specific API Operation.
|
||||
type Operation struct {
|
||||
API *API `json:"-"`
|
||||
ExportedName string
|
||||
Name string
|
||||
Documentation string
|
||||
HTTP HTTPInfo
|
||||
InputRef ShapeRef `json:"input"`
|
||||
OutputRef ShapeRef `json:"output"`
|
||||
ErrorRefs []ShapeRef `json:"errors"`
|
||||
Paginator *Paginator
|
||||
Deprecated bool `json:"deprecated"`
|
||||
AuthType string `json:"authtype"`
|
||||
imports map[string]bool
|
||||
API *API `json:"-"`
|
||||
ExportedName string
|
||||
Name string
|
||||
Documentation string
|
||||
HTTP HTTPInfo
|
||||
Host string `json:"host"`
|
||||
InputRef ShapeRef `json:"input"`
|
||||
OutputRef ShapeRef `json:"output"`
|
||||
ErrorRefs []ShapeRef `json:"errors"`
|
||||
Paginator *Paginator
|
||||
Deprecated bool `json:"deprecated"`
|
||||
DeprecatedMsg string `json:"deprecatedMessage"`
|
||||
AuthType AuthType `json:"authtype"`
|
||||
imports map[string]bool
|
||||
CustomBuildHandlers []string
|
||||
|
||||
EventStreamAPI *EventStreamAPI
|
||||
|
||||
IsEndpointDiscoveryOp bool `json:"endpointoperation"`
|
||||
EndpointDiscovery *EndpointDiscovery `json:"endpointdiscovery"`
|
||||
Endpoint *EndpointTrait `json:"endpoint"`
|
||||
}
|
||||
|
||||
// EndpointTrait provides the structure of the modeled enpdoint trait, and its
|
||||
// properties.
|
||||
type EndpointTrait struct {
|
||||
// Specifies the hostPrefix template to prepend to the operation's request
|
||||
// endpoint host.
|
||||
HostPrefix string `json:"hostPrefix"`
|
||||
}
|
||||
|
||||
// EndpointDiscovery represents a map of key values pairs that represents
|
||||
// metadata about how a given API will make a call to the discovery endpoint.
|
||||
type EndpointDiscovery struct {
|
||||
// Required indicates that for a given operation that endpoint is required.
|
||||
// Any required endpoint discovery operation cannot have endpoint discovery
|
||||
// turned off.
|
||||
Required bool `json:"required"`
|
||||
}
|
||||
|
||||
// OperationForMethod returns the API operation name that corresponds to the
|
||||
// client method name provided.
|
||||
func (a *API) OperationForMethod(name string) *Operation {
|
||||
for _, op := range a.Operations {
|
||||
for _, m := range op.Methods() {
|
||||
if m == name {
|
||||
return op
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// A HTTPInfo defines the method of HTTP request for the Operation.
|
||||
@@ -34,6 +74,24 @@ type HTTPInfo struct {
|
||||
ResponseCode uint
|
||||
}
|
||||
|
||||
// Methods Returns a list of method names that will be generated.
|
||||
func (o *Operation) Methods() []string {
|
||||
methods := []string{
|
||||
o.ExportedName,
|
||||
o.ExportedName + "Request",
|
||||
o.ExportedName + "WithContext",
|
||||
}
|
||||
|
||||
if o.Paginator != nil {
|
||||
methods = append(methods, []string{
|
||||
o.ExportedName + "Pages",
|
||||
o.ExportedName + "PagesWithContext",
|
||||
}...)
|
||||
}
|
||||
|
||||
return methods
|
||||
}
|
||||
|
||||
// HasInput returns if the Operation accepts an input paramater
|
||||
func (o *Operation) HasInput() bool {
|
||||
return o.InputRef.ShapeName != ""
|
||||
@@ -44,17 +102,27 @@ func (o *Operation) HasOutput() bool {
|
||||
return o.OutputRef.ShapeName != ""
|
||||
}
|
||||
|
||||
func (o *Operation) GetSigner() string {
|
||||
if o.AuthType == "v4-unsigned-body" {
|
||||
o.API.imports["github.com/aws/aws-sdk-go/aws/signer/v4"] = true
|
||||
}
|
||||
// AuthType provides the enumeration of AuthType trait.
|
||||
type AuthType string
|
||||
|
||||
// Enumeration values for AuthType trait
|
||||
const (
|
||||
NoneAuthType AuthType = "none"
|
||||
V4UnsignedBodyAuthType AuthType = "v4-unsigned-body"
|
||||
)
|
||||
|
||||
// GetSigner returns the signer that should be used for a API request.
|
||||
func (o *Operation) GetSigner() string {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
|
||||
switch o.AuthType {
|
||||
case "none":
|
||||
case NoneAuthType:
|
||||
o.API.AddSDKImport("aws/credentials")
|
||||
|
||||
buf.WriteString("req.Config.Credentials = credentials.AnonymousCredentials")
|
||||
case "v4-unsigned-body":
|
||||
case V4UnsignedBodyAuthType:
|
||||
o.API.AddSDKImport("aws/signer/v4")
|
||||
|
||||
buf.WriteString("req.Handlers.Sign.Remove(v4.SignRequestHandler)\n")
|
||||
buf.WriteString("handler := v4.BuildNamedHandler(\"v4.CustomSignerHandler\", v4.WithUnsignedPayload)\n")
|
||||
buf.WriteString("req.Handlers.Sign.PushFrontNamed(handler)")
|
||||
@@ -64,16 +132,18 @@ func (o *Operation) GetSigner() string {
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// tplOperation defines a template for rendering an API Operation
|
||||
var tplOperation = template.Must(template.New("operation").Funcs(template.FuncMap{
|
||||
"GetCrosslinkURL": GetCrosslinkURL,
|
||||
// operationTmpl defines a template for rendering an API Operation
|
||||
var operationTmpl = template.Must(template.New("operation").Funcs(template.FuncMap{
|
||||
"GetCrosslinkURL": GetCrosslinkURL,
|
||||
"EnableStopOnSameToken": enableStopOnSameToken,
|
||||
"GetDeprecatedMsg": getDeprecatedMessage,
|
||||
}).Parse(`
|
||||
const op{{ .ExportedName }} = "{{ .Name }}"
|
||||
|
||||
// {{ .ExportedName }}Request generates a "aws/request.Request" representing the
|
||||
// client's request for the {{ .ExportedName }} operation. The "output" return
|
||||
// value will be populated with the request's response once the request completes
|
||||
// successfuly.
|
||||
// successfully.
|
||||
//
|
||||
// Use "Send" method on the returned Request to send the API call to the service.
|
||||
// the "output" return value is not valid until after Send returns without error.
|
||||
@@ -93,16 +163,19 @@ const op{{ .ExportedName }} = "{{ .Name }}"
|
||||
// fmt.Println(resp)
|
||||
// }
|
||||
{{ $crosslinkURL := GetCrosslinkURL $.API.BaseCrosslinkURL $.API.Metadata.UID $.ExportedName -}}
|
||||
{{ if ne $crosslinkURL "" -}}
|
||||
{{ if ne $crosslinkURL "" -}}
|
||||
//
|
||||
// See also, {{ $crosslinkURL }}
|
||||
{{ end -}}
|
||||
{{- if .Deprecated }}//
|
||||
// Deprecated: {{ GetDeprecatedMsg .DeprecatedMsg .ExportedName }}
|
||||
{{ end -}}
|
||||
func (c *{{ .API.StructName }}) {{ .ExportedName }}Request(` +
|
||||
`input {{ .InputRef.GoType }}) (req *request.Request, output {{ .OutputRef.GoType }}) {
|
||||
{{ if (or .Deprecated (or .InputRef.Deprecated .OutputRef.Deprecated)) }}if c.Client.Config.Logger != nil {
|
||||
c.Client.Config.Logger.Log("This operation, {{ .ExportedName }}, has been deprecated")
|
||||
}
|
||||
op := &request.Operation{ {{ else }} op := &request.Operation{ {{ end }}
|
||||
op := &request.Operation{ {{ else }} op := &request.Operation{ {{ end }}
|
||||
Name: op{{ .ExportedName }},
|
||||
{{ if ne .HTTP.Method "" }}HTTPMethod: "{{ .HTTP.Method }}",
|
||||
{{ end }}HTTPPath: {{ if ne .HTTP.RequestURI "" }}"{{ .HTTP.RequestURI }}"{{ else }}"/"{{ end }},
|
||||
@@ -120,10 +193,57 @@ func (c *{{ .API.StructName }}) {{ .ExportedName }}Request(` +
|
||||
}
|
||||
|
||||
output = &{{ .OutputRef.GoTypeElem }}{}
|
||||
req = c.newRequest(op, input, output){{ if eq .OutputRef.Shape.Placeholder true }}
|
||||
req.Handlers.Unmarshal.Remove({{ .API.ProtocolPackage }}.UnmarshalHandler)
|
||||
req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler){{ end }}
|
||||
{{ if ne .AuthType "" }}{{ .GetSigner }}{{ end -}}
|
||||
req = c.newRequest(op, input, output)
|
||||
{{ if ne .AuthType "" }}{{ .GetSigner }}{{ end }}
|
||||
{{- if .ShouldDiscardResponse -}}
|
||||
{{- $_ := .API.AddSDKImport "private/protocol" -}}
|
||||
{{- $_ := .API.AddSDKImport "private/protocol" .API.ProtocolPackage -}}
|
||||
req.Handlers.Unmarshal.Swap({{ .API.ProtocolPackage }}.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
|
||||
{{ else if .OutputRef.Shape.EventStreamsMemberName -}}
|
||||
{{- $_ := .API.AddSDKImport "private/protocol" .API.ProtocolPackage -}}
|
||||
{{- $_ := .API.AddSDKImport "private/protocol/rest" -}}
|
||||
req.Handlers.Send.Swap(client.LogHTTPResponseHandler.Name, client.LogHTTPResponseHeaderHandler)
|
||||
req.Handlers.Unmarshal.Swap({{ .API.ProtocolPackage }}.UnmarshalHandler.Name, rest.UnmarshalHandler)
|
||||
req.Handlers.Unmarshal.PushBack(output.runEventStreamLoop)
|
||||
{{ if eq .API.Metadata.Protocol "json" -}}
|
||||
req.Handlers.Unmarshal.PushBack(output.unmarshalInitialResponse)
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{ if .EndpointDiscovery -}}
|
||||
{{if not .EndpointDiscovery.Required -}}
|
||||
if aws.BoolValue(req.Config.EnableEndpointDiscovery) {
|
||||
{{end -}}
|
||||
de := discoverer{{ .API.EndpointDiscoveryOp.Name }}{
|
||||
Required: {{ .EndpointDiscovery.Required }},
|
||||
EndpointCache: c.endpointCache,
|
||||
Params: map[string]*string{
|
||||
"op": aws.String(req.Operation.Name),
|
||||
{{ range $key, $ref := .InputRef.Shape.MemberRefs -}}
|
||||
{{ if $ref.EndpointDiscoveryID -}}
|
||||
"{{ $ref.OrigShapeName }}": input.{{ $key }},
|
||||
{{ end -}}
|
||||
{{- end }}
|
||||
},
|
||||
Client: c,
|
||||
}
|
||||
|
||||
for k, v := range de.Params {
|
||||
if v == nil {
|
||||
delete(de.Params, k)
|
||||
}
|
||||
}
|
||||
|
||||
req.Handlers.Build.PushFrontNamed(request.NamedHandler{
|
||||
Name: "crr.endpointdiscovery",
|
||||
Fn: de.Handler,
|
||||
})
|
||||
{{if not .EndpointDiscovery.Required -}}
|
||||
}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{- range $_, $handler := $.CustomBuildHandlers -}}
|
||||
req.Handlers.Build.PushBackNamed({{ $handler }})
|
||||
{{ end -}}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -151,9 +271,12 @@ func (c *{{ .API.StructName }}) {{ .ExportedName }}Request(` +
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{ $crosslinkURL := GetCrosslinkURL $.API.BaseCrosslinkURL $.API.Metadata.UID $.ExportedName -}}
|
||||
{{ if ne $crosslinkURL "" -}}
|
||||
{{ if ne $crosslinkURL "" -}}
|
||||
// See also, {{ $crosslinkURL }}
|
||||
{{ end -}}
|
||||
{{- if .Deprecated }}//
|
||||
// Deprecated: {{ GetDeprecatedMsg .DeprecatedMsg .ExportedName }}
|
||||
{{ end -}}
|
||||
func (c *{{ .API.StructName }}) {{ .ExportedName }}(` +
|
||||
`input {{ .InputRef.GoType }}) ({{ .OutputRef.GoType }}, error) {
|
||||
req, out := c.{{ .ExportedName }}Request(input)
|
||||
@@ -169,6 +292,9 @@ func (c *{{ .API.StructName }}) {{ .ExportedName }}(` +
|
||||
// the context is nil a panic will occur. In the future the SDK may create
|
||||
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
|
||||
// for more information on using Contexts.
|
||||
{{ if .Deprecated }}//
|
||||
// Deprecated: {{ GetDeprecatedMsg .DeprecatedMsg (printf "%s%s" .ExportedName "WithContext") }}
|
||||
{{ end -}}
|
||||
func (c *{{ .API.StructName }}) {{ .ExportedName }}WithContext(` +
|
||||
`ctx aws.Context, input {{ .InputRef.GoType }}, opts ...request.Option) ` +
|
||||
`({{ .OutputRef.GoType }}, error) {
|
||||
@@ -190,12 +316,15 @@ func (c *{{ .API.StructName }}) {{ .ExportedName }}WithContext(` +
|
||||
// // Example iterating over at most 3 pages of a {{ .ExportedName }} operation.
|
||||
// pageNum := 0
|
||||
// err := client.{{ .ExportedName }}Pages(params,
|
||||
// func(page {{ .OutputRef.GoType }}, lastPage bool) bool {
|
||||
// func(page {{ .OutputRef.Shape.GoTypeWithPkgName }}, lastPage bool) bool {
|
||||
// pageNum++
|
||||
// fmt.Println(page)
|
||||
// return pageNum <= 3
|
||||
// })
|
||||
//
|
||||
{{ if .Deprecated }}//
|
||||
// Deprecated: {{ GetDeprecatedMsg .DeprecatedMsg (printf "%s%s" .ExportedName "Pages") }}
|
||||
{{ end -}}
|
||||
func (c *{{ .API.StructName }}) {{ .ExportedName }}Pages(` +
|
||||
`input {{ .InputRef.GoType }}, fn func({{ .OutputRef.GoType }}, bool) bool) error {
|
||||
return c.{{ .ExportedName }}PagesWithContext(aws.BackgroundContext(), input, fn)
|
||||
@@ -208,12 +337,17 @@ func (c *{{ .API.StructName }}) {{ .ExportedName }}Pages(` +
|
||||
// the context is nil a panic will occur. In the future the SDK may create
|
||||
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
|
||||
// for more information on using Contexts.
|
||||
{{ if .Deprecated }}//
|
||||
// Deprecated: {{ GetDeprecatedMsg .DeprecatedMsg (printf "%s%s" .ExportedName "PagesWithContext") }}
|
||||
{{ end -}}
|
||||
func (c *{{ .API.StructName }}) {{ .ExportedName }}PagesWithContext(` +
|
||||
`ctx aws.Context, ` +
|
||||
`input {{ .InputRef.GoType }}, ` +
|
||||
`fn func({{ .OutputRef.GoType }}, bool) bool, ` +
|
||||
`opts ...request.Option) error {
|
||||
p := request.Pagination {
|
||||
{{ if EnableStopOnSameToken .API.PackageName -}}EndPageOnSameToken: true,
|
||||
{{ end -}}
|
||||
NewRequest: func() (*request.Request, error) {
|
||||
var inCpy {{ .InputRef.GoType }}
|
||||
if input != nil {
|
||||
@@ -234,12 +368,100 @@ func (c *{{ .API.StructName }}) {{ .ExportedName }}PagesWithContext(` +
|
||||
return p.Err()
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ if .IsEndpointDiscoveryOp -}}
|
||||
|
||||
type discoverer{{ .ExportedName }} struct {
|
||||
Client *{{ .API.StructName }}
|
||||
Required bool
|
||||
EndpointCache *crr.EndpointCache
|
||||
Params map[string]*string
|
||||
Key string
|
||||
}
|
||||
|
||||
func (d *discoverer{{ .ExportedName }}) Discover() (crr.Endpoint, error) {
|
||||
input := &{{ .API.EndpointDiscoveryOp.InputRef.ShapeName }}{
|
||||
{{ if .API.EndpointDiscoveryOp.InputRef.Shape.HasMember "Operation" -}}
|
||||
Operation: d.Params["op"],
|
||||
{{ end -}}
|
||||
{{ if .API.EndpointDiscoveryOp.InputRef.Shape.HasMember "Identifiers" -}}
|
||||
Identifiers: d.Params,
|
||||
{{ end -}}
|
||||
}
|
||||
|
||||
resp, err := d.Client.{{ .API.EndpointDiscoveryOp.Name }}(input)
|
||||
if err != nil {
|
||||
return crr.Endpoint{}, err
|
||||
}
|
||||
|
||||
endpoint := crr.Endpoint{
|
||||
Key: d.Key,
|
||||
}
|
||||
|
||||
for _, e := range resp.Endpoints {
|
||||
if e.Address == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
cachedInMinutes := aws.Int64Value(e.CachePeriodInMinutes)
|
||||
u, err := url.Parse(*e.Address)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
addr := crr.WeightedAddress{
|
||||
URL: u,
|
||||
Expired: time.Now().Add(time.Duration(cachedInMinutes) * time.Minute),
|
||||
}
|
||||
|
||||
endpoint.Add(addr)
|
||||
}
|
||||
|
||||
d.EndpointCache.Add(endpoint)
|
||||
|
||||
return endpoint, nil
|
||||
}
|
||||
|
||||
func (d *discoverer{{ .ExportedName }}) Handler(r *request.Request) {
|
||||
endpointKey := crr.BuildEndpointKey(d.Params)
|
||||
d.Key = endpointKey
|
||||
|
||||
endpoint, err := d.EndpointCache.Get(d, endpointKey, d.Required)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return
|
||||
}
|
||||
|
||||
if endpoint.URL != nil && len(endpoint.URL.String()) > 0 {
|
||||
r.HTTPRequest.URL = endpoint.URL
|
||||
}
|
||||
}
|
||||
{{ end -}}
|
||||
|
||||
`))
|
||||
|
||||
// GoCode returns a string of rendered GoCode for this Operation
|
||||
func (o *Operation) GoCode() string {
|
||||
var buf bytes.Buffer
|
||||
err := tplOperation.Execute(&buf, o)
|
||||
|
||||
if len(o.OutputRef.Shape.EventStreamsMemberName) != 0 {
|
||||
o.API.AddSDKImport("aws/client")
|
||||
o.API.AddSDKImport("private/protocol")
|
||||
o.API.AddSDKImport("private/protocol/rest")
|
||||
o.API.AddSDKImport("private/protocol", o.API.ProtocolPackage())
|
||||
}
|
||||
|
||||
if o.API.EndpointDiscoveryOp != nil {
|
||||
o.API.AddSDKImport("aws/crr")
|
||||
o.API.AddImport("time")
|
||||
o.API.AddImport("net/url")
|
||||
}
|
||||
|
||||
if o.Endpoint != nil && len(o.Endpoint.HostPrefix) != 0 {
|
||||
setupEndpointHostPrefix(o)
|
||||
}
|
||||
|
||||
err := operationTmpl.Execute(&buf, o)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -308,7 +530,7 @@ func (o *Operation) Example() string {
|
||||
func (o *Operation) ExampleInput() string {
|
||||
if len(o.InputRef.Shape.MemberRefs) == 0 {
|
||||
if strings.Contains(o.InputRef.GoTypeElem(), ".") {
|
||||
o.imports["github.com/aws/aws-sdk-go/service/"+strings.Split(o.InputRef.GoTypeElem(), ".")[0]] = true
|
||||
o.imports[SDKImportRoot+"service/"+strings.Split(o.InputRef.GoTypeElem(), ".")[0]] = true
|
||||
return fmt.Sprintf("var params *%s", o.InputRef.GoTypeElem())
|
||||
}
|
||||
return fmt.Sprintf("var params *%s.%s",
|
||||
@@ -318,6 +540,13 @@ func (o *Operation) ExampleInput() string {
|
||||
return "params := " + e.traverseAny(o.InputRef.Shape, false, false)
|
||||
}
|
||||
|
||||
// ShouldDiscardResponse returns if the operation should discard the response
|
||||
// returned by the service.
|
||||
func (o *Operation) ShouldDiscardResponse() bool {
|
||||
s := o.OutputRef.Shape
|
||||
return s.Placeholder || len(s.MemberRefs) == 0
|
||||
}
|
||||
|
||||
// A example provides
|
||||
type example struct {
|
||||
*Operation
|
||||
|
||||
+9
@@ -89,3 +89,12 @@ func (p *paginationDefinitions) setup() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func enableStopOnSameToken(service string) bool {
|
||||
switch service {
|
||||
case "cloudwatchlogs":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
@@ -83,7 +83,7 @@ func (f paramFiller) paramsStructAny(value interface{}, shape *Shape) string {
|
||||
case "jsonvalue":
|
||||
v, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
panic("failed to marshal JSONValue, "+err.Error())
|
||||
panic("failed to marshal JSONValue, " + err.Error())
|
||||
}
|
||||
const tmpl = `func() aws.JSONValue {
|
||||
var m aws.JSONValue
|
||||
|
||||
+115
-61
@@ -58,7 +58,8 @@ func (a *API) resolveReferences() {
|
||||
// Resolve references for errors also
|
||||
for i := range o.ErrorRefs {
|
||||
resolver.resolveReference(&o.ErrorRefs[i])
|
||||
o.ErrorRefs[i].Shape.IsError = true
|
||||
o.ErrorRefs[i].Shape.Exception = true
|
||||
o.ErrorRefs[i].Shape.ErrorInfo.Type = o.ErrorRefs[i].Shape.ShapeName
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,14 +71,6 @@ type referenceResolver struct {
|
||||
visited map[*ShapeRef]bool
|
||||
}
|
||||
|
||||
var jsonvalueShape = &Shape{
|
||||
ShapeName: "JSONValue",
|
||||
Type: "jsonvalue",
|
||||
ValueRef: ShapeRef{
|
||||
JSONValue: true,
|
||||
},
|
||||
}
|
||||
|
||||
// resolveReference updates a shape reference to reference the API and
|
||||
// its shape definition. All other nested references are also resolved.
|
||||
func (r *referenceResolver) resolveReference(ref *ShapeRef) {
|
||||
@@ -88,12 +81,20 @@ func (r *referenceResolver) resolveReference(ref *ShapeRef) {
|
||||
shape, ok := r.API.Shapes[ref.ShapeName]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("unable resolve reference, %s", ref.ShapeName))
|
||||
return
|
||||
}
|
||||
|
||||
if ref.JSONValue {
|
||||
ref.ShapeName = "JSONValue"
|
||||
r.API.Shapes[ref.ShapeName] = jsonvalueShape
|
||||
if _, ok := r.API.Shapes[ref.ShapeName]; !ok {
|
||||
r.API.Shapes[ref.ShapeName] = &Shape{
|
||||
API: r.API,
|
||||
ShapeName: "JSONValue",
|
||||
Type: "jsonvalue",
|
||||
ValueRef: ShapeRef{
|
||||
JSONValue: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ref.API = r.API // resolve reference back to API
|
||||
@@ -121,40 +122,6 @@ func (r *referenceResolver) resolveShape(shape *Shape) {
|
||||
}
|
||||
}
|
||||
|
||||
// renameToplevelShapes renames all top level shapes of an API to their
|
||||
// exportable variant. The shapes are also updated to include notations
|
||||
// if they are Input or Outputs.
|
||||
func (a *API) renameToplevelShapes() {
|
||||
for _, v := range a.OperationList() {
|
||||
if v.HasInput() {
|
||||
name := v.ExportedName + "Input"
|
||||
switch {
|
||||
case a.Shapes[name] == nil:
|
||||
if service, ok := shamelist[a.name]; ok {
|
||||
if check, ok := service[v.Name]; ok && check.input {
|
||||
break
|
||||
}
|
||||
}
|
||||
v.InputRef.Shape.Rename(name)
|
||||
}
|
||||
}
|
||||
if v.HasOutput() {
|
||||
name := v.ExportedName + "Output"
|
||||
switch {
|
||||
case a.Shapes[name] == nil:
|
||||
if service, ok := shamelist[a.name]; ok {
|
||||
if check, ok := service[v.Name]; ok && check.output {
|
||||
break
|
||||
}
|
||||
}
|
||||
v.OutputRef.Shape.Rename(name)
|
||||
}
|
||||
}
|
||||
v.InputRef.Payload = a.ExportableName(v.InputRef.Payload)
|
||||
v.OutputRef.Payload = a.ExportableName(v.OutputRef.Payload)
|
||||
}
|
||||
}
|
||||
|
||||
// fixStutterNames fixes all name struttering based on Go naming conventions.
|
||||
// "Stuttering" is when the prefix of a structure or function matches the
|
||||
// package name (case insensitive).
|
||||
@@ -205,6 +172,10 @@ func (a *API) renameExportable() {
|
||||
}
|
||||
|
||||
for mName, member := range s.MemberRefs {
|
||||
ref := s.MemberRefs[mName]
|
||||
ref.OrigShapeName = mName
|
||||
s.MemberRefs[mName] = ref
|
||||
|
||||
newName := a.ExportableName(mName)
|
||||
if newName != mName {
|
||||
delete(s.MemberRefs, mName)
|
||||
@@ -254,28 +225,26 @@ func (a *API) renameCollidingFields() {
|
||||
for _, v := range a.Shapes {
|
||||
namesWithSet := map[string]struct{}{}
|
||||
for k, field := range v.MemberRefs {
|
||||
if strings.HasPrefix(k, "Set") {
|
||||
namesWithSet[k] = struct{}{}
|
||||
if _, ok := v.MemberRefs["Set"+k]; ok {
|
||||
namesWithSet["Set"+k] = struct{}{}
|
||||
}
|
||||
|
||||
if collides(k) {
|
||||
if collides(k) || (v.Exception && exceptionCollides(k)) {
|
||||
renameCollidingField(k, v, field)
|
||||
}
|
||||
}
|
||||
|
||||
// checks if any field names collide with setters.
|
||||
for name := range namesWithSet {
|
||||
if field, ok := v.MemberRefs["Set"+name]; ok {
|
||||
renameCollidingField(name, v, field)
|
||||
}
|
||||
field := v.MemberRefs[name]
|
||||
renameCollidingField(name, v, field)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func renameCollidingField(name string, v *Shape, field *ShapeRef) {
|
||||
newName := name + "_"
|
||||
fmt.Printf("Shape %s's field %q renamed to %q\n", v.ShapeName, name, newName)
|
||||
debugLogger.Logf("Shape %s's field %q renamed to %q", v.ShapeName, name, newName)
|
||||
delete(v.MemberRefs, name)
|
||||
v.MemberRefs[newName] = field
|
||||
}
|
||||
@@ -287,8 +256,32 @@ func collides(name string) bool {
|
||||
"GoString",
|
||||
"Validate":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func exceptionCollides(name string) bool {
|
||||
switch name {
|
||||
case "Code",
|
||||
"Message",
|
||||
"OrigErr":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *API) applyShapeNameAliases() {
|
||||
service, ok := shapeNameAliases[a.name]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// Generic Shape Aliases
|
||||
for name, s := range a.Shapes {
|
||||
if alias, ok := service[name]; ok {
|
||||
s.Rename(alias)
|
||||
s.AliasedShapeName = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,15 +290,47 @@ func collides(name string) bool {
|
||||
// have an input and output structure in the signature.
|
||||
func (a *API) createInputOutputShapes() {
|
||||
for _, op := range a.Operations {
|
||||
if !op.HasInput() {
|
||||
setAsPlacholderShape(&op.InputRef, op.ExportedName+"Input", a)
|
||||
}
|
||||
if !op.HasOutput() {
|
||||
setAsPlacholderShape(&op.OutputRef, op.ExportedName+"Output", a)
|
||||
}
|
||||
createAPIParamShape(a, op.Name, &op.InputRef, op.ExportedName+"Input",
|
||||
shamelist.Input,
|
||||
)
|
||||
createAPIParamShape(a, op.Name, &op.OutputRef, op.ExportedName+"Output",
|
||||
shamelist.Output,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) renameAPIPayloadShapes() {
|
||||
for _, op := range a.Operations {
|
||||
op.InputRef.Payload = a.ExportableName(op.InputRef.Payload)
|
||||
op.OutputRef.Payload = a.ExportableName(op.OutputRef.Payload)
|
||||
}
|
||||
}
|
||||
|
||||
func createAPIParamShape(a *API, opName string, ref *ShapeRef, shapeName string, shamelistLookup func(string, string) bool) {
|
||||
if len(ref.ShapeName) == 0 {
|
||||
setAsPlacholderShape(ref, shapeName, a)
|
||||
return
|
||||
}
|
||||
|
||||
// nothing to do if already the correct name.
|
||||
if s := ref.Shape; s.AliasedShapeName || s.ShapeName == shapeName || shamelistLookup(a.name, opName) {
|
||||
return
|
||||
}
|
||||
|
||||
if s, ok := a.Shapes[shapeName]; ok {
|
||||
panic(fmt.Sprintf(
|
||||
"attempting to create duplicate API parameter shape, %v, %v, %v, %v\n",
|
||||
shapeName, opName, ref.ShapeName, s.OrigShapeName,
|
||||
))
|
||||
}
|
||||
|
||||
ref.Shape.removeRef(ref)
|
||||
ref.OrigShapeName = shapeName
|
||||
ref.ShapeName = shapeName
|
||||
ref.Shape = ref.Shape.Clone(shapeName)
|
||||
ref.Shape.refs = append(ref.Shape.refs, ref)
|
||||
}
|
||||
|
||||
func setAsPlacholderShape(tgtShapeRef *ShapeRef, name string, a *API) {
|
||||
shape := a.makeIOShape(name)
|
||||
shape.Placeholder = true
|
||||
@@ -352,3 +377,32 @@ func (a *API) setMetadataEndpointsKey() {
|
||||
a.Metadata.EndpointsID = a.Metadata.EndpointPrefix
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) findEndpointDiscoveryOp() {
|
||||
for _, op := range a.Operations {
|
||||
if op.IsEndpointDiscoveryOp {
|
||||
a.EndpointDiscoveryOp = op
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
func (a *API) injectUnboundedOutputStreaming() {
|
||||
for _, op := range a.Operations {
|
||||
if op.AuthType != V4UnsignedBodyAuthType {
|
||||
continue
|
||||
}
|
||||
for _, ref := range op.InputRef.Shape.MemberRefs {
|
||||
if ref.Streaming || ref.Shape.Streaming {
|
||||
if len(ref.Documentation) != 0 {
|
||||
ref.Documentation += `
|
||||
//`
|
||||
}
|
||||
ref.Documentation += `
|
||||
// To use an non-seekable io.Reader for this request wrap the io.Reader with
|
||||
// "aws.ReadSeekCloser". The SDK will not retry request errors for non-seekable
|
||||
// readers. This will allow the SDK to send the reader's payload as chunked
|
||||
// transfer encoding.`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+461
-111
@@ -1,35 +1,35 @@
|
||||
// +build 1.6,codegen
|
||||
// +build go1.8,codegen
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUniqueInputAndOutputs(t *testing.T) {
|
||||
shamelist["FooService"] = map[string]struct {
|
||||
input bool
|
||||
output bool
|
||||
}{}
|
||||
v := shamelist["FooService"]["OpOutputNoRename"]
|
||||
v.output = true
|
||||
shamelist["FooService"]["OpOutputNoRename"] = v
|
||||
v = shamelist["FooService"]["InputNoRename"]
|
||||
v.input = true
|
||||
shamelist["FooService"]["OpInputNoRename"] = v
|
||||
v = shamelist["FooService"]["BothNoRename"]
|
||||
v.input = true
|
||||
v.output = true
|
||||
shamelist["FooService"]["OpBothNoRename"] = v
|
||||
const serviceName = "FooService"
|
||||
|
||||
shamelist[serviceName] = map[string]persistAPIType{
|
||||
"OpOutputNoRename": {
|
||||
output: true,
|
||||
},
|
||||
"OpInputNoRename": {
|
||||
input: true,
|
||||
},
|
||||
"OpBothNoRename": {
|
||||
input: true,
|
||||
output: true,
|
||||
},
|
||||
}
|
||||
|
||||
cases := [][]struct {
|
||||
expectedInput string
|
||||
expectedOutput string
|
||||
operation string
|
||||
input string
|
||||
inputRef string
|
||||
output string
|
||||
outputRef string
|
||||
}{
|
||||
{
|
||||
{
|
||||
@@ -37,18 +37,14 @@ func TestUniqueInputAndOutputs(t *testing.T) {
|
||||
expectedOutput: "FooOperationOutput",
|
||||
operation: "FooOperation",
|
||||
input: "FooInputShape",
|
||||
inputRef: "FooInputShapeRef",
|
||||
output: "FooOutputShape",
|
||||
outputRef: "FooOutputShapeRef",
|
||||
},
|
||||
{
|
||||
expectedInput: "BarOperationInput",
|
||||
expectedOutput: "BarOperationOutput",
|
||||
operation: "BarOperation",
|
||||
input: "FooInputShape",
|
||||
inputRef: "FooInputShapeRef",
|
||||
output: "FooOutputShape",
|
||||
outputRef: "FooOutputShapeRef",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -57,18 +53,14 @@ func TestUniqueInputAndOutputs(t *testing.T) {
|
||||
expectedOutput: "FooOperationOutput",
|
||||
operation: "FooOperation",
|
||||
input: "FooInputShape",
|
||||
inputRef: "FooInputShapeRef",
|
||||
output: "FooOutputShape",
|
||||
outputRef: "FooOutputShapeRef",
|
||||
},
|
||||
{
|
||||
expectedInput: "OpOutputNoRenameInput",
|
||||
expectedOutput: "OpOutputNoRenameOutputShape",
|
||||
operation: "OpOutputNoRename",
|
||||
input: "OpOutputNoRenameInputShape",
|
||||
inputRef: "OpOutputNoRenameInputRef",
|
||||
output: "OpOutputNoRenameOutputShape",
|
||||
outputRef: "OpOutputNoRenameOutputRef",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -77,18 +69,14 @@ func TestUniqueInputAndOutputs(t *testing.T) {
|
||||
expectedOutput: "FooOperationOutput",
|
||||
operation: "FooOperation",
|
||||
input: "FooInputShape",
|
||||
inputRef: "FooInputShapeRef",
|
||||
output: "FooOutputShape",
|
||||
outputRef: "FooOutputShapeRef",
|
||||
},
|
||||
{
|
||||
expectedInput: "OpInputNoRenameInputShape",
|
||||
expectedOutput: "OpInputNoRenameOutput",
|
||||
operation: "OpInputNoRename",
|
||||
input: "OpInputNoRenameInputShape",
|
||||
inputRef: "OpInputNoRenameInputRef",
|
||||
output: "OpInputNoRenameOutputShape",
|
||||
outputRef: "OpInputNoRenameOutputRef",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -97,115 +85,477 @@ func TestUniqueInputAndOutputs(t *testing.T) {
|
||||
expectedOutput: "FooOperationOutput",
|
||||
operation: "FooOperation",
|
||||
input: "FooInputShape",
|
||||
inputRef: "FooInputShapeRef",
|
||||
output: "FooOutputShape",
|
||||
outputRef: "FooOutputShapeRef",
|
||||
},
|
||||
{
|
||||
expectedInput: "OpInputNoRenameInputShape",
|
||||
expectedOutput: "OpInputNoRenameOutputShape",
|
||||
operation: "OpBothNoRename",
|
||||
input: "OpInputNoRenameInputShape",
|
||||
inputRef: "OpInputNoRenameInputRef",
|
||||
output: "OpInputNoRenameOutputShape",
|
||||
outputRef: "OpInputNoRenameOutputRef",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
a := &API{
|
||||
name: "FooService",
|
||||
Operations: map[string]*Operation{},
|
||||
}
|
||||
|
||||
expected := map[string][]string{}
|
||||
a.Shapes = map[string]*Shape{}
|
||||
for _, op := range c {
|
||||
a.Operations[op.operation] = &Operation{
|
||||
ExportedName: op.operation,
|
||||
}
|
||||
a.Operations[op.operation].Name = op.operation
|
||||
a.Operations[op.operation].InputRef = ShapeRef{
|
||||
API: a,
|
||||
ShapeName: op.inputRef,
|
||||
Shape: &Shape{
|
||||
API: a,
|
||||
ShapeName: op.input,
|
||||
},
|
||||
}
|
||||
a.Operations[op.operation].OutputRef = ShapeRef{
|
||||
API: a,
|
||||
ShapeName: op.outputRef,
|
||||
Shape: &Shape{
|
||||
API: a,
|
||||
ShapeName: op.output,
|
||||
},
|
||||
for i, c := range cases {
|
||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||
a := &API{
|
||||
name: serviceName,
|
||||
Operations: map[string]*Operation{},
|
||||
Shapes: map[string]*Shape{},
|
||||
}
|
||||
|
||||
a.Shapes[op.input] = &Shape{
|
||||
ShapeName: op.input,
|
||||
}
|
||||
a.Shapes[op.output] = &Shape{
|
||||
ShapeName: op.output,
|
||||
expected := map[string][]string{}
|
||||
for _, op := range c {
|
||||
o := &Operation{
|
||||
Name: op.operation,
|
||||
ExportedName: op.operation,
|
||||
InputRef: ShapeRef{
|
||||
API: a,
|
||||
ShapeName: op.input,
|
||||
Shape: &Shape{
|
||||
API: a,
|
||||
ShapeName: op.input,
|
||||
},
|
||||
},
|
||||
OutputRef: ShapeRef{
|
||||
API: a,
|
||||
ShapeName: op.input,
|
||||
Shape: &Shape{
|
||||
API: a,
|
||||
ShapeName: op.input,
|
||||
},
|
||||
},
|
||||
}
|
||||
o.InputRef.Shape.refs = append(o.InputRef.Shape.refs, &o.InputRef)
|
||||
o.OutputRef.Shape.refs = append(o.OutputRef.Shape.refs, &o.OutputRef)
|
||||
|
||||
a.Operations[o.Name] = o
|
||||
|
||||
a.Shapes[op.input] = o.InputRef.Shape
|
||||
a.Shapes[op.output] = o.OutputRef.Shape
|
||||
|
||||
expected[op.operation] = append(expected[op.operation],
|
||||
op.expectedInput,
|
||||
op.expectedOutput,
|
||||
)
|
||||
}
|
||||
|
||||
expected[op.operation] = append(expected[op.operation], op.expectedInput)
|
||||
expected[op.operation] = append(expected[op.operation], op.expectedOutput)
|
||||
}
|
||||
|
||||
a.fixStutterNames()
|
||||
a.renameToplevelShapes()
|
||||
for k, v := range expected {
|
||||
if a.Operations[k].InputRef.Shape.ShapeName != v[0] {
|
||||
t.Errorf("Error %d case: Expected %q, but received %q", k, v[0], a.Operations[k].InputRef.Shape.ShapeName)
|
||||
a.fixStutterNames()
|
||||
a.applyShapeNameAliases()
|
||||
a.createInputOutputShapes()
|
||||
for k, v := range expected {
|
||||
if a.Operations[k].InputRef.Shape.ShapeName != v[0] {
|
||||
t.Errorf("Error %s case: Expected %q, but received %q", k, v[0], a.Operations[k].InputRef.Shape.ShapeName)
|
||||
}
|
||||
if a.Operations[k].OutputRef.Shape.ShapeName != v[1] {
|
||||
t.Errorf("Error %s case: Expected %q, but received %q", k, v[1], a.Operations[k].OutputRef.Shape.ShapeName)
|
||||
}
|
||||
}
|
||||
if a.Operations[k].OutputRef.Shape.ShapeName != v[1] {
|
||||
t.Errorf("Error %d case: Expected %q, but received %q", k, v[1], a.Operations[k].OutputRef.Shape.ShapeName)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestCollidingFields(t *testing.T) {
|
||||
cases := []struct {
|
||||
api *API
|
||||
expected []*Shapes
|
||||
cases := map[string]struct {
|
||||
MemberRefs map[string]*ShapeRef
|
||||
Expect []string
|
||||
IsException bool
|
||||
}{
|
||||
{
|
||||
&API{
|
||||
name: "FooService",
|
||||
Shapes: []*Shapes{
|
||||
{
|
||||
MemberRefs: map[string]*ShapeRef{
|
||||
"String": &ShapeRef{},
|
||||
"GoString": &ShapeRef{},
|
||||
"Validate": &ShapeRef{},
|
||||
"Foo": &ShapeRef{},
|
||||
"SetFoo": &ShapeRef{},
|
||||
},
|
||||
},
|
||||
},
|
||||
"SimpleMembers": {
|
||||
MemberRefs: map[string]*ShapeRef{
|
||||
"Code": {},
|
||||
"Foo": {},
|
||||
"GoString": {},
|
||||
"Message": {},
|
||||
"OrigErr": {},
|
||||
"SetFoo": {},
|
||||
"String": {},
|
||||
"Validate": {},
|
||||
},
|
||||
[]*Shapes{
|
||||
{
|
||||
MemberRefs: map[string]*ShapeRef{
|
||||
"String_": &ShapeRef{},
|
||||
"GoString_": &ShapeRef{},
|
||||
"Validate_": &ShapeRef{},
|
||||
"Foo": &ShapeRef{},
|
||||
"SetFoo_": &ShapeRef{},
|
||||
},
|
||||
},
|
||||
Expect: []string{
|
||||
"Code",
|
||||
"Foo",
|
||||
"GoString_",
|
||||
"Message",
|
||||
"OrigErr",
|
||||
"SetFoo_",
|
||||
"String_",
|
||||
"Validate_",
|
||||
},
|
||||
},
|
||||
"ExceptionShape": {
|
||||
IsException: true,
|
||||
MemberRefs: map[string]*ShapeRef{
|
||||
"Code": {},
|
||||
"Message": {},
|
||||
"OrigErr": {},
|
||||
"Other": {},
|
||||
"String": {},
|
||||
},
|
||||
Expect: []string{
|
||||
"Code_",
|
||||
"Message_",
|
||||
"OrigErr_",
|
||||
"Other",
|
||||
"String_",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range testCases {
|
||||
c.api.renameCollidingFields()
|
||||
if !reflect.DeepEqual(c.api.Shapes, c.expected) {
|
||||
t.Errorf("expected %v, but received %v", c.expected, c.api.Shapes)
|
||||
}
|
||||
for k, c := range cases {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
a := &API{
|
||||
Shapes: map[string]*Shape{
|
||||
"shapename": {
|
||||
ShapeName: k,
|
||||
MemberRefs: c.MemberRefs,
|
||||
Exception: c.IsException,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
a.renameCollidingFields()
|
||||
|
||||
for i, name := range a.Shapes["shapename"].MemberNames() {
|
||||
if e, a := c.Expect[i], name; e != a {
|
||||
t.Errorf("expect %v, got %v", e, a)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateInputOutputShapes(t *testing.T) {
|
||||
meta := Metadata{
|
||||
APIVersion: "0000-00-00",
|
||||
EndpointPrefix: "rpcservice",
|
||||
JSONVersion: "1.1",
|
||||
Protocol: "json",
|
||||
ServiceAbbreviation: "RPCService",
|
||||
ServiceFullName: "RPC Service",
|
||||
ServiceID: "RPCService",
|
||||
SignatureVersion: "v4",
|
||||
TargetPrefix: "RPCService_00000000",
|
||||
UID: "RPCService-0000-00-00",
|
||||
}
|
||||
|
||||
type OpExpect struct {
|
||||
Input string
|
||||
Output string
|
||||
}
|
||||
|
||||
cases := map[string]struct {
|
||||
API *API
|
||||
ExpectOps map[string]OpExpect
|
||||
ExpectShapes []string
|
||||
}{
|
||||
"allRename": {
|
||||
API: &API{Metadata: meta,
|
||||
Operations: map[string]*Operation{
|
||||
"FirstOp": {Name: "FirstOp",
|
||||
InputRef: ShapeRef{ShapeName: "FirstOpRequest"},
|
||||
OutputRef: ShapeRef{ShapeName: "FirstOpResponse"},
|
||||
},
|
||||
"SecondOp": {Name: "SecondOp",
|
||||
InputRef: ShapeRef{ShapeName: "SecondOpRequest"},
|
||||
OutputRef: ShapeRef{ShapeName: "SecondOpResponse"},
|
||||
},
|
||||
},
|
||||
Shapes: map[string]*Shape{
|
||||
"FirstOpRequest": {ShapeName: "FirstOpRequest", Type: "structure"},
|
||||
"FirstOpResponse": {ShapeName: "FirstOpResponse", Type: "structure"},
|
||||
"SecondOpRequest": {ShapeName: "SecondOpRequest", Type: "structure"},
|
||||
"SecondOpResponse": {ShapeName: "SecondOpResponse", Type: "structure"},
|
||||
},
|
||||
},
|
||||
ExpectOps: map[string]OpExpect{
|
||||
"FirstOp": {
|
||||
Input: "FirstOpInput",
|
||||
Output: "FirstOpOutput",
|
||||
},
|
||||
"SecondOp": {
|
||||
Input: "SecondOpInput",
|
||||
Output: "SecondOpOutput",
|
||||
},
|
||||
},
|
||||
ExpectShapes: []string{
|
||||
"FirstOpInput", "FirstOpOutput",
|
||||
"SecondOpInput", "SecondOpOutput",
|
||||
},
|
||||
},
|
||||
"noRename": {
|
||||
API: &API{Metadata: meta,
|
||||
Operations: map[string]*Operation{
|
||||
"FirstOp": {Name: "FirstOp",
|
||||
InputRef: ShapeRef{ShapeName: "FirstOpInput"},
|
||||
OutputRef: ShapeRef{ShapeName: "FirstOpOutput"},
|
||||
},
|
||||
"SecondOp": {Name: "SecondOp",
|
||||
InputRef: ShapeRef{ShapeName: "SecondOpInput"},
|
||||
OutputRef: ShapeRef{ShapeName: "SecondOpOutput"},
|
||||
},
|
||||
},
|
||||
Shapes: map[string]*Shape{
|
||||
"FirstOpInput": {ShapeName: "FirstOpInput", Type: "structure"},
|
||||
"FirstOpOutput": {ShapeName: "FirstOpOutput", Type: "structure"},
|
||||
"SecondOpInput": {ShapeName: "SecondOpInput", Type: "structure"},
|
||||
"SecondOpOutput": {ShapeName: "SecondOpOutput", Type: "structure"},
|
||||
},
|
||||
},
|
||||
ExpectOps: map[string]OpExpect{
|
||||
"FirstOp": {
|
||||
Input: "FirstOpInput",
|
||||
Output: "FirstOpOutput",
|
||||
},
|
||||
"SecondOp": {
|
||||
Input: "SecondOpInput",
|
||||
Output: "SecondOpOutput",
|
||||
},
|
||||
},
|
||||
ExpectShapes: []string{
|
||||
"FirstOpInput", "FirstOpOutput",
|
||||
"SecondOpInput", "SecondOpOutput",
|
||||
},
|
||||
},
|
||||
"renameWithNested": {
|
||||
API: &API{Metadata: meta,
|
||||
Operations: map[string]*Operation{
|
||||
"FirstOp": {Name: "FirstOp",
|
||||
InputRef: ShapeRef{ShapeName: "FirstOpWriteMe"},
|
||||
OutputRef: ShapeRef{ShapeName: "FirstOpReadMe"},
|
||||
},
|
||||
"SecondOp": {Name: "SecondOp",
|
||||
InputRef: ShapeRef{ShapeName: "SecondOpWriteMe"},
|
||||
OutputRef: ShapeRef{ShapeName: "SecondOpReadMe"},
|
||||
},
|
||||
},
|
||||
Shapes: map[string]*Shape{
|
||||
"FirstOpWriteMe": {ShapeName: "FirstOpWriteMe", Type: "structure",
|
||||
MemberRefs: map[string]*ShapeRef{
|
||||
"Foo": {ShapeName: "String"},
|
||||
},
|
||||
},
|
||||
"FirstOpReadMe": {ShapeName: "FirstOpReadMe", Type: "structure",
|
||||
MemberRefs: map[string]*ShapeRef{
|
||||
"Bar": {ShapeName: "Struct"},
|
||||
"Once": {ShapeName: "Once"},
|
||||
},
|
||||
},
|
||||
"SecondOpWriteMe": {ShapeName: "SecondOpWriteMe", Type: "structure"},
|
||||
"SecondOpReadMe": {ShapeName: "SecondOpReadMe", Type: "structure"},
|
||||
"Once": {ShapeName: "Once", Type: "string"},
|
||||
"String": {ShapeName: "String", Type: "string"},
|
||||
"Struct": {ShapeName: "Struct", Type: "structure",
|
||||
MemberRefs: map[string]*ShapeRef{
|
||||
"Foo": {ShapeName: "String"},
|
||||
"Bar": {ShapeName: "Struct"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ExpectOps: map[string]OpExpect{
|
||||
"FirstOp": {
|
||||
Input: "FirstOpInput",
|
||||
Output: "FirstOpOutput",
|
||||
},
|
||||
"SecondOp": {
|
||||
Input: "SecondOpInput",
|
||||
Output: "SecondOpOutput",
|
||||
},
|
||||
},
|
||||
ExpectShapes: []string{
|
||||
"FirstOpInput", "FirstOpOutput",
|
||||
"Once",
|
||||
"SecondOpInput", "SecondOpOutput",
|
||||
"String", "Struct",
|
||||
},
|
||||
},
|
||||
"aliasedInput": {
|
||||
API: &API{Metadata: meta,
|
||||
Operations: map[string]*Operation{
|
||||
"FirstOp": {Name: "FirstOp",
|
||||
InputRef: ShapeRef{ShapeName: "FirstOpRequest"},
|
||||
OutputRef: ShapeRef{ShapeName: "FirstOpResponse"},
|
||||
},
|
||||
},
|
||||
Shapes: map[string]*Shape{
|
||||
"FirstOpRequest": {ShapeName: "FirstOpRequest", Type: "structure",
|
||||
AliasedShapeName: true,
|
||||
},
|
||||
"FirstOpResponse": {ShapeName: "FirstOpResponse", Type: "structure"},
|
||||
},
|
||||
},
|
||||
ExpectOps: map[string]OpExpect{
|
||||
"FirstOp": {
|
||||
Input: "FirstOpRequest",
|
||||
Output: "FirstOpOutput",
|
||||
},
|
||||
},
|
||||
ExpectShapes: []string{
|
||||
"FirstOpOutput", "FirstOpRequest",
|
||||
},
|
||||
},
|
||||
"aliasedOutput": {
|
||||
API: &API{Metadata: meta,
|
||||
Operations: map[string]*Operation{
|
||||
"FirstOp": {Name: "FirstOp",
|
||||
InputRef: ShapeRef{ShapeName: "FirstOpRequest"},
|
||||
OutputRef: ShapeRef{ShapeName: "FirstOpResponse"},
|
||||
},
|
||||
},
|
||||
Shapes: map[string]*Shape{
|
||||
"FirstOpRequest": {ShapeName: "FirstOpRequest", Type: "structure"},
|
||||
"FirstOpResponse": {ShapeName: "FirstOpResponse", Type: "structure",
|
||||
AliasedShapeName: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
ExpectOps: map[string]OpExpect{
|
||||
"FirstOp": {
|
||||
Input: "FirstOpInput",
|
||||
Output: "FirstOpResponse",
|
||||
},
|
||||
},
|
||||
ExpectShapes: []string{
|
||||
"FirstOpInput", "FirstOpResponse",
|
||||
},
|
||||
},
|
||||
"resusedShape": {
|
||||
API: &API{Metadata: meta,
|
||||
Operations: map[string]*Operation{
|
||||
"FirstOp": {Name: "FirstOp",
|
||||
InputRef: ShapeRef{ShapeName: "FirstOpRequest"},
|
||||
OutputRef: ShapeRef{ShapeName: "ReusedShape"},
|
||||
},
|
||||
},
|
||||
Shapes: map[string]*Shape{
|
||||
"FirstOpRequest": {ShapeName: "FirstOpRequest", Type: "structure",
|
||||
MemberRefs: map[string]*ShapeRef{
|
||||
"Foo": {ShapeName: "ReusedShape"},
|
||||
"ooF": {ShapeName: "ReusedShapeList"},
|
||||
},
|
||||
},
|
||||
"ReusedShape": {ShapeName: "ReusedShape", Type: "structure"},
|
||||
"ReusedShapeList": {ShapeName: "ReusedShapeList", Type: "list",
|
||||
MemberRef: ShapeRef{ShapeName: "ReusedShape"},
|
||||
},
|
||||
},
|
||||
},
|
||||
ExpectOps: map[string]OpExpect{
|
||||
"FirstOp": {
|
||||
Input: "FirstOpInput",
|
||||
Output: "FirstOpOutput",
|
||||
},
|
||||
},
|
||||
ExpectShapes: []string{
|
||||
"FirstOpInput", "FirstOpOutput",
|
||||
"ReusedShape", "ReusedShapeList",
|
||||
},
|
||||
},
|
||||
"aliasedResusedShape": {
|
||||
API: &API{Metadata: meta,
|
||||
Operations: map[string]*Operation{
|
||||
"FirstOp": {Name: "FirstOp",
|
||||
InputRef: ShapeRef{ShapeName: "FirstOpRequest"},
|
||||
OutputRef: ShapeRef{ShapeName: "ReusedShape"},
|
||||
},
|
||||
},
|
||||
Shapes: map[string]*Shape{
|
||||
"FirstOpRequest": {ShapeName: "FirstOpRequest", Type: "structure",
|
||||
MemberRefs: map[string]*ShapeRef{
|
||||
"Foo": {ShapeName: "ReusedShape"},
|
||||
"ooF": {ShapeName: "ReusedShapeList"},
|
||||
},
|
||||
},
|
||||
"ReusedShape": {ShapeName: "ReusedShape", Type: "structure",
|
||||
AliasedShapeName: true,
|
||||
},
|
||||
"ReusedShapeList": {ShapeName: "ReusedShapeList", Type: "list",
|
||||
MemberRef: ShapeRef{ShapeName: "ReusedShape"},
|
||||
},
|
||||
},
|
||||
},
|
||||
ExpectOps: map[string]OpExpect{
|
||||
"FirstOp": {
|
||||
Input: "FirstOpInput",
|
||||
Output: "ReusedShape",
|
||||
},
|
||||
},
|
||||
ExpectShapes: []string{
|
||||
"FirstOpInput",
|
||||
"ReusedShape", "ReusedShapeList",
|
||||
},
|
||||
},
|
||||
"unsetInput": {
|
||||
API: &API{Metadata: meta,
|
||||
Operations: map[string]*Operation{
|
||||
"FirstOp": {Name: "FirstOp",
|
||||
OutputRef: ShapeRef{ShapeName: "FirstOpResponse"},
|
||||
},
|
||||
},
|
||||
Shapes: map[string]*Shape{
|
||||
"FirstOpResponse": {ShapeName: "FirstOpResponse", Type: "structure"},
|
||||
},
|
||||
},
|
||||
ExpectOps: map[string]OpExpect{
|
||||
"FirstOp": {
|
||||
Input: "FirstOpInput",
|
||||
Output: "FirstOpOutput",
|
||||
},
|
||||
},
|
||||
ExpectShapes: []string{
|
||||
"FirstOpInput", "FirstOpOutput",
|
||||
},
|
||||
},
|
||||
"unsetOutput": {
|
||||
API: &API{Metadata: meta,
|
||||
Operations: map[string]*Operation{
|
||||
"FirstOp": {Name: "FirstOp",
|
||||
InputRef: ShapeRef{ShapeName: "FirstOpRequest"},
|
||||
},
|
||||
},
|
||||
Shapes: map[string]*Shape{
|
||||
"FirstOpRequest": {ShapeName: "FirstOpRequest", Type: "structure"},
|
||||
},
|
||||
},
|
||||
ExpectOps: map[string]OpExpect{
|
||||
"FirstOp": {
|
||||
Input: "FirstOpInput",
|
||||
Output: "FirstOpOutput",
|
||||
},
|
||||
},
|
||||
ExpectShapes: []string{
|
||||
"FirstOpInput", "FirstOpOutput",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, c := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
a := c.API
|
||||
a.Setup()
|
||||
|
||||
for opName, op := range a.Operations {
|
||||
if e, a := op.InputRef.ShapeName, op.InputRef.Shape.ShapeName; e != a {
|
||||
t.Errorf("expect input ref and shape names to match, %s, %s", e, a)
|
||||
}
|
||||
if e, a := c.ExpectOps[opName].Input, op.InputRef.ShapeName; e != a {
|
||||
t.Errorf("expect %v input shape, got %v", e, a)
|
||||
}
|
||||
|
||||
if e, a := op.OutputRef.ShapeName, op.OutputRef.Shape.ShapeName; e != a {
|
||||
t.Errorf("expect output ref and shape names to match, %s, %s", e, a)
|
||||
}
|
||||
if e, a := c.ExpectOps[opName].Output, op.OutputRef.ShapeName; e != a {
|
||||
t.Errorf("expect %v output shape, got %v", e, a)
|
||||
}
|
||||
}
|
||||
|
||||
if e, a := c.ExpectShapes, a.ShapeNames(); !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("expect %v shapes, got %v", e, a)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
// +build codegen
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// S3ManagerUploadInputGoCode returns the Go code for the S3 Upload Manager's
|
||||
// input structure.
|
||||
func S3ManagerUploadInputGoCode(a *API) string {
|
||||
if v := a.PackageName(); v != "s3" {
|
||||
panic(fmt.Sprintf("unexpected API model %s", v))
|
||||
}
|
||||
|
||||
s, ok := a.Shapes["PutObjectInput"]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("unable to find PutObjectInput shape in S3 model"))
|
||||
}
|
||||
|
||||
a.resetImports()
|
||||
a.AddImport("io")
|
||||
a.AddImport("time")
|
||||
|
||||
var w bytes.Buffer
|
||||
if err := s3managerUploadInputTmpl.Execute(&w, s); err != nil {
|
||||
panic(fmt.Sprintf("failed to execute %s template, %v",
|
||||
s3managerUploadInputTmpl.Name(), err))
|
||||
}
|
||||
|
||||
return a.importsGoCode() + w.String()
|
||||
}
|
||||
|
||||
var s3managerUploadInputTmpl = template.Must(
|
||||
template.New("s3managerUploadInputTmpl").
|
||||
Funcs(template.FuncMap{
|
||||
"GetDeprecatedMsg": getDeprecatedMessage,
|
||||
}).
|
||||
Parse(s3managerUploadInputTmplDef),
|
||||
)
|
||||
|
||||
const s3managerUploadInputTmplDef = `
|
||||
// UploadInput provides the input parameters for uploading a stream or buffer
|
||||
// to an object in an Amazon S3 bucket. This type is similar to the s3
|
||||
// package's PutObjectInput with the exception that the Body member is an
|
||||
// io.Reader instead of an io.ReadSeeker.
|
||||
type UploadInput struct {
|
||||
_ struct{} {{ .GoTags true false }}
|
||||
|
||||
{{ range $name, $ref := $.MemberRefs -}}
|
||||
{{ if eq $name "Body" }}
|
||||
// The readable body payload to send to S3.
|
||||
Body io.Reader
|
||||
{{ else if eq $name "ContentLength" }}
|
||||
{{/* S3 Upload Manager does not use modeled content length */}}
|
||||
{{ else }}
|
||||
{{ $isBlob := $.WillRefBeBase64Encoded $name -}}
|
||||
{{ $isRequired := $.IsRequired $name -}}
|
||||
{{ $doc := $ref.Docstring -}}
|
||||
|
||||
{{ if $doc -}}
|
||||
{{ $doc }}
|
||||
{{ if $ref.Deprecated -}}
|
||||
//
|
||||
// Deprecated: {{ GetDeprecatedMsg $ref.DeprecatedMsg $name }}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{ if $isBlob -}}
|
||||
{{ if $doc -}}
|
||||
//
|
||||
{{ end -}}
|
||||
// {{ $name }} is automatically base64 encoded/decoded by the SDK.
|
||||
{{ end -}}
|
||||
{{ if $isRequired -}}
|
||||
{{ if or $doc $isBlob -}}
|
||||
//
|
||||
{{ end -}}
|
||||
// {{ $name }} is a required field
|
||||
{{ end -}}
|
||||
{{ $name }} {{ $.GoStructType $name $ref }} {{ $ref.GoTags false $isRequired }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
}
|
||||
`
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
// +build codegen
|
||||
|
||||
package api
|
||||
|
||||
// ServiceName returns the SDK's naming of the service. Has
|
||||
// backwards compatibility built in for services that were
|
||||
// incorrectly named with the service's endpoint prefix.
|
||||
func ServiceName(a *API) string {
|
||||
if oldName, ok := oldServiceNames[a.PackageName()]; ok {
|
||||
return oldName
|
||||
}
|
||||
|
||||
return ServiceID(a)
|
||||
}
|
||||
|
||||
var oldServiceNames = map[string]string{
|
||||
"migrationhub": "mgh",
|
||||
"acmpca": "acm-pca",
|
||||
"acm": "acm",
|
||||
"alexaforbusiness": "a4b",
|
||||
"apigateway": "apigateway",
|
||||
"applicationautoscaling": "autoscaling",
|
||||
"appstream": "appstream2",
|
||||
"appsync": "appsync",
|
||||
"athena": "athena",
|
||||
"autoscalingplans": "autoscaling",
|
||||
"autoscaling": "autoscaling",
|
||||
"batch": "batch",
|
||||
"budgets": "budgets",
|
||||
"costexplorer": "ce",
|
||||
"cloud9": "cloud9",
|
||||
"clouddirectory": "clouddirectory",
|
||||
"cloudformation": "cloudformation",
|
||||
"cloudfront": "cloudfront",
|
||||
"cloudhsm": "cloudhsm",
|
||||
"cloudhsmv2": "cloudhsmv2",
|
||||
"cloudsearch": "cloudsearch",
|
||||
"cloudsearchdomain": "cloudsearchdomain",
|
||||
"cloudtrail": "cloudtrail",
|
||||
"codebuild": "codebuild",
|
||||
"codecommit": "codecommit",
|
||||
"codedeploy": "codedeploy",
|
||||
"codepipeline": "codepipeline",
|
||||
"codestar": "codestar",
|
||||
"cognitoidentity": "cognito-identity",
|
||||
"cognitoidentityprovider": "cognito-idp",
|
||||
"cognitosync": "cognito-sync",
|
||||
"comprehend": "comprehend",
|
||||
"configservice": "config",
|
||||
"connect": "connect",
|
||||
"costandusagereportservice": "cur",
|
||||
"datapipeline": "datapipeline",
|
||||
"dax": "dax",
|
||||
"devicefarm": "devicefarm",
|
||||
"directconnect": "directconnect",
|
||||
"applicationdiscoveryservice": "discovery",
|
||||
"databasemigrationservice": "dms",
|
||||
"directoryservice": "ds",
|
||||
"dynamodb": "dynamodb",
|
||||
"ec2": "ec2",
|
||||
"ecr": "ecr",
|
||||
"ecs": "ecs",
|
||||
"eks": "eks",
|
||||
"elasticache": "elasticache",
|
||||
"elasticbeanstalk": "elasticbeanstalk",
|
||||
"efs": "elasticfilesystem",
|
||||
"elb": "elasticloadbalancing",
|
||||
"elbv2": "elasticloadbalancing",
|
||||
"emr": "elasticmapreduce",
|
||||
"elastictranscoder": "elastictranscoder",
|
||||
"ses": "email",
|
||||
"marketplaceentitlementservice": "entitlement.marketplace",
|
||||
"elasticsearchservice": "es",
|
||||
"cloudwatchevents": "events",
|
||||
"firehose": "firehose",
|
||||
"fms": "fms",
|
||||
"gamelift": "gamelift",
|
||||
"glacier": "glacier",
|
||||
"glue": "glue",
|
||||
"greengrass": "greengrass",
|
||||
"guardduty": "guardduty",
|
||||
"health": "health",
|
||||
"iam": "iam",
|
||||
"inspector": "inspector",
|
||||
"iotdataplane": "data.iot",
|
||||
"iotjobsdataplane": "data.jobs.iot",
|
||||
"iot": "iot",
|
||||
"iot1clickdevicesservice": "devices.iot1click",
|
||||
"iot1clickprojects": "projects.iot1click",
|
||||
"iotanalytics": "iotanalytics",
|
||||
"kinesisvideoarchivedmedia": "kinesisvideo",
|
||||
"kinesisvideomedia": "kinesisvideo",
|
||||
"kinesis": "kinesis",
|
||||
"kinesisanalytics": "kinesisanalytics",
|
||||
"kinesisvideo": "kinesisvideo",
|
||||
"kms": "kms",
|
||||
"lambda": "lambda",
|
||||
"lexmodelbuildingservice": "models.lex",
|
||||
"lightsail": "lightsail",
|
||||
"cloudwatchlogs": "logs",
|
||||
"machinelearning": "machinelearning",
|
||||
"marketplacecommerceanalytics": "marketplacecommerceanalytics",
|
||||
"mediaconvert": "mediaconvert",
|
||||
"medialive": "medialive",
|
||||
"mediapackage": "mediapackage",
|
||||
"mediastoredata": "data.mediastore",
|
||||
"mediastore": "mediastore",
|
||||
"mediatailor": "api.mediatailor",
|
||||
"marketplacemetering": "metering.marketplace",
|
||||
"mobile": "mobile",
|
||||
"mobileanalytics": "mobileanalytics",
|
||||
"cloudwatch": "monitoring",
|
||||
"mq": "mq",
|
||||
"mturk": "mturk-requester",
|
||||
"neptune": "rds",
|
||||
"opsworks": "opsworks",
|
||||
"opsworkscm": "opsworks-cm",
|
||||
"organizations": "organizations",
|
||||
"pi": "pi",
|
||||
"pinpoint": "pinpoint",
|
||||
"polly": "polly",
|
||||
"pricing": "api.pricing",
|
||||
"rds": "rds",
|
||||
"redshift": "redshift",
|
||||
"rekognition": "rekognition",
|
||||
"resourcegroups": "resource-groups",
|
||||
"resourcegroupstaggingapi": "tagging",
|
||||
"route53": "route53",
|
||||
"route53domains": "route53domains",
|
||||
"lexruntimeservice": "runtime.lex",
|
||||
"sagemakerruntime": "runtime.sagemaker",
|
||||
"s3": "s3",
|
||||
"sagemaker": "sagemaker",
|
||||
"simpledb": "sdb",
|
||||
"secretsmanager": "secretsmanager",
|
||||
"serverlessapplicationrepository": "serverlessrepo",
|
||||
"servicecatalog": "servicecatalog",
|
||||
"servicediscovery": "servicediscovery",
|
||||
"shield": "shield",
|
||||
"sms": "sms",
|
||||
"snowball": "snowball",
|
||||
"sns": "sns",
|
||||
"sqs": "sqs",
|
||||
"ssm": "ssm",
|
||||
"sfn": "states",
|
||||
"storagegateway": "storagegateway",
|
||||
"dynamodbstreams": "streams.dynamodb",
|
||||
"sts": "sts",
|
||||
"support": "support",
|
||||
"swf": "swf",
|
||||
"transcribeservice": "transcribe",
|
||||
"translate": "translate",
|
||||
"wafregional": "waf-regional",
|
||||
"waf": "waf",
|
||||
"workdocs": "workdocs",
|
||||
"workmail": "workmail",
|
||||
"workspaces": "workspaces",
|
||||
"xray": "xray",
|
||||
}
|
||||
+314
-77
@@ -10,8 +10,23 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/aws/aws-sdk-go/private/protocol"
|
||||
)
|
||||
|
||||
// ErrorInfo represents the error block of a shape's structure
|
||||
type ErrorInfo struct {
|
||||
Type string
|
||||
Code string
|
||||
HTTPStatusCode int
|
||||
}
|
||||
|
||||
// A XMLInfo defines URL and prefix for Shapes when rendered as XML
|
||||
type XMLInfo struct {
|
||||
Prefix string
|
||||
URI string
|
||||
}
|
||||
|
||||
// A ShapeRef defines the usage of a shape within the API.
|
||||
type ShapeRef struct {
|
||||
API *API `json:"-"`
|
||||
@@ -25,28 +40,26 @@ type ShapeRef struct {
|
||||
Streaming bool
|
||||
XMLAttribute bool
|
||||
// Ignore, if set, will not be sent over the wire
|
||||
Ignore bool
|
||||
XMLNamespace XMLInfo
|
||||
Payload string
|
||||
IdempotencyToken bool `json:"idempotencyToken"`
|
||||
JSONValue bool `json:"jsonvalue"`
|
||||
Deprecated bool `json:"deprecated"`
|
||||
Ignore bool
|
||||
XMLNamespace XMLInfo
|
||||
Payload string
|
||||
IdempotencyToken bool `json:"idempotencyToken"`
|
||||
TimestampFormat string `json:"timestampFormat"`
|
||||
JSONValue bool `json:"jsonvalue"`
|
||||
Deprecated bool `json:"deprecated"`
|
||||
DeprecatedMsg string `json:"deprecatedMessage"`
|
||||
EndpointDiscoveryID bool `json:"endpointdiscoveryid"`
|
||||
HostLabel bool `json:"hostLabel"`
|
||||
|
||||
OrigShapeName string `json:"-"`
|
||||
|
||||
GenerateGetter bool
|
||||
}
|
||||
|
||||
// ErrorInfo represents the error block of a shape's structure
|
||||
type ErrorInfo struct {
|
||||
Code string
|
||||
HTTPStatusCode int
|
||||
}
|
||||
IsEventPayload bool `json:"eventpayload"`
|
||||
IsEventHeader bool `json:"eventheader"`
|
||||
|
||||
// A XMLInfo defines URL and prefix for Shapes when rendered as XML
|
||||
type XMLInfo struct {
|
||||
Prefix string
|
||||
URI string
|
||||
// Collection of custom tags the shape reference includes.
|
||||
CustomTags ShapeTags
|
||||
}
|
||||
|
||||
// A Shape defines the definition of a shape type
|
||||
@@ -68,12 +81,17 @@ type Shape struct {
|
||||
Streaming bool
|
||||
Location string
|
||||
LocationName string
|
||||
IdempotencyToken bool `json:"idempotencyToken"`
|
||||
IdempotencyToken bool `json:"idempotencyToken"`
|
||||
TimestampFormat string `json:"timestampFormat"`
|
||||
XMLNamespace XMLInfo
|
||||
Min float64 // optional Minimum length (string, list) or value (number)
|
||||
Max float64 // optional Maximum length (string, list) or value (number)
|
||||
|
||||
EventStreamsMemberName string `json:"-"`
|
||||
EventStreamAPI *EventStreamAPI `json:"-"`
|
||||
EventFor []*EventStream `json:"-"`
|
||||
|
||||
IsEventStream bool `json:"eventstream"`
|
||||
IsEvent bool `json:"event"`
|
||||
|
||||
refs []*ShapeRef // References to this shape
|
||||
resolvePkg string // use this package in the goType() if present
|
||||
@@ -83,13 +101,34 @@ type Shape struct {
|
||||
// Defines if the shape is a placeholder and should not be used directly
|
||||
Placeholder bool
|
||||
|
||||
Deprecated bool `json:"deprecated"`
|
||||
Deprecated bool `json:"deprecated"`
|
||||
DeprecatedMsg string `json:"deprecatedMessage"`
|
||||
|
||||
Validations ShapeValidations
|
||||
|
||||
// Error information that is set if the shape is an error shape.
|
||||
IsError bool
|
||||
ErrorInfo ErrorInfo `json:"error"`
|
||||
|
||||
// Flags that the shape cannot be rename. Prevents the shape from being
|
||||
// renamed further by the Input/Output.
|
||||
AliasedShapeName bool
|
||||
|
||||
// Sensitive types should not be logged by SDK type loggers.
|
||||
Sensitive bool `json:"sensitive"`
|
||||
}
|
||||
|
||||
// CanBeEmpty returns if the shape value can sent request as an empty value.
|
||||
// String, blob, list, and map are types must not be empty when the member is
|
||||
// serialized to the uri path, or decorated with HostLabel.
|
||||
func (ref *ShapeRef) CanBeEmpty() bool {
|
||||
switch ref.Shape.Type {
|
||||
case "string":
|
||||
return !(ref.Location == "uri" || ref.HostLabel)
|
||||
case "blob", "map", "list":
|
||||
return !(ref.Location == "uri")
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorCodeName will return the error shape's name formated for
|
||||
@@ -101,7 +140,7 @@ func (s *Shape) ErrorCodeName() string {
|
||||
// ErrorName will return the shape's name or error code if available based
|
||||
// on the API's protocol. This is the error code string returned by the service.
|
||||
func (s *Shape) ErrorName() string {
|
||||
name := s.ShapeName
|
||||
name := s.ErrorInfo.Type
|
||||
switch s.API.Metadata.Protocol {
|
||||
case "query", "ec2query", "rest-xml":
|
||||
if len(s.ErrorInfo.Code) > 0 {
|
||||
@@ -109,9 +148,33 @@ func (s *Shape) ErrorName() string {
|
||||
}
|
||||
}
|
||||
|
||||
if len(name) == 0 {
|
||||
name = s.OrigShapeName
|
||||
}
|
||||
if len(name) == 0 {
|
||||
name = s.ShapeName
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
// PayloadRefName returns the payload member of the shape if there is one
|
||||
// modeled. If no payload is modeled, empty string will be returned.
|
||||
func (s *Shape) PayloadRefName() string {
|
||||
if name := s.Payload; len(name) != 0 {
|
||||
// Root shape
|
||||
return name
|
||||
}
|
||||
|
||||
for name, ref := range s.MemberRefs {
|
||||
if ref.IsEventPayload {
|
||||
return name
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// GoTags returns the struct tags for a shape.
|
||||
func (s *Shape) GoTags(root, required bool) string {
|
||||
ref := &ShapeRef{ShapeName: s.ShapeName, API: s.API, Shape: s}
|
||||
@@ -121,6 +184,11 @@ func (s *Shape) GoTags(root, required bool) string {
|
||||
// Rename changes the name of the Shape to newName. Also updates
|
||||
// the associated API's reference to use newName.
|
||||
func (s *Shape) Rename(newName string) {
|
||||
if s.AliasedShapeName {
|
||||
panic(fmt.Sprintf("attempted to rename %s, but flagged as aliased",
|
||||
s.ShapeName))
|
||||
}
|
||||
|
||||
for _, r := range s.refs {
|
||||
r.OrigShapeName = r.ShapeName
|
||||
r.ShapeName = newName
|
||||
@@ -143,12 +211,21 @@ func (s *Shape) MemberNames() []string {
|
||||
return names
|
||||
}
|
||||
|
||||
// HasMember will return whether or not the shape has a given
|
||||
// member by name.
|
||||
func (s *Shape) HasMember(name string) bool {
|
||||
_, ok := s.MemberRefs[name]
|
||||
return ok
|
||||
}
|
||||
|
||||
// GoTypeWithPkgName returns a shape's type as a string with the package name in
|
||||
// <packageName>.<type> format. Package naming only applies to structures.
|
||||
func (s *Shape) GoTypeWithPkgName() string {
|
||||
return goType(s, true)
|
||||
}
|
||||
|
||||
// GoTypeWithPkgNameElem returns the shapes type as a string with the "*"
|
||||
// removed if there was one preset.
|
||||
func (s *Shape) GoTypeWithPkgNameElem() string {
|
||||
t := goType(s, true)
|
||||
if strings.HasPrefix(t, "*") {
|
||||
@@ -157,7 +234,7 @@ func (s *Shape) GoTypeWithPkgNameElem() string {
|
||||
return t
|
||||
}
|
||||
|
||||
// GenAccessors returns if the shape's reference should have setters generated.
|
||||
// UseIndirection returns if the shape's reference should use indirection or not.
|
||||
func (s *ShapeRef) UseIndirection() bool {
|
||||
switch s.Shape.Type {
|
||||
case "map", "list", "blob", "structure", "jsonvalue":
|
||||
@@ -175,6 +252,32 @@ func (s *ShapeRef) UseIndirection() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s Shape) GetTimestampFormat() string {
|
||||
format := s.TimestampFormat
|
||||
|
||||
if len(format) > 0 && !protocol.IsKnownTimestampFormat(format) {
|
||||
panic(fmt.Sprintf("Unknown timestampFormat %s, for %s",
|
||||
format, s.ShapeName))
|
||||
}
|
||||
|
||||
return format
|
||||
}
|
||||
|
||||
func (ref ShapeRef) GetTimestampFormat() string {
|
||||
format := ref.TimestampFormat
|
||||
|
||||
if len(format) == 0 {
|
||||
format = ref.Shape.TimestampFormat
|
||||
}
|
||||
|
||||
if len(format) > 0 && !protocol.IsKnownTimestampFormat(format) {
|
||||
panic(fmt.Sprintf("Unknown timestampFormat %s, for %s",
|
||||
format, ref.ShapeName))
|
||||
}
|
||||
|
||||
return format
|
||||
}
|
||||
|
||||
// GoStructValueType returns the Shape's Go type value instead of a pointer
|
||||
// for the type.
|
||||
func (s *Shape) GoStructValueType(name string, ref *ShapeRef) string {
|
||||
@@ -201,7 +304,7 @@ func (s *Shape) GoStructType(name string, ref *ShapeRef) string {
|
||||
}
|
||||
|
||||
if ref.JSONValue {
|
||||
s.API.imports["github.com/aws/aws-sdk-go/aws"] = true
|
||||
s.API.AddSDKImport("aws")
|
||||
return "aws.JSONValue"
|
||||
}
|
||||
|
||||
@@ -267,7 +370,7 @@ func goType(s *Shape, withPkgName bool) string {
|
||||
return "*string"
|
||||
case "blob":
|
||||
return "[]byte"
|
||||
case "integer", "long":
|
||||
case "byte", "short", "integer", "long":
|
||||
return "*int64"
|
||||
case "float", "double":
|
||||
return "*float64"
|
||||
@@ -334,18 +437,23 @@ func (s ShapeTags) String() string {
|
||||
|
||||
// GoTags returns the rendered tags string for the ShapeRef
|
||||
func (ref *ShapeRef) GoTags(toplevel bool, isRequired bool) string {
|
||||
tags := ShapeTags{}
|
||||
tags := append(ShapeTags{}, ref.CustomTags...)
|
||||
|
||||
if ref.Location != "" {
|
||||
tags = append(tags, ShapeTag{"location", ref.Location})
|
||||
} else if ref.Shape.Location != "" {
|
||||
tags = append(tags, ShapeTag{"location", ref.Shape.Location})
|
||||
} else if ref.IsEventHeader {
|
||||
tags = append(tags, ShapeTag{"location", "header"})
|
||||
}
|
||||
|
||||
if ref.LocationName != "" {
|
||||
tags = append(tags, ShapeTag{"locationName", ref.LocationName})
|
||||
} else if ref.Shape.LocationName != "" {
|
||||
tags = append(tags, ShapeTag{"locationName", ref.Shape.LocationName})
|
||||
} else if len(ref.Shape.EventFor) != 0 && ref.API.Metadata.Protocol == "rest-xml" {
|
||||
// RPC JSON events need to have location name modeled for round trip testing.
|
||||
tags = append(tags, ShapeTag{"locationName", ref.Shape.ShapeName})
|
||||
}
|
||||
|
||||
if ref.QueryName != "" {
|
||||
@@ -373,18 +481,12 @@ func (ref *ShapeRef) GoTags(toplevel bool, isRequired bool) string {
|
||||
|
||||
// embed the timestamp type for easier lookups
|
||||
if ref.Shape.Type == "timestamp" {
|
||||
t := ShapeTag{Key: "timestampFormat"}
|
||||
if ref.Location == "header" {
|
||||
t.Val = "rfc822"
|
||||
} else {
|
||||
switch ref.API.Metadata.Protocol {
|
||||
case "json", "rest-json":
|
||||
t.Val = "unix"
|
||||
case "rest-xml", "ec2", "query":
|
||||
t.Val = "iso8601"
|
||||
}
|
||||
if format := ref.GetTimestampFormat(); len(format) > 0 {
|
||||
tags = append(tags, ShapeTag{
|
||||
Key: "timestampFormat",
|
||||
Val: format,
|
||||
})
|
||||
}
|
||||
tags = append(tags, t)
|
||||
}
|
||||
|
||||
if ref.Shape.Flattened || ref.Flattened {
|
||||
@@ -401,8 +503,8 @@ func (ref *ShapeRef) GoTags(toplevel bool, isRequired bool) string {
|
||||
}
|
||||
|
||||
if toplevel {
|
||||
if ref.Shape.Payload != "" {
|
||||
tags = append(tags, ShapeTag{"payload", ref.Shape.Payload})
|
||||
if name := ref.Shape.PayloadRefName(); len(name) > 0 {
|
||||
tags = append(tags, ShapeTag{"payload", name})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,6 +528,10 @@ func (ref *ShapeRef) GoTags(toplevel bool, isRequired bool) string {
|
||||
tags = append(tags, ShapeTag{"ignore", "true"})
|
||||
}
|
||||
|
||||
if ref.Shape.Sensitive {
|
||||
tags = append(tags, ShapeTag{"sensitive", "true"})
|
||||
}
|
||||
|
||||
return fmt.Sprintf("`%s`", tags)
|
||||
}
|
||||
|
||||
@@ -514,10 +620,49 @@ func (s *Shape) NestedShape() *Shape {
|
||||
return nestedShape
|
||||
}
|
||||
|
||||
var structShapeTmpl = template.Must(template.New("StructShape").Funcs(template.FuncMap{
|
||||
"GetCrosslinkURL": GetCrosslinkURL,
|
||||
}).Parse(`
|
||||
var structShapeTmpl = func() *template.Template {
|
||||
shapeTmpl := template.Must(
|
||||
template.New("structShapeTmpl").
|
||||
Funcs(template.FuncMap{
|
||||
"GetCrosslinkURL": GetCrosslinkURL,
|
||||
"GetDeprecatedMsg": getDeprecatedMessage,
|
||||
}).
|
||||
Parse(structShapeTmplDef),
|
||||
)
|
||||
|
||||
template.Must(
|
||||
shapeTmpl.AddParseTree(
|
||||
"eventStreamAPILoopMethodTmpl", eventStreamAPILoopMethodTmpl.Tree),
|
||||
)
|
||||
|
||||
template.Must(
|
||||
shapeTmpl.AddParseTree(
|
||||
"eventStreamEventShapeTmpl", eventStreamEventShapeTmpl.Tree),
|
||||
)
|
||||
template.Must(
|
||||
shapeTmpl.AddParseTree(
|
||||
"eventStreamExceptionEventShapeTmpl",
|
||||
eventStreamExceptionEventShapeTmpl.Tree),
|
||||
)
|
||||
shapeTmpl.Funcs(eventStreamEventShapeTmplFuncs)
|
||||
|
||||
template.Must(
|
||||
shapeTmpl.AddParseTree(
|
||||
"hostLabelsShapeTmpl",
|
||||
hostLabelsShapeTmpl.Tree),
|
||||
)
|
||||
|
||||
return shapeTmpl
|
||||
}()
|
||||
|
||||
const structShapeTmplDef = `
|
||||
{{ .Docstring }}
|
||||
{{ if .Deprecated -}}
|
||||
{{ if .Docstring -}}
|
||||
//
|
||||
{{ end -}}
|
||||
// Deprecated: {{ GetDeprecatedMsg .DeprecatedMsg .ShapeName }}
|
||||
{{ end -}}
|
||||
{{ $context := . -}}
|
||||
type {{ .ShapeName }} struct {
|
||||
_ struct{} {{ .GoTags true false }}
|
||||
@@ -530,6 +675,10 @@ type {{ .ShapeName }} struct {
|
||||
|
||||
{{ if $doc -}}
|
||||
{{ $doc }}
|
||||
{{ if $elem.Deprecated -}}
|
||||
//
|
||||
// Deprecated: {{ GetDeprecatedMsg $elem.DeprecatedMsg $name }}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{ if $isBlob -}}
|
||||
{{ if $doc -}}
|
||||
@@ -550,45 +699,58 @@ type {{ .ShapeName }} struct {
|
||||
{{ if not .API.NoStringerMethods }}
|
||||
{{ .GoCodeStringers }}
|
||||
{{ end }}
|
||||
{{ if not .API.NoValidataShapeMethods }}
|
||||
{{ if not (or .API.NoValidataShapeMethods .Exception) }}
|
||||
{{ if .Validations -}}
|
||||
{{ .Validations.GoCode . }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ if not .API.NoGenStructFieldAccessors }}
|
||||
{{ if not (or .API.NoGenStructFieldAccessors .Exception) }}
|
||||
{{ $builderShapeName := print .ShapeName -}}
|
||||
{{ range $_, $name := $context.MemberNames -}}
|
||||
{{ $elem := index $context.MemberRefs $name -}}
|
||||
|
||||
{{ $builderShapeName := print .ShapeName -}}
|
||||
|
||||
{{ range $_, $name := $context.MemberNames -}}
|
||||
{{ $elem := index $context.MemberRefs $name -}}
|
||||
|
||||
// Set{{ $name }} sets the {{ $name }} field's value.
|
||||
func (s *{{ $builderShapeName }}) Set{{ $name }}(v {{ $context.GoStructValueType $name $elem }}) *{{ $builderShapeName }} {
|
||||
{{ if $elem.UseIndirection -}}
|
||||
s.{{ $name }} = &v
|
||||
{{ else -}}
|
||||
s.{{ $name }} = v
|
||||
{{ end -}}
|
||||
return s
|
||||
}
|
||||
|
||||
{{ if $elem.GenerateGetter -}}
|
||||
func (s *{{ $builderShapeName }}) get{{ $name }}() (v {{ $context.GoStructValueType $name $elem }}) {
|
||||
{{ if $elem.UseIndirection -}}
|
||||
if s.{{ $name }} == nil {
|
||||
return v
|
||||
// Set{{ $name }} sets the {{ $name }} field's value.
|
||||
func (s *{{ $builderShapeName }}) Set{{ $name }}(v {{ $context.GoStructValueType $name $elem }}) *{{ $builderShapeName }} {
|
||||
{{ if $elem.UseIndirection -}}
|
||||
s.{{ $name }} = &v
|
||||
{{ else -}}
|
||||
s.{{ $name }} = v
|
||||
{{ end -}}
|
||||
return s
|
||||
}
|
||||
return *s.{{ $name }}
|
||||
{{ else -}}
|
||||
return s.{{ $name }}
|
||||
{{ end -}}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{ if $elem.GenerateGetter -}}
|
||||
func (s *{{ $builderShapeName }}) get{{ $name }}() (v {{ $context.GoStructValueType $name $elem }}) {
|
||||
{{ if $elem.UseIndirection -}}
|
||||
if s.{{ $name }} == nil {
|
||||
return v
|
||||
}
|
||||
return *s.{{ $name }}
|
||||
{{ else -}}
|
||||
return s.{{ $name }}
|
||||
{{ end -}}
|
||||
}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ if $.EventStreamsMemberName }}
|
||||
{{ template "eventStreamAPILoopMethodTmpl" $ }}
|
||||
{{ end }}
|
||||
`))
|
||||
|
||||
{{ if $.EventFor }}
|
||||
{{ template "eventStreamEventShapeTmpl" $ }}
|
||||
|
||||
{{- if $.Exception }}
|
||||
{{ template "eventStreamExceptionEventShapeTmpl" $ }}
|
||||
{{ end -}}
|
||||
{{ end }}
|
||||
|
||||
{{ if $.HasHostLabelMembers }}
|
||||
{{ template "hostLabelsShapeTmpl" $ }}
|
||||
{{ end }}
|
||||
`
|
||||
|
||||
var enumShapeTmpl = template.Must(template.New("EnumShape").Parse(`
|
||||
{{ .Docstring }}
|
||||
@@ -605,22 +767,38 @@ const (
|
||||
|
||||
// GoCode returns the rendered Go code for the Shape.
|
||||
func (s *Shape) GoCode() string {
|
||||
b := &bytes.Buffer{}
|
||||
w := &bytes.Buffer{}
|
||||
|
||||
switch {
|
||||
case s.EventStreamAPI != nil:
|
||||
if err := renderEventStreamAPIShape(w, s); err != nil {
|
||||
panic(
|
||||
fmt.Sprintf(
|
||||
"failed to generate eventstream API shape, %s, %v",
|
||||
s.ShapeName, err),
|
||||
)
|
||||
}
|
||||
case s.Type == "structure":
|
||||
if err := structShapeTmpl.Execute(b, s); err != nil {
|
||||
panic(fmt.Sprintf("Failed to generate struct shape %s, %v\n", s.ShapeName, err))
|
||||
if err := structShapeTmpl.Execute(w, s); err != nil {
|
||||
panic(
|
||||
fmt.Sprintf(
|
||||
"Failed to generate struct shape %s, %v",
|
||||
s.ShapeName, err),
|
||||
)
|
||||
}
|
||||
case s.IsEnum():
|
||||
if err := enumShapeTmpl.Execute(b, s); err != nil {
|
||||
panic(fmt.Sprintf("Failed to generate enum shape %s, %v\n", s.ShapeName, err))
|
||||
if err := enumShapeTmpl.Execute(w, s); err != nil {
|
||||
panic(
|
||||
fmt.Sprintf(
|
||||
"Failed to generate enum shape %s, %v",
|
||||
s.ShapeName, err),
|
||||
)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintln("Cannot generate toplevel shape for", s.Type))
|
||||
}
|
||||
|
||||
return b.String()
|
||||
return w.String()
|
||||
}
|
||||
|
||||
// IsEnum returns whether this shape is an enum list
|
||||
@@ -628,8 +806,22 @@ func (s *Shape) IsEnum() bool {
|
||||
return s.Type == "string" && len(s.Enum) > 0
|
||||
}
|
||||
|
||||
// IsRequired returns if member is a required field.
|
||||
// IsRequired returns if member is a required field. Required fields are fields
|
||||
// marked as required, hostLabels, or location of uri path.
|
||||
func (s *Shape) IsRequired(member string) bool {
|
||||
ref, ok := s.MemberRefs[member]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf(
|
||||
"attempted to check required for unknown member, %s.%s",
|
||||
s.ShapeName, member,
|
||||
))
|
||||
}
|
||||
if ref.IdempotencyToken || ref.Shape.IdempotencyToken {
|
||||
return false
|
||||
}
|
||||
if ref.Location == "uri" || ref.HostLabel {
|
||||
return true
|
||||
}
|
||||
for _, n := range s.Required {
|
||||
if n == member {
|
||||
return true
|
||||
@@ -673,3 +865,48 @@ func (s *Shape) WillRefBeBase64Encoded(refName string) bool {
|
||||
|
||||
return ref.Shape.Type == "blob"
|
||||
}
|
||||
|
||||
// Clone returns a cloned version of the shape with all references clones.
|
||||
//
|
||||
// Does not clone EventStream or Validate related values.
|
||||
func (s *Shape) Clone(newName string) *Shape {
|
||||
if s.AliasedShapeName {
|
||||
panic(fmt.Sprintf("attempted to clone and rename %s, but flagged as aliased",
|
||||
s.ShapeName))
|
||||
}
|
||||
|
||||
n := new(Shape)
|
||||
*n = *s
|
||||
|
||||
debugLogger.Logln("cloning", s.ShapeName, "to", newName)
|
||||
|
||||
n.MemberRefs = map[string]*ShapeRef{}
|
||||
for k, r := range s.MemberRefs {
|
||||
nr := new(ShapeRef)
|
||||
*nr = *r
|
||||
nr.Shape.refs = append(nr.Shape.refs, nr)
|
||||
n.MemberRefs[k] = nr
|
||||
}
|
||||
|
||||
if n.MemberRef.Shape != nil {
|
||||
n.MemberRef.Shape.refs = append(n.MemberRef.Shape.refs, &n.MemberRef)
|
||||
}
|
||||
if n.KeyRef.Shape != nil {
|
||||
n.KeyRef.Shape.refs = append(n.KeyRef.Shape.refs, &n.KeyRef)
|
||||
}
|
||||
if n.ValueRef.Shape != nil {
|
||||
n.ValueRef.Shape.refs = append(n.ValueRef.Shape.refs, &n.ValueRef)
|
||||
}
|
||||
|
||||
n.refs = []*ShapeRef{}
|
||||
|
||||
n.Required = append([]string{}, n.Required...)
|
||||
n.Enum = append([]string{}, n.Enum...)
|
||||
n.EnumConsts = append([]string{}, n.EnumConsts...)
|
||||
|
||||
n.OrigShapeName = n.ShapeName
|
||||
n.API.Shapes[newName] = n
|
||||
n.ShapeName = newName
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package api
|
||||
|
||||
var shapeNameAliases = map[string]map[string]string{
|
||||
"APIGateway": map[string]string{
|
||||
"RequestValidator": "UpdateRequestValidatorOutput",
|
||||
"VpcLink": "UpdateVpcLinkOutput",
|
||||
"GatewayResponse": "UpdateGatewayResponseOutput",
|
||||
},
|
||||
"Lambda": map[string]string{
|
||||
"Concurrency": "PutFunctionConcurrencyOutput",
|
||||
},
|
||||
"Neptune": map[string]string{
|
||||
"DBClusterParameterGroupNameMessage": "ResetDBClusterParameterGroupOutput",
|
||||
"DBParameterGroupNameMessage": "ResetDBParameterGroupOutput",
|
||||
},
|
||||
"RDS": map[string]string{
|
||||
"DBClusterBacktrack": "BacktrackDBClusterOutput",
|
||||
},
|
||||
}
|
||||
+24
-10
@@ -35,29 +35,43 @@ type ShapeValidation struct {
|
||||
Type ShapeValidationType
|
||||
}
|
||||
|
||||
var validationGoCodeTmpls = template.Must(template.New("validationGoCodeTmpls").Parse(`
|
||||
var validationGoCodeTmpls = template.Must(
|
||||
template.New("validationGoCodeTmpls").
|
||||
Funcs(template.FuncMap{
|
||||
"getMin": func(ref *ShapeRef) float64 {
|
||||
if !ref.CanBeEmpty() && ref.Shape.Min <= 0 {
|
||||
return 1
|
||||
}
|
||||
|
||||
return ref.Shape.Min
|
||||
},
|
||||
}).
|
||||
Parse(`
|
||||
{{ define "requiredValue" -}}
|
||||
if s.{{ .Name }} == nil {
|
||||
if s.{{ .Name }} == nil {
|
||||
invalidParams.Add(request.NewErrParamRequired("{{ .Name }}"))
|
||||
}
|
||||
{{- end }}
|
||||
{{ define "minLen" -}}
|
||||
if s.{{ .Name }} != nil && len(s.{{ .Name }}) < {{ .Ref.Shape.Min }} {
|
||||
invalidParams.Add(request.NewErrParamMinLen("{{ .Name }}", {{ .Ref.Shape.Min }}))
|
||||
{{- $min := getMin .Ref -}}
|
||||
if s.{{ .Name }} != nil && len(s.{{ .Name }}) < {{ $min }} {
|
||||
invalidParams.Add(request.NewErrParamMinLen("{{ .Name }}", {{ $min }}))
|
||||
}
|
||||
{{- end }}
|
||||
{{ define "minLenString" -}}
|
||||
if s.{{ .Name }} != nil && len(*s.{{ .Name }}) < {{ .Ref.Shape.Min }} {
|
||||
invalidParams.Add(request.NewErrParamMinLen("{{ .Name }}", {{ .Ref.Shape.Min }}))
|
||||
{{- $min := getMin .Ref -}}
|
||||
if s.{{ .Name }} != nil && len(*s.{{ .Name }}) < {{ $min }} {
|
||||
invalidParams.Add(request.NewErrParamMinLen("{{ .Name }}", {{ $min }}))
|
||||
}
|
||||
{{- end }}
|
||||
{{ define "minVal" -}}
|
||||
if s.{{ .Name }} != nil && *s.{{ .Name }} < {{ .Ref.Shape.Min }} {
|
||||
invalidParams.Add(request.NewErrParamMinValue("{{ .Name }}", {{ .Ref.Shape.Min }}))
|
||||
{{- $min := getMin .Ref -}}
|
||||
if s.{{ .Name }} != nil && *s.{{ .Name }} < {{ $min }} {
|
||||
invalidParams.Add(request.NewErrParamMinValue("{{ .Name }}", {{ $min }}))
|
||||
}
|
||||
{{- end }}
|
||||
{{ define "nestedMapList" -}}
|
||||
if s.{{ .Name }} != nil {
|
||||
if s.{{ .Name }} != nil {
|
||||
for i, v := range s.{{ .Name }} {
|
||||
if v == nil { continue }
|
||||
if err := v.Validate(); err != nil {
|
||||
@@ -67,7 +81,7 @@ var validationGoCodeTmpls = template.Must(template.New("validationGoCodeTmpls").
|
||||
}
|
||||
{{- end }}
|
||||
{{ define "nestedStruct" -}}
|
||||
if s.{{ .Name }} != nil {
|
||||
if s.{{ .Name }} != nil {
|
||||
if err := s.{{ .Name }}.Validate(); err != nil {
|
||||
invalidParams.AddNested("{{ .Name }}", err.(request.ErrInvalidParams))
|
||||
}
|
||||
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
// +build codegen
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ShapeValueBuilder provides the logic to build the nested values for a shape.
|
||||
type ShapeValueBuilder struct{}
|
||||
|
||||
// BuildShape will recursively build the referenced shape based on the json
|
||||
// object provided. isMap will dictate how the field name is specified. If
|
||||
// isMap is true, we will expect the member name to be quotes like "Foo".
|
||||
func (b ShapeValueBuilder) BuildShape(ref *ShapeRef, shapes map[string]interface{}, isMap bool) string {
|
||||
order := make([]string, len(shapes))
|
||||
for k := range shapes {
|
||||
order = append(order, k)
|
||||
}
|
||||
sort.Strings(order)
|
||||
|
||||
ret := ""
|
||||
for _, name := range order {
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
shape := shapes[name]
|
||||
|
||||
// If the shape isn't a map, we want to export the value, since every field
|
||||
// defined in our shapes are exported.
|
||||
if len(name) > 0 && !isMap && strings.ToLower(name[0:1]) == name[0:1] {
|
||||
name = strings.Title(name)
|
||||
}
|
||||
|
||||
memName := name
|
||||
passRef := ref.Shape.MemberRefs[name]
|
||||
|
||||
if isMap {
|
||||
memName = fmt.Sprintf("%q", memName)
|
||||
passRef = &ref.Shape.ValueRef
|
||||
}
|
||||
|
||||
switch v := shape.(type) {
|
||||
case map[string]interface{}:
|
||||
ret += b.BuildComplex(name, memName, passRef, v)
|
||||
case []interface{}:
|
||||
ret += b.BuildList(name, memName, passRef, v)
|
||||
default:
|
||||
ret += b.BuildScalar(name, memName, passRef, v, ref.Shape.Payload == name)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// BuildList will construct a list shape based off the service's definition of
|
||||
// that list.
|
||||
func (b ShapeValueBuilder) BuildList(name, memName string, ref *ShapeRef, v []interface{}) string {
|
||||
ret := ""
|
||||
|
||||
if len(v) == 0 || ref == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
passRef := &ref.Shape.MemberRef
|
||||
ret += fmt.Sprintf("%s: %s {\n", memName, b.GoType(ref, false))
|
||||
ret += b.buildListElements(passRef, v)
|
||||
ret += "},\n"
|
||||
return ret
|
||||
}
|
||||
|
||||
func (b ShapeValueBuilder) buildListElements(ref *ShapeRef, v []interface{}) string {
|
||||
if len(v) == 0 || ref == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
ret := ""
|
||||
format := ""
|
||||
isComplex := false
|
||||
isList := false
|
||||
|
||||
// get format for atomic type. If it is not an atomic type,
|
||||
// get the element.
|
||||
switch v[0].(type) {
|
||||
case string:
|
||||
format = "%s"
|
||||
case bool:
|
||||
format = "%t"
|
||||
case float64:
|
||||
switch ref.Shape.Type {
|
||||
case "integer", "int64", "long":
|
||||
format = "%d"
|
||||
default:
|
||||
format = "%f"
|
||||
}
|
||||
case []interface{}:
|
||||
isList = true
|
||||
case map[string]interface{}:
|
||||
isComplex = true
|
||||
}
|
||||
|
||||
for _, elem := range v {
|
||||
if isComplex {
|
||||
ret += fmt.Sprintf("{\n%s\n},\n", b.BuildShape(ref, elem.(map[string]interface{}), ref.Shape.Type == "map"))
|
||||
} else if isList {
|
||||
ret += fmt.Sprintf("{\n%s\n},\n", b.buildListElements(&ref.Shape.MemberRef, elem.([]interface{})))
|
||||
} else {
|
||||
switch ref.Shape.Type {
|
||||
case "integer", "int64", "long":
|
||||
elem = int(elem.(float64))
|
||||
}
|
||||
ret += fmt.Sprintf("%s,\n", getValue(ref.Shape.Type, fmt.Sprintf(format, elem)))
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// BuildScalar will build atomic Go types.
|
||||
func (b ShapeValueBuilder) BuildScalar(name, memName string, ref *ShapeRef, shape interface{}, isPayload bool) string {
|
||||
if ref == nil || ref.Shape == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch v := shape.(type) {
|
||||
case bool:
|
||||
return convertToCorrectType(memName, ref.Shape.Type, fmt.Sprintf("%t", v))
|
||||
case int:
|
||||
if ref.Shape.Type == "timestamp" {
|
||||
return parseTimeString(ref, memName, fmt.Sprintf("%d", v))
|
||||
}
|
||||
return convertToCorrectType(memName, ref.Shape.Type, fmt.Sprintf("%d", v))
|
||||
case float64:
|
||||
dataType := ref.Shape.Type
|
||||
if dataType == "integer" || dataType == "int64" || dataType == "long" {
|
||||
return convertToCorrectType(memName, ref.Shape.Type, fmt.Sprintf("%d", int(shape.(float64))))
|
||||
}
|
||||
return convertToCorrectType(memName, ref.Shape.Type, fmt.Sprintf("%f", v))
|
||||
case string:
|
||||
t := ref.Shape.Type
|
||||
switch t {
|
||||
case "timestamp":
|
||||
return parseTimeString(ref, memName, fmt.Sprintf("%s", v))
|
||||
case "blob":
|
||||
if (ref.Streaming || ref.Shape.Streaming) && isPayload {
|
||||
return fmt.Sprintf("%s: aws.ReadSeekCloser(strings.NewReader(%q)),\n", memName, v)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s: []byte(%q),\n", memName, v)
|
||||
default:
|
||||
return convertToCorrectType(memName, t, v)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("Unsupported scalar type: %v", reflect.TypeOf(v)))
|
||||
}
|
||||
}
|
||||
|
||||
// BuildComplex will build the shape's value for complex types such as structs,
|
||||
// and maps.
|
||||
func (b ShapeValueBuilder) BuildComplex(name, memName string, ref *ShapeRef, v map[string]interface{}) string {
|
||||
switch ref.Shape.Type {
|
||||
case "structure":
|
||||
return fmt.Sprintf(`%s: &%s{
|
||||
%s
|
||||
},
|
||||
`, memName, b.GoType(ref, true), b.BuildShape(ref, v, false))
|
||||
case "map":
|
||||
return fmt.Sprintf(`%s: %s{
|
||||
%s
|
||||
},
|
||||
`, name, b.GoType(ref, false), b.BuildShape(ref, v, true))
|
||||
default:
|
||||
panic(fmt.Sprintf("Expected complex type but received %q", ref.Shape.Type))
|
||||
}
|
||||
}
|
||||
|
||||
// GoType returns the string of the shape's Go type identifier.
|
||||
func (b ShapeValueBuilder) GoType(ref *ShapeRef, elem bool) string {
|
||||
if ref.Shape.Type != "structure" && ref.Shape.Type != "list" && ref.Shape.Type != "map" {
|
||||
// Scalars are always pointers.
|
||||
return ref.GoTypeWithPkgName()
|
||||
}
|
||||
|
||||
prefix := ""
|
||||
if ref.Shape.Type == "list" {
|
||||
ref = &ref.Shape.MemberRef
|
||||
prefix = "[]"
|
||||
}
|
||||
|
||||
if elem {
|
||||
return prefix + ref.Shape.GoTypeWithPkgNameElem()
|
||||
}
|
||||
return prefix + ref.GoTypeWithPkgName()
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
// +build codegen
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// SmokeTestSuite defines the test suite for smoke tests.
|
||||
type SmokeTestSuite struct {
|
||||
Version int `json:"version"`
|
||||
DefaultRegion string `json:"defaultRegion"`
|
||||
TestCases []SmokeTestCase `json:"testCases"`
|
||||
}
|
||||
|
||||
// SmokeTestCase provides the definition for a integration smoke test case.
|
||||
type SmokeTestCase struct {
|
||||
OpName string `json:"operationName"`
|
||||
Input map[string]interface{} `json:"input"`
|
||||
ExpectErr bool `json:"errorExpectedFromService"`
|
||||
}
|
||||
|
||||
// BuildInputShape returns the Go code as a string for initializing the test
|
||||
// case's input shape.
|
||||
func (c SmokeTestCase) BuildInputShape(ref *ShapeRef) string {
|
||||
var b ShapeValueBuilder
|
||||
return fmt.Sprintf("&%s{\n%s\n}",
|
||||
b.GoType(ref, true),
|
||||
b.BuildShape(ref, c.Input, false),
|
||||
)
|
||||
}
|
||||
|
||||
// AttachSmokeTests attaches the smoke test cases to the API model.
|
||||
func (a *API) AttachSmokeTests(filename string) {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to open smoke tests %s, err: %v", filename, err))
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if err := json.NewDecoder(f).Decode(&a.SmokeTests); err != nil {
|
||||
panic(fmt.Sprintf("failed to decode smoke tests %s, err: %v", filename, err))
|
||||
}
|
||||
|
||||
if v := a.SmokeTests.Version; v != 1 {
|
||||
panic(fmt.Sprintf("invalid smoke test version, %d", v))
|
||||
}
|
||||
}
|
||||
|
||||
// APISmokeTestsGoCode returns the Go Code string for the smoke tests.
|
||||
func (a *API) APISmokeTestsGoCode() string {
|
||||
w := bytes.NewBuffer(nil)
|
||||
|
||||
a.resetImports()
|
||||
a.AddImport("context")
|
||||
a.AddImport("testing")
|
||||
a.AddImport("time")
|
||||
a.AddSDKImport("aws")
|
||||
a.AddSDKImport("aws/request")
|
||||
a.AddSDKImport("aws/awserr")
|
||||
a.AddSDKImport("aws/request")
|
||||
a.AddSDKImport("awstesting/integration")
|
||||
a.AddImport(a.ImportPath())
|
||||
|
||||
smokeTests := struct {
|
||||
API *API
|
||||
SmokeTestSuite
|
||||
}{
|
||||
API: a,
|
||||
SmokeTestSuite: a.SmokeTests,
|
||||
}
|
||||
|
||||
if err := smokeTestTmpl.Execute(w, smokeTests); err != nil {
|
||||
panic(fmt.Sprintf("failed to create smoke tests, %v", err))
|
||||
}
|
||||
|
||||
ignoreImports := `
|
||||
var _ aws.Config
|
||||
var _ awserr.Error
|
||||
var _ request.Request
|
||||
`
|
||||
|
||||
return a.importsGoCode() + ignoreImports + w.String()
|
||||
}
|
||||
|
||||
var smokeTestTmpl = template.Must(template.New(`smokeTestTmpl`).Parse(`
|
||||
{{- range $i, $testCase := $.TestCases }}
|
||||
{{- $op := index $.API.Operations $testCase.OpName }}
|
||||
func TestInteg_{{ printf "%02d" $i }}_{{ $op.ExportedName }}(t *testing.T) {
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), 5 *time.Second)
|
||||
defer cancelFn()
|
||||
|
||||
sess := integration.SessionWithDefaultRegion("{{ $.DefaultRegion }}")
|
||||
svc := {{ $.API.PackageName }}.New(sess)
|
||||
params := {{ $testCase.BuildInputShape $op.InputRef }}
|
||||
_, err := svc.{{ $op.ExportedName }}WithContext(ctx, params)
|
||||
{{- if $testCase.ExpectErr }}
|
||||
if err == nil {
|
||||
t.Fatalf("expect request to fail")
|
||||
}
|
||||
aerr, ok := err.(awserr.RequestFailure)
|
||||
if !ok {
|
||||
t.Fatalf("expect awserr, was %T", err)
|
||||
}
|
||||
if len(aerr.Code()) == 0 {
|
||||
t.Errorf("expect non-empty error code")
|
||||
}
|
||||
if v := aerr.Code(); v == request.ErrCodeSerialization {
|
||||
t.Errorf("expect API error code got serialization failure")
|
||||
}
|
||||
{{- else }}
|
||||
if err != nil {
|
||||
t.Errorf("expect no error, got %v", err)
|
||||
}
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
`))
|
||||
+2
-2
@@ -47,8 +47,8 @@ func (a *API) WaitersGoCode() string {
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, "import (\n%q\n\n%q\n%q\n)",
|
||||
"time",
|
||||
"github.com/aws/aws-sdk-go/aws",
|
||||
"github.com/aws/aws-sdk-go/aws/request",
|
||||
SDKImportRoot+"/aws",
|
||||
SDKImportRoot+"/aws/request",
|
||||
)
|
||||
|
||||
for _, w := range a.Waiters {
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// +build codegen
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/aws/aws-sdk-go/private/model/api"
|
||||
)
|
||||
|
||||
func main() {
|
||||
glob := filepath.FromSlash(os.Args[1])
|
||||
modelPaths, err := api.ExpandModelGlobPath(glob)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "failed to expand glob, %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
_, excluded := api.TrimModelServiceVersions(modelPaths)
|
||||
|
||||
for _, exclude := range excluded {
|
||||
modelPath := filepath.Dir(exclude)
|
||||
fmt.Println("removing:", modelPath)
|
||||
os.RemoveAll(modelPath)
|
||||
}
|
||||
}
|
||||
+128
-135
@@ -13,7 +13,6 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime/debug"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -21,87 +20,21 @@ import (
|
||||
"github.com/aws/aws-sdk-go/private/util"
|
||||
)
|
||||
|
||||
type generateInfo struct {
|
||||
*api.API
|
||||
PackageDir string
|
||||
}
|
||||
func usage() {
|
||||
fmt.Fprintln(os.Stderr, `Usage: api-gen <options> [model path | file path]
|
||||
Loads API models from file and generates SDK clients from the models.
|
||||
|
||||
var excludeServices = map[string]struct{}{
|
||||
"importexport": {},
|
||||
}
|
||||
The model path arguments can be globs, or paths to individual files. The
|
||||
utiliity requires that the API model files follow the following pattern:
|
||||
|
||||
// newGenerateInfo initializes the service API's folder structure for a specific service.
|
||||
// If the SERVICES environment variable is set, and this service is not apart of the list
|
||||
// this service will be skipped.
|
||||
func newGenerateInfo(modelFile, svcPath, svcImportPath string) *generateInfo {
|
||||
g := &generateInfo{API: &api.API{SvcClientImportPath: svcImportPath, BaseCrosslinkURL: "https://docs.aws.amazon.com"}}
|
||||
g.API.Attach(modelFile)
|
||||
<root>/<servicename>/<api-version>/<model json files>
|
||||
|
||||
if _, ok := excludeServices[g.API.PackageName()]; ok {
|
||||
return nil
|
||||
}
|
||||
e.g:
|
||||
|
||||
paginatorsFile := strings.Replace(modelFile, "api-2.json", "paginators-1.json", -1)
|
||||
if _, err := os.Stat(paginatorsFile); err == nil {
|
||||
g.API.AttachPaginators(paginatorsFile)
|
||||
} else if !os.IsNotExist(err) {
|
||||
fmt.Println("api-2.json error:", err)
|
||||
}
|
||||
./models/apis/s3/2006-03-01/*.json
|
||||
|
||||
docsFile := strings.Replace(modelFile, "api-2.json", "docs-2.json", -1)
|
||||
if _, err := os.Stat(docsFile); err == nil {
|
||||
g.API.AttachDocs(docsFile)
|
||||
} else {
|
||||
fmt.Println("docs-2.json error:", err)
|
||||
}
|
||||
|
||||
waitersFile := strings.Replace(modelFile, "api-2.json", "waiters-2.json", -1)
|
||||
if _, err := os.Stat(waitersFile); err == nil {
|
||||
g.API.AttachWaiters(waitersFile)
|
||||
} else if !os.IsNotExist(err) {
|
||||
fmt.Println("waiters-2.json error:", err)
|
||||
}
|
||||
|
||||
examplesFile := strings.Replace(modelFile, "api-2.json", "examples-1.json", -1)
|
||||
if _, err := os.Stat(examplesFile); err == nil {
|
||||
g.API.AttachExamples(examplesFile)
|
||||
} else if !os.IsNotExist(err) {
|
||||
fmt.Println("examples-1.json error:", err)
|
||||
}
|
||||
|
||||
// pkgDocAddonsFile := strings.Replace(modelFile, "api-2.json", "go-pkg-doc.gotmpl", -1)
|
||||
// if _, err := os.Stat(pkgDocAddonsFile); err == nil {
|
||||
// g.API.AttachPackageDocAddons(pkgDocAddonsFile)
|
||||
// } else if !os.IsNotExist(err) {
|
||||
// fmt.Println("go-pkg-doc.gotmpl error:", err)
|
||||
// }
|
||||
|
||||
g.API.Setup()
|
||||
|
||||
if svc := os.Getenv("SERVICES"); svc != "" {
|
||||
svcs := strings.Split(svc, ",")
|
||||
|
||||
included := false
|
||||
for _, s := range svcs {
|
||||
if s == g.API.PackageName() {
|
||||
included = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !included {
|
||||
// skip this non-included service
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ensure the directory exists
|
||||
pkgDir := filepath.Join(svcPath, g.API.PackageName())
|
||||
os.MkdirAll(pkgDir, 0775)
|
||||
os.MkdirAll(filepath.Join(pkgDir, g.API.InterfacePackageName()), 0775)
|
||||
|
||||
g.PackageDir = pkgDir
|
||||
|
||||
return g
|
||||
Flags:`)
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
// Generates service api, examples, and interface from api json definition files.
|
||||
@@ -112,88 +45,109 @@ func newGenerateInfo(modelFile, svcPath, svcImportPath string) *generateInfo {
|
||||
// Env:
|
||||
// SERVICES comma separated list of services to generate.
|
||||
func main() {
|
||||
var svcPath, sessionPath, svcImportPath string
|
||||
flag.StringVar(&svcPath, "path", "service", "directory to generate service clients in")
|
||||
flag.StringVar(&sessionPath, "sessionPath", filepath.Join("aws", "session"), "generate session service client factories")
|
||||
flag.StringVar(&svcImportPath, "svc-import-path", "github.com/aws/aws-sdk-go/service", "namespace to generate service client Go code import path under")
|
||||
var svcPath, svcImportPath string
|
||||
flag.StringVar(&svcPath, "path", "service",
|
||||
"The `path` to generate service clients in to.",
|
||||
)
|
||||
flag.StringVar(&svcImportPath, "svc-import-path",
|
||||
api.SDKImportRoot+"/service",
|
||||
"The Go `import path` to generate client to be under.",
|
||||
)
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
api.Bootstrap()
|
||||
|
||||
files := []string{}
|
||||
for i := 0; i < flag.NArg(); i++ {
|
||||
file := flag.Arg(i)
|
||||
if strings.Contains(file, "*") {
|
||||
paths, _ := filepath.Glob(file)
|
||||
files = append(files, paths...)
|
||||
} else {
|
||||
files = append(files, file)
|
||||
if len(os.Getenv("AWS_SDK_CODEGEN_DEBUG")) != 0 {
|
||||
api.LogDebug(os.Stdout)
|
||||
}
|
||||
|
||||
// Make sure all paths are based on platform's pathing not Unix
|
||||
globs := flag.Args()
|
||||
for i, g := range globs {
|
||||
globs[i] = filepath.FromSlash(g)
|
||||
}
|
||||
svcPath = filepath.FromSlash(svcPath)
|
||||
|
||||
modelPaths, err := api.ExpandModelGlobPath(globs...)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "failed to glob file pattern", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
modelPaths, _ = api.TrimModelServiceVersions(modelPaths)
|
||||
|
||||
apis, err := api.LoadAPIs(modelPaths, svcImportPath)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "failed to load API models", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if len(apis) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "expected to load models, but found none")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if v := os.Getenv("SERVICES"); len(v) != 0 {
|
||||
svcs := strings.Split(v, ",")
|
||||
for pkgName, a := range apis {
|
||||
var found bool
|
||||
for _, include := range svcs {
|
||||
if a.PackageName() == include {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
delete(apis, pkgName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for svcName := range excludeServices {
|
||||
if strings.Contains(os.Getenv("SERVICES"), svcName) {
|
||||
fmt.Fprintf(os.Stderr, "Service %s is not supported\n", svcName)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Strings(files)
|
||||
|
||||
// Remove old API versions from list
|
||||
m := map[string]bool{}
|
||||
// caches paths to ensure we are not overriding previously generated
|
||||
// code.
|
||||
var wg sync.WaitGroup
|
||||
servicePaths := map[string]struct{}{}
|
||||
|
||||
for i := range files {
|
||||
idx := len(files) - 1 - i
|
||||
parts := strings.Split(files[idx], string(filepath.Separator))
|
||||
svc := parts[len(parts)-3] // service name is 2nd-to-last component
|
||||
|
||||
if m[svc] {
|
||||
files[idx] = "" // wipe this one out if we already saw the service
|
||||
}
|
||||
m[svc] = true
|
||||
}
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
for i := range files {
|
||||
filename := files[i]
|
||||
if filename == "" { // empty file
|
||||
for _, a := range apis {
|
||||
if _, ok := excludeServices[a.PackageName()]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
genInfo := newGenerateInfo(filename, svcPath, svcImportPath)
|
||||
if genInfo == nil {
|
||||
continue
|
||||
}
|
||||
if _, ok := excludeServices[genInfo.API.PackageName()]; ok {
|
||||
// Skip services not yet supported.
|
||||
continue
|
||||
}
|
||||
// Create the output path for the model.
|
||||
pkgDir := filepath.Join(svcPath, a.PackageName())
|
||||
os.MkdirAll(filepath.Join(pkgDir, a.InterfacePackageName()), 0775)
|
||||
|
||||
if _, ok := servicePaths[genInfo.PackageDir]; ok {
|
||||
fmt.Fprintf(os.Stderr, "Path %q has already been generated", genInfo.PackageDir)
|
||||
if _, ok := servicePaths[pkgDir]; ok {
|
||||
fmt.Fprintf(os.Stderr,
|
||||
"attempted to generate a client into %s twice. Second model package, %v\n",
|
||||
pkgDir, a.PackageName())
|
||||
os.Exit(1)
|
||||
}
|
||||
servicePaths[pkgDir] = struct{}{}
|
||||
|
||||
servicePaths[genInfo.PackageDir] = struct{}{}
|
||||
g := &generateInfo{
|
||||
API: a,
|
||||
PackageDir: pkgDir,
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func(g *generateInfo, filename string) {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
writeServiceFiles(g, filename)
|
||||
}(genInfo, filename)
|
||||
writeServiceFiles(g, pkgDir)
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func writeServiceFiles(g *generateInfo, filename string) {
|
||||
type generateInfo struct {
|
||||
*api.API
|
||||
PackageDir string
|
||||
}
|
||||
|
||||
var excludeServices = map[string]struct{}{
|
||||
"importexport": {},
|
||||
}
|
||||
|
||||
func writeServiceFiles(g *generateInfo, pkgDir string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error generating %s\n%s\n%s\n",
|
||||
filename, r, debug.Stack())
|
||||
pkgDir, r, debug.Stack())
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
@@ -209,6 +163,18 @@ func writeServiceFiles(g *generateInfo, filename string) {
|
||||
Must(writeWaitersFile(g))
|
||||
Must(writeAPIErrorsFile(g))
|
||||
Must(writeExamplesFile(g))
|
||||
|
||||
if g.API.HasEventStream {
|
||||
Must(writeAPIEventStreamTestFile(g))
|
||||
}
|
||||
|
||||
if g.API.PackageName() == "s3" {
|
||||
Must(writeS3ManagerUploadInputFile(g))
|
||||
}
|
||||
|
||||
if len(g.API.SmokeTests.TestCases) > 0 {
|
||||
Must(writeAPISmokeTestsFile(g))
|
||||
}
|
||||
}
|
||||
|
||||
// Must will panic if the error passed in is not nil.
|
||||
@@ -313,3 +279,30 @@ func writeAPIErrorsFile(g *generateInfo) error {
|
||||
g.API.APIErrorsGoCode(),
|
||||
)
|
||||
}
|
||||
|
||||
func writeAPIEventStreamTestFile(g *generateInfo) error {
|
||||
return writeGoFile(filepath.Join(g.PackageDir, "eventstream_test.go"),
|
||||
codeLayout,
|
||||
"// +build go1.6\n",
|
||||
g.API.PackageName(),
|
||||
g.API.APIEventStreamTestGoCode(),
|
||||
)
|
||||
}
|
||||
|
||||
func writeS3ManagerUploadInputFile(g *generateInfo) error {
|
||||
return writeGoFile(filepath.Join(g.PackageDir, "s3manager", "upload_input.go"),
|
||||
codeLayout,
|
||||
"",
|
||||
"s3manager",
|
||||
api.S3ManagerUploadInputGoCode(g.API),
|
||||
)
|
||||
}
|
||||
|
||||
func writeAPISmokeTestsFile(g *generateInfo) error {
|
||||
return writeGoFile(filepath.Join(g.PackageDir, "integ_test.go"),
|
||||
codeLayout,
|
||||
"// +build go1.10,integration\n",
|
||||
g.API.PackageName()+"_test",
|
||||
g.API.APISmokeTestsGoCode(),
|
||||
)
|
||||
}
|
||||
|
||||
+3
-1
@@ -45,7 +45,9 @@ func main() {
|
||||
}
|
||||
}()
|
||||
|
||||
if err := endpoints.CodeGenModel(modelFile, outFile); err != nil {
|
||||
if err := endpoints.CodeGenModel(modelFile, outFile, func(o *endpoints.CodeGenOptions) {
|
||||
o.DisableGenerateServiceIDs = true
|
||||
}); err != nil {
|
||||
exitErrorf("failed to codegen model, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user