Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure correct OpenAPI 3.1.0 spec. #646

Merged
merged 30 commits into from
Nov 6, 2024

Conversation

dblock
Copy link
Member

@dblock dblock commented Oct 25, 2024

Description

Use a Python and a Ruby OpenAPI spec validator and ensure correct OpenAPI 3.1.0 spec.

Issues Resolved

Closes #633.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

Copy link
Contributor

github-actions bot commented Oct 25, 2024

Changes Analysis

Commit SHA: 04716ca
Comparing To SHA: 07e329e

API Changes

Summary

└─┬Paths
  ├─┬/_cat/master
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27178:13)❌ 
  ├─┬/{index}/_mapping
  │ └─┬GET
  │   └─┬Parameters
  │     └──[🔀] style (19757:14)
  ├─┬/_cat/aliases
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27054:13)❌ 
  ├─┬/_cat/pending_tasks
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27211:13)❌ 
  ├─┬/_cat/aliases/{name}
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27054:13)❌ 
  ├─┬/_cat/count
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27098:13)❌ 
  ├─┬/_cat/shards/{index}
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27288:13)❌ 
  ├─┬/_plugins/_flow_framework/workflow/{workflow_id}
  │ ├─┬GET
  │ │ └─┬Responses
  │ │   ├─┬200
  │ │   │ └─┬application/json
  │ │   │   └──[➕] schema (47301:7)❌ 
  │ │   └─┬404
  │ │     └─┬application/json
  │ │       └──[➕] schema (47759:7)❌ 
  │ ├─┬PUT
  │ │ └─┬Responses
  │ │   ├─┬400
  │ │   │ └─┬application/json
  │ │   │   └──[➕] schema (27978:13)❌ 
  │ │   └─┬404
  │ │     └─┬application/json
  │ │       └──[➕] schema (47759:7)❌ 
  │ └─┬DELETE
  │   └─┬Responses
  │     ├─┬403
  │     │ └─┬application/json
  │     │   └──[➕] schema (47665:7)❌ 
  │     ├─┬200
  │     │ └─┬application/json
  │     │   └──[➕] schema (47275:7)❌ 
  │     └─┬400
  │       └─┬application/json
  │         └──[➕] schema (47778:7)❌ 
  ├─┬/_opendistro/_sql/settings
  │ └─┬PUT
  │   └─┬Requestbody
  │     └──[➖] required (26883:17)❌ 
  ├─┬/_cat/cluster_manager
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27087:13)❌ 
  ├─┬/_cat/templates/{name}
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27321:13)❌ 
  ├─┬/_cat/tasks
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27310:13)❌ 
  ├─┬/_opendistro/_sql/_explain
  │ └─┬POST
  │   └─┬Requestbody
  │     └──[➖] required (26863:17)❌ 
  ├─┬/_plugins/_flow_framework/workflow/state/_search
  │ ├─┬GET
  │ │ └─┬Responses
  │ │   ├─┬200
  │ │   │ └─┬application/json
  │ │   │   └──[➕] schema (47523:7)❌ 
  │ │   ├─┬408
  │ │   │ └─┬application/json
  │ │   │   └──[➕] schema (47743:7)❌ 
  │ │   ├─┬400
  │ │   │ └─┬application/json
  │ │   │   └──[➕] schema (47616:7)❌ 
  │ │   └─┬403
  │ │     └─┬application/json
  │ │       └──[➕] schema (47665:7)❌ 
  │ └─┬POST
  │   └─┬Responses
  │     ├─┬408
  │     │ └─┬application/json
  │     │   └──[➕] schema (47743:7)❌ 
  │     ├─┬400
  │     │ └─┬application/json
  │     │   └──[➕] schema (47616:7)❌ 
  │     ├─┬403
  │     │ └─┬application/json
  │     │   └──[➕] schema (47665:7)❌ 
  │     └─┬200
  │       └─┬application/json
  │         └──[➕] schema (47523:7)❌ 
  ├─┬/_plugins/_flow_framework/workflow/{workflow_id}/_status
  │ └─┬GET
  │   └─┬Responses
  │     ├─┬200
  │     │ └─┬application/json
  │     │   └──[➕] schema (27845:13)❌ 
  │     ├─┬403
  │     │ └─┬application/json
  │     │   └──[➕] schema (47665:7)❌ 
  │     └─┬404
  │       └─┬application/json
  │         └──[➕] schema (47759:7)❌ 
  ├─┬/_cat/segment_replication/{index}
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27266:13)❌ 
  ├─┬/_opendistro/_sql/stats
  │ └─┬POST
  │   └─┬Requestbody
  │     └──[➖] required (26869:17)❌ 
  ├─┬/_cat/nodes
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27200:13)❌ 
  ├─┬/_plugins/_flow_framework/workflow
  │ └─┬POST
  │   └─┬Responses
  │     ├─┬400
  │     │ └─┬application/json
  │     │   └──[➕] schema (27780:13)❌ 
  │     └─┬403
  │       └─┬application/json
  │         └──[➕] schema (47665:7)❌ 
  ├─┬/_cat/thread_pool/{thread_pool_patterns}
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27332:13)❌ 
  ├─┬/_cat/repositories
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27255:13)❌ 
  ├─┬/_cat/snapshots/{repository}
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27299:13)❌ 
  ├─┬/_cat/segments/{index}
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27277:13)❌ 
  ├─┬/_cat/allocation
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27076:13)❌ 
  ├─┬/_cat/pit_segments/_all
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27065:13)❌ 
  ├─┬/_cat/segment_replication
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27266:13)❌ 
  ├─┬/_cat/pit_segments
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27222:13)❌ 
  ├─┬/_plugins/_security/tenantinfo
  │ ├─┬GET
  │ │ └─┬Responses
  │ │   └─┬403
  │ │     └─┬text/plain
  │ │       └──[➕] schema (30162:13)❌ 
  │ └─┬POST
  │   └─┬Responses
  │     └─┬403
  │       └─┬text/plain
  │         └──[➕] schema (30162:13)❌ 
  ├─┬/_plugins/_flow_framework/workflow/_search
  │ ├─┬GET
  │ │ └─┬Responses
  │ │   ├─┬200
  │ │   │ └─┬application/json
  │ │   │   └──[➕] schema (47510:7)❌ 
  │ │   ├─┬400
  │ │   │ └─┬application/json
  │ │   │   └──[➕] schema (47616:7)❌ 
  │ │   ├─┬403
  │ │   │ └─┬application/json
  │ │   │   └──[➕] schema (47665:7)❌ 
  │ │   └─┬408
  │ │     └─┬application/json
  │ │       └──[➕] schema (47743:7)❌ 
  │ └─┬POST
  │   └─┬Responses
  │     ├─┬200
  │     │ └─┬application/json
  │     │   └──[➕] schema (47510:7)❌ 
  │     ├─┬408
  │     │ └─┬application/json
  │     │   └──[➕] schema (47743:7)❌ 
  │     ├─┬400
  │     │ └─┬application/json
  │     │   └──[➕] schema (47616:7)❌ 
  │     └─┬403
  │       └─┬application/json
  │         └──[➕] schema (47665:7)❌ 
  ├─┬/_plugins/_sql/stats
  │ └─┬POST
  │   └─┬Requestbody
  │     └──[➖] required (26869:17)❌ 
  ├─┬/_opendistro/_sql/close
  │ └─┬POST
  │   └─┬Requestbody
  │     └──[➖] required (26857:17)❌ 
  ├─┬/_cat/recovery
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27244:13)❌ 
  ├─┬/_opendistro/_asynchronous_search/{id}
  │ ├─┬GET
  │ │ └─┬Parameters
  │ │   └──[➕] required (14417:17)❌ 
  │ └─┬DELETE
  │   └─┬Parameters
  │     └──[➕] required (14411:17)❌ 
  ├─┬/_cat/indices/{index}
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27152:13)❌ 
  ├─┬/_opendistro/_sql
  │ └─┬POST
  │   └─┬Requestbody
  │     └──[➖] required (26875:17)❌ 
  ├─┬/_cat/nodeattrs
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27189:13)❌ 
  ├─┬/_cat/thread_pool
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27332:13)❌ 
  ├─┬/_cat/segments
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27277:13)❌ 
  ├─┬/_cat/count/{index}
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27098:13)❌ 
  ├─┬/_plugins/_sql/_explain
  │ └─┬POST
  │   └─┬Requestbody
  │     └──[➖] required (26863:17)❌ 
  ├─┬/_plugins/_asynchronous_search/{id}
  │ ├─┬GET
  │ │ └─┬Parameters
  │ │   └──[➕] required (14417:17)❌ 
  │ └─┬DELETE
  │   └─┬Parameters
  │     └──[➕] required (14411:17)❌ 
  ├─┬/_opendistro/_security/tenantinfo
  │ ├─┬GET
  │ │ └─┬Responses
  │ │   └─┬403
  │ │     └─┬text/plain
  │ │       └──[➕] schema (30162:13)❌ 
  │ └─┬POST
  │   └─┬Responses
  │     └─┬403
  │       └─┬text/plain
  │         └──[➕] schema (30162:13)❌ 
  ├─┬/_cat/allocation/{node_id}
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27076:13)❌ 
  ├─┬/_plugins/_flow_framework/workflow/{workflow_id}/_deprovision
  │ └─┬POST
  │   └─┬Responses
  │     ├─┬200
  │     │ └─┬application/json
  │     │   └──[➕] schema (47508:7)❌ 
  │     ├─┬202
  │     │ └─┬application/json
  │     │   └──[➕] schema (47637:7)❌ 
  │     ├─┬403
  │     │ └─┬application/json
  │     │   └──[➕] schema (27831:13)❌ 
  │     └─┬404
  │       └─┬application/json
  │         └──[➕] schema (47759:7)❌ 
  ├─┬/_search/pipeline/{id}
  │ └─┬GET
  │   └─┬Parameters
  │     └──[➕] required (23142:17)❌ 
  ├─┬/_cat/recovery/{index}
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27244:13)❌ 
  ├─┬/_cat/shards
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27288:13)❌ 
  ├─┬/_cat/snapshots
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27299:13)❌ 
  ├─┬/_plugins/_query/settings
  │ └─┬PUT
  │   └─┬Requestbody
  │     └──[➖] required (26883:17)❌ 
  ├─┬/_cat/plugins
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27233:13)❌ 
  ├─┬/_cat/fielddata/{fields}
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27109:13)❌ 
  ├─┬/_plugins/_sql/close
  │ └─┬POST
  │   └─┬Requestbody
  │     └──[➖] required (26857:17)❌ 
  ├─┬/_plugins/_flow_framework/workflow/_steps
  │ └─┬GET
  │   └─┬Responses
  │     ├─┬200
  │     │ └─┬application/json
  │     │   └──[➕] schema (47596:7)❌ 
  │     ├─┬403
  │     │ └─┬application/json
  │     │   └──[➕] schema (47665:7)❌ 
  │     └─┬400
  │       └─┬application/json
  │         └──[➕] schema (47807:7)❌ 
  ├─┬/_mapping
  │ └─┬GET
  │   └─┬Parameters
  │     └──[🔀] style (19757:14)
  ├─┬/_cat/health
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27120:13)❌ 
  ├─┬/_plugins/_sql
  │ └─┬POST
  │   └─┬Requestbody
  │     └──[➖] required (26875:17)❌ 
  ├─┬/_cat/indices
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27152:13)❌ 
  ├─┬/_plugins/_security/api/generateonbehalfoftoken
  │ └─┬POST
  │   └─┬Responses
  │     └─┬400
  │       └─┬text/plain
  │         └──[➕] schema (29686:13)❌ 
  ├─┬/_plugins/_flow_framework/workflow/{workflow_id}/_provision
  │ └─┬POST
  │   └─┬Responses
  │     ├─┬403
  │     │ └─┬application/json
  │     │   └──[➕] schema (47665:7)❌ 
  │     ├─┬400
  │     │ └─┬application/json
  │     │   └──[➕] schema (27901:13)❌ 
  │     └─┬200
  │       └─┬application/json
  │         └──[➕] schema (47508:7)❌ 
  ├─┬/_cat/templates
  │ └─┬GET
  │   └─┬Responses
  │     └─┬200
  │       └─┬text/plain
  │         └──[➕] schema (27321:13)❌ 
  └─┬/_cat/fielddata
    └─┬GET
      └─┬Responses
        └─┬200
          └─┬text/plain
            └──[➕] schema (27109:13)❌ 

Document Element Total Changes Breaking Changes
paths 95 93
  • BREAKING Changes: 93 out of 95
  • Modifications: 2
  • Removals: 10
  • Additions: 83
  • Breaking Removals: 10
  • Breaking Additions: 83

Report

The full API changes report is available at: https://github.com/opensearch-project/opensearch-api-specification/actions/runs/11672332764/artifacts/2143280585

API Coverage

Before After Δ
Covered (%) 588 (57.59 %) 588 (57.59 %) 0 (0 %)
Uncovered (%) 433 (42.41 %) 433 (42.41 %) 0 (0 %)
Unknown 35 35 0

@dblock dblock force-pushed the validate-spec-py branch 2 times, most recently from 8cf1c31 to 05c5254 Compare October 25, 2024 14:01
Copy link
Contributor

github-actions bot commented Oct 25, 2024

Spec Test Coverage Analysis

Total Tested
510 315 (61.76 %)

@dblock
Copy link
Member Author

dblock commented Oct 30, 2024

With b9b4f4e we go down from 4593 to 3713 and with 5e65b0a down to 3501 issues with the Ruby validator.

Signed-off-by: dblock <dblock@amazon.com>
…refs.

Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
@dblock dblock marked this pull request as ready for review November 5, 2024 14:34
@dblock
Copy link
Member Author

