Skip to content

Commit 9787088

Browse files
CLOUDP-333549: --output is required when downloading logs, but this is not documented (#843)
1 parent 2da7209 commit 9787088

19 files changed

+414
-199
lines changed

.github/workflows/code-health-foascli.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,4 @@ jobs:
102102
go-version-file: 'tools/cli/go.mod'
103103
- name: Run e2e tests
104104
working-directory: tools/cli
105-
run: make e2e-test
105+
run: make devtools e2e-test

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
/tools/cli/test/e2e/cli/output/**
1010
!/tools/cli/test/e2e/cli/output/.gitkeep
1111
/tools/*/dist/*
12+
/tools/*/output/*
1213
# We don't want to commit env variables
1314
*.env
1415

tools/cli/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ deps: ## Download go module dependencies
3434
devtools: ## Install dev tools
3535
@echo "==> Installing dev tools..."
3636
go install go.uber.org/mock/mockgen@latest
37+
go install github.com/tufin/[email protected]
3738
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(shell go env GOPATH)/bin $(GOLANGCI_VERSION)
3839

3940
.PHONY: setup
@@ -70,6 +71,7 @@ list: ## List all make targets
7071
.PHONY: e2e-test
7172
e2e-test: build ## Run E2E tests
7273
@echo "==> Running E2E tests..."
74+
rm -rf test/e2e/cli/output
7375
$(TEST_CMD) -v -p 1 -parallel $(E2E_PARALLEL) -timeout $(E2E_TIMEOUT) ./test/e2e... $(E2E_EXTRA_ARGS)
7476

7577
.PHONY: gen-docs

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

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,30 @@ func (f *CodeSampleFilter) Apply() error {
6565
return nil
6666
}
6767

68-
func (f *CodeSampleFilter) newDigestCurlCodeSamplesForOperation(pathName, opMethod string) codeSample {
68+
func getFileExtension(format string) string {
69+
switch format {
70+
case "gzip":
71+
return "gz"
72+
default:
73+
return format
74+
}
75+
}
76+
77+
func (f *CodeSampleFilter) newDigestCurlCodeSamplesForOperation(pathName, opMethod, format string) codeSample {
6978
version := apiVersion(f.metadata.targetVersion)
7079
source := "curl --user \"${PUBLIC_KEY}:${PRIVATE_KEY}\" \\\n --digest \\\n " +
71-
"--header \"Accept: application/vnd.atlas." + version + "+json\" \\\n "
80+
"--header \"Accept: application/vnd.atlas." + version + "+" + format + "\" \\\n "
7281

7382
switch opMethod {
7483
case "GET":
75-
source += "-X " + opMethod + " \"https://cloud.mongodb.com" + pathName + "?pretty=true\""
84+
source += "-X " + opMethod + " \"https://cloud.mongodb.com" + pathName
85+
if format == "gzip" {
86+
source += "\" \\\n "
87+
source += "--output \"file_name." + getFileExtension(format) + "\""
88+
} else {
89+
source += "?pretty=true\""
90+
}
91+
7692
case "DELETE":
7793
source += "-X " + opMethod + " \"https://cloud.mongodb.com" + pathName + "\""
7894
case "POST", "PATCH", "PUT":
@@ -88,14 +104,20 @@ func (f *CodeSampleFilter) newDigestCurlCodeSamplesForOperation(pathName, opMeth
88104
}
89105
}
90106

91-
func (f *CodeSampleFilter) newServiceAccountCurlCodeSamplesForOperation(pathName, opMethod string) codeSample {
107+
func (f *CodeSampleFilter) newServiceAccountCurlCodeSamplesForOperation(pathName, opMethod, format string) codeSample {
92108
version := apiVersion(f.metadata.targetVersion)
93109
source := "curl --header \"Authorization: Bearer ${ACCESS_TOKEN}\" \\\n " +
94-
"--header \"Accept: application/vnd.atlas." + version + "+json\" \\\n "
110+
"--header \"Accept: application/vnd.atlas." + version + "+" + format + "\" \\\n "
95111

96112
switch opMethod {
97113
case "GET":
98-
source += "-X " + opMethod + " \"https://cloud.mongodb.com" + pathName + "?pretty=true\""
114+
source += "-X " + opMethod + " \"https://cloud.mongodb.com" + pathName
115+
if format == "gzip" {
116+
source += "\" \\\n "
117+
source += "--output \"file_name." + getFileExtension(format) + "\""
118+
} else {
119+
source += "?pretty=true\""
120+
}
99121
case "DELETE":
100122
source += "-X " + opMethod + " \"https://cloud.mongodb.com" + pathName + "\""
101123
case "POST", "PATCH", "PUT":
@@ -193,10 +215,55 @@ func (f *CodeSampleFilter) includeCodeSamplesForOperation(pathName, opMethod str
193215
codeSamples = append(codeSamples, *sdkSample)
194216
}
195217

218+
supportedFormat := getSupportedFormat(op)
196219
codeSamples = append(
197220
codeSamples,
198-
f.newServiceAccountCurlCodeSamplesForOperation(pathName, opMethod),
199-
f.newDigestCurlCodeSamplesForOperation(pathName, opMethod))
221+
f.newServiceAccountCurlCodeSamplesForOperation(pathName, opMethod, supportedFormat),
222+
f.newDigestCurlCodeSamplesForOperation(pathName, opMethod, supportedFormat))
200223
op.Extensions[codeSampleExtensionName] = codeSamples
201224
return nil
202225
}
226+
227+
// getSupportedFormat inspects the response content types of a given OpenAPI operation,
228+
// looking for a content type string in the format "application/vnd.atlas.<api_version>+<supported_format>".
229+
// It splits the content type on the '+' character and returns the last part, which represents the supported format (e.g., "json").
230+
// If no such content type is found, it defaults to returning "json".
231+
func getSupportedFormat(op *openapi3.Operation) string {
232+
responseMap := successResponseExtensions(op.Responses.Map())
233+
format := "json"
234+
for k := range responseMap {
235+
// k is a string with the format "application/vnd.atlas.<api_version>+<supported_format>"
236+
parts := strings.Split(k, "+")
237+
if len(parts) == 0 {
238+
continue
239+
}
240+
241+
format = parts[len(parts)-1]
242+
// If the endpoint supports "json", we return it as "json" is the best supported format in our APIs
243+
// and users should use it when available.
244+
if format == "json" {
245+
return format
246+
}
247+
}
248+
249+
return format
250+
}
251+
252+
// successResponseExtensions returns the Content object of the first successful HTTP response (status 200, 201, 202, or 204)
253+
// found in the provided responses map.
254+
func successResponseExtensions(responsesMap map[string]*openapi3.ResponseRef) openapi3.Content {
255+
if val, ok := responsesMap["200"]; ok {
256+
return val.Value.Content
257+
}
258+
if val, ok := responsesMap["201"]; ok {
259+
return val.Value.Content
260+
}
261+
if val, ok := responsesMap["202"]; ok {
262+
return val.Value.Content
263+
}
264+
if val, ok := responsesMap["204"]; ok {
265+
return val.Value.Content
266+
}
267+
268+
return nil
269+
}

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

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,97 @@ func TestCodeSampleFilter(t *testing.T) {
257257
})),
258258
},
259259
},
260+
{
261+
name: "stable api gzip",
262+
version: "2025-01-01",
263+
oas: &openapi3.T{
264+
Paths: openapi3.NewPaths(openapi3.WithPath("/test", &openapi3.PathItem{
265+
Get: &openapi3.Operation{
266+
OperationID: "testOperationID",
267+
Summary: "testSummary",
268+
Responses: openapi3.NewResponses(openapi3.WithName("200", &openapi3.Response{
269+
Content: openapi3.Content{
270+
"application/vnd.atlas.2025-01-01+gzip": {
271+
Schema: &openapi3.SchemaRef{
272+
Ref: "#/components/schemas/PaginatedAppUserView",
273+
},
274+
Extensions: map[string]any{
275+
"x-gen-version": "2025-01-01",
276+
},
277+
},
278+
},
279+
})),
280+
Tags: []string{"TestTag"},
281+
Extensions: map[string]any{
282+
"x-sunset": "9999-12-31",
283+
},
284+
},
285+
})),
286+
},
287+
expectedOas: &openapi3.T{
288+
Paths: openapi3.NewPaths(openapi3.WithPath("/test", &openapi3.PathItem{
289+
Get: &openapi3.Operation{
290+
OperationID: "testOperationID",
291+
Summary: "testSummary",
292+
Responses: openapi3.NewResponses(openapi3.WithName("200", &openapi3.Response{
293+
Content: openapi3.Content{
294+
"application/vnd.atlas.2025-01-01+gzip": {
295+
Schema: &openapi3.SchemaRef{
296+
Ref: "#/components/schemas/PaginatedAppUserView",
297+
},
298+
Extensions: map[string]any{
299+
"x-gen-version": "2025-01-01",
300+
},
301+
},
302+
},
303+
})),
304+
Tags: []string{"TestTag"},
305+
Extensions: map[string]any{
306+
"x-sunset": "9999-12-31",
307+
"x-codeSamples": []codeSample{
308+
{
309+
Lang: "cURL",
310+
Label: "Atlas CLI",
311+
Source: "atlas api testOperationID --help",
312+
},
313+
{
314+
Lang: "go",
315+
Label: "Go",
316+
Source: "import (\n" +
317+
"\t\"os\"\n \"context\"\n" + "\t\"log\"\n" +
318+
"\tsdk \"go.mongodb.org/atlas-sdk/v20250101001/admin\"\n)\n\n" +
319+
"func main() {\n" +
320+
"\tctx := context.Background()\n" +
321+
"\tclientID := os.Getenv(\"MONGODB_ATLAS_CLIENT_ID\")\n" +
322+
"\tclientSecret := os.Getenv(\"MONGODB_ATLAS_CLIENT_SECRET\")\n\n" +
323+
"\t// See https://dochub.mongodb.org/core/atlas-go-sdk-oauth\n" +
324+
"\tclient, err := sdk.NewClient(sdk.UseOAuthAuth(clientID, clientSecret))\n\n" +
325+
"\tif err != nil {\n" + "\t\tlog.Fatalf(\"Error: %v\", err)\n\t}\n\n" +
326+
"\tparams = &sdk.TestOperationIDApiParams{}\n" +
327+
"\tsdkResp, httpResp, err := client.TestTagApi.\n" +
328+
"\t\tTestOperationIDWithParams(ctx, params).\n" +
329+
"\t\tExecute()" + "\n}\n",
330+
},
331+
{
332+
Lang: "cURL",
333+
Label: "curl (Service Accounts)",
334+
Source: "curl --header \"Authorization: Bearer ${ACCESS_TOKEN}\" \\\n " +
335+
"--header \"Accept: application/vnd.atlas.2025-01-01+gzip\" \\\n " +
336+
"-X GET \"https://cloud.mongodb.com/test\" \\\n --output \"file_name.gz\"",
337+
},
338+
{
339+
Lang: "cURL",
340+
Label: "curl (Digest)",
341+
Source: "curl --user \"${PUBLIC_KEY}:${PRIVATE_KEY}\" \\\n --digest \\\n " +
342+
"--header \"Accept: application/vnd.atlas.2025-01-01+gzip\" \\\n " +
343+
"-X GET \"https://cloud.mongodb.com/test\" \\\n --output \"file_name.gz\"",
344+
},
345+
},
346+
},
347+
},
348+
})),
349+
},
350+
},
260351
}
261352

262353
for _, tt := range testCases {

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43904,12 +43904,12 @@
4390443904
{
4390543905
"lang": "cURL",
4390643906
"label": "curl (Service Accounts)",
43907-
"source": "curl --header \"Authorization: Bearer ${ACCESS_TOKEN}\" \\\n --header \"Accept: application/vnd.atlas.2023-01-01+json\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/onlineArchives/queryLogs.gz?pretty=true\""
43907+
"source": "curl --header \"Authorization: Bearer ${ACCESS_TOKEN}\" \\\n --header \"Accept: application/vnd.atlas.2023-01-01+gzip\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/onlineArchives/queryLogs.gz\" \\\n --output \"file_name.gz\""
4390843908
},
4390943909
{
4391043910
"lang": "cURL",
4391143911
"label": "curl (Digest)",
43912-
"source": "curl --user \"${PUBLIC_KEY}:${PRIVATE_KEY}\" \\\n --digest \\\n --header \"Accept: application/vnd.atlas.2023-01-01+json\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/onlineArchives/queryLogs.gz?pretty=true\""
43912+
"source": "curl --user \"${PUBLIC_KEY}:${PRIVATE_KEY}\" \\\n --digest \\\n --header \"Accept: application/vnd.atlas.2023-01-01+gzip\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/onlineArchives/queryLogs.gz\" \\\n --output \"file_name.gz\""
4391343913
}
4391443914
]
4391543915
}
@@ -46165,12 +46165,12 @@
4616546165
{
4616646166
"lang": "cURL",
4616746167
"label": "curl (Service Accounts)",
46168-
"source": "curl --header \"Authorization: Bearer ${ACCESS_TOKEN}\" \\\n --header \"Accept: application/vnd.atlas.2023-01-01+json\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{hostName}/logs/{logName}.gz?pretty=true\""
46168+
"source": "curl --header \"Authorization: Bearer ${ACCESS_TOKEN}\" \\\n --header \"Accept: application/vnd.atlas.2023-01-01+gzip\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{hostName}/logs/{logName}.gz\" \\\n --output \"file_name.gz\""
4616946169
},
4617046170
{
4617146171
"lang": "cURL",
4617246172
"label": "curl (Digest)",
46173-
"source": "curl --user \"${PUBLIC_KEY}:${PRIVATE_KEY}\" \\\n --digest \\\n --header \"Accept: application/vnd.atlas.2023-01-01+json\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{hostName}/logs/{logName}.gz?pretty=true\""
46173+
"source": "curl --user \"${PUBLIC_KEY}:${PRIVATE_KEY}\" \\\n --digest \\\n --header \"Accept: application/vnd.atlas.2023-01-01+gzip\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{hostName}/logs/{logName}.gz\" \\\n --output \"file_name.gz\""
4617446174
}
4617546175
],
4617646176
"x-sunset": "2025-06-01"
@@ -47992,12 +47992,12 @@
4799247992
{
4799347993
"lang": "cURL",
4799447994
"label": "curl (Service Accounts)",
47995-
"source": "curl --header \"Authorization: Bearer ${ACCESS_TOKEN}\" \\\n --header \"Accept: application/vnd.atlas.2023-01-01+json\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/dataFederation/{tenantName}/queryLogs.gz?pretty=true\""
47995+
"source": "curl --header \"Authorization: Bearer ${ACCESS_TOKEN}\" \\\n --header \"Accept: application/vnd.atlas.2023-01-01+gzip\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/dataFederation/{tenantName}/queryLogs.gz\" \\\n --output \"file_name.gz\""
4799647996
},
4799747997
{
4799847998
"lang": "cURL",
4799947999
"label": "curl (Digest)",
48000-
"source": "curl --user \"${PUBLIC_KEY}:${PRIVATE_KEY}\" \\\n --digest \\\n --header \"Accept: application/vnd.atlas.2023-01-01+json\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/dataFederation/{tenantName}/queryLogs.gz?pretty=true\""
48000+
"source": "curl --user \"${PUBLIC_KEY}:${PRIVATE_KEY}\" \\\n --digest \\\n --header \"Accept: application/vnd.atlas.2023-01-01+gzip\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/dataFederation/{tenantName}/queryLogs.gz\" \\\n --output \"file_name.gz\""
4800148001
}
4800248002
]
4800348003
}
@@ -62827,12 +62827,12 @@
6282762827
{
6282862828
"lang": "cURL",
6282962829
"label": "curl (Service Accounts)",
62830-
"source": "curl --header \"Authorization: Bearer ${ACCESS_TOKEN}\" \\\n --header \"Accept: application/vnd.atlas.2023-01-01+json\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/orgs/{orgId}/invoices/{invoiceId}/csv?pretty=true\""
62830+
"source": "curl --header \"Authorization: Bearer ${ACCESS_TOKEN}\" \\\n --header \"Accept: application/vnd.atlas.2023-01-01+csv\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/orgs/{orgId}/invoices/{invoiceId}/csv?pretty=true\""
6283162831
},
6283262832
{
6283362833
"lang": "cURL",
6283462834
"label": "curl (Digest)",
62835-
"source": "curl --user \"${PUBLIC_KEY}:${PRIVATE_KEY}\" \\\n --digest \\\n --header \"Accept: application/vnd.atlas.2023-01-01+json\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/orgs/{orgId}/invoices/{invoiceId}/csv?pretty=true\""
62835+
"source": "curl --user \"${PUBLIC_KEY}:${PRIVATE_KEY}\" \\\n --digest \\\n --header \"Accept: application/vnd.atlas.2023-01-01+csv\" \\\n -X GET \"https://cloud.mongodb.com/api/atlas/v2/orgs/{orgId}/invoices/{invoiceId}/csv?pretty=true\""
6283662836
}
6283762837
]
6283862838
}

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

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37470,15 +37470,17 @@ paths:
3747037470
lang: cURL
3747137471
source: |-
3747237472
curl --header "Authorization: Bearer ${ACCESS_TOKEN}" \
37473-
--header "Accept: application/vnd.atlas.2023-01-01+json" \
37474-
-X GET "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/onlineArchives/queryLogs.gz?pretty=true"
37473+
--header "Accept: application/vnd.atlas.2023-01-01+gzip" \
37474+
-X GET "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/onlineArchives/queryLogs.gz" \
37475+
--output "file_name.gz"
3747537476
- label: curl (Digest)
3747637477
lang: cURL
3747737478
source: |-
3747837479
curl --user "${PUBLIC_KEY}:${PRIVATE_KEY}" \
3747937480
--digest \
37480-
--header "Accept: application/vnd.atlas.2023-01-01+json" \
37481-
-X GET "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/onlineArchives/queryLogs.gz?pretty=true"
37481+
--header "Accept: application/vnd.atlas.2023-01-01+gzip" \
37482+
-X GET "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/onlineArchives/queryLogs.gz" \
37483+
--output "file_name.gz"
3748237484
/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/outageSimulation:
3748337485
delete:
3748437486
description: Ends a cluster outage simulation.
@@ -39360,15 +39362,17 @@ paths:
3936039362
lang: cURL
3936139363
source: |-
3936239364
curl --header "Authorization: Bearer ${ACCESS_TOKEN}" \
39363-
--header "Accept: application/vnd.atlas.2023-01-01+json" \
39364-
-X GET "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{hostName}/logs/{logName}.gz?pretty=true"
39365+
--header "Accept: application/vnd.atlas.2023-01-01+gzip" \
39366+
-X GET "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{hostName}/logs/{logName}.gz" \
39367+
--output "file_name.gz"
3936539368
- label: curl (Digest)
3936639369
lang: cURL
3936739370
source: |-
3936839371
curl --user "${PUBLIC_KEY}:${PRIVATE_KEY}" \
3936939372
--digest \
39370-
--header "Accept: application/vnd.atlas.2023-01-01+json" \
39371-
-X GET "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{hostName}/logs/{logName}.gz?pretty=true"
39373+
--header "Accept: application/vnd.atlas.2023-01-01+gzip" \
39374+
-X GET "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{hostName}/logs/{logName}.gz" \
39375+
--output "file_name.gz"
3937239376
x-sunset: "2025-06-01"
3937339377
/api/atlas/v2/groups/{groupId}/clusters/provider/regions:
3937439378
get:
@@ -41412,15 +41416,17 @@ paths:
4141241416
lang: cURL
4141341417
source: |-
4141441418
curl --header "Authorization: Bearer ${ACCESS_TOKEN}" \
41415-
--header "Accept: application/vnd.atlas.2023-01-01+json" \
41416-
-X GET "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/dataFederation/{tenantName}/queryLogs.gz?pretty=true"
41419+
--header "Accept: application/vnd.atlas.2023-01-01+gzip" \
41420+
-X GET "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/dataFederation/{tenantName}/queryLogs.gz" \
41421+
--output "file_name.gz"
4141741422
- label: curl (Digest)
4141841423
lang: cURL
4141941424
source: |-
4142041425
curl --user "${PUBLIC_KEY}:${PRIVATE_KEY}" \
4142141426
--digest \
41422-
--header "Accept: application/vnd.atlas.2023-01-01+json" \
41423-
-X GET "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/dataFederation/{tenantName}/queryLogs.gz?pretty=true"
41427+
--header "Accept: application/vnd.atlas.2023-01-01+gzip" \
41428+
-X GET "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/dataFederation/{tenantName}/queryLogs.gz" \
41429+
--output "file_name.gz"
4142441430
/api/atlas/v2/groups/{groupId}/databaseUsers:
4142541431
get:
4142641432
description: Returns all database users that belong to the specified project. To use this resource, the requesting API Key must have the Project Read Only role.
@@ -55868,14 +55874,14 @@ paths:
5586855874
lang: cURL
5586955875
source: |-
5587055876
curl --header "Authorization: Bearer ${ACCESS_TOKEN}" \
55871-
--header "Accept: application/vnd.atlas.2023-01-01+json" \
55877+
--header "Accept: application/vnd.atlas.2023-01-01+csv" \
5587255878
-X GET "https://cloud.mongodb.com/api/atlas/v2/orgs/{orgId}/invoices/{invoiceId}/csv?pretty=true"
5587355879
- label: curl (Digest)
5587455880
lang: cURL
5587555881
source: |-
5587655882
curl --user "${PUBLIC_KEY}:${PRIVATE_KEY}" \
5587755883
--digest \
55878-
--header "Accept: application/vnd.atlas.2023-01-01+json" \
55884+
--header "Accept: application/vnd.atlas.2023-01-01+csv" \
5587955885
-X GET "https://cloud.mongodb.com/api/atlas/v2/orgs/{orgId}/invoices/{invoiceId}/csv?pretty=true"
5588055886
/api/atlas/v2/orgs/{orgId}/invoices/pending:
5588155887
get:

0 commit comments

Comments
 (0)