Distinguish LIST-only paths in OpenAPI (#13643)
* Distinguish LIST-only paths in OpenAPI * add changelog * Put enum field inside schema
This commit is contained in:
parent
daefbd0a54
commit
6652203569
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:bug
|
||||||
|
sdk: Fixes OpenAPI to distinguish between paths that can do only List, or both List and Read.
|
||||||
|
```
|
|
@ -368,8 +368,18 @@ func documentPath(p *Path, specialPaths *logical.Paths, backendType logical.Back
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LIST is represented as GET with a `list` query parameter
|
// LIST is represented as GET with a `list` query parameter.
|
||||||
if opType == logical.ListOperation || (opType == logical.ReadOperation && operations[logical.ListOperation] != nil) {
|
if opType == logical.ListOperation {
|
||||||
|
// Only accepts List (due to the above skipping of ListOperations that also have ReadOperations)
|
||||||
|
op.Parameters = append(op.Parameters, OASParameter{
|
||||||
|
Name: "list",
|
||||||
|
Description: "Must be set to `true`",
|
||||||
|
Required: true,
|
||||||
|
In: "query",
|
||||||
|
Schema: &OASSchema{Type: "string", Enum: []interface{}{"true"}},
|
||||||
|
})
|
||||||
|
} else if opType == logical.ReadOperation && operations[logical.ListOperation] != nil {
|
||||||
|
// Accepts both Read and List
|
||||||
op.Parameters = append(op.Parameters, OASParameter{
|
op.Parameters = append(op.Parameters, OASParameter{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Description: "Return a list if `true`",
|
Description: "Return a list if `true`",
|
||||||
|
|
|
@ -320,7 +320,7 @@ func TestOpenAPI_Paths(t *testing.T) {
|
||||||
testPath(t, p, sp, expected("legacy"))
|
testPath(t, p, sp, expected("legacy"))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Operations", func(t *testing.T) {
|
t.Run("Operations - All Operations", func(t *testing.T) {
|
||||||
p := &Path{
|
p := &Path{
|
||||||
Pattern: "foo/" + GenericNameRegex("id"),
|
Pattern: "foo/" + GenericNameRegex("id"),
|
||||||
Fields: map[string]*FieldSchema{
|
Fields: map[string]*FieldSchema{
|
||||||
|
@ -395,6 +395,65 @@ func TestOpenAPI_Paths(t *testing.T) {
|
||||||
testPath(t, p, sp, expected("operations"))
|
testPath(t, p, sp, expected("operations"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("Operations - List Only", func(t *testing.T) {
|
||||||
|
p := &Path{
|
||||||
|
Pattern: "foo/" + GenericNameRegex("id"),
|
||||||
|
Fields: map[string]*FieldSchema{
|
||||||
|
"id": {
|
||||||
|
Type: TypeString,
|
||||||
|
Description: "id path parameter",
|
||||||
|
},
|
||||||
|
"flavors": {
|
||||||
|
Type: TypeCommaStringSlice,
|
||||||
|
Description: "the flavors",
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
Type: TypeNameString,
|
||||||
|
Default: "Larry",
|
||||||
|
Description: "the name",
|
||||||
|
},
|
||||||
|
"age": {
|
||||||
|
Type: TypeInt,
|
||||||
|
Description: "the age",
|
||||||
|
AllowedValues: []interface{}{1, 2, 3},
|
||||||
|
Required: true,
|
||||||
|
DisplayAttrs: &DisplayAttributes{
|
||||||
|
Name: "Age",
|
||||||
|
Sensitive: true,
|
||||||
|
Group: "Some Group",
|
||||||
|
Value: 7,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"x-abc-token": {
|
||||||
|
Type: TypeHeader,
|
||||||
|
Description: "a header value",
|
||||||
|
AllowedValues: []interface{}{"a", "b", "c"},
|
||||||
|
},
|
||||||
|
"format": {
|
||||||
|
Type: TypeString,
|
||||||
|
Description: "a query param",
|
||||||
|
Query: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
HelpSynopsis: "Synopsis",
|
||||||
|
HelpDescription: "Description",
|
||||||
|
Operations: map[logical.Operation]OperationHandler{
|
||||||
|
logical.ListOperation: &PathOperation{
|
||||||
|
Summary: "List Summary",
|
||||||
|
Description: "List Description",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DisplayAttrs: &DisplayAttributes{
|
||||||
|
Navigation: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
sp := &logical.Paths{
|
||||||
|
Root: []string{"foo*"},
|
||||||
|
}
|
||||||
|
testPath(t, p, sp, expected("operations_list"))
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("Responses", func(t *testing.T) {
|
t.Run("Responses", func(t *testing.T) {
|
||||||
p := &Path{
|
p := &Path{
|
||||||
Pattern: "foo",
|
Pattern: "foo",
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
{
|
||||||
|
"openapi": "3.0.2",
|
||||||
|
"info": {
|
||||||
|
"title": "HashiCorp Vault API",
|
||||||
|
"description": "HTTP API that gives you full access to Vault. All API routes are prefixed with `/v1/`.",
|
||||||
|
"version": "<vault_version>",
|
||||||
|
"license": {
|
||||||
|
"name": "Mozilla Public License 2.0",
|
||||||
|
"url": "https://www.mozilla.org/en-US/MPL/2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"/foo/{id}": {
|
||||||
|
"description": "Synopsis",
|
||||||
|
"x-vault-sudo": true,
|
||||||
|
"x-vault-displayAttrs": {
|
||||||
|
"navigation": true
|
||||||
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "format",
|
||||||
|
"description": "a query param",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"description": "id path parameter",
|
||||||
|
"in": "path",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"get": {
|
||||||
|
"operationId": "getFooId",
|
||||||
|
"tags": ["secrets"],
|
||||||
|
"summary": "List Summary",
|
||||||
|
"description": "List Description",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "list",
|
||||||
|
"description": "Must be set to `true`",
|
||||||
|
"required": true,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["true"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue