| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- // +build codegen
- // Command aws-gen-gocli parses a JSON description of an AWS API and generates a
- // Go file containing a client for the API.
- //
- // aws-gen-gocli apis/s3/2006-03-03/api-2.json
- package main
- import (
- "flag"
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
- "runtime/debug"
- "strings"
- "sync"
- "github.com/aws/aws-sdk-go/private/model/api"
- "github.com/aws/aws-sdk-go/private/util"
- )
- 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.
- The model path arguments can be globs, or paths to individual files. The
- utiliity requires that the API model files follow the following pattern:
- <root>/<servicename>/<api-version>/<model json files>
- e.g:
- ./models/apis/s3/2006-03-01/*.json
- Flags:`)
- flag.PrintDefaults()
- }
- // Generates service api, examples, and interface from api json definition files.
- //
- // Flags:
- // -path alternative service path to write generated files to for each service.
- //
- // Env:
- // SERVICES comma separated list of services to generate.
- func main() {
- var svcPath, svcImportPath string
- flag.StringVar(&svcPath, "path", "service",
- "The `path` to generate service clients in to.",
- )
- flag.StringVar(&svcImportPath, "svc-import-path",
- "github.com/aws/aws-sdk-go/service",
- "The Go `import path` to generate client to be under.",
- )
- flag.Usage = usage
- flag.Parse()
- 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)
- }
- }
- }
- var wg sync.WaitGroup
- servicePaths := map[string]struct{}{}
- for _, a := range apis {
- if _, ok := excludeServices[a.PackageName()]; ok {
- 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[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{}{}
- g := &generateInfo{
- API: a,
- PackageDir: pkgDir,
- }
- wg.Add(1)
- go func() {
- defer wg.Done()
- writeServiceFiles(g, pkgDir)
- }()
- }
- wg.Wait()
- }
- 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",
- pkgDir, r, debug.Stack())
- os.Exit(1)
- }
- }()
- fmt.Printf("Generating %s (%s)...\n",
- g.API.PackageName(), g.API.Metadata.APIVersion)
- // write files for service client and API
- Must(writeServiceDocFile(g))
- Must(writeAPIFile(g))
- Must(writeServiceFile(g))
- Must(writeInterfaceFile(g))
- 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.
- func Must(err error) {
- if err != nil {
- panic(err)
- }
- }
- const codeLayout = `// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
- %s
- package %s
- %s
- `
- func writeGoFile(file string, layout string, args ...interface{}) error {
- return ioutil.WriteFile(file, []byte(util.GoFmt(fmt.Sprintf(layout, args...))), 0664)
- }
- // writeServiceDocFile generates the documentation for service package.
- func writeServiceDocFile(g *generateInfo) error {
- return writeGoFile(filepath.Join(g.PackageDir, "doc.go"),
- codeLayout,
- strings.TrimSpace(g.API.ServicePackageDoc()),
- g.API.PackageName(),
- "",
- )
- }
- // writeExamplesFile writes out the service example file.
- func writeExamplesFile(g *generateInfo) error {
- code := g.API.ExamplesGoCode()
- if len(code) > 0 {
- return writeGoFile(filepath.Join(g.PackageDir, "examples_test.go"),
- codeLayout,
- "",
- g.API.PackageName()+"_test",
- code,
- )
- }
- return nil
- }
- // writeServiceFile writes out the service initialization file.
- func writeServiceFile(g *generateInfo) error {
- return writeGoFile(filepath.Join(g.PackageDir, "service.go"),
- codeLayout,
- "",
- g.API.PackageName(),
- g.API.ServiceGoCode(),
- )
- }
- // writeInterfaceFile writes out the service interface file.
- func writeInterfaceFile(g *generateInfo) error {
- const pkgDoc = `
- // Package %s provides an interface to enable mocking the %s 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.`
- return writeGoFile(filepath.Join(g.PackageDir, g.API.InterfacePackageName(), "interface.go"),
- codeLayout,
- fmt.Sprintf(pkgDoc, g.API.InterfacePackageName(), g.API.Metadata.ServiceFullName),
- g.API.InterfacePackageName(),
- g.API.InterfaceGoCode(),
- )
- }
- func writeWaitersFile(g *generateInfo) error {
- if len(g.API.Waiters) == 0 {
- return nil
- }
- return writeGoFile(filepath.Join(g.PackageDir, "waiters.go"),
- codeLayout,
- "",
- g.API.PackageName(),
- g.API.WaitersGoCode(),
- )
- }
- // writeAPIFile writes out the service API file.
- func writeAPIFile(g *generateInfo) error {
- return writeGoFile(filepath.Join(g.PackageDir, "api.go"),
- codeLayout,
- "",
- g.API.PackageName(),
- g.API.APIGoCode(),
- )
- }
- // writeAPIErrorsFile writes out the service API errors file.
- func writeAPIErrorsFile(g *generateInfo) error {
- return writeGoFile(filepath.Join(g.PackageDir, "errors.go"),
- codeLayout,
- "",
- g.API.PackageName(),
- 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(),
- )
- }
|