Skip to content

Commit c435669

Browse files
feat: autogenerate go SDK example in the codeSample (#772)
1 parent 65d39c9 commit c435669

16 files changed

+86341
-3
lines changed

tools/cli/internal/openapi/filter/code_sample.go

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,47 @@
1515
package filter
1616

1717
import (
18+
"bytes"
19+
"fmt"
20+
goFormat "go/format"
21+
"strings"
22+
"text/template"
1823
"time"
1924

2025
"github.com/getkin/kin-openapi/openapi3"
2126
"github.com/mongodb/openapi/tools/cli/internal/apiversion"
27+
"golang.org/x/text/cases"
28+
"golang.org/x/text/language"
2229
)
2330

31+
const goSDKTemplate = `import (
32+
"os"
33+
"context"
34+
"log"
35+
sdk "go.mongodb.org/atlas-sdk/v{{ .Version }}/admin"
36+
)
37+
38+
func main() {
39+
ctx := context.Background()
40+
clientID := os.Getenv("MONGODB_ATLAS_CLIENT_ID")
41+
clientSecret := os.Getenv("MONGODB_ATLAS_CLIENT_SECRET")
42+
43+
client, err := sdk.NewClient(
44+
sdk.UseOAuthAuth(clientID, clientSecret),
45+
sdk.UseBaseURL(url))
46+
47+
if err != nil {
48+
log.Fatalf("Error: %v", err)
49+
}
50+
51+
params = &sdk.{{ .OperationID }}ApiParams{}
52+
{{ if eq .Method "DELETE" }} httpResp, err := client.{{ .Tag }}Api.
53+
{{ .OperationID }}WithParams(ctx, params).
54+
Execute(){{ else }} sdkResp, httpResp, err := client.{{ .Tag }}Api.
55+
{{ .OperationID }}WithParams(ctx, params).
56+
Execute(){{ end}}
57+
}`
58+
2459
const codeSampleExtensionName = "x-codeSamples"
2560

2661
// https://redocly.com/docs-legacy/api-reference-docs/specification-extensions/x-code-samples#x-codesamples
@@ -121,6 +156,47 @@ func newAtlasCliCodeSamplesForOperation(op *openapi3.Operation) codeSample {
121156
}
122157
}
123158

159+
func (f *CodeSampleFilter) newGoSdkCodeSamplesForOperation(op *openapi3.Operation, opMethod string) (*codeSample, error) {
160+
version := strings.ReplaceAll(apiVersion(f.metadata.targetVersion), "-", "") + "001"
161+
operationID := cases.Title(language.English, cases.NoLower).String(op.OperationID)
162+
tag := strings.ReplaceAll(op.Tags[0], " ", "")
163+
tag = strings.ReplaceAll(tag, ".", "")
164+
165+
t, err := template.New("goSDK").Parse(goSDKTemplate)
166+
if err != nil {
167+
return nil, err
168+
}
169+
170+
var buffer bytes.Buffer
171+
err = t.Execute(&buffer, struct {
172+
Tag string
173+
OperationID string
174+
Version string
175+
Method string
176+
}{
177+
Tag: tag,
178+
OperationID: operationID,
179+
Version: version,
180+
Method: opMethod,
181+
})
182+
183+
if err != nil {
184+
return nil, err
185+
}
186+
187+
formattedResult, err := goFormat.Source(buffer.Bytes())
188+
if err != nil {
189+
return nil, fmt.Errorf("tag: %q, operationId: %q code: %q: error: %w",
190+
op.Tags[0], operationID, buffer.String(), err)
191+
}
192+
193+
return &codeSample{
194+
Lang: "go",
195+
Label: "Go",
196+
Source: string(formattedResult),
197+
}, nil
198+
}
199+
124200
func (f *CodeSampleFilter) includeCodeSamplesForOperation(pathName, opMethod string, op *openapi3.Operation) error {
125201
if op == nil || opMethod == "" || pathName == "" {
126202
return nil
@@ -130,10 +206,22 @@ func (f *CodeSampleFilter) includeCodeSamplesForOperation(pathName, opMethod str
130206
op.Extensions = map[string]any{}
131207
}
132208

133-
op.Extensions[codeSampleExtensionName] = []codeSample{
209+
codeSamples := []codeSample{
134210
newAtlasCliCodeSamplesForOperation(op),
135-
f.newServiceAccountCurlCodeSamplesForOperation(pathName, opMethod),
136-
f.newDigestCurlCodeSamplesForOperation(pathName, opMethod),
137211
}
212+
213+
if f.metadata.targetVersion.IsStable() {
214+
sdkSample, err := f.newGoSdkCodeSamplesForOperation(op, opMethod)
215+
if err != nil {
216+
return err
217+
}
218+
codeSamples = append(codeSamples, *sdkSample)
219+
}
220+
221+
codeSamples = append(
222+
codeSamples,
223+
f.newServiceAccountCurlCodeSamplesForOperation(pathName, opMethod),
224+
f.newDigestCurlCodeSamplesForOperation(pathName, opMethod))
225+
op.Extensions[codeSampleExtensionName] = codeSamples
138226
return nil
139227
}

tools/cli/internal/openapi/filter/code_sample_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ func TestCodeSampleFilter(t *testing.T) {
5050
},
5151
},
5252
})),
53+
Tags: []string{"TestTag"},
5354
Extensions: map[string]any{
5455
"x-sunset": "9999-12-31",
5556
},
@@ -73,6 +74,7 @@ func TestCodeSampleFilter(t *testing.T) {
7374
},
7475
},
7576
})),
77+
Tags: []string{"TestTag"},
7678
Extensions: map[string]any{
7779
"x-sunset": "9999-12-31",
7880
"x-codeSamples": []codeSample{
@@ -81,6 +83,25 @@ func TestCodeSampleFilter(t *testing.T) {
8183
Label: "Atlas CLI",
8284
Source: "atlas api testOperationID --help",
8385
},
86+
{
87+
Lang: "go",
88+
Label: "Go",
89+
Source: "import (\n" +
90+
"\t\"os\"\n \"context\"\n" + "\t\"log\"\n" +
91+
"\tsdk \"go.mongodb.org/atlas-sdk/v20250101001/admin\"\n)\n\n" +
92+
"func main() {\n" +
93+
"\tctx := context.Background()\n" +
94+
"\tclientID := os.Getenv(\"MONGODB_ATLAS_CLIENT_ID\")\n" +
95+
"\tclientSecret := os.Getenv(\"MONGODB_ATLAS_CLIENT_SECRET\")\n\n" +
96+
"\tclient, err := sdk.NewClient(\n" +
97+
"\t\tsdk.UseOAuthAuth(clientID, clientSecret),\n" +
98+
"\t\tsdk.UseBaseURL(url))\n\n" +
99+
"\tif err != nil {\n" + "\t\tlog.Fatalf(\"Error: %v\", err)\n\t}\n\n" +
100+
"\tparams = &sdk.TestOperationIDApiParams{}\n" +
101+
"\tsdkResp, httpResp, err := client.TestTagApi.\n" +
102+
"\t\tTestOperationIDWithParams(ctx, params).\n" +
103+
"\t\tExecute()" + "\n}",
104+
},
84105
{
85106
Lang: "cURL",
86107
Label: "curl (Service Accounts)",

tools/cli/test/data/split/dev/openapi-v2-2023-01-01.json

Lines changed: 1685 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)