Skip to content

Commit

Permalink
Added support for application/yaml response payloads. (#363)
Browse files Browse the repository at this point in the history
* Added application/yaml support and responses to cat APIs.

Signed-off-by: dblock <[email protected]>

* Corrected /_cat/indices response schema.

Signed-off-by: dblock <[email protected]>

* Removed an unevaluate property.

Signed-off-by: dblock <[email protected]>

---------

Signed-off-by: dblock <[email protected]>
Signed-off-by: Theo Nam Truong <[email protected]>
Co-authored-by: Theo Nam Truong <[email protected]>
  • Loading branch information
dblock and nhtruong authored Jun 28, 2024
1 parent bb63d76 commit ed3fb4d
Show file tree
Hide file tree
Showing 11 changed files with 203 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- Added SPECIFICATION_TESTING.md [#359](https://github.com/opensearch-project/opensearch-api-specification/pull/359)
- Added StoryValidator to validate stories before running them ([#354](https://github.com/opensearch-project/opensearch-api-specification/issues/354))
- Added support for `text/plain` responses in `_cat` APIs ([#360](https://github.com/opensearch-project/opensearch-api-specification/pull/360))
- Added support for `application/yaml` responses ([#363](https://github.com/opensearch-project/opensearch-api-specification/pull/363))
- Added test for search with seq_no_primary_term ([#367](https://github.com/opensearch-project/opensearch-api-specification/pull/367))

### Changed
Expand Down
10 changes: 10 additions & 0 deletions spec/namespaces/cat.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,11 @@ components:
type: array
items:
$ref: '../schemas/cat.health.yaml#/components/schemas/HealthRecord'
application/yaml:
schema:
type: array
items:
$ref: '../schemas/cat.health.yaml#/components/schemas/HealthRecord'
cat.help@200:
description: ''
content:
Expand All @@ -864,6 +869,11 @@ components:
type: array
items:
$ref: '../schemas/cat.indices.yaml#/components/schemas/IndicesRecord'
application/yaml:
schema:
type: array
items:
$ref: '../schemas/cat.indices.yaml#/components/schemas/IndicesRecord'
cat.master@200:
description: ''
content:
Expand Down
8 changes: 4 additions & 4 deletions spec/schemas/cat.indices.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ components:
type: string
docs.count:
description: available docs
oneOf:
anyOf:
- type: string
- nullable: true
type: string
docs.deleted:
description: deleted docs
oneOf:
anyOf:
- type: string
- nullable: true
type: string
Expand All @@ -47,13 +47,13 @@ components:
type: string
store.size:
description: store size of primaries & replicas
oneOf:
anyOf:
- type: string
- nullable: true
type: string
pri.store.size:
description: store size of primaries
oneOf:
anyOf:
- type: string
- nullable: true
type: string
Expand Down
15 changes: 14 additions & 1 deletion tests/cat/health.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ chapters:
response:
status: 200
content_type: text/plain
- synopsis: Cat with a json response.
- synopsis: Cat in different formats (format=json).
method: GET
path: /_cat/health
parameters:
Expand All @@ -56,3 +56,16 @@ chapters:
status: yellow
node.data: '1'
discovered_cluster_manager: 'true'
- synopsis: Cat in different formats (format=yaml).
method: GET
path: /_cat/health
parameters:
format: yaml
response:
status: 200
content_type: application/yaml
payload:
- node.total: '1'
status: yellow
node.data: '1'
discovered_cluster_manager: 'true'
72 changes: 72 additions & 0 deletions tests/cat/indices.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
$schema: ../../json_schemas/test_story.schema.yaml

description: Test cat/indices endpoints.
prologues:
- path: /{index}
method: PUT
parameters:
index: books
request_body:
payload: {}
epilogues:
- path: /books
method: DELETE
status: [200, 404]
chapters:
- synopsis: Cat with a default text response.
method: GET
path: /_cat/indices
response:
status: 200
content_type: text/plain
- synopsis: Cat with verbose output (v=true).
method: GET
path: /_cat/indices
parameters:
v: true
response:
status: 200
content_type: text/plain
- synopsis: Cat with headers (h=header1,header2).
method: GET
path: /_cat/indices
parameters:
h:
- health
- status
response:
status: 200
content_type: text/plain
- synopsis: Cat displaying all available headers (help=true).
method: GET
path: /_cat/indices
parameters:
help: true
response:
status: 200
content_type: text/plain
- synopsis: Cat with sorted results.
method: GET
path: /_cat/indices
parameters:
s:
- status
response:
status: 200
content_type: text/plain
- synopsis: Cat in different formats (format=json).
method: GET
path: /_cat/indices
parameters:
format: json
response:
status: 200
content_type: application/json
- synopsis: Cat in different formats (format=yaml).
method: GET
path: /_cat/indices
parameters:
format: yaml
response:
status: 200
content_type: application/yaml
15 changes: 13 additions & 2 deletions tools/src/tester/ChapterEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type SchemaValidator from './SchemaValidator'
import { type StoryOutputs } from './StoryOutputs'
import { ChapterOutput } from './ChapterOutput'
import { Operation, atomizeChangeset, diff } from 'json-diff-ts'
import YAML from 'yaml'
import _ from 'lodash'

export default class ChapterEvaluator {
Expand Down Expand Up @@ -85,7 +86,9 @@ export default class ChapterEvaluator {

#evaluate_payload_body(response: ActualResponse, expected_payload?: Payload): Evaluation {
if (expected_payload == null) return { result: Result.PASSED }
const delta = atomizeChangeset(diff(expected_payload, response.payload))
const content_type = response.content_type ?? 'application/json'
const payload = this.#deserialize_payload(response.payload, content_type)
const delta = atomizeChangeset(diff(expected_payload, payload))
const messages: string[] = _.compact(delta.map((value, _index, _array) => {
switch (value.type) {
case Operation.UPDATE:
Expand All @@ -103,6 +106,14 @@ export default class ChapterEvaluator {
const schema = content?.schema
if (schema == null && content != null) return { result: Result.PASSED }
if (schema == null) return { result: Result.FAILED, message: `Schema for "${response.status}: ${response.content_type}" response not found in the spec.` }
return this._schema_validator.validate(schema, response.payload)
return this._schema_validator.validate(schema, this.#deserialize_payload(response.payload, content_type))
}

#deserialize_payload(payload: any, content_type: string): any {
if (payload === undefined) return undefined
switch (content_type) {
case 'application/yaml': return YAML.parse(payload as string)
default: return payload
}
}
}
2 changes: 1 addition & 1 deletion tools/tests/tester/fixtures/evals/failed/not_found.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ chapters:
- title: This chapter should fail because the operation is not defined in the spec.
overall:
result: FAILED
message: Operation "GET /_cat/health" not found in the spec.
message: Operation "GET /_cat/does_not_exist" not found in the spec.
- title: This chapter should fail because the parameter is not defined in the spec.
overall:
result: FAILED
Expand Down
35 changes: 33 additions & 2 deletions tools/tests/tester/fixtures/evals/passed.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ chapters:
result: PASSED
payload_schema:
result: PASSED
- title: This GET /_cat chapter should pass.
- title: This GET /_cat chapter returns text/plain and should pass.
overall:
result: PASSED
request:
Expand All @@ -37,7 +37,38 @@ chapters:
result: PASSED
payload_schema:
result: PASSED

- title: This GET /_cat/health chapter returns application/json and should pass.
overall:
result: PASSED
request:
parameters:
format:
result: PASSED
request_body:
result: PASSED
response:
status:
result: PASSED
payload_body:
result: PASSED
payload_schema:
result: PASSED
- title: This GET /_cat/health chapter returns application/yaml and should pass.
overall:
result: PASSED
request:
parameters:
format:
result: PASSED
request_body:
result: PASSED
response:
status:
result: PASSED
payload_body:
result: PASSED
payload_schema:
result: PASSED
epilogues:
- title: DELETE /books
overall:
Expand Down
33 changes: 33 additions & 0 deletions tools/tests/tester/fixtures/specs/excerpt.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,22 @@ paths:
x-operation-group: cat.help
x-version-added: '1.0'
description: Returns help for the Cat APIs.
parameters:
- $ref: '#/components/parameters/cat.help::query.format'
responses:
'200':
$ref: '#/components/responses/cat.help@200'
/_cat/health:
get:
operationId: cat.health.0
x-operation-group: cat.health
x-version-added: '1.0'
description: Returns health for the Cat APIs.
parameters:
- $ref: '#/components/parameters/cat.health::query.format'
responses:
'200':
$ref: '#/components/responses/cat.health@200'
/{index}:
delete:
operationId: indices.delete.0
Expand Down Expand Up @@ -73,6 +86,21 @@ components:
text/plain:
schema:
type: string
cat.health@200:
content:
text/plain:
schema:
type: string
application/json:
schema:
type: array
items:
type: object
application/yaml:
schema:
type: array
items:
type: object
indices.delete@200:
description: ''
content:
Expand Down Expand Up @@ -101,6 +129,11 @@ components:
- shards_acknowledged
- acknowledged
parameters:
cat.health::query.format:
in: query
name: format
schema:
type: string
indices.delete::path.index:
in: path
name: index
Expand Down
2 changes: 1 addition & 1 deletion tools/tests/tester/fixtures/stories/failed/not_found.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ epilogues:
status: [200, 404]
chapters:
- synopsis: This chapter should fail because the operation is not defined in the spec.
path: /_cat/health
path: /_cat/does_not_exist
method: GET
- synopsis: This chapter should fail because the parameter is not defined in the spec.
path: /{index}
Expand Down
22 changes: 21 additions & 1 deletion tools/tests/tester/fixtures/stories/passed.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,26 @@ chapters:
method: PUT
parameters:
index: books
- synopsis: This GET /_cat chapter should pass.
- synopsis: This GET /_cat chapter returns text/plain and should pass.
path: /_cat
method: GET
- synopsis: This GET /_cat/health chapter returns application/json and should pass.
path: /_cat/health
parameters:
format: json
method: GET
response:
status: 200
content_type: application/json
payload:
- node.total: '1'
- synopsis: This GET /_cat/health chapter returns application/yaml and should pass.
path: /_cat/health
parameters:
format: yaml
method: GET
response:
status: 200
content_type: application/yaml
payload:
- node.total: '1'

0 comments on commit ed3fb4d

Please sign in to comment.