daemon/import.go
4352da78
 package daemon
 
 import (
 	"encoding/json"
 	"io"
 	"net/http"
 	"net/url"
 	"runtime"
e050f176
 	"strings"
4352da78
 	"time"
 
3a127939
 	"github.com/docker/distribution/reference"
91e197d6
 	"github.com/docker/docker/api/types/container"
93e02efa
 	"github.com/docker/docker/builder/dockerfile"
4060d6ee
 	"github.com/docker/docker/builder/remotecontext"
4352da78
 	"github.com/docker/docker/dockerversion"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/layer"
e1c2eb0d
 	"github.com/docker/docker/pkg/archive"
572ce802
 	"github.com/docker/docker/pkg/progress"
4352da78
 	"github.com/docker/docker/pkg/streamformatter"
3a127939
 	"github.com/pkg/errors"
4352da78
 )
 
 // ImportImage imports an image, getting the archived layer data either from
 // inConfig (if src is "-"), or from a URI specified in src. Progress output is
 // written to outStream. Repository and tag names can optionally be given in
 // the repo and tag arguments, respectively.
0380fbff
 func (daemon *Daemon) ImportImage(src string, repository, os string, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
4352da78
 	var (
47afe6bd
 		rc     io.ReadCloser
 		resp   *http.Response
 		newRef reference.Named
4352da78
 	)
 
0380fbff
 	// Default the operating system if not supplied.
 	if os == "" {
 		os = runtime.GOOS
3d5cec70
 	}
 
47afe6bd
 	if repository != "" {
 		var err error
3a127939
 		newRef, err = reference.ParseNormalizedNamed(repository)
47afe6bd
 		if err != nil {
ebcb7d6b
 			return validationError{err}
47afe6bd
 		}
 		if _, isCanonical := newRef.(reference.Canonical); isCanonical {
ebcb7d6b
 			return validationError{errors.New("cannot import digest reference")}
47afe6bd
 		}
 
 		if tag != "" {
 			newRef, err = reference.WithTag(newRef, tag)
 			if err != nil {
ebcb7d6b
 				return validationError{err}
47afe6bd
 			}
 		}
 	}
 
93e02efa
 	config, err := dockerfile.BuildFromConfig(&container.Config{}, changes)
 	if err != nil {
 		return err
 	}
4352da78
 	if src == "-" {
e1c2eb0d
 		rc = inConfig
4352da78
 	} else {
 		inConfig.Close()
e050f176
 		if len(strings.Split(src, "://")) == 1 {
 			src = "http://" + src
 		}
4352da78
 		u, err := url.Parse(src)
 		if err != nil {
ebcb7d6b
 			return validationError{err}
4352da78
 		}
e050f176
 
4060d6ee
 		resp, err = remotecontext.GetWithStatusError(u.String())
4352da78
 		if err != nil {
 			return err
 		}
c87d67b0
 		outStream.Write(streamformatter.FormatStatus("", "Downloading from %s", u))
 		progressOutput := streamformatter.NewJSONProgressOutput(outStream, true)
e1c2eb0d
 		rc = progress.NewProgressReader(resp.Body, progressOutput, resp.ContentLength, "", "Importing")
4352da78
 	}
 
e1c2eb0d
 	defer rc.Close()
4352da78
 	if len(msg) == 0 {
 		msg = "Imported from " + src
 	}
e1c2eb0d
 
 	inflatedLayerData, err := archive.DecompressStream(rc)
 	if err != nil {
 		return err
 	}
0380fbff
 	l, err := daemon.stores[os].layerStore.Register(inflatedLayerData, "", layer.OS(os))
4352da78
 	if err != nil {
 		return err
 	}
0380fbff
 	defer layer.ReleaseAndLog(daemon.stores[os].layerStore, l)
4352da78
 
 	created := time.Now().UTC()
 	imgConfig, err := json.Marshal(&image.Image{
 		V1Image: image.V1Image{
 			DockerVersion: dockerversion.Version,
 			Config:        config,
 			Architecture:  runtime.GOARCH,
0380fbff
 			OS:            os,
4352da78
 			Created:       created,
 			Comment:       msg,
 		},
 		RootFS: &image.RootFS{
 			Type:    "layers",
 			DiffIDs: []layer.DiffID{l.DiffID()},
 		},
 		History: []image.History{{
 			Created: created,
 			Comment: msg,
 		}},
 	})
 	if err != nil {
 		return err
 	}
 
0380fbff
 	id, err := daemon.stores[os].imageStore.Create(imgConfig)
4352da78
 	if err != nil {
 		return err
 	}
 
2655954c
 	// FIXME: connect with commit code and call refstore directly
4352da78
 	if newRef != nil {
0380fbff
 		if err := daemon.TagImageWithReference(id, os, newRef); err != nil {
4352da78
 			return err
 		}
 	}
 
72f1881d
 	daemon.LogImageEvent(id.String(), id.String(), "import")
c87d67b0
 	outStream.Write(streamformatter.FormatStatus("", id.String()))
4352da78
 	return nil
 }