1414package model
1515
1616import (
17- "errors"
18- "fmt"
19- "io/ioutil"
20- "os"
21- "path/filepath"
22- "sort"
2317 "strings"
2418
25- "gopkg.in/src-d/go-git.v4 "
19+ awssdkmodel "github.com/aws/aws-sdk-go/private/model/api "
2620
2721 ackgenconfig "github.com/aws-controllers-k8s/code-generator/pkg/generate/config"
2822 "github.com/aws-controllers-k8s/code-generator/pkg/names"
2923 "github.com/aws-controllers-k8s/code-generator/pkg/util"
30-
31- awssdkmodel "github.com/aws/aws-sdk-go/private/model/api"
3224)
3325
34- var (
35- ErrInvalidVersionDirectory = errors .New (
36- "expected to find only directories in api model directory but found non-directory" ,
37- )
38- ErrNoValidVersionDirectory = errors .New (
39- "no valid version directories found" ,
40- )
41- ErrServiceNotFound = errors .New (
42- "no such service" ,
43- )
44- ErrAPIVersionNotFound = errors .New (
45- "no such api version" ,
46- )
26+ const (
27+ // ConflictingNameSuffix is appended to type names when they overlap with
28+ // well-known common struct names for things like a CRD itself, or its
29+ // Spec/Status subfield struct type name.
30+ ConflictingNameSuffix = "_SDK"
4731)
4832
49- // SDKHelper is a helper struct that helps work with the aws-sdk-go models and
50- // API model loader
51- type SDKHelper struct {
52- gitRepository * git.Repository
53- basePath string
54- loader * awssdkmodel.Loader
55- // Default is set by `FirstAPIVersion`
56- apiVersion string
57- // Default is "services.k8s.aws"
58- APIGroupSuffix string
59- }
60-
61- // NewSDKHelper returns a new SDKHelper object
62- func NewSDKHelper (basePath string ) * SDKHelper {
63- return & SDKHelper {
64- basePath : basePath ,
65- loader : & awssdkmodel.Loader {
66- BaseImport : basePath ,
67- IgnoreUnsupportedAPIs : true ,
68- },
69- }
70- }
71-
72- // WithSDKVersion checks out the sdk git repository to the provided version. To use
73- // this function h.basePath should point to a git repository.
74- func (h * SDKHelper ) WithSDKVersion (version string ) error {
75- if h .gitRepository == nil {
76- gitRepository , err := util .LoadRepository (h .basePath )
77- if err != nil {
78- return fmt .Errorf ("error loading repository from %s: %v" , h .basePath , err )
79- }
80- h .gitRepository = gitRepository
81- }
82-
83- err := util .CheckoutRepositoryTag (h .gitRepository , version )
84- if err != nil {
85- return fmt .Errorf ("cannot checkout tag %s: %v" , version , err )
86- }
87- return nil
88- }
89-
90- // WithAPIVersion sets the `apiVersion` field.
91- func (h * SDKHelper ) WithAPIVersion (apiVersion string ) {
92- h .apiVersion = apiVersion
93- }
94-
95- // API returns the aws-sdk-go API model for a supplied service model name.
96- func (h * SDKHelper ) API (serviceModelName string ) (* SDKAPI , error ) {
97- modelPath , _ , err := h .ModelAndDocsPath (serviceModelName )
98- if err != nil {
99- return nil , err
100- }
101- apis , err := h .loader .Load ([]string {modelPath })
102- if err != nil {
103- return nil , err
104- }
105- // apis is a map, keyed by the service alias, of pointers to aws-sdk-go
106- // model API objects
107- for _ , api := range apis {
108- // If we don't do this, we can end up with panic()'s like this:
109- // panic: assignment to entry in nil map
110- // when trying to execute Shape.GoType().
111- //
112- // Calling API.ServicePackageDoc() ends up resetting the API.imports
113- // unexported map variable...
114- _ = api .ServicePackageDoc ()
115- return & SDKAPI {api , nil , nil , h .APIGroupSuffix }, nil
116- }
117- return nil , ErrServiceNotFound
118- }
119-
120- // ModelAndDocsPath returns two string paths to the supplied service's API and
121- // doc JSON files
122- func (h * SDKHelper ) ModelAndDocsPath (
123- serviceModelName string ,
124- ) (string , string , error ) {
125- if h .apiVersion == "" {
126- apiVersion , err := h .FirstAPIVersion (serviceModelName )
127- if err != nil {
128- return "" , "" , err
129- }
130- h .apiVersion = apiVersion
131- }
132- versionPath := filepath .Join (
133- h .basePath , "models" , "apis" , serviceModelName , h .apiVersion ,
134- )
135- modelPath := filepath .Join (versionPath , "api-2.json" )
136- docsPath := filepath .Join (versionPath , "docs-2.json" )
137- return modelPath , docsPath , nil
138- }
139-
140- // FirstAPIVersion returns the first found API version for a service API.
141- // (e.h. "2012-10-03")
142- func (h * SDKHelper ) FirstAPIVersion (serviceModelName string ) (string , error ) {
143- versions , err := h .GetAPIVersions (serviceModelName )
144- if err != nil {
145- return "" , err
146- }
147- sort .Strings (versions )
148- return versions [0 ], nil
149- }
150-
151- // GetAPIVersions returns the list of API Versions found in a service directory.
152- func (h * SDKHelper ) GetAPIVersions (serviceModelName string ) ([]string , error ) {
153- apiPath := filepath .Join (h .basePath , "models" , "apis" , serviceModelName )
154- versionDirs , err := ioutil .ReadDir (apiPath )
155- if err != nil {
156- return nil , err
157- }
158- versions := []string {}
159- for _ , f := range versionDirs {
160- version := f .Name ()
161- fp := filepath .Join (apiPath , version )
162- fi , err := os .Lstat (fp )
163- if err != nil {
164- return nil , err
165- }
166- if ! fi .IsDir () {
167- return nil , fmt .Errorf ("found %s: %v" , version , ErrInvalidVersionDirectory )
168- }
169- versions = append (versions , version )
170- }
171- if len (versions ) == 0 {
172- return nil , ErrNoValidVersionDirectory
173- }
174- return versions , nil
175- }
176-
17733// SDKAPI contains an API model for a single AWS service API
17834type SDKAPI struct {
179- API * awssdkmodel.API
35+ API * awssdkmodel.API
36+ APIGroupSuffix string
18037 // A map of operation type and resource name to
18138 // aws-sdk-go/private/model/api.Operation structs
18239 opMap * OperationMap
18340 // Map, keyed by original Shape GoTypeElem(), with the values being a
18441 // renamed type name (due to conflicting names)
18542 typeRenames map [string ]string
18643 // Default is "services.k8s.aws"
187- apiGroupSuffix string
18844}
18945
19046// GetPayloads returns a slice of strings of Shape names representing input and
@@ -245,41 +101,6 @@ func (a *SDKAPI) GetOutputShapeRef(
245101 return getMemberByPath (op .OutputRef .Shape , path )
246102}
247103
248- // getMemberByPath returns a ShapeRef given a root Shape and a dot-notation
249- // object search path. Given the explicit type check for list type members
250- // both ".." and "." notations work currently.
251- // TODO: Add support for other types such as map.
252- func getMemberByPath (
253- shape * awssdkmodel.Shape ,
254- path string ,
255- ) (* awssdkmodel.ShapeRef , bool ) {
256- elements := strings .Split (path , "." )
257- last := len (elements ) - 1
258- for x , elem := range elements {
259- if elem == "" {
260- continue
261- }
262- if shape == nil {
263- return nil , false
264- }
265- shapeRef , ok := shape .MemberRefs [elem ]
266- if ! ok {
267- return nil , false
268- }
269- if x == last {
270- return shapeRef , true
271- }
272- elemType := shapeRef .Shape .Type
273- switch elemType {
274- case "list" :
275- shape = shapeRef .Shape .MemberRef .Shape
276- default :
277- shape = shapeRef .Shape
278- }
279- }
280- return nil , false
281- }
282-
283104// CRDNames returns a slice of names structs for all top-level resources in the
284105// API
285106func (a * SDKAPI ) CRDNames (cfg * ackgenconfig.Config ) []names.Names {
@@ -380,6 +201,17 @@ func (a *SDKAPI) APIInterfaceTypeName() string {
380201 return a .API .StructName ()
381202}
382203
204+ // NewSDKAPI returns a pointer to a new `ackmodel.SDKAPI` struct that describes
205+ // the AWS SDK API and its respective groupings, mappings and renamings.
206+ func NewSDKAPI (api * awssdkmodel.API , apiGroupSuffix string ) * SDKAPI {
207+ return & SDKAPI {
208+ API : api ,
209+ APIGroupSuffix : apiGroupSuffix ,
210+ opMap : nil ,
211+ typeRenames : nil ,
212+ }
213+ }
214+
383215// Override the operation type and/or resource name if specified in config
384216func getOpTypeAndResourceName (opID string , cfg * ackgenconfig.Config ) ([]OpType , string ) {
385217 opType , resName := GetOpTypeAndResourceNameFromOpID (opID , cfg )
@@ -400,3 +232,38 @@ func getOpTypeAndResourceName(opID string, cfg *ackgenconfig.Config) ([]OpType,
400232 }
401233 return opTypes , resName
402234}
235+
236+ // getMemberByPath returns a ShapeRef given a root Shape and a dot-notation
237+ // object search path. Given the explicit type check for list type members
238+ // both ".." and "." notations work currently.
239+ // TODO: Add support for other types such as map.
240+ func getMemberByPath (
241+ shape * awssdkmodel.Shape ,
242+ path string ,
243+ ) (* awssdkmodel.ShapeRef , bool ) {
244+ elements := strings .Split (path , "." )
245+ last := len (elements ) - 1
246+ for x , elem := range elements {
247+ if elem == "" {
248+ continue
249+ }
250+ if shape == nil {
251+ return nil , false
252+ }
253+ shapeRef , ok := shape .MemberRefs [elem ]
254+ if ! ok {
255+ return nil , false
256+ }
257+ if x == last {
258+ return shapeRef , true
259+ }
260+ elemType := shapeRef .Shape .Type
261+ switch elemType {
262+ case "list" :
263+ shape = shapeRef .Shape .MemberRef .Shape
264+ default :
265+ shape = shapeRef .Shape
266+ }
267+ }
268+ return nil , false
269+ }
0 commit comments