github.com/akerouanton/docker@v1.11.0-rc3/daemon/import.go (about)

     1  package daemon
     2  
     3  import (
     4  	"encoding/json"
     5  	"io"
     6  	"net/http"
     7  	"net/url"
     8  	"runtime"
     9  	"time"
    10  
    11  	"github.com/docker/docker/dockerversion"
    12  	"github.com/docker/docker/image"
    13  	"github.com/docker/docker/layer"
    14  	"github.com/docker/docker/pkg/archive"
    15  	"github.com/docker/docker/pkg/httputils"
    16  	"github.com/docker/docker/pkg/progress"
    17  	"github.com/docker/docker/pkg/streamformatter"
    18  	"github.com/docker/docker/reference"
    19  	"github.com/docker/engine-api/types/container"
    20  )
    21  
    22  // ImportImage imports an image, getting the archived layer data either from
    23  // inConfig (if src is "-"), or from a URI specified in src. Progress output is
    24  // written to outStream. Repository and tag names can optionally be given in
    25  // the repo and tag arguments, respectively.
    26  func (daemon *Daemon) ImportImage(src string, newRef reference.Named, msg string, inConfig io.ReadCloser, outStream io.Writer, config *container.Config) error {
    27  	var (
    28  		sf   = streamformatter.NewJSONStreamFormatter()
    29  		rc   io.ReadCloser
    30  		resp *http.Response
    31  	)
    32  
    33  	if src == "-" {
    34  		rc = inConfig
    35  	} else {
    36  		inConfig.Close()
    37  		u, err := url.Parse(src)
    38  		if err != nil {
    39  			return err
    40  		}
    41  		if u.Scheme == "" {
    42  			u.Scheme = "http"
    43  			u.Host = src
    44  			u.Path = ""
    45  		}
    46  		outStream.Write(sf.FormatStatus("", "Downloading from %s", u))
    47  		resp, err = httputils.Download(u.String())
    48  		if err != nil {
    49  			return err
    50  		}
    51  		progressOutput := sf.NewProgressOutput(outStream, true)
    52  		rc = progress.NewProgressReader(resp.Body, progressOutput, resp.ContentLength, "", "Importing")
    53  	}
    54  
    55  	defer rc.Close()
    56  	if len(msg) == 0 {
    57  		msg = "Imported from " + src
    58  	}
    59  
    60  	inflatedLayerData, err := archive.DecompressStream(rc)
    61  	if err != nil {
    62  		return err
    63  	}
    64  	// TODO: support windows baselayer?
    65  	l, err := daemon.layerStore.Register(inflatedLayerData, "")
    66  	if err != nil {
    67  		return err
    68  	}
    69  	defer layer.ReleaseAndLog(daemon.layerStore, l)
    70  
    71  	created := time.Now().UTC()
    72  	imgConfig, err := json.Marshal(&image.Image{
    73  		V1Image: image.V1Image{
    74  			DockerVersion: dockerversion.Version,
    75  			Config:        config,
    76  			Architecture:  runtime.GOARCH,
    77  			OS:            runtime.GOOS,
    78  			Created:       created,
    79  			Comment:       msg,
    80  		},
    81  		RootFS: &image.RootFS{
    82  			Type:    "layers",
    83  			DiffIDs: []layer.DiffID{l.DiffID()},
    84  		},
    85  		History: []image.History{{
    86  			Created: created,
    87  			Comment: msg,
    88  		}},
    89  	})
    90  	if err != nil {
    91  		return err
    92  	}
    93  
    94  	id, err := daemon.imageStore.Create(imgConfig)
    95  	if err != nil {
    96  		return err
    97  	}
    98  
    99  	// FIXME: connect with commit code and call refstore directly
   100  	if newRef != nil {
   101  		if err := daemon.TagImage(newRef, id.String()); err != nil {
   102  			return err
   103  		}
   104  	}
   105  
   106  	daemon.LogImageEvent(id.String(), id.String(), "import")
   107  	outStream.Write(sf.FormatStatus("", id.String()))
   108  	return nil
   109  }