Generate new version of SDK resources and Add Tests (#331)

This commit is contained in:
Todd Knight authored and GitHub committed 2020-09-08 16:27:51 -04:00
1 parent 96e4b1cdba
commit c3ecea172d
93 files changed
+3414 -2826

No files matched your search

+17 -22
View File
@@ -47,6 +47,10 @@ type structInfo struct {
// the attributes map.
subtypeName string
// For non-top-level collections, this can be used to indicate the name of
// the argument that should be used
parentTypeName string
// mappings of names of resources and param names for sub slice types, e.g.
// role principals and group members
sliceSubTypes map[string]string
@@ -76,10 +80,6 @@ type structInfo struct {
// given type, e.g. arguments only valid for one call or purpose and not
// conveyed within the item itself
extraOptions []fieldInfo
useNewStyle bool
disableOldStyle bool
}
var inputStructs = []*structInfo{
@@ -231,7 +231,8 @@ var inputStructs = []*structInfo{
deleteTemplate,
listTemplate,
},
pathArgs: []string{"auth-method", "account"},
pathArgs: []string{"account"},
parentTypeName: "auth-method",
versionEnabled: true,
},
{
@@ -278,7 +279,8 @@ var inputStructs = []*structInfo{
deleteTemplate,
listTemplate,
},
pathArgs: []string{"host-catalog", "host"},
pathArgs: []string{"host"},
parentTypeName: "host-catalog",
versionEnabled: true,
},
{
@@ -296,18 +298,13 @@ var inputStructs = []*structInfo{
updateTemplate,
deleteTemplate,
listTemplate,
createTemplate2,
readTemplate2,
updateTemplate2,
deleteTemplate2,
listTemplate2,
},
pathArgs: []string{"host-catalog", "host-set"},
pathArgs: []string{"host-set"},
parentTypeName: "host-catalog",
sliceSubTypes: map[string]string{
"Hosts": "hostIds",
},
versionEnabled: true,
useNewStyle: true,
},
{
inProto: &targets.HostSet{},
@@ -318,19 +315,17 @@ var inputStructs = []*structInfo{
outFile: "targets/target.gen.go",
templates: []*template.Template{
clientTemplate,
createTemplate2,
readTemplate2,
updateTemplate2,
deleteTemplate2,
listTemplate2,
createTemplate,
readTemplate,
updateTemplate,
deleteTemplate,
listTemplate,
},
pathArgs: []string{"target"},
sliceSubTypes: map[string]string{
"HostSets": "hostSetIds",
},
versionEnabled: true,
typeOnCreate: true,
useNewStyle: true,
disableOldStyle: true,
versionEnabled: true,
typeOnCreate: true,
},
}
+69 -434
View File
@@ -39,32 +39,17 @@ func toPath(segments []string, action string) string {
return fmt.Sprintf("fmt.Sprintf(\"%s%s\", %s)", strings.Join(printfString, "/"), action, strings.Join(printfArg, ", "))
}
func getArgsAndPaths(in []string, action string) (colArgs, resArgs []string, colPath, resPath string) {
var argNames, pathSegment []string
for _, s := range in {
varName := fmt.Sprintf("%sId", strcase.ToLowerCamel(strings.ReplaceAll(s, "-", "_")))
collectionName := fmt.Sprintf("%ss", s)
argNames = append(argNames, varName)
pathSegment = append(pathSegment, collectionName, varName)
}
colArgs, resArgs, colPath, resPath = argNames[:len(argNames)-1], argNames, toPath(pathSegment[:len(pathSegment)-1], action), toPath(pathSegment, action)
// Scopes create and list operations always need scope ID
if colPath == `"scopes"` {
colArgs = append(colArgs, "scopeId")
}
return
}
func getArgsAndPathsNewStyle(in []string, action string) (colArg, resArg string, colPath, resPath string) {
func getArgsAndPaths(in []string, parentTypeName, action string) (colArg, resArg string, colPath, resPath string) {
resArg = fmt.Sprintf("%sId", strcase.ToLowerCamel(strings.ReplaceAll(in[len(in)-1], "-", "_")))
strToReplace := "scope"
if len(in) == 1 {
colArg = "scopeId"
if parentTypeName != "" {
strToReplace = parentTypeName
}
} else {
colArg = fmt.Sprintf("%sId", strcase.ToLowerCamel(strings.ReplaceAll(in[len(in)-2], "-", "_")))
strToReplace = in[len(in)-2]
}
colArg = fmt.Sprintf("%sId", strcase.ToLowerCamel(strings.ReplaceAll(strToReplace, "-", "_")))
colPath = fmt.Sprintf("%ss", in[len(in)-1])
if action != "" {
@@ -75,23 +60,19 @@ func getArgsAndPathsNewStyle(in []string, action string) (colArg, resArg string,
}
type templateInput struct {
Name string
Package string
Fields []fieldInfo
PathArgs []string
CollectionFunctionArgs []string
ResourceFunctionArgs []string
CollectionPath string
ResourcePath string
CollectionFunctionArg2 string
ResourceFunctionArg2 string
CollectionPath2 string
ResourcePath2 string
SliceSubTypes map[string]string
ExtraOptions []fieldInfo
VersionEnabled bool
TypeOnCreate bool
Two string
Name string
Package string
Fields []fieldInfo
PathArgs []string
CollectionFunctionArg string
ResourceFunctionArg string
CollectionPath string
ResourcePath string
ParentTypeName string
SliceSubTypes map[string]string
ExtraOptions []fieldInfo
VersionEnabled bool
TypeOnCreate bool
}
func fillTemplates() {
@@ -103,19 +84,14 @@ func fillTemplates() {
Package: in.generatedStructure.pkg,
Fields: in.generatedStructure.fields,
PathArgs: in.pathArgs,
ParentTypeName: in.parentTypeName,
ExtraOptions: in.extraOptions,
VersionEnabled: in.versionEnabled,
TypeOnCreate: in.typeOnCreate,
Two: "2",
}
if in.useNewStyle && in.disableOldStyle {
input.Two = ""
}
if len(in.pathArgs) > 0 {
input.CollectionFunctionArgs, input.ResourceFunctionArgs, input.CollectionPath, input.ResourcePath = getArgsAndPaths(in.pathArgs, "")
input.CollectionFunctionArg2, input.ResourceFunctionArg2, input.CollectionPath2, input.ResourcePath2 = getArgsAndPathsNewStyle(in.pathArgs, "")
input.CollectionFunctionArg, input.ResourceFunctionArg, input.CollectionPath, input.ResourcePath = getArgsAndPaths(in.pathArgs, in.parentTypeName, "")
}
if err := structTemplate.Execute(outBuf, input); err != nil {
@@ -125,12 +101,7 @@ func fillTemplates() {
if len(in.sliceSubTypes) > 0 {
input.SliceSubTypes = in.sliceSubTypes
if !in.disableOldStyle {
in.templates = append(in.templates, sliceSubTypeTemplate)
}
if in.useNewStyle {
in.templates = append(in.templates, sliceSubTypeTemplate2)
}
in.templates = append(in.templates, sliceSubTypeTemplate)
}
for _, t := range in.templates {
@@ -229,24 +200,23 @@ func fillTemplates() {
}
}
var listTemplate2 = template.Must(template.New("").Funcs(
var listTemplate = template.Must(template.New("").Funcs(
template.FuncMap{
"snakeCase": snakeCase,
},
).Parse(`
func (c *Client) List{{ .Two }}(ctx context.Context, {{ .CollectionFunctionArg2 }} string, opt... Option) ([]*{{ .Name }}, *api.Error, error) {
if {{ .CollectionFunctionArg2 }} == "" {
return nil, nil, fmt.Errorf("empty {{ .CollectionFunctionArg2 }} value passed into List request")
func (c *Client) List(ctx context.Context, {{ .CollectionFunctionArg }} string, opt... Option) ([]*{{ .Name }}, *api.Error, error) {
if {{ .CollectionFunctionArg }} == "" {
return nil, nil, fmt.Errorf("empty {{ .CollectionFunctionArg }} value passed into List request")
}
if c.client == nil {
return nil, nil, fmt.Errorf("nil client")
}
opts, apiOpts := getOpts(opt...)
apiOpts = append(apiOpts, api.WithNewStyle())
opts.queryMap["{{ snakeCase .CollectionFunctionArg2 }}"] = {{ .CollectionFunctionArg2 }}
opts.queryMap["{{ snakeCase .CollectionFunctionArg }}"] = {{ .CollectionFunctionArg }}
req, err := c.client.NewRequest(ctx, "GET", "{{ .CollectionPath2 }}", nil, apiOpts...)
req, err := c.client.NewRequest(ctx, "GET", "{{ .CollectionPath }}", nil, apiOpts...)
if err != nil {
return nil, nil, fmt.Errorf("error creating List request: %w", err)
}
@@ -281,101 +251,11 @@ func (c *Client) List{{ .Two }}(ctx context.Context, {{ .CollectionFunctionArg2
}
`))
var listTemplate = template.Must(template.New("").Parse(`
func (c *Client) List(ctx context.Context, {{ range .CollectionFunctionArgs }} {{ . }} string, {{ end }}opt... Option) ([]*{{ .Name }}, *api.Error, error) { {{ range .CollectionFunctionArgs }}
if {{ . }} == "" {
return nil, nil, fmt.Errorf("empty {{ . }} value passed into List request")
}
{{ end }}
if c.client == nil {
return nil, nil, fmt.Errorf("nil client")
}
opts, apiOpts := getOpts(opt...)
req, err := c.client.NewRequest(ctx, "GET", {{ .CollectionPath }}, nil, apiOpts...)
if err != nil {
return nil, nil, fmt.Errorf("error creating List request: %w", err)
}
{{ if ( eq .CollectionPath "\"scopes\"" ) }}
opts.queryMap["scope_id"] = scopeId
{{ end }}
if len(opts.queryMap) > 0 {
q := url.Values{}
for k, v := range opts.queryMap {
q.Add(k, v)
}
req.URL.RawQuery = q.Encode()
}
resp, err := c.client.Do(req)
if err != nil {
return nil, nil, fmt.Errorf("error performing client request during List call: %w", err)
}
type listResponse struct {
Items []*{{ .Name }}
}
target := &listResponse{}
apiErr, err := resp.Decode(target)
if err != nil {
return nil, nil, fmt.Errorf("error decoding List response: %w", err)
}
if apiErr != nil {
return nil, apiErr, nil
}
return target.Items, apiErr, nil
}
`))
var readTemplate2 = template.Must(template.New("").Parse(`
func (c *Client) Read{{ .Two }}(ctx context.Context, {{ .ResourceFunctionArg2 }} string, opt... Option) (*{{ .Name }}, *api.Error, error) {
if {{ .ResourceFunctionArg2 }} == "" {
return nil, nil, fmt.Errorf("empty {{ .ResourceFunctionArg2 }} value passed into Read request")
}
if c.client == nil {
return nil, nil, fmt.Errorf("nil client")
}
opts, apiOpts := getOpts(opt...)
apiOpts = append(apiOpts, api.WithNewStyle())
req, err := c.client.NewRequest(ctx, "GET", {{ .ResourcePath2 }}, nil, apiOpts...)
if err != nil {
return nil, nil, fmt.Errorf("error creating Read request: %w", err)
}
if len(opts.queryMap) > 0 {
q := url.Values{}
for k, v := range opts.queryMap {
q.Add(k, v)
}
req.URL.RawQuery = q.Encode()
}
resp, err := c.client.Do(req)
if err != nil {
return nil, nil, fmt.Errorf("error performing client request during Read call: %w", err)
}
target := new({{ .Name }})
apiErr, err := resp.Decode(target)
if err != nil {
return nil, nil, fmt.Errorf("error decoding Read response: %w", err)
}
if apiErr != nil {
return nil, apiErr, nil
}
return target, apiErr, nil
}
`))
var readTemplate = template.Must(template.New("").Parse(`
func (c *Client) Read(ctx context.Context, {{ range .ResourceFunctionArgs }} {{ . }} string, {{ end }} opt... Option) (*{{ .Name }}, *api.Error, error) { {{ range .ResourceFunctionArgs }}
if {{ . }} == "" {
return nil, nil, fmt.Errorf("empty {{ . }} value passed into Read request")
func (c *Client) Read(ctx context.Context, {{ .ResourceFunctionArg }} string, opt... Option) (*{{ .Name }}, *api.Error, error) {
if {{ .ResourceFunctionArg }} == "" {
return nil, nil, fmt.Errorf("empty {{ .ResourceFunctionArg }} value passed into Read request")
}
{{ end }}
if c.client == nil {
return nil, nil, fmt.Errorf("nil client")
}
@@ -412,57 +292,11 @@ func (c *Client) Read(ctx context.Context, {{ range .ResourceFunctionArgs }} {{
}
`))
var deleteTemplate2 = template.Must(template.New("").Parse(`
func (c *Client) Delete{{ .Two }}(ctx context.Context, {{ .ResourceFunctionArg2 }} string, opt... Option) (bool, *api.Error, error) {
if {{ .ResourceFunctionArg2 }} == "" {
return false, nil, fmt.Errorf("empty {{ .ResourceFunctionArg2 }} value passed into Delete request")
}
if c.client == nil {
return false, nil, fmt.Errorf("nil client")
}
opts, apiOpts := getOpts(opt...)
apiOpts = append(apiOpts, api.WithNewStyle())
req, err := c.client.NewRequest(ctx, "DELETE", {{ .ResourcePath2 }}, nil, apiOpts...)
if err != nil {
return false, nil, fmt.Errorf("error creating Delete request: %w", err)
}
if len(opts.queryMap) > 0 {
q := url.Values{}
for k, v := range opts.queryMap {
q.Add(k, v)
}
req.URL.RawQuery = q.Encode()
}
resp, err := c.client.Do(req)
if err != nil {
return false, nil, fmt.Errorf("error performing client request during Delete call: %w", err)
}
type deleteResponse struct {
Existed bool
}
target := &deleteResponse{}
apiErr, err := resp.Decode(target)
if err != nil {
return false, nil, fmt.Errorf("error decoding Delete response: %w", err)
}
if apiErr != nil {
return false, apiErr, nil
}
return target.Existed, apiErr, nil
}
`))
var deleteTemplate = template.Must(template.New("").Parse(`
func (c *Client) Delete(ctx context.Context, {{ range .ResourceFunctionArgs }} {{ . }} string, {{ end }} opt... Option) (bool, *api.Error, error) { {{ range .ResourceFunctionArgs }}
if {{ . }} == "" {
return false, nil, fmt.Errorf("empty {{ . }} value passed into Delete request")
func (c *Client) Delete(ctx context.Context, {{ .ResourceFunctionArg }} string, opt... Option) (bool, *api.Error, error) {
if {{ .ResourceFunctionArg }} == "" {
return false, nil, fmt.Errorf("empty {{ .ResourceFunctionArg }} value passed into Delete request")
}
{{ end }}
if c.client == nil {
return false, nil, fmt.Errorf("nil client")
}
@@ -502,17 +336,18 @@ func (c *Client) Delete(ctx context.Context, {{ range .ResourceFunctionArgs }} {
}
`))
var createTemplate2 = template.Must(template.New("").Funcs(
var createTemplate = template.Must(template.New("").Funcs(
template.FuncMap{
"snakeCase": snakeCase,
},
).Parse(`
func (c *Client) Create{{ .Two }} (ctx context.Context, {{ if .TypeOnCreate }} resourceType string, {{ end }} {{ .CollectionFunctionArg2 }} string, opt... Option) (*{{ .Name }}, *api.Error, error) {
if {{ .CollectionFunctionArg2 }} == "" {
return nil, nil, fmt.Errorf("empty {{ .CollectionFunctionArg2 }} value passed into Create request")
func (c *Client) Create (ctx context.Context, {{ if .TypeOnCreate }} resourceType string, {{ end }} {{ .CollectionFunctionArg }} string, opt... Option) (*{{ .Name }}, *api.Error, error) {
if {{ .CollectionFunctionArg }} == "" {
return nil, nil, fmt.Errorf("empty {{ .CollectionFunctionArg }} value passed into Create request")
}
opts, apiOpts := getOpts(opt...)
apiOpts = append(apiOpts, api.WithNewStyle())
if c.client == nil {
return nil, nil, fmt.Errorf("nil client")
}
@@ -522,9 +357,9 @@ func (c *Client) Create{{ .Two }} (ctx context.Context, {{ if .TypeOnCreate }} r
opts.postMap["type"] = resourceType
}{{ end }}
opts.postMap["{{ snakeCase .CollectionFunctionArg2 }}"] = {{ .CollectionFunctionArg2 }}
opts.postMap["{{ snakeCase .CollectionFunctionArg }}"] = {{ .CollectionFunctionArg }}
req, err := c.client.NewRequest(ctx, "POST", "{{ .CollectionPath2 }}", opts.postMap, apiOpts...)
req, err := c.client.NewRequest(ctx, "POST", "{{ .CollectionPath }}", opts.postMap, apiOpts...)
if err != nil {
return nil, nil, fmt.Errorf("error creating Create request: %w", err)
}
@@ -556,121 +391,11 @@ func (c *Client) Create{{ .Two }} (ctx context.Context, {{ if .TypeOnCreate }} r
}
`))
var createTemplate = template.Must(template.New("").Parse(`
func (c *Client) Create(ctx context.Context, {{ if .TypeOnCreate }} resourceType string, {{ end }} {{ range .CollectionFunctionArgs }} {{ . }} string, {{ end }} opt... Option) (*{{ .Name }}, *api.Error, error) { {{ range .CollectionFunctionArgs }}
if {{ . }} == "" {
return nil, nil, fmt.Errorf("empty {{ . }} value passed into Create request")
}
{{ end }}opts, apiOpts := getOpts(opt...)
if c.client == nil {
return nil, nil, fmt.Errorf("nil client")
}
{{ if .TypeOnCreate }} if resourceType == "" {
return nil, nil, fmt.Errorf("empty resourceType value passed into Create request")
} else {
opts.postMap["type"] = resourceType
}{{ end }}
{{ if ( eq .CollectionPath "\"scopes\"" ) }}
opts.postMap["scope_id"] = scopeId
{{ end }}
req, err := c.client.NewRequest(ctx, "POST", {{ .CollectionPath }}, opts.postMap, apiOpts...)
if err != nil {
return nil, nil, fmt.Errorf("error creating Create request: %w", err)
}
if len(opts.queryMap) > 0 {
q := url.Values{}
for k, v := range opts.queryMap {
q.Add(k, v)
}
req.URL.RawQuery = q.Encode()
}
resp, err := c.client.Do(req)
if err != nil {
return nil, nil, fmt.Errorf("error performing client request during Create call: %w", err)
}
target := new({{ .Name }})
apiErr, err := resp.Decode(target)
if err != nil {
return nil, nil, fmt.Errorf("error decoding Create response: %w", err)
}
if apiErr != nil {
return nil, apiErr, nil
}
return target, apiErr, nil
}
`))
var updateTemplate2 = template.Must(template.New("").Parse(`
func (c *Client) Update{{ .Two }}(ctx context.Context, {{ .ResourceFunctionArg2 }} string, version uint32, opt... Option) (*{{ .Name }}, *api.Error, error) {
if {{ .ResourceFunctionArg2 }} == "" {
return nil, nil, fmt.Errorf("empty {{ .ResourceFunctionArg2 }} value passed into Update request")
}
if c.client == nil {
return nil, nil, fmt.Errorf("nil client")
}
opts, apiOpts := getOpts(opt...)
apiOpts = append(apiOpts, api.WithNewStyle())
{{ if .VersionEnabled }}
if version == 0 {
if !opts.withAutomaticVersioning {
return nil, nil, errors.New("zero version number passed into Update request and automatic versioning not specified")
}
existingTarget, existingApiErr, existingErr := c.Read{{ .Two }}(ctx, {{ .ResourceFunctionArg2 }}, opt...)
if existingErr != nil {
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
}
if existingApiErr != nil {
return nil, nil, fmt.Errorf("error from controller when performing initial check-and-set read: %s", pretty.Sprint(existingApiErr))
}
if existingTarget == nil {
return nil, nil, errors.New("nil resource found when performing initial check-and-set read")
}
version = existingTarget.Version
}
{{ end }}
opts.postMap["version"] = version
req, err := c.client.NewRequest(ctx, "PATCH", {{ .ResourcePath2 }}, opts.postMap, apiOpts...)
if err != nil {
return nil, nil, fmt.Errorf("error creating Update request: %w", err)
}
if len(opts.queryMap) > 0 {
q := url.Values{}
for k, v := range opts.queryMap {
q.Add(k, v)
}
req.URL.RawQuery = q.Encode()
}
resp, err := c.client.Do(req)
if err != nil {
return nil, nil, fmt.Errorf("error performing client request during Update call: %w", err)
}
target := new({{ .Name }})
apiErr, err := resp.Decode(target)
if err != nil {
return nil, nil, fmt.Errorf("error decoding Update response: %w", err)
}
if apiErr != nil {
return nil, apiErr, nil
}
return target, apiErr, nil
}
`))
var updateTemplate = template.Must(template.New("").Parse(`
func (c *Client) Update(ctx context.Context, {{ range .ResourceFunctionArgs }} {{ . }} string, {{ end }}version uint32, opt... Option) (*{{ .Name }}, *api.Error, error) { {{ range .ResourceFunctionArgs }}
if {{ . }} == "" {
return nil, nil, fmt.Errorf("empty {{ . }} value passed into Update request")
}{{ end }}
func (c *Client) Update(ctx context.Context, {{ .ResourceFunctionArg }} string, version uint32, opt... Option) (*{{ .Name }}, *api.Error, error) {
if {{ .ResourceFunctionArg }} == "" {
return nil, nil, fmt.Errorf("empty {{ .ResourceFunctionArg }} value passed into Update request")
}
if c.client == nil {
return nil, nil, fmt.Errorf("nil client")
}
@@ -682,7 +407,7 @@ func (c *Client) Update(ctx context.Context, {{ range .ResourceFunctionArgs }} {
if !opts.withAutomaticVersioning {
return nil, nil, errors.New("zero version number passed into Update request and automatic versioning not specified")
}
existingTarget, existingApiErr, existingErr := c.Read(ctx, {{ range .ResourceFunctionArgs }} {{ . }}, {{ end }} opt...)
existingTarget, existingApiErr, existingErr := c.Read(ctx, {{ .ResourceFunctionArg }}, opt...)
if existingErr != nil {
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
}
@@ -741,11 +466,11 @@ var sliceSubTypeTemplate = template.Must(template.New("").Funcs(
{{ range $key, $value := $input.SliceSubTypes }}
{{ $fullName := print $op $key }}
{{ $actionName := kebabCase $fullName }}
{{ $resPath := getPathWithAction $input.PathArgs $actionName }}
func (c *Client) {{ $fullName }}(ctx context.Context, {{ range $input.ResourceFunctionArgs }} {{ . }} string, {{ end }}version uint32, {{ $value }} []string, opt... Option) (*{{ $input.Name }}, *api.Error, error) { {{ range $input.ResourceFunctionArgs }}
if {{ . }} == "" {
return nil, nil, fmt.Errorf("empty {{ . }} value passed into {{ $fullName }} request")
}{{ end }}
{{ $resPath := getPathWithAction $input.PathArgs $input.ParentTypeName $actionName }}
func (c *Client) {{ $fullName }}(ctx context.Context, {{ $input.ResourceFunctionArg }} string, version uint32, {{ $value }} []string, opt... Option) (*{{ $input.Name }}, *api.Error, error) {
if {{ $input.ResourceFunctionArg }} == "" {
return nil, nil, fmt.Errorf("empty {{ $input.ResourceFunctionArg }} value passed into {{ $fullName }} request")
}
if c.client == nil {
return nil, nil, fmt.Errorf("nil client")
}
@@ -757,92 +482,7 @@ func (c *Client) {{ $fullName }}(ctx context.Context, {{ range $input.ResourceFu
if !opts.withAutomaticVersioning {
return nil, nil, errors.New("zero version number passed into {{ $fullName }} request")
}
existingTarget, existingApiErr, existingErr := c.Read(ctx, {{ range $input.ResourceFunctionArgs }} {{ . }}, {{ end }} opt...)
if existingErr != nil {
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
}
if existingApiErr != nil {
return nil, nil, fmt.Errorf("error from controller when performing initial check-and-set read: %s", pretty.Sprint(existingApiErr))
}
if existingTarget == nil {
return nil, nil, errors.New("nil resource found when performing initial check-and-set read")
}
version = existingTarget.Version
}
{{ end }}
opts.postMap["version"] = version
if len({{ $value }}) > 0 {
opts.postMap["{{ snakeCase $value }}"] = {{ $value }}
}{{ if ( eq $op "Set" ) }} else if {{ $value }} != nil {
// In this function, a non-nil but empty list means clear out
opts.postMap["{{ snakeCase $value }}"] = nil
}
{{ end }}
req, err := c.client.NewRequest(ctx, "POST", {{ $resPath }}, opts.postMap, apiOpts...)
if err != nil {
return nil, nil, fmt.Errorf("error creating {{ $fullName }} request: %w", err)
}
if len(opts.queryMap) > 0 {
q := url.Values{}
for k, v := range opts.queryMap {
q.Add(k, v)
}
req.URL.RawQuery = q.Encode()
}
resp, err := c.client.Do(req)
if err != nil {
return nil, nil, fmt.Errorf("error performing client request during {{ $fullName }} call: %w", err)
}
target := new({{ $input.Name }})
apiErr, err := resp.Decode(target)
if err != nil {
return nil, nil, fmt.Errorf("error decoding {{ $fullName }} response: %w", err)
}
if apiErr != nil {
return nil, apiErr, nil
}
return target, apiErr, nil
}
{{ end }}
{{ end }}
`))
var sliceSubTypeTemplate2 = template.Must(template.New("").Funcs(
template.FuncMap{
"makeSlice": makeSlice,
"snakeCase": snakeCase,
"kebabCase": kebabCase,
"getPathWithActionNewStyle": getPathWithActionNewStyle,
},
).Parse(`
{{ $input := . }}
{{ range $index, $op := makeSlice "Add" "Set" "Remove" }}
{{ range $key, $value := $input.SliceSubTypes }}
{{ $fullName := print $op $key }}
{{ $actionName := kebabCase $fullName }}
{{ $resPath := getPathWithActionNewStyle $input.PathArgs $actionName }}
func (c *Client) {{ $fullName }}{{ $input.Two }}(ctx context.Context, {{ $input.ResourceFunctionArg2 }} string, version uint32, {{ $value }} []string, opt... Option) (*{{ $input.Name }}, *api.Error, error) {
if {{ $input.ResourceFunctionArg2 }} == "" {
return nil, nil, fmt.Errorf("empty {{ $input.ResourceFunctionArg2 }} value passed into {{ $fullName }} request")
}
if c.client == nil {
return nil, nil, fmt.Errorf("nil client")
}
opts, apiOpts := getOpts(opt...)
apiOpts = append(apiOpts, api.WithNewStyle())
{{ if $input.VersionEnabled }}
if version == 0 {
if !opts.withAutomaticVersioning {
return nil, nil, errors.New("zero version number passed into {{ $fullName }} request")
}
existingTarget, existingApiErr, existingErr := c.Read{{ $input.Two }}(ctx, {{ $input.ResourceFunctionArg2 }}, opt...)
existingTarget, existingApiErr, existingErr := c.Read(ctx, {{ $input.ResourceFunctionArg }}, opt...)
if existingErr != nil {
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
}
@@ -918,12 +558,22 @@ type {{ .Name }} struct { {{ range .Fields }}
`)))
var clientTemplate = template.Must(template.New("").Parse(`
// Client is a client for this collection
type Client struct {
client *api.Client
}
// Creates a new client for this collection. The submitted API client is cloned;
// modifications to it after generating this client will not have effect. If you
// need to make changes to the underlying API client, use ApiClient() to access
// it.
func NewClient(c *api.Client) *Client {
return &Client{ client: c }
return &Client{ client: c.Clone() }
}
// ApiClient returns the underlying API client
func (c *Client) ApiClient() *api.Client {
return c.client
}
`))
@@ -950,7 +600,6 @@ type Option func(*options)
type options struct {
postMap map[string]interface{}
queryMap map[string]string
withScopeId string
withAutomaticVersioning bool
}
@@ -967,25 +616,16 @@ func getOpts(opt ...Option) (options, []api.Option) {
o(&opts)
}
var apiOpts []api.Option
if opts.withScopeId != "" {
apiOpts = append(apiOpts, api.WithScopeId(opts.withScopeId))
}
return opts, apiOpts
}
func WithScopeId(id string) Option {
return func(o *options) {
o.withScopeId = id
}
}
// If set, and if the version is zero during an update, the API will perform a
// fetch to get the current version of the resource and populate it during the
// update call. This is convenient but opens up the possibility for subtle
// order-of-modification issues, so use carefully.
func WithAutomaticVersioning() Option {
func WithAutomaticVersioning(enable bool) Option {
return func(o *options) {
o.withAutomaticVersioning = true
o.withAutomaticVersioning = enable
}
}
{{ range .Fields }}
@@ -1033,12 +673,7 @@ func kebabCase(in string) string {
return strcase.ToKebab(in)
}
func getPathWithAction(resArgs []string, action string) string {
_, _, _, resPath := getArgsAndPaths(resArgs, action)
return resPath
}
func getPathWithActionNewStyle(resArgs []string, action string) string {
_, _, _, resPath := getArgsAndPathsNewStyle(resArgs, action)
func getPathWithAction(resArgs []string, parentTypeName, action string) string {
_, _, _, resPath := getArgsAndPaths(resArgs, parentTypeName, action)
return resPath
}