-
Notifications
You must be signed in to change notification settings - Fork 40
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
Add routes to lookup resources by id #1266
Conversation
/by_id/
routes for common /by_id/
routes for common resources
Nice! In terms of prioritizing review, what's the level of urgency on reviewing this? Is this blocking work for Tuesday? |
I consider this low priority and isn't blocking anything that's critical to have on Tuesday. |
This is real nice!!! Just popping in to say that looking up an item by ID is crucial imo. For example, when implementing the resource for VPCs in the Terraform provider I was already having to disable name updates https://github.com/oxidecomputer/terraform-provider-oxide-demo/blob/main/oxide/resource_vpc.go#L147-L154 |
From @ahl in chat:
I agree that it'd be nice to be able to supply something like |
I am 100% on board with adding PUT and DELETE. I'd even go as far as saying they are crucial as well. Everything should be identifiable by an immutable identifier imo |
Yeah it makes sense to me to have the by-id endpoints function exactly like the corresponding ones in the by-name hierarchy (so yes, support PUT/DELETE, and eventually maybe have the same child resources too?), since it's really just another identifier path to the same HTTP resource. |
A given entity can be named either by its UUID or by some Name tuple (agreed?). This may be a radical change, but another approach would be to dispense with the paths for the name tuple and instead prefer query/body params. In other words, for a single endpoint we could accept either the UUId or the appropriate collection of names. A GET for a disk, e.g., could take either a UUID or a org/instance/disk Name. This is as opposed to the alternative where every CRUD operation would effective have two versions: one by UUID and one by Name-tuple. I don't claim to be an HTTP API aficionado so it may be that what I'm suggesting would be ugly or horrible. From the perspective of the CLI, with either model of the API I imagine we'd give users the option of specifying, say, a disk either way. Approximately:
|
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 looks great. Two non-blocking thoughts:
- We might want to name these
<resource>_get_by_id
as it looks like RFD 285 is going to change things to<resource>_<action>
for the non-by-id versions - I don't think we need to do it in this PR, but would we want to do
by_id
versions for the other actions? Is it weird to double the size of the API?
Awesome. I'm with Adam about putting the resource name first. |
I'm going to gate this behind #1329. Having that in will make it easier to organize this work I believe. |
/by_id/
routes for common resources/// populates `id` params for later route lookups | ||
id_routes: Vec<&'static str>, |
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 could've been more generic to allow arbitrarily mapping fields to params but it makes the types a lot harder. Given it's hard for me to imagine a usecase outside of needing to do id
lookups, I just focused it on solving that problem.
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 seems like a great simplification.
The authorization tests are still failing. I think it's likely happening on the first
|
Okay, I finally got things worked out. I was having a few problems...
|
url: "/by-id/images/{id}", | ||
visibility: Visibility::Protected, | ||
allowed_methods: vec![ | ||
AllowedMethod::GetUnimplemented, |
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 lookup isn't implemented due to the underlying create/fetch not being implemented. Project images are still stubs at this point.
url: "/by-id/snapshots/{id}", | ||
visibility: Visibility::Protected, | ||
allowed_methods: vec![ | ||
AllowedMethod::GetUnimplemented, |
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.
Same as above
@@ -579,6 +579,15 @@ lazy_static! { | |||
) | |||
], | |||
}, | |||
|
|||
VerifyEndpoint { | |||
url: "/by-id/organizations/{id}", |
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.
Note the {id}
is important here. That's the only way the id will get substituted.
// Lookup the previously created NIC | ||
SetupReq::Get { | ||
url: &*DEMO_INSTANCE_NIC_URL, | ||
id_routes: vec!["/by-id/network-interfaces/{id}"], | ||
}, |
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 is the (first) usecase of somewhere we may lookup a resource instead of creating a new resource mainly for the purpose of populating the id
param.
None => endpoint | ||
.url | ||
.replace("{id}", "00000000-0000-0000-0000-000000000000"), |
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.
In this case there was no entry in setup_requests
for some given endpoint that included {id}
. This is true in the case of unimplemented endpoints like images
and snapshots
right now.
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.
Thanks for taking this on. Really looking forward to having these endpoints available!
@@ -4,6 +4,7 @@ disk_create /organizations/{organization_name}/proj | |||
disk_delete /organizations/{organization_name}/projects/{project_name}/disks/{disk_name} | |||
disk_list /organizations/{organization_name}/projects/{project_name}/disks | |||
disk_view /organizations/{organization_name}/projects/{project_name}/disks/{disk_name} | |||
disk_view_by_id /by-id/disks/{id} |
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 you think about flipping the paths around like this:
disk_view_by_id /by-id/disks/{id} | |
disk_view_by_id /disks/by-id/{id} |
It follows path convention a little closer and it would make command generation a little easier.
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.
Would the idea be that you'd have /disks
, /projects
, /instances
, and all the others at the top level, and each of these would contain only one HTTP resource beneath them which was by_id
?
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.
You'd have to, which I think is why Justin didn't do it that way
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'm not sure if we are planning to have more global actions on resources? For example, we might want to have batch actions in the future where several resources are acted on.
In that case having the by-id
bit of the path wouldn't make too much sense any more, the way I'm proposing 🤔
Also, we'll probably want to have an endpoint for attaching disks with an ID as well. That would make it instances/{id}/disks/attach/{id}
I'm OK with either way we go :) If the majority prefer having by-id
at the top level I'm ok with that :)
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 guess, what I'm saying is that we might have other global actions for endpoints where being under by-id/
might not make sense, and if this scheme fits with that
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 don't think flipping it gains us much. With by_id
at the front we have fewer top level routes overall which keeps things a bit cleaner. It'll be slightly easier for us to filter down on id only endpoints.
My mental model of this is that it's actually just all one endpoint with different parameters:
/by-id/{resource}/{id}
From an API design perspective I believe the fewer top level endpoints we have, the better off we are. This is largely related to #1383 where we actually have different contexts for top level apis (e.g. if they run inside the context of a silo or not) and introducing more top level apis would make that even harder to document.
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.
As for batching, I think the current endpoint could still support that. Something like /by-id/{resource}?ids[]=1,2,3,4
is a rough approximation of how it could work.
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.
Ha! I had not seen #1383. Sounds good to me then :)
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.
Nice! This looks like the sort of thing that looks simple and clean now but probably involved a lot of grind to get here. Thanks for doing it!
In regards to your specific feedback:
Should the resource names in the route stay plural or be changed to be singular?
I'd go with plural, and that matches the existing stuff.
I've spread the id implementations to be co-located near the associated GET method. Does that feel right or should I move back to having all the /by-id/ routes grouped together?
What you've got feels right to me.
/// body of the `POST` request | ||
body: serde_json::Value, | ||
/// The setup phase takes a list of `SetupReq` enums and issues a `GET` or `POST` | ||
/// request to each one's `url`. The `id_routes` field is a list of URLs that result |
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.
typo here? ("that result the result")
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.
Cool, yeah. I improved it.
/// populates `id` params for later route lookups | ||
id_routes: Vec<&'static str>, |
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 seems like a great simplification.
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 realized that I neglected to click submit earlier. Belated, but LGTM!! Nice work
This will address #485
The intent is to provide a mechanism for fetching resources by id. I'd failed at previous attempts at this but #798 has made it much more feasible. In previous conversations we'd discussed using
/by_id/<resource>/<id>
as the general shape of the route which is represented here. Big shout out to @ahl for #1329 which helped to clean up the organization.Note that while we've discussed adding PUT and DELETE endpoints as well, I'm not tackling that in this PR.
Requested feedback
? I've decided to use the/by_id/
or/by-id/
dash
. We have inconsistent usage of dashes and underscores but there's more of the former than the latter. I've got a openapi-lint issue open to help us enforce consistency here./by-id/
routes grouped together?