Skip to content

Commit 210b64d

Browse files
Create sdk package (#221)
Description of changes: Creates a new `sdk` package that strictly serves the purpose of loading the operations and shapes from the AWS SDK. This is useful to isolate creating the custom fields that need to be injected during this stage. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent a328190 commit 210b64d

File tree

15 files changed

+248
-214
lines changed

15 files changed

+248
-214
lines changed

cmd/ack-generate/command/common.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
ackgenerate "github.com/aws-controllers-k8s/code-generator/pkg/generate/ack"
3131
ackgenconfig "github.com/aws-controllers-k8s/code-generator/pkg/generate/config"
3232
ackmodel "github.com/aws-controllers-k8s/code-generator/pkg/model"
33+
acksdk "github.com/aws-controllers-k8s/code-generator/pkg/sdk"
3334
"github.com/aws-controllers-k8s/code-generator/pkg/util"
3435
k8sversion "k8s.io/apimachinery/pkg/version"
3536
)
@@ -236,7 +237,7 @@ func loadModel(svcAlias string, apiVersion string) (*ackmodel.Model, error) {
236237
modelName = svcAlias
237238
}
238239

239-
sdkHelper := ackmodel.NewSDKHelper(sdkDir)
240+
sdkHelper := acksdk.NewHelper(sdkDir)
240241
sdkAPI, err := sdkHelper.API(modelName)
241242
if err != nil {
242243
retryModelName, err := FallBackFindServiceID(sdkDir, svcAlias)

cmd/ack-generate/command/crossplane.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ import (
2828
ackgenerate "github.com/aws-controllers-k8s/code-generator/pkg/generate/ack"
2929
ackgenconfig "github.com/aws-controllers-k8s/code-generator/pkg/generate/config"
3030
cpgenerate "github.com/aws-controllers-k8s/code-generator/pkg/generate/crossplane"
31-
"github.com/aws-controllers-k8s/code-generator/pkg/model"
3231
ackmodel "github.com/aws-controllers-k8s/code-generator/pkg/model"
32+
acksdk "github.com/aws-controllers-k8s/code-generator/pkg/sdk"
3333
)
3434

3535
// crossplaneCmd is the command that generates Crossplane API types
@@ -70,7 +70,7 @@ func generateCrossplane(_ *cobra.Command, args []string) error {
7070
if err != nil {
7171
return err
7272
}
73-
sdkHelper := model.NewSDKHelper(sdkDir)
73+
sdkHelper := acksdk.NewHelper(sdkDir)
7474
sdkHelper.APIGroupSuffix = "aws.crossplane.io"
7575
sdkAPI, err := sdkHelper.API(svcAlias)
7676
if err != nil {

pkg/generate/code/check.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,5 +192,3 @@ func checkRequiredFieldsMissingFromShapeReadMany(
192192
result = fmt.Sprintf("%s == nil", resVarPath)
193193
return fmt.Sprintf("%sreturn %s\n", indent, result)
194194
}
195-
196-

pkg/generate/code/check_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,4 @@ func TestCheckRequiredFields_StatusField_ReadMany(t *testing.T) {
135135
strings.TrimSpace(expRequiredFieldsCode),
136136
strings.TrimSpace(gotCode),
137137
)
138-
}
138+
}

pkg/generate/code/set_sdk_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1799,4 +1799,4 @@ func TestSetSDK_EC2_VPC_ReadMany(t *testing.T) {
17991799
expected,
18001800
code.SetSDK(crd.Config(), crd, model.OpTypeList, "r.ko", "res", 1),
18011801
)
1802-
}
1802+
}

pkg/model/crd.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ func (r *CRD) GetOutputShape(
472472
wrapperOutputShape, err := r.getWrapperOutputShape(outputShape,
473473
*wrapperFieldPath)
474474
if err != nil {
475-
msg := fmt.Sprintf("Unable to unwrap the output shape: %s " +
475+
msg := fmt.Sprintf("Unable to unwrap the output shape: %s "+
476476
"with field path override: %s. error: %v",
477477
outputShape.OrigShapeName, *wrapperFieldPath, err)
478478
panic(msg)
@@ -506,7 +506,7 @@ func (r *CRD) getWrapperOutputShape(
506506
// wrapper field must be structure; otherwise cannot unpack
507507
if memberRef.Shape.Type != "structure" {
508508
return nil, fmt.Errorf(
509-
"output wrapper overrides can only contain fields of type" +
509+
"output wrapper overrides can only contain fields of type"+
510510
" 'structure'. Found wrapper override field %s of type '%s'",
511511
wrapperField, memberRef.Shape.Type)
512512
}

pkg/model/field.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func NewField(
9696
}
9797

9898
if shape != nil {
99-
gte, gt, gtwp = cleanGoType(crd.sdkAPI, crd.cfg, shape, cfg)
99+
gte, gt, gtwp = CleanGoType(crd.sdkAPI, crd.cfg, shape, cfg)
100100
} else {
101101
gte = "string"
102102
gt = "*string"

pkg/model/model.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -695,8 +695,8 @@ func (m *Model) GetConfig() *ackgenconfig.Config {
695695
// e.g. "sns.services.k8s.aws"
696696
func (m *Model) APIGroup() string {
697697
suffix := "services.k8s.aws"
698-
if m.SDKAPI.apiGroupSuffix != "" {
699-
suffix = m.SDKAPI.apiGroupSuffix
698+
if m.SDKAPI.APIGroupSuffix != "" {
699+
suffix = m.SDKAPI.APIGroupSuffix
700700
}
701701
return fmt.Sprintf("%s.%s", m.servicePackageName, suffix)
702702
}

pkg/model/multiversion/manager.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
ackgenconfig "github.com/aws-controllers-k8s/code-generator/pkg/generate/config"
2424
ackmetadata "github.com/aws-controllers-k8s/code-generator/pkg/metadata"
2525
ackmodel "github.com/aws-controllers-k8s/code-generator/pkg/model"
26+
acksdk "github.com/aws-controllers-k8s/code-generator/pkg/sdk"
2627
"github.com/aws-controllers-k8s/code-generator/pkg/util"
2728
)
2829

@@ -71,7 +72,7 @@ func NewAPIVersionManager(
7172
return nil, fmt.Errorf("cannot read sdk git repository: %v", err)
7273
}
7374

74-
SDKAPIHelper := ackmodel.NewSDKHelper(sdkCacheDir)
75+
SDKAPIHelper := acksdk.NewHelper(sdkCacheDir)
7576

7677
// create model for each non-deprecated api version
7778
models := map[string]*ackmodel.Model{}

pkg/model/sdk_helper.go renamed to pkg/model/sdk_api.go

Lines changed: 54 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -14,177 +14,33 @@
1414
package model
1515

1616
import (
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
17834
type 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
285106
func (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
384216
func 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

Comments
 (0)