-
Notifications
You must be signed in to change notification settings - Fork 76
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
support for specifying version numbers in API endpoints #1115
Conversation
…d types in OpenAPI spec
I think this one is nearly ready to go (but after #1127). The one change I'm leaning towards is that I think |
@jgallagher and @leftwo raised the excellent point that earlier versions of this PR would cause a Dropshot server to happily serve requests for API versions newer than the server was built with. For now, we can make this the responsibility of the Stepping back: my goal for this work is to provide a minimal base for us to go prototype versioning in some real consumers. I think it's pretty likely that as we do that, we will find changes we want to make to this. I wouldn't be surprised if we wind up with some common impls of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very nice
.into_iter() | ||
.collect(); | ||
return Err(syn::Error::new_spanned( | ||
span, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want
span, | |
input.span(), |
Maybe? In particular I'm thinking of this test:
dropshot/tests/fail/bad_version_backwards.stderr
error: semver range (from ... until ...) has the endpoints out of order
--> tests/fail/bad_version_backwards.rs:17:16
|
17 | versions = "1.2.3".."1.2.2"
|
Should we be underlining both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't quite work:
error[E0277]: the trait bound `proc_macro2::Span: ToTokens` is not satisfied
--> dropshot_endpoint/src/metadata.rs:354:25
|
353 | return Err(syn::Error::new_spanned(
| ----------------------- required by a bound introduced by this call
354 | input.span(),
| ^^^^^^^^^^^^ the trait `ToTokens` is not implemented for `proc_macro2::Span`
|
= help: the following other types implement trait `ToTokens`:
&'a T
&'a mut T
Abstract
AndAnd
AndEq
AngleBracketedGenericArguments
Arm
As
and 308 others
note: required by a bound in `syn::Error::new_spanned`
--> /Users/dap/.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.79/src/error.rs:189:27
|
189 | pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
| ^^^^^^^^ required by this bound in `Error::new_spanned`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `dropshot_endpoint` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...
I poked around a bit but did not immediately see how to turn that span into something that impls ToTokens
(besides what the code is already doing).
v.value() | ||
.parse::<semver::Version>() | ||
.map_err(|e| { | ||
syn::Error::new_spanned(v, format!("expected semver: {}", e)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what do Semver::parse() errors look like? Are those more useful than something like "{} is not of the form MAJOR.MINOR.PATCH"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the messages it produces are okay. Here are a few examples:
dropshot/dropshot_endpoint/src/endpoint.rs
Lines 1070 to 1085 in e747169
versions = "one dot two dot three", | |
}, | |
quote! { | |
pub async fn handler_xyz( | |
_rqctx: RequestContext<()>, | |
) -> Result<HttpResponseOk<()>, HttpError> { | |
Ok(()) | |
} | |
}, | |
); | |
assert!(!errors.is_empty()); | |
assert_eq!( | |
errors.get(0).map(ToString::to_string), | |
Some( | |
"expected semver: unexpected character 'o' while \ | |
parsing major version number" |
dropshot/dropshot_endpoint/src/endpoint.rs
Lines 1094 to 1109 in e747169
versions = "1.2", | |
}, | |
quote! { | |
pub async fn handler_xyz( | |
_rqctx: RequestContext<()>, | |
) -> Result<HttpResponseOk<()>, HttpError> { | |
Ok(()) | |
} | |
}, | |
); | |
assert!(!errors.is_empty()); | |
assert_eq!( | |
errors.get(0).map(ToString::to_string), | |
Some( | |
"expected semver: unexpected end of input while parsing \ | |
minor version number" |
Do we definitely want to allow users to specify the version number header (i.e. in We could document (in OpenAPI) this optional header for all API endpoints; that seems quite annoying. Alternatively we could invent an extension to tell progenitor if there's a version header and--if so--what to call it. |
We discussed this offline and concluded:
|
I considered leaving this open until I'd done the consumer-side workflow. But with all the other work going on in Dropshot, I don't think it makes sense to maintain this as a feature branch. Nor is it worth a compile-time feature to exclude it. I'm going to just mark it as experimental for now (in documentation) and land it. |
I did want to at least verify that Omicron could be made to compile easily with this change, and here it is: It's not easy to get CI to run because of the local patches required but I'm going to manually check clippy and |
I've run into a few flakes like oxidecomputer/omicron#7051 but I believe they're unrelated. |
Supersedes #862 (and is based on it). Fixes #869.
Also based on #1127. This includes a test that uses that option to make sure that operations have the same names in different versions, even when they have different handler function names.