builder: fix copy —from conflict with force pull

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Upstream-commit: c268d9da4b658b2dd1fe48010a8929b603913e92
Component: engine
This commit is contained in:
Tonis Tiigi
2017-06-20 15:45:33 -07:00
parent 8c7c972d20
commit d3db128900
6 changed files with 87 additions and 20 deletions
@@ -196,6 +196,7 @@ func (b *Builder) getImageMount(fromFlag *Flag) (*imageMount, error) {
return nil, nil
}
var localOnly bool
imageRefOrID := fromFlag.Value
stage, err := b.buildStages.get(fromFlag.Value)
if err != nil {
@@ -203,8 +204,9 @@ func (b *Builder) getImageMount(fromFlag *Flag) (*imageMount, error) {
}
if stage != nil {
imageRefOrID = stage.ImageID()
localOnly = true
}
return b.imageSources.Get(imageRefOrID)
return b.imageSources.Get(imageRefOrID, localOnly)
}
// FROM imagename[:tag | @digest] [AS build-stage-name]
@@ -266,8 +268,10 @@ func (b *Builder) getFromImage(shlex *ShellLex, name string) (builder.Image, err
return nil, err
}
var localOnly bool
if stage, ok := b.buildStages.getByName(name); ok {
name = stage.ImageID()
localOnly = true
}
// Windows cannot support a container with no base image.
@@ -277,7 +281,7 @@ func (b *Builder) getFromImage(shlex *ShellLex, name string) (builder.Image, err
}
return scratchImage, nil
}
imageMount, err := b.imageSources.Get(name)
imageMount, err := b.imageSources.Get(name, localOnly)
if err != nil {
return nil, err
}
@@ -86,21 +86,29 @@ func (s *buildStages) update(imageID string) {
s.sequence[len(s.sequence)-1].update(imageID)
}
type getAndMountFunc func(string) (builder.Image, builder.ReleaseableLayer, error)
type getAndMountFunc func(string, bool) (builder.Image, builder.ReleaseableLayer, error)
// imageSources mounts images and provides a cache for mounted images. It tracks
// all images so they can be unmounted at the end of the build.
type imageSources struct {
byImageID map[string]*imageMount
withoutID []*imageMount
mounts []*imageMount
getImage getAndMountFunc
cache pathCache // TODO: remove
}
func newImageSources(ctx context.Context, options builderOptions) *imageSources {
getAndMount := func(idOrRef string) (builder.Image, builder.ReleaseableLayer, error) {
getAndMount := func(idOrRef string, localOnly bool) (builder.Image, builder.ReleaseableLayer, error) {
pullOption := backend.PullOptionNoPull
if !localOnly {
if options.Options.PullParent {
pullOption = backend.PullOptionForcePull
} else {
pullOption = backend.PullOptionPreferLocal
}
}
return options.Backend.GetImageAndReleasableLayer(ctx, idOrRef, backend.GetImageAndLayerOptions{
ForcePull: options.Options.PullParent,
PullOption: pullOption,
AuthConfig: options.Options.AuthConfigs,
Output: options.ProgressWriter.Output,
})
@@ -112,12 +120,12 @@ func newImageSources(ctx context.Context, options builderOptions) *imageSources
}
}
func (m *imageSources) Get(idOrRef string) (*imageMount, error) {
func (m *imageSources) Get(idOrRef string, localOnly bool) (*imageMount, error) {
if im, ok := m.byImageID[idOrRef]; ok {
return im, nil
}
image, layer, err := m.getImage(idOrRef)
image, layer, err := m.getImage(idOrRef, localOnly)
if err != nil {
return nil, err
}
@@ -127,13 +135,7 @@ func (m *imageSources) Get(idOrRef string) (*imageMount, error) {
}
func (m *imageSources) Unmount() (retErr error) {
for _, im := range m.byImageID {
if err := im.unmount(); err != nil {
logrus.Error(err)
retErr = err
}
}
for _, im := range m.withoutID {
for _, im := range m.mounts {
if err := im.unmount(); err != nil {
logrus.Error(err)
retErr = err
@@ -146,10 +148,10 @@ func (m *imageSources) Add(im *imageMount) {
switch im.image {
case nil:
im.image = &dockerimage.Image{}
m.withoutID = append(m.withoutID, im)
default:
m.byImageID[im.image.ImageID()] = im
}
m.mounts = append(m.mounts, im)
}
// imageMount is a reference to an image that can be used as a builder.Source
@@ -116,7 +116,7 @@ func (b *Builder) performCopy(state *dispatchState, inst copyInstruction) error
return err
}
imageMount, err := b.imageSources.Get(state.imageID)
imageMount, err := b.imageSources.Get(state.imageID, true)
if err != nil {
return errors.Wrapf(err, "failed to get destination image %q", state.imageID)
}