Skip to content

[Builder] Expose GetImage interface for builder#33054

Merged
dnephin merged 3 commits intomoby:masterfrom
dnephin:refactor-builder-named-contexts-interface
May 11, 2017
Merged

[Builder] Expose GetImage interface for builder#33054
dnephin merged 3 commits intomoby:masterfrom
dnephin:refactor-builder-named-contexts-interface

Conversation

@dnephin
Copy link
Member

@dnephin dnephin commented May 5, 2017

Implement the second task in #32904

This PR removes the previous 3 Image functions from the builder.Backend interface and replaces them with a single function. Also refactors the interfaces between imageMount, imageContects, and dispatchers.from

@tonistiigi
Copy link
Member

Design LGTM

@dnephin dnephin added status/2-code-review status/failing-ci Indicates that the PR in its current state fails the test suite and removed status/1-design-review labels May 5, 2017
@dnephin dnephin force-pushed the refactor-builder-named-contexts-interface branch from a5b6bd9 to 8c35320 Compare May 5, 2017 22:18
@dnephin dnephin removed the status/failing-ci Indicates that the PR in its current state fails the test suite label May 5, 2017
@dnephin
Copy link
Member Author

dnephin commented May 5, 2017

I think I fixed the test failures. The problem was that releaseableLayer was being returned with a closer over the original image/imageID. This meant that updates to the base layer were not reflected in the layer.

The change was to add an imageID to ReleasableLayer.Mount(). This works, but it makes the interface a bit weird. Now the first call returns an object that really has nothing to do with the image that it returns, it's more of an uninitialized object that happens to have a reference to the daemon.

My concern is that it wouldn't really be possible to model this with a remote API. We might want to consider a separate MountImage() like we had better. Will this interface make more sense later? WDYT?

@dnephin dnephin force-pushed the refactor-builder-named-contexts-interface branch from 8c35320 to efa5d8d Compare May 5, 2017 22:24
@tonistiigi
Copy link
Member

As discussed privately the need for Mount() parameter should go away and releaseableLayer should be always backed by layer.Layer. Putting back to design-review until that is resolved.

@dnephin
Copy link
Member Author

dnephin commented May 6, 2017

What do you mean by "backed by layer.Layer" ? There is a RWLayer underlying the releaseableLayer

@tonistiigi
Copy link
Member

@dnephin Every instance of releasableLayer needs to be an instance of(or keep a reference to) layer.Layer that is the rootfs of the image returned. That makes sure that the data is protected until builder runs. When Mount() for that layer is called, RWLayer is created on top of that layer.Layer and mountpoint for that is made available. releasableLayer.Release() calls layerstore.Release(layer) in the implementation.

daemon/build.go Outdated
Copy link
Member

Choose a reason for hiding this comment

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

roLayer still needs to be released. Might be simpler to add a ref to roLayer in releaseableLayer instead of defining these callback methods.

Copy link
Member

Choose a reason for hiding this comment

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

For extra safety, maybe makes sense to define a finalizer for this type.

Copy link
Member Author

@dnephin dnephin May 8, 2017

Choose a reason for hiding this comment

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

Oops, right. Thanks.

I don't really want to expose the daemon , so I will still need some closures. They are not really callbacks.

I guess I could use the layerStore reference

daemon/build.go Outdated
Copy link
Member

Choose a reason for hiding this comment

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

roLayer.ChainID is bit safer

@dnephin dnephin force-pushed the refactor-builder-named-contexts-interface branch 2 times, most recently from 516249d to b4363ad Compare May 8, 2017 22:20
@dnephin
Copy link
Member Author

dnephin commented May 9, 2017

The build is green!

I believe I've addressed the issues with roLayer in releaseableLayer as well as the bug described in #33090

Ready for another design review

daemon/build.go Outdated
Copy link
Member Author

Choose a reason for hiding this comment

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

When an image is created from scratch and doesn't include any copy/add this chainID is empty. I'll add a comment about this with the next round of changes after design review.

I guess ill also need to add a check to Mount() and provide a better error when roLayer is nil

Copy link
Member

Choose a reason for hiding this comment

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

Yes, Mount() seems unprotected atm. Other way would be return nil(or not call GetImage for scratch) as there is no point for keeping a reference for scratch.

Copy link
Member Author

Choose a reason for hiding this comment

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

GetImage() is never called with a scratch object. But if you do FROM someimage and that image doesn't have any COPY/ADD, then this ChainID() is still the empty string.

