Fixing Image struct to no longer use Graph.
| ... | ... |
@@ -24,6 +24,7 @@ import ( |
| 24 | 24 |
"github.com/docker/docker/cliconfig" |
| 25 | 25 |
"github.com/docker/docker/daemon" |
| 26 | 26 |
"github.com/docker/docker/graph" |
| 27 |
+ "github.com/docker/docker/image" |
|
| 27 | 28 |
"github.com/docker/docker/pkg/archive" |
| 28 | 29 |
"github.com/docker/docker/pkg/chrootarchive" |
| 29 | 30 |
"github.com/docker/docker/pkg/httputils" |
| ... | ... |
@@ -486,7 +487,7 @@ func ContainsWildcards(name string) bool {
|
| 486 | 486 |
return false |
| 487 | 487 |
} |
| 488 | 488 |
|
| 489 |
-func (b *Builder) pullImage(name string) (*graph.Image, error) {
|
|
| 489 |
+func (b *Builder) pullImage(name string) (*image.Image, error) {
|
|
| 490 | 490 |
remote, tag := parsers.ParseRepositoryTag(name) |
| 491 | 491 |
if tag == "" {
|
| 492 | 492 |
tag = "latest" |
| ... | ... |
@@ -524,7 +525,7 @@ func (b *Builder) pullImage(name string) (*graph.Image, error) {
|
| 524 | 524 |
return image, nil |
| 525 | 525 |
} |
| 526 | 526 |
|
| 527 |
-func (b *Builder) processImageFrom(img *graph.Image) error {
|
|
| 527 |
+func (b *Builder) processImageFrom(img *image.Image) error {
|
|
| 528 | 528 |
b.image = img.ID |
| 529 | 529 |
|
| 530 | 530 |
if img.Config != nil {
|
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
package daemon |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "github.com/docker/docker/graph" |
|
| 4 |
+ "github.com/docker/docker/image" |
|
| 5 | 5 |
"github.com/docker/docker/runconfig" |
| 6 | 6 |
) |
| 7 | 7 |
|
| ... | ... |
@@ -16,7 +16,7 @@ type ContainerCommitConfig struct {
|
| 16 | 16 |
|
| 17 | 17 |
// Commit creates a new filesystem image from the current state of a container. |
| 18 | 18 |
// The image can optionally be tagged into a repository |
| 19 |
-func (daemon *Daemon) Commit(container *Container, c *ContainerCommitConfig) (*graph.Image, error) {
|
|
| 19 |
+func (daemon *Daemon) Commit(container *Container, c *ContainerCommitConfig) (*image.Image, error) {
|
|
| 20 | 20 |
if c.Pause && !container.IsPaused() {
|
| 21 | 21 |
container.Pause() |
| 22 | 22 |
defer container.Unpause() |
| ... | ... |
@@ -20,7 +20,7 @@ import ( |
| 20 | 20 |
"github.com/docker/docker/daemon/logger" |
| 21 | 21 |
"github.com/docker/docker/daemon/logger/jsonfilelog" |
| 22 | 22 |
"github.com/docker/docker/daemon/network" |
| 23 |
- "github.com/docker/docker/graph" |
|
| 23 |
+ "github.com/docker/docker/image" |
|
| 24 | 24 |
"github.com/docker/docker/pkg/archive" |
| 25 | 25 |
"github.com/docker/docker/pkg/broadcastwriter" |
| 26 | 26 |
"github.com/docker/docker/pkg/fileutils" |
| ... | ... |
@@ -584,7 +584,7 @@ func (container *Container) Changes() ([]archive.Change, error) {
|
| 584 | 584 |
return container.changes() |
| 585 | 585 |
} |
| 586 | 586 |
|
| 587 |
-func (container *Container) GetImage() (*graph.Image, error) {
|
|
| 587 |
+func (container *Container) GetImage() (*image.Image, error) {
|
|
| 588 | 588 |
if container.daemon == nil {
|
| 589 | 589 |
return nil, fmt.Errorf("Can't get image of unregistered container")
|
| 590 | 590 |
} |
| ... | ... |
@@ -9,7 +9,7 @@ import ( |
| 9 | 9 |
|
| 10 | 10 |
"github.com/docker/docker/daemon/execdriver" |
| 11 | 11 |
"github.com/docker/docker/daemon/graphdriver/windows" |
| 12 |
- "github.com/docker/docker/graph" |
|
| 12 |
+ "github.com/docker/docker/image" |
|
| 13 | 13 |
"github.com/docker/docker/pkg/archive" |
| 14 | 14 |
"github.com/microsoft/hcsshim" |
| 15 | 15 |
) |
| ... | ... |
@@ -114,7 +114,7 @@ func populateCommand(c *Container, env []string) error {
|
| 114 | 114 |
// enable VFS to continue operating for development purposes. |
| 115 | 115 |
if wd, ok := c.daemon.driver.(*windows.WindowsGraphDriver); ok {
|
| 116 | 116 |
var err error |
| 117 |
- var img *graph.Image |
|
| 117 |
+ var img *image.Image |
|
| 118 | 118 |
var ids []string |
| 119 | 119 |
|
| 120 | 120 |
if img, err = c.daemon.graph.Get(c.ImageID); err != nil {
|
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
|
| 9 | 9 |
"github.com/Sirupsen/logrus" |
| 10 | 10 |
"github.com/docker/docker/graph" |
| 11 |
+ "github.com/docker/docker/image" |
|
| 11 | 12 |
"github.com/docker/docker/pkg/parsers" |
| 12 | 13 |
"github.com/docker/docker/pkg/stringid" |
| 13 | 14 |
"github.com/docker/docker/runconfig" |
| ... | ... |
@@ -46,7 +47,7 @@ func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.Hos |
| 46 | 46 |
var ( |
| 47 | 47 |
container *Container |
| 48 | 48 |
warnings []string |
| 49 |
- img *graph.Image |
|
| 49 |
+ img *image.Image |
|
| 50 | 50 |
imgID string |
| 51 | 51 |
err error |
| 52 | 52 |
) |
| ... | ... |
@@ -23,6 +23,7 @@ import ( |
| 23 | 23 |
"github.com/docker/docker/daemon/logger" |
| 24 | 24 |
"github.com/docker/docker/daemon/network" |
| 25 | 25 |
"github.com/docker/docker/graph" |
| 26 |
+ "github.com/docker/docker/image" |
|
| 26 | 27 |
"github.com/docker/docker/pkg/broadcastwriter" |
| 27 | 28 |
"github.com/docker/docker/pkg/fileutils" |
| 28 | 29 |
"github.com/docker/docker/pkg/graphdb" |
| ... | ... |
@@ -336,7 +337,7 @@ func (daemon *Daemon) restore() error {
|
| 336 | 336 |
return nil |
| 337 | 337 |
} |
| 338 | 338 |
|
| 339 |
-func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *graph.Image) error {
|
|
| 339 |
+func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *image.Image) error {
|
|
| 340 | 340 |
if img != nil && img.Config != nil {
|
| 341 | 341 |
if err := runconfig.Merge(config, img.Config); err != nil {
|
| 342 | 342 |
return err |
| ... | ... |
@@ -882,7 +883,7 @@ func (daemon *Daemon) ContainerGraph() *graphdb.Database {
|
| 882 | 882 |
return daemon.containerGraph |
| 883 | 883 |
} |
| 884 | 884 |
|
| 885 |
-func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*graph.Image, error) {
|
|
| 885 |
+func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*image.Image, error) {
|
|
| 886 | 886 |
// Retrieve all images |
| 887 | 887 |
images := daemon.Graph().Map() |
| 888 | 888 |
|
| ... | ... |
@@ -896,7 +897,7 @@ func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*g |
| 896 | 896 |
} |
| 897 | 897 |
|
| 898 | 898 |
// Loop on the children of the given image and check the config |
| 899 |
- var match *graph.Image |
|
| 899 |
+ var match *image.Image |
|
| 900 | 900 |
for elem := range imageMap[imgID] {
|
| 901 | 901 |
img, ok := images[elem] |
| 902 | 902 |
if !ok {
|
| ... | ... |
@@ -7,6 +7,7 @@ import ( |
| 7 | 7 |
"github.com/Sirupsen/logrus" |
| 8 | 8 |
"github.com/docker/docker/api/types" |
| 9 | 9 |
"github.com/docker/docker/graph" |
| 10 |
+ "github.com/docker/docker/image" |
|
| 10 | 11 |
"github.com/docker/docker/pkg/parsers" |
| 11 | 12 |
"github.com/docker/docker/pkg/stringid" |
| 12 | 13 |
"github.com/docker/docker/utils" |
| ... | ... |
@@ -159,7 +160,7 @@ func (daemon *Daemon) canDeleteImage(imgID string, force bool) error {
|
| 159 | 159 |
return err |
| 160 | 160 |
} |
| 161 | 161 |
|
| 162 |
- if err := daemon.graph.WalkHistory(parent, func(p graph.Image) error {
|
|
| 162 |
+ if err := daemon.graph.WalkHistory(parent, func(p image.Image) error {
|
|
| 163 | 163 |
if imgID == p.ID {
|
| 164 | 164 |
if container.IsRunning() {
|
| 165 | 165 |
if force {
|
| ... | ... |
@@ -82,22 +82,6 @@ type Graph struct {
|
| 82 | 82 |
retained *retainedLayers |
| 83 | 83 |
} |
| 84 | 84 |
|
| 85 |
-type Image struct {
|
|
| 86 |
- ID string `json:"id"` |
|
| 87 |
- Parent string `json:"parent,omitempty"` |
|
| 88 |
- Comment string `json:"comment,omitempty"` |
|
| 89 |
- Created time.Time `json:"created"` |
|
| 90 |
- Container string `json:"container,omitempty"` |
|
| 91 |
- ContainerConfig runconfig.Config `json:"container_config,omitempty"` |
|
| 92 |
- DockerVersion string `json:"docker_version,omitempty"` |
|
| 93 |
- Author string `json:"author,omitempty"` |
|
| 94 |
- Config *runconfig.Config `json:"config,omitempty"` |
|
| 95 |
- Architecture string `json:"architecture,omitempty"` |
|
| 96 |
- OS string `json:"os,omitempty"` |
|
| 97 |
- Size int64 |
|
| 98 |
- graph Graph |
|
| 99 |
-} |
|
| 100 |
- |
|
| 101 | 85 |
var ( |
| 102 | 86 |
// ErrDigestNotSet is used when request the digest for a layer |
| 103 | 87 |
// but the layer has no digest value or content to compute the |
| ... | ... |
@@ -174,7 +158,7 @@ func (graph *Graph) Exists(id string) bool {
|
| 174 | 174 |
} |
| 175 | 175 |
|
| 176 | 176 |
// Get returns the image with the given id, or an error if the image doesn't exist. |
| 177 |
-func (graph *Graph) Get(name string) (*Image, error) {
|
|
| 177 |
+func (graph *Graph) Get(name string) (*image.Image, error) {
|
|
| 178 | 178 |
id, err := graph.idIndex.Get(name) |
| 179 | 179 |
if err != nil {
|
| 180 | 180 |
return nil, fmt.Errorf("could not find image: %v", err)
|
| ... | ... |
@@ -202,8 +186,8 @@ func (graph *Graph) Get(name string) (*Image, error) {
|
| 202 | 202 |
} |
| 203 | 203 |
|
| 204 | 204 |
// Create creates a new image and registers it in the graph. |
| 205 |
-func (graph *Graph) Create(layerData archive.ArchiveReader, containerID, containerImage, comment, author string, containerConfig, config *runconfig.Config) (*Image, error) {
|
|
| 206 |
- img := &Image{
|
|
| 205 |
+func (graph *Graph) Create(layerData archive.ArchiveReader, containerID, containerImage, comment, author string, containerConfig, config *runconfig.Config) (*image.Image, error) {
|
|
| 206 |
+ img := &image.Image{
|
|
| 207 | 207 |
ID: stringid.GenerateRandomID(), |
| 208 | 208 |
Comment: comment, |
| 209 | 209 |
Created: time.Now().UTC(), |
| ... | ... |
@@ -227,7 +211,7 @@ func (graph *Graph) Create(layerData archive.ArchiveReader, containerID, contain |
| 227 | 227 |
} |
| 228 | 228 |
|
| 229 | 229 |
// Register imports a pre-existing image into the graph. |
| 230 |
-func (graph *Graph) Register(img *Image, layerData archive.ArchiveReader) (err error) {
|
|
| 230 |
+func (graph *Graph) Register(img *image.Image, layerData archive.ArchiveReader) (err error) {
|
|
| 231 | 231 |
|
| 232 | 232 |
if err := image.ValidateID(img.ID); err != nil {
|
| 233 | 233 |
return err |
| ... | ... |
@@ -380,9 +364,9 @@ func (graph *Graph) Delete(name string) error {
|
| 380 | 380 |
} |
| 381 | 381 |
|
| 382 | 382 |
// Map returns a list of all images in the graph, addressable by ID. |
| 383 |
-func (graph *Graph) Map() map[string]*Image {
|
|
| 384 |
- images := make(map[string]*Image) |
|
| 385 |
- graph.walkAll(func(image *Image) {
|
|
| 383 |
+func (graph *Graph) Map() map[string]*image.Image {
|
|
| 384 |
+ images := make(map[string]*image.Image) |
|
| 385 |
+ graph.walkAll(func(image *image.Image) {
|
|
| 386 | 386 |
images[image.ID] = image |
| 387 | 387 |
}) |
| 388 | 388 |
return images |
| ... | ... |
@@ -390,7 +374,7 @@ func (graph *Graph) Map() map[string]*Image {
|
| 390 | 390 |
|
| 391 | 391 |
// walkAll iterates over each image in the graph, and passes it to a handler. |
| 392 | 392 |
// The walking order is undetermined. |
| 393 |
-func (graph *Graph) walkAll(handler func(*Image)) {
|
|
| 393 |
+func (graph *Graph) walkAll(handler func(*image.Image)) {
|
|
| 394 | 394 |
graph.idIndex.Iterate(func(id string) {
|
| 395 | 395 |
if img, err := graph.Get(id); err != nil {
|
| 396 | 396 |
return |
| ... | ... |
@@ -404,9 +388,9 @@ func (graph *Graph) walkAll(handler func(*Image)) {
|
| 404 | 404 |
// If an image of id ID has 3 children images, then the value for key ID |
| 405 | 405 |
// will be a list of 3 images. |
| 406 | 406 |
// If an image has no children, it will not have an entry in the table. |
| 407 |
-func (graph *Graph) ByParent() map[string][]*Image {
|
|
| 408 |
- byParent := make(map[string][]*Image) |
|
| 409 |
- graph.walkAll(func(img *Image) {
|
|
| 407 |
+func (graph *Graph) ByParent() map[string][]*image.Image {
|
|
| 408 |
+ byParent := make(map[string][]*image.Image) |
|
| 409 |
+ graph.walkAll(func(img *image.Image) {
|
|
| 410 | 410 |
parent, err := graph.Get(img.Parent) |
| 411 | 411 |
if err != nil {
|
| 412 | 412 |
return |
| ... | ... |
@@ -414,7 +398,7 @@ func (graph *Graph) ByParent() map[string][]*Image {
|
| 414 | 414 |
if children, exists := byParent[parent.ID]; exists {
|
| 415 | 415 |
byParent[parent.ID] = append(children, img) |
| 416 | 416 |
} else {
|
| 417 |
- byParent[parent.ID] = []*Image{img}
|
|
| 417 |
+ byParent[parent.ID] = []*image.Image{img}
|
|
| 418 | 418 |
} |
| 419 | 419 |
}) |
| 420 | 420 |
return byParent |
| ... | ... |
@@ -433,10 +417,10 @@ func (graph *Graph) Release(sessionID string, layerIDs ...string) {
|
| 433 | 433 |
|
| 434 | 434 |
// Heads returns all heads in the graph, keyed by id. |
| 435 | 435 |
// A head is an image which is not the parent of another image in the graph. |
| 436 |
-func (graph *Graph) Heads() map[string]*Image {
|
|
| 437 |
- heads := make(map[string]*Image) |
|
| 436 |
+func (graph *Graph) Heads() map[string]*image.Image {
|
|
| 437 |
+ heads := make(map[string]*image.Image) |
|
| 438 | 438 |
byParent := graph.ByParent() |
| 439 |
- graph.walkAll(func(image *Image) {
|
|
| 439 |
+ graph.walkAll(func(image *image.Image) {
|
|
| 440 | 440 |
// If it's not in the byParent lookup table, then |
| 441 | 441 |
// it's not a parent -> so it's a head! |
| 442 | 442 |
if _, exists := byParent[image.ID]; !exists {
|
| ... | ... |
@@ -451,7 +435,7 @@ func (graph *Graph) imageRoot(id string) string {
|
| 451 | 451 |
} |
| 452 | 452 |
|
| 453 | 453 |
// loadImage fetches the image with the given id from the graph. |
| 454 |
-func (graph *Graph) loadImage(id string) (*Image, error) {
|
|
| 454 |
+func (graph *Graph) loadImage(id string) (*image.Image, error) {
|
|
| 455 | 455 |
root := graph.imageRoot(id) |
| 456 | 456 |
|
| 457 | 457 |
// Open the JSON file to decode by streaming |
| ... | ... |
@@ -461,7 +445,7 @@ func (graph *Graph) loadImage(id string) (*Image, error) {
|
| 461 | 461 |
} |
| 462 | 462 |
defer jsonSource.Close() |
| 463 | 463 |
|
| 464 |
- img := &Image{}
|
|
| 464 |
+ img := &image.Image{}
|
|
| 465 | 465 |
dec := json.NewDecoder(jsonSource) |
| 466 | 466 |
|
| 467 | 467 |
// Decode the JSON data |
| ... | ... |
@@ -538,14 +522,3 @@ func (graph *Graph) RawJSON(id string) ([]byte, error) {
|
| 538 | 538 |
func jsonPath(root string) string {
|
| 539 | 539 |
return filepath.Join(root, "json") |
| 540 | 540 |
} |
| 541 |
- |
|
| 542 |
-// Build an Image object from raw json data |
|
| 543 |
-func NewImgJSON(src []byte) (*Image, error) {
|
|
| 544 |
- ret := &Image{}
|
|
| 545 |
- |
|
| 546 |
- // FIXME: Is there a cleaner way to "purify" the input json? |
|
| 547 |
- if err := json.Unmarshal(src, ret); err != nil {
|
|
| 548 |
- return nil, err |
|
| 549 |
- } |
|
| 550 |
- return ret, nil |
|
| 551 |
-} |
| ... | ... |
@@ -67,7 +67,7 @@ func TestInterruptedRegister(t *testing.T) {
|
| 67 | 67 |
graph, _ := tempGraph(t) |
| 68 | 68 |
defer nukeGraph(graph) |
| 69 | 69 |
badArchive, w := io.Pipe() // Use a pipe reader as a fake archive which never yields data |
| 70 |
- image := &Image{
|
|
| 70 |
+ image := &image.Image{
|
|
| 71 | 71 |
ID: stringid.GenerateRandomID(), |
| 72 | 72 |
Comment: "testing", |
| 73 | 73 |
Created: time.Now(), |
| ... | ... |
@@ -125,7 +125,7 @@ func TestRegister(t *testing.T) {
|
| 125 | 125 |
if err != nil {
|
| 126 | 126 |
t.Fatal(err) |
| 127 | 127 |
} |
| 128 |
- image := &Image{
|
|
| 128 |
+ image := &image.Image{
|
|
| 129 | 129 |
ID: stringid.GenerateRandomID(), |
| 130 | 130 |
Comment: "testing", |
| 131 | 131 |
Created: time.Now(), |
| ... | ... |
@@ -228,19 +228,19 @@ func TestByParent(t *testing.T) {
|
| 228 | 228 |
|
| 229 | 229 |
graph, _ := tempGraph(t) |
| 230 | 230 |
defer nukeGraph(graph) |
| 231 |
- parentImage := &Image{
|
|
| 231 |
+ parentImage := &image.Image{
|
|
| 232 | 232 |
ID: stringid.GenerateRandomID(), |
| 233 | 233 |
Comment: "parent", |
| 234 | 234 |
Created: time.Now(), |
| 235 | 235 |
Parent: "", |
| 236 | 236 |
} |
| 237 |
- childImage1 := &Image{
|
|
| 237 |
+ childImage1 := &image.Image{
|
|
| 238 | 238 |
ID: stringid.GenerateRandomID(), |
| 239 | 239 |
Comment: "child1", |
| 240 | 240 |
Created: time.Now(), |
| 241 | 241 |
Parent: parentImage.ID, |
| 242 | 242 |
} |
| 243 |
- childImage2 := &Image{
|
|
| 243 |
+ childImage2 := &image.Image{
|
|
| 244 | 244 |
ID: stringid.GenerateRandomID(), |
| 245 | 245 |
Comment: "child2", |
| 246 | 246 |
Created: time.Now(), |
| ... | ... |
@@ -257,7 +257,7 @@ func TestByParent(t *testing.T) {
|
| 257 | 257 |
} |
| 258 | 258 |
} |
| 259 | 259 |
|
| 260 |
-func createTestImage(graph *Graph, t *testing.T) *Image {
|
|
| 260 |
+func createTestImage(graph *Graph, t *testing.T) *image.Image {
|
|
| 261 | 261 |
archive, err := fakeTar() |
| 262 | 262 |
if err != nil {
|
| 263 | 263 |
t.Fatal(err) |
| ... | ... |
@@ -10,6 +10,7 @@ import ( |
| 10 | 10 |
"strings" |
| 11 | 11 |
"syscall" |
| 12 | 12 |
|
| 13 |
+ "github.com/docker/docker/image" |
|
| 13 | 14 |
"github.com/docker/docker/pkg/archive" |
| 14 | 15 |
"github.com/docker/docker/pkg/system" |
| 15 | 16 |
) |
| ... | ... |
@@ -72,7 +73,7 @@ func SetupInitLayer(initLayer string) error {
|
| 72 | 72 |
return nil |
| 73 | 73 |
} |
| 74 | 74 |
|
| 75 |
-func createRootFilesystemInDriver(graph *Graph, img *Image, layerData archive.ArchiveReader) error {
|
|
| 75 |
+func createRootFilesystemInDriver(graph *Graph, img *image.Image, layerData archive.ArchiveReader) error {
|
|
| 76 | 76 |
if err := graph.driver.Create(img.ID, img.Parent); err != nil {
|
| 77 | 77 |
return fmt.Errorf("Driver %s failed to create image rootfs %s: %s", graph.driver, img.ID, err)
|
| 78 | 78 |
} |
| ... | ... |
@@ -86,7 +87,7 @@ func (graph *Graph) restoreBaseImages() ([]string, error) {
|
| 86 | 86 |
// storeImage stores file system layer data for the given image to the |
| 87 | 87 |
// graph's storage driver. Image metadata is stored in a file |
| 88 | 88 |
// at the specified root directory. |
| 89 |
-func (graph *Graph) storeImage(img *Image, layerData archive.ArchiveReader, root string) (err error) {
|
|
| 89 |
+func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader, root string) (err error) {
|
|
| 90 | 90 |
// Store the layer. If layerData is not nil, unpack it into the new layer |
| 91 | 91 |
if layerData != nil {
|
| 92 | 92 |
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 |
| 109 | 109 |
} |
| 110 | 110 |
|
| 111 | 111 |
// TarLayer returns a tar archive of the image's filesystem layer. |
| 112 |
-func (graph *Graph) TarLayer(img *Image) (arch archive.Archive, err error) {
|
|
| 112 |
+func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error) {
|
|
| 113 | 113 |
return graph.driver.Diff(img.ID, img.Parent) |
| 114 | 114 |
} |
| ... | ... |
@@ -9,6 +9,7 @@ import ( |
| 9 | 9 |
|
| 10 | 10 |
"github.com/Sirupsen/logrus" |
| 11 | 11 |
"github.com/docker/docker/daemon/graphdriver/windows" |
| 12 |
+ "github.com/docker/docker/image" |
|
| 12 | 13 |
"github.com/docker/docker/pkg/archive" |
| 13 | 14 |
) |
| 14 | 15 |
|
| ... | ... |
@@ -18,7 +19,7 @@ func SetupInitLayer(initLayer string) error {
|
| 18 | 18 |
return nil |
| 19 | 19 |
} |
| 20 | 20 |
|
| 21 |
-func createRootFilesystemInDriver(graph *Graph, img *Image, layerData archive.ArchiveReader) error {
|
|
| 21 |
+func createRootFilesystemInDriver(graph *Graph, img *image.Image, layerData archive.ArchiveReader) error {
|
|
| 22 | 22 |
if wd, ok := graph.driver.(*windows.WindowsGraphDriver); ok {
|
| 23 | 23 |
if img.Container != "" && layerData == nil {
|
| 24 | 24 |
logrus.Debugf("Copying from container %s.", img.Container)
|
| ... | ... |
@@ -59,7 +60,7 @@ func (graph *Graph) restoreBaseImages() ([]string, error) {
|
| 59 | 59 |
} |
| 60 | 60 |
|
| 61 | 61 |
// ParentLayerIds returns a list of all parent image IDs for the given image. |
| 62 |
-func (graph *Graph) ParentLayerIds(img *Image) (ids []string, err error) {
|
|
| 62 |
+func (graph *Graph) ParentLayerIds(img *image.Image) (ids []string, err error) {
|
|
| 63 | 63 |
for i := img; i != nil && err == nil; i, err = graph.GetParent(i) {
|
| 64 | 64 |
ids = append(ids, i.ID) |
| 65 | 65 |
} |
| ... | ... |
@@ -70,7 +71,7 @@ func (graph *Graph) ParentLayerIds(img *Image) (ids []string, err error) {
|
| 70 | 70 |
// storeImage stores file system layer data for the given image to the |
| 71 | 71 |
// graph's storage driver. Image metadata is stored in a file |
| 72 | 72 |
// at the specified root directory. |
| 73 |
-func (graph *Graph) storeImage(img *Image, layerData archive.ArchiveReader, root string) (err error) {
|
|
| 73 |
+func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader, root string) (err error) {
|
|
| 74 | 74 |
|
| 75 | 75 |
if wd, ok := graph.driver.(*windows.WindowsGraphDriver); ok {
|
| 76 | 76 |
// 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 |
| 135 | 135 |
} |
| 136 | 136 |
|
| 137 | 137 |
// TarLayer returns a tar archive of the image's filesystem layer. |
| 138 |
-func (graph *Graph) TarLayer(img *Image) (arch archive.Archive, err error) {
|
|
| 138 |
+func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error) {
|
|
| 139 | 139 |
if wd, ok := graph.driver.(*windows.WindowsGraphDriver); ok {
|
| 140 | 140 |
var ids []string |
| 141 | 141 |
if img.Parent != "" {
|
| ... | ... |
@@ -5,12 +5,13 @@ import ( |
| 5 | 5 |
"strings" |
| 6 | 6 |
|
| 7 | 7 |
"github.com/docker/docker/api/types" |
| 8 |
+ "github.com/docker/docker/image" |
|
| 8 | 9 |
"github.com/docker/docker/utils" |
| 9 | 10 |
) |
| 10 | 11 |
|
| 11 | 12 |
// WalkHistory calls the handler function for each image in the |
| 12 | 13 |
// provided images lineage starting from immediate parent. |
| 13 |
-func (graph *Graph) WalkHistory(img *Image, handler func(Image) error) (err error) {
|
|
| 14 |
+func (graph *Graph) WalkHistory(img *image.Image, handler func(image.Image) error) (err error) {
|
|
| 14 | 15 |
currentImg := img |
| 15 | 16 |
for currentImg != nil {
|
| 16 | 17 |
if handler != nil {
|
| ... | ... |
@@ -28,7 +29,7 @@ func (graph *Graph) WalkHistory(img *Image, handler func(Image) error) (err erro |
| 28 | 28 |
|
| 29 | 29 |
// depth returns the number of parents for a |
| 30 | 30 |
// current image |
| 31 |
-func (graph *Graph) depth(img *Image) (int, error) {
|
|
| 31 |
+func (graph *Graph) depth(img *image.Image) (int, error) {
|
|
| 32 | 32 |
var ( |
| 33 | 33 |
count = 0 |
| 34 | 34 |
parent = img |
| ... | ... |
@@ -53,7 +54,7 @@ const MaxImageDepth = 127 |
| 53 | 53 |
// CheckDepth returns an error if the depth of an image, as returned |
| 54 | 54 |
// by ImageDepth, is too large to support creating a container from it |
| 55 | 55 |
// on this daemon. |
| 56 |
-func (graph *Graph) CheckDepth(img *Image) error {
|
|
| 56 |
+func (graph *Graph) CheckDepth(img *image.Image) error {
|
|
| 57 | 57 |
// We add 2 layers to the depth because the container's rw and |
| 58 | 58 |
// init layer add to the restriction |
| 59 | 59 |
depth, err := graph.depth(img) |
| ... | ... |
@@ -85,7 +86,7 @@ func (s *TagStore) History(name string) ([]*types.ImageHistory, error) {
|
| 85 | 85 |
|
| 86 | 86 |
history := []*types.ImageHistory{}
|
| 87 | 87 |
|
| 88 |
- err = s.graph.WalkHistory(foundImage, func(img Image) error {
|
|
| 88 |
+ err = s.graph.WalkHistory(foundImage, func(img image.Image) error {
|
|
| 89 | 89 |
history = append(history, &types.ImageHistory{
|
| 90 | 90 |
ID: img.ID, |
| 91 | 91 |
Created: img.Created.Unix(), |
| ... | ... |
@@ -100,14 +101,14 @@ func (s *TagStore) History(name string) ([]*types.ImageHistory, error) {
|
| 100 | 100 |
return history, err |
| 101 | 101 |
} |
| 102 | 102 |
|
| 103 |
-func (graph *Graph) GetParent(img *Image) (*Image, error) {
|
|
| 103 |
+func (graph *Graph) GetParent(img *image.Image) (*image.Image, error) {
|
|
| 104 | 104 |
if img.Parent == "" {
|
| 105 | 105 |
return nil, nil |
| 106 | 106 |
} |
| 107 | 107 |
return graph.Get(img.Parent) |
| 108 | 108 |
} |
| 109 | 109 |
|
| 110 |
-func (graph *Graph) GetParentsSize(img *Image, size int64) int64 {
|
|
| 110 |
+func (graph *Graph) GetParentsSize(img *image.Image, size int64) int64 {
|
|
| 111 | 111 |
parentImage, err := graph.GetParent(img) |
| 112 | 112 |
if err != nil || parentImage == nil {
|
| 113 | 113 |
return size |
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
|
| 9 | 9 |
"github.com/Sirupsen/logrus" |
| 10 | 10 |
"github.com/docker/docker/api/types" |
| 11 |
+ "github.com/docker/docker/image" |
|
| 11 | 12 |
"github.com/docker/docker/pkg/parsers/filters" |
| 12 | 13 |
"github.com/docker/docker/utils" |
| 13 | 14 |
) |
| ... | ... |
@@ -31,7 +32,7 @@ func (r ByCreated) Less(i, j int) bool { return r[i].Created < r[j].Created }
|
| 31 | 31 |
|
| 32 | 32 |
func (s *TagStore) Images(config *ImagesConfig) ([]*types.Image, error) {
|
| 33 | 33 |
var ( |
| 34 |
- allImages map[string]*Image |
|
| 34 |
+ allImages map[string]*image.Image |
|
| 35 | 35 |
err error |
| 36 | 36 |
filtTagged = true |
| 37 | 37 |
filtLabel = false |
| ... | ... |
@@ -95,7 +95,7 @@ func (s *TagStore) recursiveLoad(address, tmpImageDir string) error {
|
| 95 | 95 |
logrus.Debugf("Error reading embedded tar: %v", err)
|
| 96 | 96 |
return err |
| 97 | 97 |
} |
| 98 |
- img, err := NewImgJSON(imageJson) |
|
| 98 |
+ img, err := image.NewImgJSON(imageJson) |
|
| 99 | 99 |
if err != nil {
|
| 100 | 100 |
logrus.Debugf("Error unmarshalling json: %v", err)
|
| 101 | 101 |
return err |
| ... | ... |
@@ -10,6 +10,7 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
"github.com/Sirupsen/logrus" |
| 12 | 12 |
"github.com/docker/distribution/registry/client/transport" |
| 13 |
+ "github.com/docker/docker/image" |
|
| 13 | 14 |
"github.com/docker/docker/pkg/progressreader" |
| 14 | 15 |
"github.com/docker/docker/pkg/streamformatter" |
| 15 | 16 |
"github.com/docker/docker/pkg/stringid" |
| ... | ... |
@@ -257,7 +258,7 @@ func (p *v1Puller) pullImage(imgID, endpoint string, token []string) (bool, erro |
| 257 | 257 |
imgJSON []byte |
| 258 | 258 |
imgSize int |
| 259 | 259 |
err error |
| 260 |
- img *Image |
|
| 260 |
+ img *image.Image |
|
| 261 | 261 |
) |
| 262 | 262 |
retries := 5 |
| 263 | 263 |
for j := 1; j <= retries; j++ {
|
| ... | ... |
@@ -269,7 +270,7 @@ func (p *v1Puller) pullImage(imgID, endpoint string, token []string) (bool, erro |
| 269 | 269 |
time.Sleep(time.Duration(j) * 500 * time.Millisecond) |
| 270 | 270 |
continue |
| 271 | 271 |
} |
| 272 |
- img, err = NewImgJSON(imgJSON) |
|
| 272 |
+ img, err = image.NewImgJSON(imgJSON) |
|
| 273 | 273 |
layersDownloaded = true |
| 274 | 274 |
if err != nil && j == retries {
|
| 275 | 275 |
out.Write(p.sf.FormatProgress(stringid.TruncateID(id), "Error pulling dependent layers", nil)) |
| ... | ... |
@@ -10,6 +10,7 @@ import ( |
| 10 | 10 |
"github.com/docker/distribution" |
| 11 | 11 |
"github.com/docker/distribution/digest" |
| 12 | 12 |
"github.com/docker/distribution/manifest" |
| 13 |
+ "github.com/docker/docker/image" |
|
| 13 | 14 |
"github.com/docker/docker/pkg/progressreader" |
| 14 | 15 |
"github.com/docker/docker/pkg/streamformatter" |
| 15 | 16 |
"github.com/docker/docker/pkg/stringid" |
| ... | ... |
@@ -94,7 +95,7 @@ func (p *v2Puller) pullV2Repository(tag string) (err error) {
|
| 94 | 94 |
|
| 95 | 95 |
// downloadInfo is used to pass information from download to extractor |
| 96 | 96 |
type downloadInfo struct {
|
| 97 |
- img *Image |
|
| 97 |
+ img *image.Image |
|
| 98 | 98 |
tmpFile *os.File |
| 99 | 99 |
digest digest.Digest |
| 100 | 100 |
layer distribution.ReadSeekCloser |
| ... | ... |
@@ -208,7 +209,7 @@ func (p *v2Puller) pullV2Tag(tag, taggedName string) (bool, error) {
|
| 208 | 208 |
}() |
| 209 | 209 |
|
| 210 | 210 |
for i := len(manifest.FSLayers) - 1; i >= 0; i-- {
|
| 211 |
- img, err := NewImgJSON([]byte(manifest.History[i].V1Compatibility)) |
|
| 211 |
+ img, err := image.NewImgJSON([]byte(manifest.History[i].V1Compatibility)) |
|
| 212 | 212 |
if err != nil {
|
| 213 | 213 |
logrus.Debugf("error getting image v1 json: %v", err)
|
| 214 | 214 |
return false, err |
| ... | ... |
@@ -9,6 +9,7 @@ import ( |
| 9 | 9 |
"github.com/docker/distribution" |
| 10 | 10 |
"github.com/docker/distribution/digest" |
| 11 | 11 |
"github.com/docker/distribution/manifest" |
| 12 |
+ "github.com/docker/docker/image" |
|
| 12 | 13 |
"github.com/docker/docker/pkg/progressreader" |
| 13 | 14 |
"github.com/docker/docker/pkg/streamformatter" |
| 14 | 15 |
"github.com/docker/docker/pkg/stringid" |
| ... | ... |
@@ -190,7 +191,7 @@ func (p *v2Pusher) pushV2Tag(tag string) error {
|
| 190 | 190 |
return p.repo.Manifests().Put(signed) |
| 191 | 191 |
} |
| 192 | 192 |
|
| 193 |
-func (p *v2Pusher) pushV2Image(bs distribution.BlobService, img *Image) (digest.Digest, error) {
|
|
| 193 |
+func (p *v2Pusher) pushV2Image(bs distribution.BlobService, img *image.Image) (digest.Digest, error) {
|
|
| 194 | 194 |
out := p.config.OutStream |
| 195 | 195 |
|
| 196 | 196 |
out.Write(p.sf.FormatProgress(stringid.TruncateID(img.ID), "Buffering to Disk", nil)) |
| ... | ... |
@@ -15,6 +15,7 @@ import ( |
| 15 | 15 |
"github.com/docker/distribution/digest" |
| 16 | 16 |
"github.com/docker/docker/daemon/events" |
| 17 | 17 |
"github.com/docker/docker/graph/tags" |
| 18 |
+ "github.com/docker/docker/image" |
|
| 18 | 19 |
"github.com/docker/docker/pkg/parsers" |
| 19 | 20 |
"github.com/docker/docker/pkg/stringid" |
| 20 | 21 |
"github.com/docker/docker/registry" |
| ... | ... |
@@ -120,7 +121,7 @@ func (store *TagStore) reload() error {
|
| 120 | 120 |
return nil |
| 121 | 121 |
} |
| 122 | 122 |
|
| 123 |
-func (store *TagStore) LookupImage(name string) (*Image, error) {
|
|
| 123 |
+func (store *TagStore) LookupImage(name string) (*image.Image, error) {
|
|
| 124 | 124 |
// FIXME: standardize on returning nil when the image doesn't exist, and err for everything else |
| 125 | 125 |
// (so we can pass all errors here) |
| 126 | 126 |
repoName, ref := parsers.ParseRepositoryTag(name) |
| ... | ... |
@@ -129,7 +130,7 @@ func (store *TagStore) LookupImage(name string) (*Image, error) {
|
| 129 | 129 |
} |
| 130 | 130 |
var ( |
| 131 | 131 |
err error |
| 132 |
- img *Image |
|
| 132 |
+ img *image.Image |
|
| 133 | 133 |
) |
| 134 | 134 |
|
| 135 | 135 |
img, err = store.GetImage(repoName, ref) |
| ... | ... |
@@ -331,7 +332,7 @@ func (store *TagStore) Get(repoName string) (Repository, error) {
|
| 331 | 331 |
return nil, nil |
| 332 | 332 |
} |
| 333 | 333 |
|
| 334 |
-func (store *TagStore) GetImage(repoName, refOrID string) (*Image, error) {
|
|
| 334 |
+func (store *TagStore) GetImage(repoName, refOrID string) (*image.Image, error) {
|
|
| 335 | 335 |
repo, err := store.Get(repoName) |
| 336 | 336 |
|
| 337 | 337 |
if err != nil {
|
| ... | ... |
@@ -11,6 +11,7 @@ import ( |
| 11 | 11 |
"github.com/docker/docker/daemon/events" |
| 12 | 12 |
"github.com/docker/docker/daemon/graphdriver" |
| 13 | 13 |
_ "github.com/docker/docker/daemon/graphdriver/vfs" // import the vfs driver so it is used in the tests |
| 14 |
+ "github.com/docker/docker/image" |
|
| 14 | 15 |
"github.com/docker/docker/trust" |
| 15 | 16 |
"github.com/docker/docker/utils" |
| 16 | 17 |
) |
| ... | ... |
@@ -79,7 +80,7 @@ func mkTestTagStore(root string, t *testing.T) *TagStore {
|
| 79 | 79 |
if err != nil {
|
| 80 | 80 |
t.Fatal(err) |
| 81 | 81 |
} |
| 82 |
- img := &Image{ID: testOfficialImageID}
|
|
| 82 |
+ img := &image.Image{ID: testOfficialImageID}
|
|
| 83 | 83 |
if err := graph.Register(img, officialArchive); err != nil {
|
| 84 | 84 |
t.Fatal(err) |
| 85 | 85 |
} |
| ... | ... |
@@ -90,7 +91,7 @@ func mkTestTagStore(root string, t *testing.T) *TagStore {
|
| 90 | 90 |
if err != nil {
|
| 91 | 91 |
t.Fatal(err) |
| 92 | 92 |
} |
| 93 |
- img = &Image{ID: testPrivateImageID}
|
|
| 93 |
+ img = &image.Image{ID: testPrivateImageID}
|
|
| 94 | 94 |
if err := graph.Register(img, privateArchive); err != nil {
|
| 95 | 95 |
t.Fatal(err) |
| 96 | 96 |
} |
| ... | ... |
@@ -1,12 +1,42 @@ |
| 1 | 1 |
package image |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "encoding/json" |
|
| 4 | 5 |
"fmt" |
| 5 | 6 |
"regexp" |
| 7 |
+ "time" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/docker/docker/runconfig" |
|
| 6 | 10 |
) |
| 7 | 11 |
|
| 8 | 12 |
var validHex = regexp.MustCompile(`^([a-f0-9]{64})$`)
|
| 9 | 13 |
|
| 14 |
+type Image struct {
|
|
| 15 |
+ ID string `json:"id"` |
|
| 16 |
+ Parent string `json:"parent,omitempty"` |
|
| 17 |
+ Comment string `json:"comment,omitempty"` |
|
| 18 |
+ Created time.Time `json:"created"` |
|
| 19 |
+ Container string `json:"container,omitempty"` |
|
| 20 |
+ ContainerConfig runconfig.Config `json:"container_config,omitempty"` |
|
| 21 |
+ DockerVersion string `json:"docker_version,omitempty"` |
|
| 22 |
+ Author string `json:"author,omitempty"` |
|
| 23 |
+ Config *runconfig.Config `json:"config,omitempty"` |
|
| 24 |
+ Architecture string `json:"architecture,omitempty"` |
|
| 25 |
+ OS string `json:"os,omitempty"` |
|
| 26 |
+ Size int64 |
|
| 27 |
+} |
|
| 28 |
+ |
|
| 29 |
+// Build an Image object from raw json data |
|
| 30 |
+func NewImgJSON(src []byte) (*Image, error) {
|
|
| 31 |
+ ret := &Image{}
|
|
| 32 |
+ |
|
| 33 |
+ // FIXME: Is there a cleaner way to "purify" the input json? |
|
| 34 |
+ if err := json.Unmarshal(src, ret); err != nil {
|
|
| 35 |
+ return nil, err |
|
| 36 |
+ } |
|
| 37 |
+ return ret, nil |
|
| 38 |
+} |
|
| 39 |
+ |
|
| 10 | 40 |
// Check wheather id is a valid image ID or not |
| 11 | 41 |
func ValidateID(id string) error {
|
| 12 | 42 |
if ok := validHex.MatchString(id); !ok {
|