-
Notifications
You must be signed in to change notification settings - Fork 18.6k
/
image_import.go
144 lines (131 loc) · 3.86 KB
/
image_import.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package images // import "github.com/docker/docker/daemon/images"
import (
"encoding/json"
"io"
"net/http"
"net/url"
"strings"
"time"
"github.com/containerd/containerd/platforms"
"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/builder/dockerfile"
"github.com/docker/docker/builder/remotecontext"
"github.com/docker/docker/dockerversion"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/image"
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/progress"
"github.com/docker/docker/pkg/streamformatter"
"github.com/docker/docker/pkg/system"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
// 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.
func (i *ImageService) ImportImage(src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
var (
rc io.ReadCloser
resp *http.Response
newRef reference.Named
)
if repository != "" {
var err error
newRef, err = reference.ParseNormalizedNamed(repository)
if err != nil {
return errdefs.InvalidParameter(err)
}
if _, isCanonical := newRef.(reference.Canonical); isCanonical {
return errdefs.InvalidParameter(errors.New("cannot import digest reference"))
}
if tag != "" {
newRef, err = reference.WithTag(newRef, tag)
if err != nil {
return errdefs.InvalidParameter(err)
}
}
}
// Normalize platform - default to the operating system and architecture if not supplied.
if platform == nil {
p := platforms.DefaultSpec()
platform = &p
}
if !system.IsOSSupported(platform.OS) {
return errdefs.InvalidParameter(system.ErrNotSupportedOperatingSystem)
}
config, err := dockerfile.BuildFromConfig(&container.Config{}, changes, platform.OS)
if err != nil {
return err
}
if src == "-" {
rc = inConfig
} else {
inConfig.Close()
if len(strings.Split(src, "://")) == 1 {
src = "http://" + src
}
u, err := url.Parse(src)
if err != nil {
return errdefs.InvalidParameter(err)
}
resp, err = remotecontext.GetWithStatusError(u.String())
if err != nil {
return err
}
outStream.Write(streamformatter.FormatStatus("", "Downloading from %s", u))
progressOutput := streamformatter.NewJSONProgressOutput(outStream, true)
rc = progress.NewProgressReader(resp.Body, progressOutput, resp.ContentLength, "", "Importing")
}
defer rc.Close()
if len(msg) == 0 {
msg = "Imported from " + src
}
inflatedLayerData, err := archive.DecompressStream(rc)
if err != nil {
return err
}
l, err := i.layerStore.Register(inflatedLayerData, "")
if err != nil {
return err
}
defer layer.ReleaseAndLog(i.layerStore, l)
created := time.Now().UTC()
imgConfig, err := json.Marshal(&image.Image{
V1Image: image.V1Image{
DockerVersion: dockerversion.Version,
Config: config,
Architecture: platform.Architecture,
Variant: platform.Variant,
OS: platform.OS,
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
}
id, err := i.imageStore.Create(imgConfig)
if err != nil {
return err
}
// FIXME: connect with commit code and call refstore directly
if newRef != nil {
if err := i.TagImageWithReference(id, newRef); err != nil {
return err
}
}
i.LogImageEvent(id.String(), id.String(), "import")
outStream.Write(streamformatter.FormatStatus("", id.String()))
return nil
}