dblock commented Nov 5, 2024

@nhtruong @Xtansia this is green and ready to review, thx

@dblock dblock changed the title Added Python and Ruby spec validators. Ensure correct OpenAPI 3.1.0 spec. Nov 5, 2024
@nhtruong
Copy link
Collaborator

nhtruong commented Nov 5, 2024

Are there discrepancies between Ruby and Python's validators where they can throw different validation errors? Just wondering why we need both.

@dblock
Copy link
Member Author

dblock commented Nov 5, 2024

Are there discrepancies between Ruby and Python's validators where they can throw different validation errors? Just wondering why we need both.

Yes, they are very different codebases and throw some different errors. The Ruby one spits out all errors and was useful for the large categories like #/paths/%2F_cat%2Fsegment_replication/get/parameters/17/%24ref: #/components/parameters/_global%3A%3Aquery.pretty does not resolve to a valid object, while the python one picked up unresolved parameters in superseded operations that the Ruby one didn't (Path parameter 'policyID' for 'get' operation in '/_opendistro/_ism/policies/{policyID}' was not resolved and Required list has not defined properties: ['order0']).

In general I like that these are acting like integration tests, ensure that the spec is usable with different libraries, and points to libraries that we know work with the spec.

Comment on lines 10 to 27
description: Whether to pretty format the returned JSON response.
schema:
type: boolean
default: false
human:
name: human
in: query
description: Whether to return human readable values for statistics.
schema:
type: boolean
default: true
error_trace:
name: error_trace
in: query
description: Whether to include the stack trace of returned errors.
schema:
type: boolean
default: false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should move the default values into their respective schemas in this case.
We should also add x-default extension for parameters when the default for the param differs from the default of the schema OR when a shared schema itself doesn't have a default but certain param using said schema does.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did the first part, didn't realize that default should/can be nested under schema when I was removing this.

