github.com/portworx/docker@v1.12.1/daemon/image.go (about) 1 package daemon 2 3 import ( 4 "fmt" 5 6 "github.com/docker/docker/builder" 7 "github.com/docker/docker/image" 8 "github.com/docker/docker/reference" 9 "github.com/docker/docker/runconfig" 10 containertypes "github.com/docker/engine-api/types/container" 11 ) 12 13 // ErrImageDoesNotExist is error returned when no image can be found for a reference. 14 type ErrImageDoesNotExist struct { 15 RefOrID string 16 } 17 18 func (e ErrImageDoesNotExist) Error() string { 19 return fmt.Sprintf("no such id: %s", e.RefOrID) 20 } 21 22 // GetImageID returns an image ID corresponding to the image referred to by 23 // refOrID. 24 func (daemon *Daemon) GetImageID(refOrID string) (image.ID, error) { 25 id, ref, err := reference.ParseIDOrReference(refOrID) 26 if err != nil { 27 return "", err 28 } 29 if id != "" { 30 if _, err := daemon.imageStore.Get(image.ID(id)); err != nil { 31 return "", ErrImageDoesNotExist{refOrID} 32 } 33 return image.ID(id), nil 34 } 35 36 if id, err := daemon.referenceStore.Get(ref); err == nil { 37 return id, nil 38 } 39 if tagged, ok := ref.(reference.NamedTagged); ok { 40 if id, err := daemon.imageStore.Search(tagged.Tag()); err == nil { 41 for _, namedRef := range daemon.referenceStore.References(id) { 42 if namedRef.Name() == ref.Name() { 43 return id, nil 44 } 45 } 46 } 47 } 48 49 // Search based on ID 50 if id, err := daemon.imageStore.Search(refOrID); err == nil { 51 return id, nil 52 } 53 54 return "", ErrImageDoesNotExist{refOrID} 55 } 56 57 // GetImage returns an image corresponding to the image referred to by refOrID. 58 func (daemon *Daemon) GetImage(refOrID string) (*image.Image, error) { 59 imgID, err := daemon.GetImageID(refOrID) 60 if err != nil { 61 return nil, err 62 } 63 return daemon.imageStore.Get(imgID) 64 } 65 66 // GetImageOnBuild looks up a Docker image referenced by `name`. 67 func (daemon *Daemon) GetImageOnBuild(name string) (builder.Image, error) { 68 img, err := daemon.GetImage(name) 69 if err != nil { 70 return nil, err 71 } 72 return img, nil 73 } 74 75 // GetCachedImage returns the most recent created image that is a child 76 // of the image with imgID, that had the same config when it was 77 // created. nil is returned if a child cannot be found. An error is 78 // returned if the parent image cannot be found. 79 func (daemon *Daemon) GetCachedImage(imgID image.ID, config *containertypes.Config) (*image.Image, error) { 80 // Loop on the children of the given image and check the config 81 getMatch := func(siblings []image.ID) (*image.Image, error) { 82 var match *image.Image 83 for _, id := range siblings { 84 img, err := daemon.imageStore.Get(id) 85 if err != nil { 86 return nil, fmt.Errorf("unable to find image %q", id) 87 } 88 89 if runconfig.Compare(&img.ContainerConfig, config) { 90 // check for the most up to date match 91 if match == nil || match.Created.Before(img.Created) { 92 match = img 93 } 94 } 95 } 96 return match, nil 97 } 98 99 // In this case, this is `FROM scratch`, which isn't an actual image. 100 if imgID == "" { 101 images := daemon.imageStore.Map() 102 var siblings []image.ID 103 for id, img := range images { 104 if img.Parent == imgID { 105 siblings = append(siblings, id) 106 } 107 } 108 return getMatch(siblings) 109 } 110 111 // find match from child images 112 siblings := daemon.imageStore.Children(imgID) 113 return getMatch(siblings) 114 } 115 116 // GetCachedImageOnBuild returns a reference to a cached image whose parent equals `parent` 117 // and runconfig equals `cfg`. A cache miss is expected to return an empty ID and a nil error. 118 func (daemon *Daemon) GetCachedImageOnBuild(imgID string, cfg *containertypes.Config) (string, error) { 119 cache, err := daemon.GetCachedImage(image.ID(imgID), cfg) 120 if cache == nil || err != nil { 121 return "", err 122 } 123 return cache.ID().String(), nil 124 }