api/types/image: move image options from api to client#50776
api/types/image: move image options from api to client#50776thaJeztah merged 1 commit intomoby:masterfrom
Conversation
|
Opened as draft to run integration tests with just the move as this move include multiple types compare to the others. Still need to rename the types for image specifier. At the same time, I see some non-exported client types whose purpose was is to wrap the option types from api and provide functional style options. Going to look if this style is more preferable than providing options via input struct. |
46b01c8 to
5af9062
Compare
|
Moving this one out of draft; ready for review. I spent some time playing with refactoring the options into subpackages would provide better code management. The challenge I ran into is 1. the client's interface is split between option struct definitions and functional style options and 2. as the options are part of the client's interface subpackages didn't help reduce the package's interface. |
|
In general we want to move to the functional style options (like in ImageLoad, ImageSave, ImageInspect, ImageHistory). |
daemon/images/image_delete.go
Outdated
| func (i *ImageService) ImageDelete(ctx context.Context, imageRef string, options imagetypes.RemoveOptions) ([]imagetypes.DeleteResponse, error) { | ||
| func (i *ImageService) ImageDelete(ctx context.Context, imageRef string, options client.ImageRemoveOptions) ([]imagetypes.DeleteResponse, error) { |
There was a problem hiding this comment.
We should avoid having the daemon / backend depend on the client options. I think the idea here originally was (as they were in the API) to just unmarshal to the option and re-use the same type for "symmetry", i.e.
client.ImageDelete(<RemoveOptions>)- -> API request
- -> API server unmarshals request (but in some cases: query-args + body) ->
<RemoveOptions> - -> call backend / daemon with
<RemoveOptions>
However, that was in a situation where daemon + api + client were all in the same module, so implicitly coupled all of those.
Now that they're separate modules, we should account for them having a different "stability"; i.e., the daemon or backend may add new features, but that not necessarily impacts the "shape" of the API. Or the reverse; a new API feature was added, but the daemon doesn't need changes.
Also as @vvoland mentions; ultimately, we want to move towards functional arguments, so the client structs may disappear at some point.
One thing we should look at though;
- if more types must be added for the different backends, the list of options (Image, Container, Volume) for the backend will grow.
- To some extent, we tried to implement the daemon with "services" (ImageService, ContainerService, VolumeService) - but not always did a great job at splitting those
- ❓ as those services may evolve (e.g. ImageService for containerd snapshotters to start taking a different shape than ImageService for graph-drivers), should we organise the backend-types into those services?
- ☝️ i.e.,
backend/imagesorbackend/imagebackendorbackend/imageservice - ☝️ and then put these types in those packages? (instead of prefixing each with
Image|Container|Volume
💯 yup. I think as an intermediate step, moving these types should be OK, but we should starting making a good design for those functional arguments; i.e. try to make a boilerplate and some guidelines, so that we take a consistent approach. Functional arguments are great, but there's multiple approaches to implement them, so we need to do some good thinking on taking the right approach that helps us remaining module compatibility. I recently watched a good talk about this, which captured quite some of the pitfalls of functional arguments, and included some good design patterns; I need to look it up again, but we can discuss those. |
|
Perhaps we need some checks in CI to make sure we don't accidentally couple modules where they shouldn't be coupled; for example;
|
9efbd23 to
e172048
Compare
|
This one needs a rebase, @austinvazquez |
e172048 to
f946ae8
Compare
thaJeztah
left a comment
There was a problem hiding this comment.
Thanks! Overall this looks good. Some suggestions;
- I think it would be a bit cleaner to have the move + rename commits together (instead of first moving to client, then adding the
Imageprefix); it would make the change more atomic. - Same (if possible) with the server-change to decouple; that's assuming Git doesn't get confused (which it may get for some that are in their own file), but it would be "move (e.g.)
api/types/images.RemoveOptionstoclient.ImageRemoveOptionis" and createdaemon/server/imagebackend.RemoveOptions. - That way each commit would give all the changes related to the move / refactor for each type.
Also left some questions on embedding/merging the apiOptions fields. Currently it looks fine, and it's a non-exported type, so we could still change of course, but wondering if we need some design pattern for these; which could be to keep the current approach for now (keep it as a field), then we can still decide whether embedding/merging or keeping them separate is better.
| func ImageLoadWithQuiet(quiet bool) ImageLoadOption { | ||
| return imageLoadOptionFunc(func(opt *imageLoadOpts) error { | ||
| opt.apiOptions.Quiet = quiet | ||
| opt.Quiet = quiet | ||
| return nil |
There was a problem hiding this comment.
We should still fix this; it doesn't really make sense to have quiet as API feature; or at least, it really feels more appropriate to be just "presentation", so to be handled on the client side, with the API responding as usual.
| type imageLoadOpts struct { | ||
| apiOptions LoadOptions | ||
| // Quiet suppresses progress output | ||
| Quiet bool |
There was a problem hiding this comment.
Could use input from @vvoland on this; slightly wondering if there would still be benefits to
- keep fields themselves non-exported
- have separation between client-side options, and options to be sent to the API
- (also considering my other comment about possibly moving Quiet to a client-side option for newer API versions)
(i.e., converge on a struct embedding api-opts and client-opts)
I haven't given this a lot of thought yet though!
There was a problem hiding this comment.
Sounds good, I believe I reverted them all now, but if I missed one. LMK :)
f946ae8 to
bc53816
Compare
bc53816 to
775da78
Compare
|
@thaJeztah , I touched up the pull request to squash the move/rename commits into a single commit and reverted the change that touched the |
4305b7a to
c8ccfd7
Compare
Signed-off-by: Austin Vazquez <austin.vazquez@docker.com>
c8ccfd7 to
853aed1
Compare
- What I did
Partial for #50740
This change moves the image options out of the api into the client module.
- How I did it
Move the image options file from the api module to the client and reconciled the changes needed to be functional.
- How to verify it
- Human readable description for the release notes
- A picture of a cute animal (not mandatory but encouraged)