I don't think we have a case where the default differs, do you know of one?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't come across on where the schema itself has a default that is different from the param that uses it. But I've come across schemas that are used in different params of different operations but have different default values depending on the operation. But That was a long time ago, before we moved onto OpenAPI. But that's still a real possibility.

tests/default/security/api/nodesdn.yaml Show resolved Hide resolved
Comment on lines 37 to 39
$ref: '#/components/responses/info@removed-2.0-refs'
$ref: '#/components/responses/info.removed-2.0-refs'
added-1.3-removed-2.0:
$ref: '#/components/responses/info@added-1.3-removed-2.0'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gets tricky with operation-group in non-root namespaces, say indices.create. We will end up with indices.create.removed-2.0. Visually it's hard to tell which is which. Is it a response for indices that's named create.remove-2.0 or, a response for indices.create that's named removed-2.0.

This is not an issue on the technical term because the CodeGen does not parse the response names (at least the ones I work don't. @Xtansia can chime in), but we loses the visual cue with this change. I'm just stating a cost of this change. It's not a blocker.

We can also replace @ with ___ --> indices.create___removed-2.0

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with this map.

      .replaceAll('::', '___')
      .replaceAll('@', '__')
      .replaceAll(':', '_')

Comment on lines -123 to -124
- $ref: '#/components/schemas/_common:Type'
- $ref: '#/components/schemas/_common:OldId'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also replace : with ___ in this case to separate the schema category from the type name? Similar to the previous comment regarding the response naming, this can get confusing with more complex schema categories say ai_dsl.aggregation_common_Type. It's hard to visually tell where the category ends and where the schema name starts. ai_dsl.aggreation_common___Type is slightly better and easier for the CodeGen to parse.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take a look at the update, we have to replace a few things, I went with the following map.

      .replaceAll('::', '___')
      .replaceAll('@', '__')
      .replaceAll(':', '_')

      .replaceAll('::', '___')
      .replaceAll('@', '__')
      .replaceAll(':', '_')

Signed-off-by: dblock <dblock@amazon.com>
Signed-off-by: dblock <dblock@amazon.com>
Comment on lines 53 to 54
const file = `schemas/${key.split('_')[0]}.yaml`
const location = `#/components/schemas/${key.split('_')[1]}`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work with _core.get_script_languages_LanguageContext since _ is also used in the name of the schema category.

Comment on lines 155 to 160
#normalize_key(key: string): string {
return key
.replaceAll('::', '___')
.replaceAll('@', '__')
.replaceAll(':', '_')
}
Copy link
Collaborator

