1
0
Fork 0
mirror of https://github.com/Luzifer/cloudkeys-go.git synced 2024-11-15 01:12:44 +00:00
cloudkeys-go/vendor/github.com/aws/aws-sdk-go/private/model/api/load.go

197 lines
4.7 KiB
Go
Raw Normal View History

// +build codegen
package api
import (
"encoding/json"
"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) {
a.path = filepath.Dir(filename)
f, err := os.Open(filename)
defer f.Close()
if err != nil {
panic(err)
}
if err := json.NewDecoder(f).Decode(a); err != nil {
panic(fmt.Errorf("failed to decode %s, err: %v", filename, err))
}
}
// AttachString will unmarshal a raw JSON string, and setup the
// API if not already done so.
func (a *API) AttachString(str string) {
json.Unmarshal([]byte(str), a)
if !a.initialized {
a.Setup()
}
}
// Setup initializes the API.
func (a *API) Setup() {
a.setServiceAliaseName()
a.setMetadataEndpointsKey()
a.writeShapeNames()
a.resolveReferences()
if !a.NoRemoveUnusedShapes {
a.removeUnusedShapes()
}
a.fixStutterNames()
a.renameExportable()
a.applyShapeNameAliases()
a.createInputOutputShapes()
a.renameAPIPayloadShapes()
a.renameCollidingFields()
a.updateTopLevelShapeReferences()
a.suppressHTTP2EventStreams()
a.setupEventStreams()
a.findEndpointDiscoveryOp()
a.customizationPasses()
if !a.NoRemoveUnusedShapes {
a.removeUnusedShapes()
}
if !a.NoValidataShapeMethods {
a.addShapeValidations()
}
a.initialized = true
}