moby/daemon/images/image_import.go
Sebastiaan van Stijn b2ef2e8c83
daemon/images: remove leftover LCOW platform checks
This removes some of the checks that were added in 0cba7740d4,
but should no longer be needed.

- `ImageService.ImageDelete()`: no need to validate image platform to delete it.
- `ImageService.ImageHistory()`: no need to validate image platform to show its
  history; if it made it into the local image cache, it should be valid.
- `ImageService.ImportImage()`: `dockerfile.BuildFromConfig()` is used for
  `docker (container) commmit` and `docker (image) import`. For `docker import`,
   it's more transparent to perform validation early.
- `ImageService.LookupImage()`: no need to validate image platform to inspect it;
  if it made it into the local image cache, it should be valid.
- `ImageService.SquashImage()`: same. This code was actually broken, because it
  wrapped an `err` that was always `nil`, so would never return an error.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-01-25 12:15:50 +01:00

144 lines
3.9 KiB
Go

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
}