@nhtruong nhtruong Nov 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's time for a quick trip down the memory lane to learn why ::, @, and : were chosen as separators for parameter, response, and schema names. Long ago, before this repo was fully in OpenAPI, there were 2 criteria for #component name separators:

  1. The character(s) used as a separator cannot appear anywhere else in the $ref. (This makes it easier to tell different component of a name apart, and easier for CodeGen to parse)
  2. The separators for parameters, responses, and schemas must be easily distinguishable from one another. (This encoding of component type into the separators helps the reader quickly identify where they are in the giant YAML file, and easier to grep for a component definition.

We can ignore criterion No.2 but I think No.1 is worth upholding. So, .replaceAll(':', '_') is not good. We can use ___ as the separator for all 3 types of #components if we let go of criteria No.2 OR come up with a different set of separators that still conform to strict OpenAPI 3.1's naming rules. Say ___, ---, and ....

Copy link
Member Author

@dblock dblock Nov 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we're only parsing :: and @ and : is pure decoration (otherwise :: vs. : would be a problem already). So, with this approach you can split by 3 ___ to get the equivalent of :: and by 2 __ to get the equivalent of @, as long as you parse in that order. We do it in tests.

I could definitely use things like ___ vs. ---, but I find them rather ugly :) WDYT?

Copy link
Collaborator

@nhtruong nhtruong Nov 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not gonna be pretty with how restrictive OpenAPI 3.1 is unfortunately. We can simply do

key
   .replaceAll('::', '___')
   .replaceAll(':', '___')
   .replaceAll('@', '___')

and can still tell which kind of OpenAPI #components we're look at (tho harder):

  • Parameters will end with <path/query>.<param> (e.g. indices.create___query.index)
  • Responses will end with a number (most of the times) (e.g. indices.create___201)
  • Named schemas will end with a PascalCased string (e.g. _common___ExpandedWildCard

The merged file is mostly read by programs anyway. So, making it easier to parse it more important than human readability.

Eventually we should replace these for all files in the ./spec folder too so that we dont have 2 different sets of separators to keep track of and reduce overhead for maintainers.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like using ___ as the separator better, even though technically someone could create a key like ___ to mess with the merger, I don't think it's a real scenario.

I don't know whether we want to just replace all keys in the spec, it's nice to use a :: and @ convention for readability/developer productivity.

Updated PR with ___.

Signed-off-by: dblock <dblock@amazon.com>
@dblock dblock requested a review from nhtruong November 6, 2024 18:27
@dblock
Copy link
Member Author

dblock commented Nov 6, 2024

@Xtansia take a look?

@Xtansia
Copy link
Collaborator

Xtansia commented Nov 6, 2024

Seems good to me, nothing that'll be a major issue for .NET or Java codegen

@Xtansia Xtansia merged commit 2a39edd into opensearch-project:main Nov 6, 2024
27 checks passed
@dblock dblock deleted the validate-spec-py branch November 7, 2024 03:42
@rursprung
Copy link
Contributor

FYI: this broke a link in the README which will now block all PRs based on this until resolved. i've created a fix for it: #657

Xtansia pushed a commit that referenced this pull request Nov 7, 2024
the workflow got renamed in commit 2a39edd (#646), thus the link is no
longer valid. this was not caught by the "check links" test as the link
was still valid until the PR got merged. this currently blocks all other
PRs.

Signed-off-by: Ralph Ursprung <Ralph.Ursprung@avaloq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] OpenAPI spec validation failed on missing descriptions and name pattern
4 participants