github.com/mforkel/docker-ce-i386@v17.12.1-ce-rc2+incompatible/components/engine/daemon/import.go (about)

     1  package daemon
     2  
     3  import (
     4  	"encoding/json"
     5  	"io"
     6  	"net/http"
     7  	"net/url"
     8  	"runtime"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/docker/distribution/reference"
    13  	"github.com/docker/docker/api/types/container"
    14  	"github.com/docker/docker/builder/dockerfile"
    15  	"github.com/docker/docker/builder/remotecontext"
    16  	"github.com/docker/docker/dockerversion"
    17  	"github.com/docker/docker/image"
    18  	"github.com/docker/docker/layer"
    19  	"github.com/docker/docker/pkg/archive"
    20  	"github.com/docker/docker/pkg/progress"
    21  	"github.com/docker/docker/pkg/streamformatter"
    22  	"github.com/pkg/errors"
    23  )
    24  
    25  // ImportImage imports an image, getting the archived layer data either from
    26  // inConfig (if src is "-"), or from a URI specified in src. Progress output is
    27  // written to outStream. Repository and tag names can optionally be given in
    28  // the repo and tag arguments, respectively.
    29  func (daemon *Daemon) ImportImage(src string, repository, os string, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
    30  	var (
    31  		rc     io.ReadCloser
    32  		resp   *http.Response
    33  		newRef reference.Named
    34  	)
    35  
    36  	// Default the operating system if not supplied.
    37  	if os == "" {
    38  		os = runtime.GOOS
    39  	}
    40  
    41  	if repository != "" {
    42  		var err error
    43  		newRef, err = reference.ParseNormalizedNamed(repository)
    44  		if err != nil {
    45  			return validationError{err}
    46  		}
    47  		if _, isCanonical := newRef.(reference.Canonical); isCanonical {
    48  			return validationError{errors.New("cannot import digest reference")}
    49  		}
    50  
    51  		if tag != "" {
    52  			newRef, err = reference.WithTag(newRef, tag)
    53  			if err != nil {
    54  				return validationError{err}
    55  			}
    56  		}
    57  	}
    58  
    59  	config, err := dockerfile.BuildFromConfig(&container.Config{}, changes)
    60  	if err != nil {
    61  		return err
    62  	}
    63  	if src == "-" {
    64  		rc = inConfig
    65  	} else {
    66  		inConfig.Close()
    67  		if len(strings.Split(src, "://")) == 1 {
    68  			src = "http://" + src
    69  		}
    70  		u, err := url.Parse(src)
    71  		if err != nil {
    72  			return validationError{err}
    73  		}
    74  
    75  		resp, err = remotecontext.GetWithStatusError(u.String())
    76  		if err != nil {
    77  			return err
    78  		}
    79  		outStream.Write(streamformatter.FormatStatus("", "Downloading from %s", u))
    80  		progressOutput := streamformatter.NewJSONProgressOutput(outStream, true)
    81  		rc = progress.NewProgressReader(resp.Body, progressOutput, resp.ContentLength, "", "Importing")
    82  	}
    83  
    84  	defer rc.Close()
    85  	if len(msg) == 0 {
    86  		msg = "Imported from " + src
    87  	}
    88  
    89  	inflatedLayerData, err := archive.DecompressStream(rc)
    90  	if err != nil {
    91  		return err
    92  	}
    93  	l, err := daemon.stores[os].layerStore.Register(inflatedLayerData, "", layer.OS(os))
    94  	if err != nil {
    95  		return err
    96  	}
    97  	defer layer.ReleaseAndLog(daemon.stores[os].layerStore, l)
    98  
    99  	created := time.Now().UTC()
   100  	imgConfig, err := json.Marshal(&image.Image{
   101  		V1Image: image.V1Image{
   102  			DockerVersion: dockerversion.Version,
   103  			Config:        config,
   104  			Architecture:  runtime.GOARCH,
   105  			OS:            os,
   106  			Created:       created,
   107  			Comment:       msg,
   108  		},
   109  		RootFS: &image.RootFS{
   110  			Type:    "layers",
   111  			DiffIDs: []layer.DiffID{l.DiffID()},
   112  		},
   113  		History: []image.History{{
   114  			Created: created,
   115  			Comment: msg,
   116  		}},
   117  	})
   118  	if err != nil {
   119  		return err
   120  	}
   121  
   122  	id, err := daemon.stores[os].imageStore.Create(imgConfig)
   123  	if err != nil {
   124  		return err
   125  	}
   126  
   127  	// FIXME: connect with commit code and call refstore directly
   128  	if newRef != nil {
   129  		if err := daemon.TagImageWithReference(id, os, newRef); err != nil {
   130  			return err
   131  		}
   132  	}
   133  
   134  	daemon.LogImageEvent(id.String(), id.String(), "import")
   135  	outStream.Write(streamformatter.FormatStatus("", id.String()))
   136  	return nil
   137  }