So we have to check for that condition here. We could either return a nop implementation of ReleasableLayer, but I decided against that because many of these nil checks are required anyway. So i thought it was be easier to just add a few more instead of creating another struct.

Copy link
Member

Choose a reason for hiding this comment

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

What about just returning nil. It could be better to detect this case here than to call Mount() and get the error. Also if we add Exec() then this takes layer as a parameter, so it would be better to detect this case before instead of passing the empty struct.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh ya, that is a lot better. The case where layer is nil is already handled.

I'll leave the nil checks in mount anyway for safety

Copy link
Member

@tonistiigi tonistiigi left a comment

Choose a reason for hiding this comment

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

Just some comments, overall looks good

Copy link
Member

Choose a reason for hiding this comment

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

If you don't want to call this GetImage then maybe ImageAndRootFS.

Copy link
Member Author

Choose a reason for hiding this comment

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

It can't be GetImage because it conflicts with another daemon method already called GetImage.

I called it Layer, since the second return is named ReleaseableLayer. Should we rename that object as well? I think they should match.

Or should I make this GetImageAndReleasableLayer() ?

Copy link
Member

Choose a reason for hiding this comment

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

Not really that important, we could also call it a snapshot and use the containerd terms.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, I'll use GetImageAndReleasableLayer() for now. It's easy to rename later when we have the ability to use snapshots. I think it will be confusing to readers if we introduce the term snapshot right now.

Copy link
Member

Choose a reason for hiding this comment

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

imageMounter is bit confusing in here as regular from never mounts anything.

Copy link
Member Author

Choose a reason for hiding this comment

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

That's true, but the purpose of the struct is still to manage the unmounts required because of the API we are using. I don't know what else to call it

Copy link
Member

Choose a reason for hiding this comment

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

nit: what's the benefit of callback instead of using the interface dependency

Copy link
Member Author

Choose a reason for hiding this comment

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

The advantage is that we don't have to store all the opts that are only used in this one place. We only need them to construct the object. By storing just the function type that relationship is clear. If we were to store all the opts it wouldn't be clear.

daemon/build.go Outdated
Copy link
Member

Choose a reason for hiding this comment

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

Yes, Mount() seems unprotected atm. Other way would be return nil(or not call GetImage for scratch) as there is no point for keeping a reference for scratch.

@dnephin dnephin force-pushed the refactor-builder-named-contexts-interface branch from 91b13fc to 73f1462 Compare May 9, 2017 22:17
Copy link
Member

Choose a reason for hiding this comment

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

Not really that important, we could also call it a snapshot and use the containerd terms.

daemon/build.go Outdated
Copy link
Member

Choose a reason for hiding this comment

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

What about just returning nil. It could be better to detect this case here than to call Mount() and get the error. Also if we add Exec() then this takes layer as a parameter, so it would be better to detect this case before instead of passing the empty struct.

Copy link
Member

Choose a reason for hiding this comment

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

re: previous comment
It isn't really that it manages unmounts. It more managers keeping the layer references. Unmount currently also happens on release but that will probably be updated. imageRefs, images, imageSources, imageCache ?

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 think we already have imageCache so I'll go with imageSources

@dnephin dnephin force-pushed the refactor-builder-named-contexts-interface branch 3 times, most recently from 5062290 to 1c16f09 Compare May 10, 2017 19:39
@dnephin
Copy link
Member Author

dnephin commented May 10, 2017

I've made those changes, and CI seems to be good except for some flaky tests

Copy link
Member

@tonistiigi tonistiigi left a comment

Choose a reason for hiding this comment

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

LGTM

dnephin added 3 commits May 10, 2017 17:58
Removes 3 methods from the builder.Backend interface
Remove the coupling between imageContexts, imageMounts and the builder.

Signed-off-by: Daniel Nephin <[email protected]>
buildStages now tracks the imageID and runConfig for a build stage

imageMounter tracks image mounts so they can released when the build ends.

Signed-off-by: Daniel Nephin <[email protected]>
Copy link
Member

@vdemeester vdemeester left a comment

Choose a reason for hiding this comment

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

LGTM 🦁

@dnephin dnephin merged commit 974cec9 into moby:master May 11, 2017
@GordonTheTurtle GordonTheTurtle added this to the 17.06.0 milestone May 11, 2017
@dnephin dnephin deleted the refactor-builder-named-contexts-interface branch May 11, 2017 15:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants