Tizen_4.0 base
[platform/upstream/docker-engine.git] / daemon / import.go
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, platform 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 platform if not supplied.
37         if platform == "" {
38                 platform = runtime.GOOS
39         }
40
41         if repository != "" {
42                 var err error
43                 newRef, err = reference.ParseNormalizedNamed(repository)
44                 if err != nil {
45                         return err
46                 }
47                 if _, isCanonical := newRef.(reference.Canonical); isCanonical {
48                         return errors.New("cannot import digest reference")
49                 }
50
51                 if tag != "" {
52                         newRef, err = reference.WithTag(newRef, tag)
53                         if err != nil {
54                                 return 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 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[platform].layerStore.Register(inflatedLayerData, "", layer.Platform(platform))
94         if err != nil {
95                 return err
96         }
97         defer layer.ReleaseAndLog(daemon.stores[platform].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:            platform,
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[platform].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, platform, 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 }