This tool manages the OpenAPI documents (JSON files) checked into Omicron’s openapi
directory, using Dropshot’s support for API traits.
Note
|
For more information about API traits, see RFD 479. |
Currently, a subset of OpenAPI documents is managed by this tool. Eventually, all of the OpenAPI documents in Omicron will be managed by this tool; work to make that happen is ongoing.
To check whether your document is managed, run cargo xtask openapi list
: it will list out all managed OpenAPI documents. If your document is not on the list, it is unmanaged.
The OpenAPI manager is meant to be invoked via cargo xtask openapi
. Currently, three commands are provided:
-
cargo xtask openapi list
: List information about currently-managed documents. -
cargo xtask openapi check
: Check that all of the managed documents are up-to-date. -
cargo xtask openapi generate
: Update and generate OpenAPI documents.
There is also a test which makes sure that all managed documents are up-to-date, and tells you to run cargo xtask openapi generate
if they aren’t.
The OpenAPI manager has dependencies on a set of API crates. An API crate is a Rust library that consists of the API trait, and possibly supporting types. Each OpenAPI document should have a separate API crate.
To keep compile times down, ensure that the API crate has as few dependencies as possible. In particular, strongly avoid any dependencies on Diesel or other database logic.
The ideal set of dependencies is:
-
Common crates within omicron:
omicron-common
, perhapsomicron-uuid-kinds
if typed UUIDs are in use, and atypes
crate for your service. -
Core external crates:
dropshot
,serde
,schemars
, anduuid
.
For an archetypal way to organize code, see the dependency graph in RFD 479’s Choosing between functions and traits.
For OpenAPI documents to be managed by this tool, the corresponding interfaces must be defined via API traits rather than traditional Dropshot function-based servers.
Tip
|
For examples within Omicron, search the repo for dropshot::api_description .
|
If you’re defining a new service fronted by OpenAPI, first create an API crate (see API crates above).
-
Add the API crate to the workspace’s
Cargo.toml
:members
anddefault-members
, and a reference in[workspace.dependencies]
. -
Following the example in RFD 479’s Trait definition, define the API trait.
In the implementation crate:
-
Add a dependency on the API crate.
-
Following the example in RFD 479’s API implementation, provide an implementation of the trait.
Once the API crate is defined, perform the steps in Adding the API crate to the manager below.
Existing, unmanaged documents are generated via function-based servers: a set of functions that some code combines into a Dropshot ApiDescription
. (There is also likely an expectorate test which ensures that the document is up-to-date.)
The first step is to convert the function-based server into an API trait. To do so, create an API crate (see API crates above).
-
Add the API crate to the workspace’s
Cargo.toml
:members
anddefault-members
, and a reference in[workspace.dependencies]
. -
Follow the instructions in RFD 479’s Converting functions to API traits for the API crate.
In the implementation crate:
-
Continue following the instructions in RFD 479’s Converting functions to API traits for where the endpoint functions are currently defined.
-
Find the test which currently manages the document (try searching the repo for
openapi_lint::validate
). If it performs any checks on the document beyondopenapi_lint::validate
oropenapi_lint::validate_external
, see Performing extra validation.
Next, perform the steps in Adding the API crate to the manager below.
Finally, remove:
-
The test which used to manage the document. The OpenAPI manager includes a test that will automatically run in CI.
-
The binary subcommand (typically called
openapi
) that generated the OpenAPI document. The test was the only practical use of this subcommand.
Once the API crate is defined, inform the OpenAPI manager of its existence. Within this directory:
-
In
Cargo.toml
, add a dependency on the API crate. -
In
src/spec.rs
, add the crate to theall_apis
function. (Please keep the list sorted by filename.)
To ensure everything works well, run cargo xtask openapi generate
.
-
Your OpenAPI document should be generated on disk and listed in the output.
-
If you’re converting an existing API, the only changes should be the ones you might have introduced as part of the refactor. If there are significant changes, something’s gone wrong—maybe you missed an endpoint?
By default, the OpenAPI manager does basic validation on the generated document. Some documents require extra validation steps.
It’s best to put extra validation next to the trait, within the API crate.
-
In the API crate, add dependencies on
anyhow
andopenapiv3
. -
Define a function with signature
fn extra_validation(openapi: &openapiv3::OpenAPI) → anyhow::Result<()>
which performs the extra validation steps. -
In
all_apis
, set theextra_validation
field to this function.
The OpenAPI manager uses the new support for Dropshot API traits described in RFD 479.
With traditional function-based Dropshot servers, generating the OpenAPI document requires the implementation to be compiled. With API traits, that is no longer necessary. The OpenAPI manager leverages this to provide a fast and easy way to regenerate API documents.
This does mean that the OpenAPI manager requires the use of API traits, and that eventually all of Omicron’s Dropshot APIs should be switched over to traits.