github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/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, 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 if repository != "" { 37 var err error 38 newRef, err = reference.ParseNormalizedNamed(repository) 39 if err != nil { 40 return err 41 } 42 if _, isCanonical := newRef.(reference.Canonical); isCanonical { 43 return errors.New("cannot import digest reference") 44 } 45 46 if tag != "" { 47 newRef, err = reference.WithTag(newRef, tag) 48 if err != nil { 49 return err 50 } 51 } 52 } 53 54 config, err := dockerfile.BuildFromConfig(&container.Config{}, changes) 55 if err != nil { 56 return err 57 } 58 if src == "-" { 59 rc = inConfig 60 } else { 61 inConfig.Close() 62 if len(strings.Split(src, "://")) == 1 { 63 src = "http://" + src 64 } 65 u, err := url.Parse(src) 66 if err != nil { 67 return err 68 } 69 70 resp, err = remotecontext.GetWithStatusError(u.String()) 71 if err != nil { 72 return err 73 } 74 outStream.Write(streamformatter.FormatStatus("", "Downloading from %s", u)) 75 progressOutput := streamformatter.NewJSONProgressOutput(outStream, true) 76 rc = progress.NewProgressReader(resp.Body, progressOutput, resp.ContentLength, "", "Importing") 77 } 78 79 defer rc.Close() 80 if len(msg) == 0 { 81 msg = "Imported from " + src 82 } 83 84 inflatedLayerData, err := archive.DecompressStream(rc) 85 if err != nil { 86 return err 87 } 88 // TODO: support windows baselayer? 89 l, err := daemon.layerStore.Register(inflatedLayerData, "") 90 if err != nil { 91 return err 92 } 93 defer layer.ReleaseAndLog(daemon.layerStore, l) 94 95 created := time.Now().UTC() 96 imgConfig, err := json.Marshal(&image.Image{ 97 V1Image: image.V1Image{ 98 DockerVersion: dockerversion.Version, 99 Config: config, 100 Architecture: runtime.GOARCH, 101 OS: runtime.GOOS, 102 Created: created, 103 Comment: msg, 104 }, 105 RootFS: &image.RootFS{ 106 Type: "layers", 107 DiffIDs: []layer.DiffID{l.DiffID()}, 108 }, 109 History: []image.History{{ 110 Created: created, 111 Comment: msg, 112 }}, 113 }) 114 if err != nil { 115 return err 116 } 117 118 id, err := daemon.imageStore.Create(imgConfig) 119 if err != nil { 120 return err 121 } 122 123 // FIXME: connect with commit code and call refstore directly 124 if newRef != nil { 125 if err := daemon.TagImageWithReference(id, newRef); err != nil { 126 return err 127 } 128 } 129 130 daemon.LogImageEvent(id.String(), id.String(), "import") 131 outStream.Write(streamformatter.FormatStatus("", id.String())) 132 return nil 133 }