From 9001ea26e7821239207586ad23c78c67d6926bfc Mon Sep 17 00:00:00 2001 From: John Howard Date: Mon, 20 Jul 2015 10:57:15 -0700 Subject: [PATCH] Fixing Image struct to no longer use Graph. Signed-off-by: John Howard --- builder/internals.go | 5 +-- daemon/commit.go | 4 +-- daemon/container.go | 4 +-- daemon/container_windows.go | 4 +-- daemon/create.go | 3 +- daemon/daemon.go | 7 +++-- daemon/image_delete.go | 3 +- graph/graph.go | 61 +++++++++++-------------------------- graph/graph_test.go | 12 ++++---- graph/graph_unix.go | 7 +++-- graph/graph_windows.go | 9 +++--- graph/history.go | 13 ++++---- graph/list.go | 3 +- graph/load.go | 2 +- graph/pull_v1.go | 5 +-- graph/pull_v2.go | 5 +-- graph/push_v2.go | 3 +- graph/tags.go | 7 +++-- graph/tags_unit_test.go | 5 +-- image/image.go | 30 ++++++++++++++++++ 20 files changed, 104 insertions(+), 88 deletions(-) diff --git a/builder/internals.go b/builder/internals.go index 7d83c8cbca..cd861186fa 100644 --- a/builder/internals.go +++ b/builder/internals.go @@ -24,6 +24,7 @@ import ( "github.com/docker/docker/cliconfig" "github.com/docker/docker/daemon" "github.com/docker/docker/graph" + "github.com/docker/docker/image" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/chrootarchive" "github.com/docker/docker/pkg/httputils" @@ -486,7 +487,7 @@ func ContainsWildcards(name string) bool { return false } -func (b *Builder) pullImage(name string) (*graph.Image, error) { +func (b *Builder) pullImage(name string) (*image.Image, error) { remote, tag := parsers.ParseRepositoryTag(name) if tag == "" { tag = "latest" @@ -524,7 +525,7 @@ func (b *Builder) pullImage(name string) (*graph.Image, error) { return image, nil } -func (b *Builder) processImageFrom(img *graph.Image) error { +func (b *Builder) processImageFrom(img *image.Image) error { b.image = img.ID if img.Config != nil { diff --git a/daemon/commit.go b/daemon/commit.go index 5321bef865..5921d77e0f 100644 --- a/daemon/commit.go +++ b/daemon/commit.go @@ -1,7 +1,7 @@ package daemon import ( - "github.com/docker/docker/graph" + "github.com/docker/docker/image" "github.com/docker/docker/runconfig" ) @@ -16,7 +16,7 @@ type ContainerCommitConfig struct { // Commit creates a new filesystem image from the current state of a container. // The image can optionally be tagged into a repository -func (daemon *Daemon) Commit(container *Container, c *ContainerCommitConfig) (*graph.Image, error) { +func (daemon *Daemon) Commit(container *Container, c *ContainerCommitConfig) (*image.Image, error) { if c.Pause && !container.IsPaused() { container.Pause() defer container.Unpause() diff --git a/daemon/container.go b/daemon/container.go index a636c30ab8..bc9d5ab043 100644 --- a/daemon/container.go +++ b/daemon/container.go @@ -20,7 +20,7 @@ import ( "github.com/docker/docker/daemon/logger" "github.com/docker/docker/daemon/logger/jsonfilelog" "github.com/docker/docker/daemon/network" - "github.com/docker/docker/graph" + "github.com/docker/docker/image" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/broadcastwriter" "github.com/docker/docker/pkg/fileutils" @@ -584,7 +584,7 @@ func (container *Container) Changes() ([]archive.Change, error) { return container.changes() } -func (container *Container) GetImage() (*graph.Image, error) { +func (container *Container) GetImage() (*image.Image, error) { if container.daemon == nil { return nil, fmt.Errorf("Can't get image of unregistered container") } diff --git a/daemon/container_windows.go b/daemon/container_windows.go index bb72a3c675..6a8fa25587 100644 --- a/daemon/container_windows.go +++ b/daemon/container_windows.go @@ -9,7 +9,7 @@ import ( "github.com/docker/docker/daemon/execdriver" "github.com/docker/docker/daemon/graphdriver/windows" - "github.com/docker/docker/graph" + "github.com/docker/docker/image" "github.com/docker/docker/pkg/archive" "github.com/microsoft/hcsshim" ) @@ -114,7 +114,7 @@ func populateCommand(c *Container, env []string) error { // enable VFS to continue operating for development purposes. if wd, ok := c.daemon.driver.(*windows.WindowsGraphDriver); ok { var err error - var img *graph.Image + var img *image.Image var ids []string if img, err = c.daemon.graph.Get(c.ImageID); err != nil { diff --git a/daemon/create.go b/daemon/create.go index ced8f9edf3..79001c6a0a 100644 --- a/daemon/create.go +++ b/daemon/create.go @@ -8,6 +8,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/graph" + "github.com/docker/docker/image" "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/stringid" "github.com/docker/docker/runconfig" @@ -46,7 +47,7 @@ func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.Hos var ( container *Container warnings []string - img *graph.Image + img *image.Image imgID string err error ) diff --git a/daemon/daemon.go b/daemon/daemon.go index 15744c71a5..987b3b69cb 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -23,6 +23,7 @@ import ( "github.com/docker/docker/daemon/logger" "github.com/docker/docker/daemon/network" "github.com/docker/docker/graph" + "github.com/docker/docker/image" "github.com/docker/docker/pkg/broadcastwriter" "github.com/docker/docker/pkg/fileutils" "github.com/docker/docker/pkg/graphdb" @@ -336,7 +337,7 @@ func (daemon *Daemon) restore() error { return nil } -func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *graph.Image) error { +func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *image.Image) error { if img != nil && img.Config != nil { if err := runconfig.Merge(config, img.Config); err != nil { return err @@ -882,7 +883,7 @@ func (daemon *Daemon) ContainerGraph() *graphdb.Database { return daemon.containerGraph } -func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*graph.Image, error) { +func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*image.Image, error) { // Retrieve all images images := daemon.Graph().Map() @@ -896,7 +897,7 @@ func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*g } // Loop on the children of the given image and check the config - var match *graph.Image + var match *image.Image for elem := range imageMap[imgID] { img, ok := images[elem] if !ok { diff --git a/daemon/image_delete.go b/daemon/image_delete.go index 1ede80660b..ccef4b339c 100644 --- a/daemon/image_delete.go +++ b/daemon/image_delete.go @@ -7,6 +7,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/api/types" "github.com/docker/docker/graph" + "github.com/docker/docker/image" "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/stringid" "github.com/docker/docker/utils" @@ -159,7 +160,7 @@ func (daemon *Daemon) canDeleteImage(imgID string, force bool) error { return err } - if err := daemon.graph.WalkHistory(parent, func(p graph.Image) error { + if err := daemon.graph.WalkHistory(parent, func(p image.Image) error { if imgID == p.ID { if container.IsRunning() { if force { diff --git a/graph/graph.go b/graph/graph.go index a501d6ea5d..52069e9556 100644 --- a/graph/graph.go +++ b/graph/graph.go @@ -82,22 +82,6 @@ type Graph struct { retained *retainedLayers } -type Image struct { - ID string `json:"id"` - Parent string `json:"parent,omitempty"` - Comment string `json:"comment,omitempty"` - Created time.Time `json:"created"` - Container string `json:"container,omitempty"` - ContainerConfig runconfig.Config `json:"container_config,omitempty"` - DockerVersion string `json:"docker_version,omitempty"` - Author string `json:"author,omitempty"` - Config *runconfig.Config `json:"config,omitempty"` - Architecture string `json:"architecture,omitempty"` - OS string `json:"os,omitempty"` - Size int64 - graph Graph -} - var ( // ErrDigestNotSet is used when request the digest for a layer // but the layer has no digest value or content to compute the @@ -174,7 +158,7 @@ func (graph *Graph) Exists(id string) bool { } // Get returns the image with the given id, or an error if the image doesn't exist. -func (graph *Graph) Get(name string) (*Image, error) { +func (graph *Graph) Get(name string) (*image.Image, error) { id, err := graph.idIndex.Get(name) if err != nil { return nil, fmt.Errorf("could not find image: %v", err) @@ -202,8 +186,8 @@ func (graph *Graph) Get(name string) (*Image, error) { } // Create creates a new image and registers it in the graph. -func (graph *Graph) Create(layerData archive.ArchiveReader, containerID, containerImage, comment, author string, containerConfig, config *runconfig.Config) (*Image, error) { - img := &Image{ +func (graph *Graph) Create(layerData archive.ArchiveReader, containerID, containerImage, comment, author string, containerConfig, config *runconfig.Config) (*image.Image, error) { + img := &image.Image{ ID: stringid.GenerateRandomID(), Comment: comment, Created: time.Now().UTC(), @@ -227,7 +211,7 @@ func (graph *Graph) Create(layerData archive.ArchiveReader, containerID, contain } // Register imports a pre-existing image into the graph. -func (graph *Graph) Register(img *Image, layerData archive.ArchiveReader) (err error) { +func (graph *Graph) Register(img *image.Image, layerData archive.ArchiveReader) (err error) { if err := image.ValidateID(img.ID); err != nil { return err @@ -380,9 +364,9 @@ func (graph *Graph) Delete(name string) error { } // Map returns a list of all images in the graph, addressable by ID. -func (graph *Graph) Map() map[string]*Image { - images := make(map[string]*Image) - graph.walkAll(func(image *Image) { +func (graph *Graph) Map() map[string]*image.Image { + images := make(map[string]*image.Image) + graph.walkAll(func(image *image.Image) { images[image.ID] = image }) return images @@ -390,7 +374,7 @@ func (graph *Graph) Map() map[string]*Image { // walkAll iterates over each image in the graph, and passes it to a handler. // The walking order is undetermined. -func (graph *Graph) walkAll(handler func(*Image)) { +func (graph *Graph) walkAll(handler func(*image.Image)) { graph.idIndex.Iterate(func(id string) { if img, err := graph.Get(id); err != nil { return @@ -404,9 +388,9 @@ func (graph *Graph) walkAll(handler func(*Image)) { // If an image of id ID has 3 children images, then the value for key ID // will be a list of 3 images. // If an image has no children, it will not have an entry in the table. -func (graph *Graph) ByParent() map[string][]*Image { - byParent := make(map[string][]*Image) - graph.walkAll(func(img *Image) { +func (graph *Graph) ByParent() map[string][]*image.Image { + byParent := make(map[string][]*image.Image) + graph.walkAll(func(img *image.Image) { parent, err := graph.Get(img.Parent) if err != nil { return @@ -414,7 +398,7 @@ func (graph *Graph) ByParent() map[string][]*Image { if children, exists := byParent[parent.ID]; exists { byParent[parent.ID] = append(children, img) } else { - byParent[parent.ID] = []*Image{img} + byParent[parent.ID] = []*image.Image{img} } }) return byParent @@ -433,10 +417,10 @@ func (graph *Graph) Release(sessionID string, layerIDs ...string) { // Heads returns all heads in the graph, keyed by id. // A head is an image which is not the parent of another image in the graph. -func (graph *Graph) Heads() map[string]*Image { - heads := make(map[string]*Image) +func (graph *Graph) Heads() map[string]*image.Image { + heads := make(map[string]*image.Image) byParent := graph.ByParent() - graph.walkAll(func(image *Image) { + graph.walkAll(func(image *image.Image) { // If it's not in the byParent lookup table, then // it's not a parent -> so it's a head! if _, exists := byParent[image.ID]; !exists { @@ -451,7 +435,7 @@ func (graph *Graph) imageRoot(id string) string { } // loadImage fetches the image with the given id from the graph. -func (graph *Graph) loadImage(id string) (*Image, error) { +func (graph *Graph) loadImage(id string) (*image.Image, error) { root := graph.imageRoot(id) // Open the JSON file to decode by streaming @@ -461,7 +445,7 @@ func (graph *Graph) loadImage(id string) (*Image, error) { } defer jsonSource.Close() - img := &Image{} + img := &image.Image{} dec := json.NewDecoder(jsonSource) // Decode the JSON data @@ -538,14 +522,3 @@ func (graph *Graph) RawJSON(id string) ([]byte, error) { func jsonPath(root string) string { return filepath.Join(root, "json") } - -// Build an Image object from raw json data -func NewImgJSON(src []byte) (*Image, error) { - ret := &Image{} - - // FIXME: Is there a cleaner way to "purify" the input json? - if err := json.Unmarshal(src, ret); err != nil { - return nil, err - } - return ret, nil -} diff --git a/graph/graph_test.go b/graph/graph_test.go index 208c9e81cd..d7dd591a3c 100644 --- a/graph/graph_test.go +++ b/graph/graph_test.go @@ -67,7 +67,7 @@ func TestInterruptedRegister(t *testing.T) { graph, _ := tempGraph(t) defer nukeGraph(graph) badArchive, w := io.Pipe() // Use a pipe reader as a fake archive which never yields data - image := &Image{ + image := &image.Image{ ID: stringid.GenerateRandomID(), Comment: "testing", Created: time.Now(), @@ -125,7 +125,7 @@ func TestRegister(t *testing.T) { if err != nil { t.Fatal(err) } - image := &Image{ + image := &image.Image{ ID: stringid.GenerateRandomID(), Comment: "testing", Created: time.Now(), @@ -228,19 +228,19 @@ func TestByParent(t *testing.T) { graph, _ := tempGraph(t) defer nukeGraph(graph) - parentImage := &Image{ + parentImage := &image.Image{ ID: stringid.GenerateRandomID(), Comment: "parent", Created: time.Now(), Parent: "", } - childImage1 := &Image{ + childImage1 := &image.Image{ ID: stringid.GenerateRandomID(), Comment: "child1", Created: time.Now(), Parent: parentImage.ID, } - childImage2 := &Image{ + childImage2 := &image.Image{ ID: stringid.GenerateRandomID(), Comment: "child2", Created: time.Now(), @@ -257,7 +257,7 @@ func TestByParent(t *testing.T) { } } -func createTestImage(graph *Graph, t *testing.T) *Image { +func createTestImage(graph *Graph, t *testing.T) *image.Image { archive, err := fakeTar() if err != nil { t.Fatal(err) diff --git a/graph/graph_unix.go b/graph/graph_unix.go index 8542767089..e42eb9bb36 100644 --- a/graph/graph_unix.go +++ b/graph/graph_unix.go @@ -10,6 +10,7 @@ import ( "strings" "syscall" + "github.com/docker/docker/image" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/system" ) @@ -72,7 +73,7 @@ func SetupInitLayer(initLayer string) error { return nil } -func createRootFilesystemInDriver(graph *Graph, img *Image, layerData archive.ArchiveReader) error { +func createRootFilesystemInDriver(graph *Graph, img *image.Image, layerData archive.ArchiveReader) error { if err := graph.driver.Create(img.ID, img.Parent); err != nil { return fmt.Errorf("Driver %s failed to create image rootfs %s: %s", graph.driver, img.ID, err) } @@ -86,7 +87,7 @@ func (graph *Graph) restoreBaseImages() ([]string, error) { // storeImage stores file system layer data for the given image to the // graph's storage driver. Image metadata is stored in a file // at the specified root directory. -func (graph *Graph) storeImage(img *Image, layerData archive.ArchiveReader, root string) (err error) { +func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader, root string) (err error) { // Store the layer. If layerData is not nil, unpack it into the new layer if layerData != nil { if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, layerData); err != nil { @@ -109,6 +110,6 @@ func (graph *Graph) storeImage(img *Image, layerData archive.ArchiveReader, root } // TarLayer returns a tar archive of the image's filesystem layer. -func (graph *Graph) TarLayer(img *Image) (arch archive.Archive, err error) { +func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error) { return graph.driver.Diff(img.ID, img.Parent) } diff --git a/graph/graph_windows.go b/graph/graph_windows.go index afa482ad10..2904f9b9f8 100644 --- a/graph/graph_windows.go +++ b/graph/graph_windows.go @@ -9,6 +9,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/daemon/graphdriver/windows" + "github.com/docker/docker/image" "github.com/docker/docker/pkg/archive" ) @@ -18,7 +19,7 @@ func SetupInitLayer(initLayer string) error { return nil } -func createRootFilesystemInDriver(graph *Graph, img *Image, layerData archive.ArchiveReader) error { +func createRootFilesystemInDriver(graph *Graph, img *image.Image, layerData archive.ArchiveReader) error { if wd, ok := graph.driver.(*windows.WindowsGraphDriver); ok { if img.Container != "" && layerData == nil { logrus.Debugf("Copying from container %s.", img.Container) @@ -59,7 +60,7 @@ func (graph *Graph) restoreBaseImages() ([]string, error) { } // ParentLayerIds returns a list of all parent image IDs for the given image. -func (graph *Graph) ParentLayerIds(img *Image) (ids []string, err error) { +func (graph *Graph) ParentLayerIds(img *image.Image) (ids []string, err error) { for i := img; i != nil && err == nil; i, err = graph.GetParent(i) { ids = append(ids, i.ID) } @@ -70,7 +71,7 @@ func (graph *Graph) ParentLayerIds(img *Image) (ids []string, err error) { // storeImage stores file system layer data for the given image to the // graph's storage driver. Image metadata is stored in a file // at the specified root directory. -func (graph *Graph) storeImage(img *Image, layerData archive.ArchiveReader, root string) (err error) { +func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader, root string) (err error) { if wd, ok := graph.driver.(*windows.WindowsGraphDriver); ok { // Store the layer. If layerData is not nil and this isn't a base image, @@ -135,7 +136,7 @@ func (graph *Graph) storeImage(img *Image, layerData archive.ArchiveReader, root } // TarLayer returns a tar archive of the image's filesystem layer. -func (graph *Graph) TarLayer(img *Image) (arch archive.Archive, err error) { +func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error) { if wd, ok := graph.driver.(*windows.WindowsGraphDriver); ok { var ids []string if img.Parent != "" { diff --git a/graph/history.go b/graph/history.go index f92ebf3b03..4bb93fc3f9 100644 --- a/graph/history.go +++ b/graph/history.go @@ -5,12 +5,13 @@ import ( "strings" "github.com/docker/docker/api/types" + "github.com/docker/docker/image" "github.com/docker/docker/utils" ) // WalkHistory calls the handler function for each image in the // provided images lineage starting from immediate parent. -func (graph *Graph) WalkHistory(img *Image, handler func(Image) error) (err error) { +func (graph *Graph) WalkHistory(img *image.Image, handler func(image.Image) error) (err error) { currentImg := img for currentImg != nil { if handler != nil { @@ -28,7 +29,7 @@ func (graph *Graph) WalkHistory(img *Image, handler func(Image) error) (err erro // depth returns the number of parents for a // current image -func (graph *Graph) depth(img *Image) (int, error) { +func (graph *Graph) depth(img *image.Image) (int, error) { var ( count = 0 parent = img @@ -53,7 +54,7 @@ const MaxImageDepth = 127 // CheckDepth returns an error if the depth of an image, as returned // by ImageDepth, is too large to support creating a container from it // on this daemon. -func (graph *Graph) CheckDepth(img *Image) error { +func (graph *Graph) CheckDepth(img *image.Image) error { // We add 2 layers to the depth because the container's rw and // init layer add to the restriction depth, err := graph.depth(img) @@ -85,7 +86,7 @@ func (s *TagStore) History(name string) ([]*types.ImageHistory, error) { history := []*types.ImageHistory{} - err = s.graph.WalkHistory(foundImage, func(img Image) error { + err = s.graph.WalkHistory(foundImage, func(img image.Image) error { history = append(history, &types.ImageHistory{ ID: img.ID, Created: img.Created.Unix(), @@ -100,14 +101,14 @@ func (s *TagStore) History(name string) ([]*types.ImageHistory, error) { return history, err } -func (graph *Graph) GetParent(img *Image) (*Image, error) { +func (graph *Graph) GetParent(img *image.Image) (*image.Image, error) { if img.Parent == "" { return nil, nil } return graph.Get(img.Parent) } -func (graph *Graph) GetParentsSize(img *Image, size int64) int64 { +func (graph *Graph) GetParentsSize(img *image.Image, size int64) int64 { parentImage, err := graph.GetParent(img) if err != nil || parentImage == nil { return size diff --git a/graph/list.go b/graph/list.go index 46ff7bb8a6..89b1a93baa 100644 --- a/graph/list.go +++ b/graph/list.go @@ -8,6 +8,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/api/types" + "github.com/docker/docker/image" "github.com/docker/docker/pkg/parsers/filters" "github.com/docker/docker/utils" ) @@ -31,7 +32,7 @@ func (r ByCreated) Less(i, j int) bool { return r[i].Created < r[j].Created } func (s *TagStore) Images(config *ImagesConfig) ([]*types.Image, error) { var ( - allImages map[string]*Image + allImages map[string]*image.Image err error filtTagged = true filtLabel = false diff --git a/graph/load.go b/graph/load.go index c622f82b62..9c19012795 100644 --- a/graph/load.go +++ b/graph/load.go @@ -95,7 +95,7 @@ func (s *TagStore) recursiveLoad(address, tmpImageDir string) error { logrus.Debugf("Error reading embedded tar: %v", err) return err } - img, err := NewImgJSON(imageJson) + img, err := image.NewImgJSON(imageJson) if err != nil { logrus.Debugf("Error unmarshalling json: %v", err) return err diff --git a/graph/pull_v1.go b/graph/pull_v1.go index 7ca8f4a242..b8ff8ea5b7 100644 --- a/graph/pull_v1.go +++ b/graph/pull_v1.go @@ -10,6 +10,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/distribution/registry/client/transport" + "github.com/docker/docker/image" "github.com/docker/docker/pkg/progressreader" "github.com/docker/docker/pkg/streamformatter" "github.com/docker/docker/pkg/stringid" @@ -257,7 +258,7 @@ func (p *v1Puller) pullImage(imgID, endpoint string, token []string) (bool, erro imgJSON []byte imgSize int err error - img *Image + img *image.Image ) retries := 5 for j := 1; j <= retries; j++ { @@ -269,7 +270,7 @@ func (p *v1Puller) pullImage(imgID, endpoint string, token []string) (bool, erro time.Sleep(time.Duration(j) * 500 * time.Millisecond) continue } - img, err = NewImgJSON(imgJSON) + img, err = image.NewImgJSON(imgJSON) layersDownloaded = true if err != nil && j == retries { out.Write(p.sf.FormatProgress(stringid.TruncateID(id), "Error pulling dependent layers", nil)) diff --git a/graph/pull_v2.go b/graph/pull_v2.go index f39632c318..46b8a0372d 100644 --- a/graph/pull_v2.go +++ b/graph/pull_v2.go @@ -10,6 +10,7 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" + "github.com/docker/docker/image" "github.com/docker/docker/pkg/progressreader" "github.com/docker/docker/pkg/streamformatter" "github.com/docker/docker/pkg/stringid" @@ -94,7 +95,7 @@ func (p *v2Puller) pullV2Repository(tag string) (err error) { // downloadInfo is used to pass information from download to extractor type downloadInfo struct { - img *Image + img *image.Image tmpFile *os.File digest digest.Digest layer distribution.ReadSeekCloser @@ -208,7 +209,7 @@ func (p *v2Puller) pullV2Tag(tag, taggedName string) (bool, error) { }() for i := len(manifest.FSLayers) - 1; i >= 0; i-- { - img, err := NewImgJSON([]byte(manifest.History[i].V1Compatibility)) + img, err := image.NewImgJSON([]byte(manifest.History[i].V1Compatibility)) if err != nil { logrus.Debugf("error getting image v1 json: %v", err) return false, err diff --git a/graph/push_v2.go b/graph/push_v2.go index 873d5cd5c4..c90cf340d9 100644 --- a/graph/push_v2.go +++ b/graph/push_v2.go @@ -9,6 +9,7 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" + "github.com/docker/docker/image" "github.com/docker/docker/pkg/progressreader" "github.com/docker/docker/pkg/streamformatter" "github.com/docker/docker/pkg/stringid" @@ -190,7 +191,7 @@ func (p *v2Pusher) pushV2Tag(tag string) error { return p.repo.Manifests().Put(signed) } -func (p *v2Pusher) pushV2Image(bs distribution.BlobService, img *Image) (digest.Digest, error) { +func (p *v2Pusher) pushV2Image(bs distribution.BlobService, img *image.Image) (digest.Digest, error) { out := p.config.OutStream out.Write(p.sf.FormatProgress(stringid.TruncateID(img.ID), "Buffering to Disk", nil)) diff --git a/graph/tags.go b/graph/tags.go index 32f8418078..a96ad94bfe 100644 --- a/graph/tags.go +++ b/graph/tags.go @@ -15,6 +15,7 @@ import ( "github.com/docker/distribution/digest" "github.com/docker/docker/daemon/events" "github.com/docker/docker/graph/tags" + "github.com/docker/docker/image" "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/stringid" "github.com/docker/docker/registry" @@ -120,7 +121,7 @@ func (store *TagStore) reload() error { return nil } -func (store *TagStore) LookupImage(name string) (*Image, error) { +func (store *TagStore) LookupImage(name string) (*image.Image, error) { // FIXME: standardize on returning nil when the image doesn't exist, and err for everything else // (so we can pass all errors here) repoName, ref := parsers.ParseRepositoryTag(name) @@ -129,7 +130,7 @@ func (store *TagStore) LookupImage(name string) (*Image, error) { } var ( err error - img *Image + img *image.Image ) img, err = store.GetImage(repoName, ref) @@ -331,7 +332,7 @@ func (store *TagStore) Get(repoName string) (Repository, error) { return nil, nil } -func (store *TagStore) GetImage(repoName, refOrID string) (*Image, error) { +func (store *TagStore) GetImage(repoName, refOrID string) (*image.Image, error) { repo, err := store.Get(repoName) if err != nil { diff --git a/graph/tags_unit_test.go b/graph/tags_unit_test.go index 5676d59d73..8dffb2a6bc 100644 --- a/graph/tags_unit_test.go +++ b/graph/tags_unit_test.go @@ -11,6 +11,7 @@ import ( "github.com/docker/docker/daemon/events" "github.com/docker/docker/daemon/graphdriver" _ "github.com/docker/docker/daemon/graphdriver/vfs" // import the vfs driver so it is used in the tests + "github.com/docker/docker/image" "github.com/docker/docker/trust" "github.com/docker/docker/utils" ) @@ -79,7 +80,7 @@ func mkTestTagStore(root string, t *testing.T) *TagStore { if err != nil { t.Fatal(err) } - img := &Image{ID: testOfficialImageID} + img := &image.Image{ID: testOfficialImageID} if err := graph.Register(img, officialArchive); err != nil { t.Fatal(err) } @@ -90,7 +91,7 @@ func mkTestTagStore(root string, t *testing.T) *TagStore { if err != nil { t.Fatal(err) } - img = &Image{ID: testPrivateImageID} + img = &image.Image{ID: testPrivateImageID} if err := graph.Register(img, privateArchive); err != nil { t.Fatal(err) } diff --git a/image/image.go b/image/image.go index 1fe4357c2b..218f18f2d7 100644 --- a/image/image.go +++ b/image/image.go @@ -1,12 +1,42 @@ package image import ( + "encoding/json" "fmt" "regexp" + "time" + + "github.com/docker/docker/runconfig" ) var validHex = regexp.MustCompile(`^([a-f0-9]{64})$`) +type Image struct { + ID string `json:"id"` + Parent string `json:"parent,omitempty"` + Comment string `json:"comment,omitempty"` + Created time.Time `json:"created"` + Container string `json:"container,omitempty"` + ContainerConfig runconfig.Config `json:"container_config,omitempty"` + DockerVersion string `json:"docker_version,omitempty"` + Author string `json:"author,omitempty"` + Config *runconfig.Config `json:"config,omitempty"` + Architecture string `json:"architecture,omitempty"` + OS string `json:"os,omitempty"` + Size int64 +} + +// Build an Image object from raw json data +func NewImgJSON(src []byte) (*Image, error) { + ret := &Image{} + + // FIXME: Is there a cleaner way to "purify" the input json? + if err := json.Unmarshal(src, ret); err != nil { + return nil, err + } + return ret, nil +} + // Check wheather id is a valid image ID or not func ValidateID(id string) error { if ok := validHex.MatchString(id); !ok {